blades

repository·main·Indexed 21 days ago

https://github.com/go-kratos/blades

A multimodal AI Agent framework for Go designed for multi-turn conversations, chain-of-thought reasoning, and structured output. It features a decoupled architecture with pluggable models, tools, and memory, including a CLI for workspace management, interactive chat, and task scheduling. The framework provides official provider support for Anthropic Claude (via Direct API, AWS Bedrock, or Google Vertex AI) and Google Gemini (via GenAI or Vertex AI).

Tokens
41.1K
Snippets
158
Records
191
Agent score
73%

What's inside blades

  1. Use OpenAI Chat, Image, and Audio providers

    main

    The openai package provides adapters that implement the blades.ModelProvider interface for OpenAI's various endpoints. It includes three main provider types:

    • NewChatProvider: For text and multimodal chat completions.
    • NewImageProvider: For image generation (/v1/images/generations). Returns results as DataPart or FilePart message contents.
    • NewAudioProvider: For text-to-speech (/v1/audio/speech). Returns synthesized audio as DataPart payloads.
  2. Understand the Blades workspace structure and key files

    main

    A Blades workspace is organized around several key markdown files that define the identity, memory, and operational context of your AI assistant. These files allow you to curate the assistant's personality, knowledge, and long-term memory.

    Core Identity and Context Files

    • SOUL.md: Defines the assistant's identity, principles, and persona.
    • USER.md: Contains information about the user the assistant is helping.
    • AGENTS.md: Configures session startup procedures and behavioral rules.

    Memory and Knowledge Files

    • MEMORY.md: Stores long-term, curated memory.
    • memory/: A directory containing daily session logs.
    • knowledges/: A directory for domain-specific reference files.

    Operational Files

    • TOOLS.md: Contains local setup notes (e.g., SSH configurations, device access).
    • HEARTBEAT.md: A task list for proactive check-ins.

    Workspace Configuration

    To ensure the assistant operates correctly, you should maintain an IDENTITY.md file in your workspace that specifies your Home directory, Workspace directory, and the Model used (as configured in agent.yaml).

  3. Manage conversation context with summarize or window

    main

    The context field controls how message history is trimmed to fit within token limits. It can be applied to the top-level spec or individual sub-agents.

    • summarize: Compresses old messages into a rolling LLM-generated summary. The most recent keep_recent messages (default: 10) are kept verbatim. Use max_tokens to trigger compression.
    • window: Drops the oldest messages to stay within max_tokens or max_messages limits.
    context:
      strategy: summarize
      max_tokens: 80000
      keep_recent: 10
      batch_size: 20
      model: gpt-4o-mini
  4. How sub-agent execution modes work

    main

    When a recipe defines sub_agents, you must specify an execution mode. This determines how the sub-agents are orchestrated:

    1. sequential: Sub-agents run one after another. Use output_key in a sub-agent to save its result to the session state, which can then be accessed by subsequent sub-agents using {{.output_key}}. In this mode, the parent's instruction and output_key are ignored.
    2. parallel: Sub-agents run concurrently. Outputs are written to session state independently. There are no data dependencies between steps.
    3. tool: Each sub-agent is treated as a tool. The parent agent's LLM decides when to call them based on their name and description. Sub-agent output_key is not supported in this mode. Function tools and sub-agent tools are merged.
    4. loop: Sub-agents run repeatedly up to max_iterations (default: 10). The loop terminates if a sub-agent calls the exit tool or if the iteration limit is reached. In this mode, the parent's instruction and output_key are ignored.
    # Example: Sequential execution passing data
    execution: sequential
    sub_agents:
      - name: syntax-checker
        instruction: Check the {{.language}} code for syntax errors.
        output_key: syntax_report
      - name: quality-reviewer
        instruction: Review code quality. Syntax report: {{.syntax_report}}
        output_key: quality_report
  5. How Agent, ModelProvider, and Tool work together

    main

    Blades uses a decoupled architecture where different components are orchestrated by an Agent:

    • Agent: The core coordinator. It integrates ModelProvider, Tool, Memory, and Middleware to understand intent and execute tasks. It implements the Agent interface, allowing it to be used in Chains or as part of a Flow.
    • ModelProvider: An abstraction layer (adapter) that translates framework requests into specific LLM API formats (e.g., OpenAI, Gemini) and back. This allows you to switch models without changing your agent logic.
    • Tool: External capabilities (APIs, databases, file systems) that an Agent can invoke. Tools use an InputSchema to guide the LLM on how to generate correct parameters and a Handle function to execute the logic.
    • Flow: A mechanism to orchestrate multiple Agent components, where the output of one agent serves as the input for the next, enabling multi-step reasoning.
    // Agent is the core interface for all executable components
    type Agent interface {
        Name() string
        Description() string
        Run(context.Context, *Invocation) Generator[*Message, error]
    }
    
    // ModelProvider abstracts the LLM interaction
    type ModelProvider interface {
        Generate(context.Context, *ModelRequest, ...ModelOption) (*ModelResponse, error)
        NewStreaming(context.Context, *ModelRequest, ...ModelOption) (Generator[*ModelResponse])
    }
  6. Understand the blades directory layout

    main

    Blades uses a dual-directory structure: a Home (root) for system-wide configuration and a Workspace for agent-specific execution and memory.

    Home (~/.blades)

    • agent.yaml: LLM provider, model, and API key settings.
    • cron.yaml: Persistent storage for scheduled jobs.
    • skills/: Global skills available to all workspaces.
    • sessions/: Conversation state indexed by session ID.
    • logs/: Runtime audit logs (YYYY-MM-DD.log).

    Workspace (~/.blades/workspace or --workspace <path>)

    • AGENTS.md: Behavior rules loaded at startup.
    • MEMORY.md: L1 long-term facts.
    • memory/: L2 daily session logs (YYYY-MM-DD.md).
    • knowledges/: L3 reference knowledge files.
    • outputs/: Files produced by the agent.
    • SOUL.md, IDENTITY.md, USER.md, TOOLS.md, HEARTBEAT.md: Core identity and tool definition files.
  7. Extend blades with the Skill system

    main

    Blades automatically discovers skills located in the global skills directory: ~/.blades/skills/.

    To create a skill:

    1. Create a new directory within ~/.blades/skills/.
    2. Add a SKILL.md file inside that directory.
    3. The SKILL.md must contain YAML front-matter followed by the skill description/body.
  8. Use automatic Tool Calling

    main

    Claude can automatically execute tools defined in the blades.Tool struct. When a tool is provided in the ModelRequest, the client handles the iterative loop: calling the tool, processing the result, and returning the final response to the user.

    // Define a tool
    weatherTool := &blades.Tool{
    	Name:        "get_weather",
    	Description: "Get current weather for a location",
    	Handle: func(ctx context.Context, arguments string) (string, error) {
    		// Parse arguments and fetch weather
    		return `{"temperature": 72, "condition": "sunny"}`, nil
    	},
    }
    
    // Add tools to request
    req := &blades.ModelRequest{
    	Model: "claude-3-5-sonnet-20241022",
    	Tools: []*blades.Tool{weatherTool},
    	Messages: []*blades.Message{
    		{
    			Role: blades.RoleUser,
    			Parts: []blades.Part{
    				blades.TextPart{Text: "What's the weather in San Francisco?"},
    			},
    		},
    	},
    }
    
    // Generate with automatic tool execution
    resp, err := client.Generate(context.Background(), req)
  9. Use Middleware for cross-cutting concerns

    main
    Blades uses a Middleware mechanism inspired by web frameworks to implement cross-cutting concerns like logging, monitoring, authentication, and rate limiting. It uses an "onion model" (function chain) to inject behavior into the execution flow of a Runner without modifying the core logic of the Agent.
  10. How blades memory architecture works

    main

    Blades uses a three-tier memory system to manage context and long-term knowledge within the workspace:

    • L1 (Long-term Facts): Stored in workspace/MEMORY.md. Used for persistent facts.
    • L2 (Daily Session Logs): Stored in workspace/memory/YYYY-MM-DD.md. If logConversation: true is set in the config, daily chat logs are appended here for long-term context.
    • L3 (Knowledge Files): Stored in workspace/knowledges/*.md. These are files used for on-demand reference.
  11. Inject Skills into an Agent

    main

    Agents can be extended with capabilities called 'Skills' using the WithSkills(...) option. Skills can be loaded from a local directory or embedded directly into your binary using embed.FS.

    Note: Skills must follow the Agent Skill specification.

    //go:embed example-skill/*
    var skillFS embed.FS
    
    func createAgent(model blades.ModelProvider) (blades.Agent, error) {
        // Directory-based loading:
        skillsFromDir, err := skills.NewFromDir("./skills")
        if err != nil {
            return nil, err
        }
        // Embedded loading:
        skillsFromEmbed, err := skills.NewFromEmbed(skillFS)
        if err != nil {
            return nil, err
        }
        allSkills := append(skillsFromDir, skillsFromEmbed...)
        return blades.NewAgent(
            "SkillsAgent",
            blades.WithModel(model),
            blades.WithSkills(allSkills...),
        )
    }