Agent 示例

工具调用

Agent 使用内置工具执行操作

工具调用示例

展示如何让 Agent 使用内置工具(文件系统、Bash 等)。

完整代码

package main

import (
    "context"
    "fmt"
    "log"
    "os"

    "github.com/astercloud/aster/pkg/agent"
    "github.com/astercloud/aster/pkg/provider"
    "github.com/astercloud/aster/pkg/sandbox"
    "github.com/astercloud/aster/pkg/store"
    "github.com/astercloud/aster/pkg/tools"
    "github.com/astercloud/aster/pkg/tools/builtin"
    "github.com/astercloud/aster/pkg/types"
)

func main() {
    ctx := context.Background()

    // 创建工具注册表并注册内置工具
    toolRegistry := tools.NewRegistry()
    builtin.RegisterAll(toolRegistry)

    // 创建依赖
    deps := &agent.Dependencies{
        ToolRegistry:     toolRegistry,
        SandboxFactory:   sandbox.NewFactory(),
        ProviderFactory:  provider.NewMultiProviderFactory(),
        Store:            store.NewMemoryStore(),
        TemplateRegistry: agent.NewTemplateRegistry(),
    }

    // 创建 Agent,启用工具
    ag, err := agent.Create(ctx, &types.AgentConfig{
        TemplateID: "assistant",
        ModelConfig: &types.ModelConfig{
            Provider: "anthropic",
            Model:    "claude-sonnet-4-5",
            APIKey:   os.Getenv("ANTHROPIC_API_KEY"),
        },
        Tools: []string{"filesystem", "bash"},  // 启用工具
    }, deps)
    if err != nil {
        log.Fatal(err)
    }
    defer ag.Close()

    // 订阅进度和控制事件
    eventCh := ag.Subscribe([]types.AgentChannel{
        types.ChannelProgress,
        types.ChannelControl,
    }, nil)

    // 处理事件
    go func() {
        for envelope := range eventCh {
            switch envelope.Event.Type {
            case types.EventTypeTextDelta:
                fmt.Print(envelope.Event.TextDelta)

            case types.EventTypeToolCallRequest:
                tool := envelope.Event.ToolCall
                fmt.Printf("\n[工具调用] %s\n", tool.Name)
                fmt.Printf("[参数] %v\n", tool.Arguments)

            case types.EventTypeToolCallResult:
                result := envelope.Event.ToolResult
                fmt.Printf("[结果] %s\n\n", result.Content)
            }
        }
    }()

    // 发送需要使用工具的请求
    err = ag.Send(ctx, "创建一个 hello.txt 文件,内容为 'Hello, aster!'")
    if err != nil {
        log.Fatal(err)
    }

    // 等待完成
    select {}
}

运行示例

export ANTHROPIC_API_KEY="sk-ant-xxx"
go run main.go

输出示例

我来为您创建这个文件。

[工具调用] filesystem_write
[参数] map[content:Hello, aster! path:hello.txt]
[结果] 文件已创建: hello.txt

文件已成功创建!您可以在当前目录找到 hello.txt 文件。

可用的内置工具

Tools: []string{
    "filesystem",  // 文件系统操作
    "bash",        // Shell 命令
    "http",        // HTTP 请求
    "websearch",   // 网页搜索
}

多步骤工具调用

Agent 可以自动链式调用多个工具:

// 请求需要多步操作
ag.Send(ctx, "列出当前目录的 .go 文件,然后统计总行数")

// Agent 会自动:
// 1. 调用 bash: ls *.go
// 2. 调用 bash: wc -l file1.go file2.go
// 3. 返回统计结果

监控工具执行

详细监控每个工具调用:

go func() {
    for envelope := range eventCh {
        switch envelope.Event.Type {
        case types.EventTypeToolCallRequest:
            tool := envelope.Event.ToolCall
            log.Printf("🔧 调用工具: %s", tool.Name)
            log.Printf("📥 输入: %+v", tool.Arguments)

        case types.EventTypeToolCallResult:
            result := envelope.Event.ToolResult
            if result.IsError {
                log.Printf("❌ 错误: %s", result.Content)
            } else {
                log.Printf("✅ 成功: %s", result.Content)
            }
        }
    }
}()

同步模式

如果不需要实时监控,可以使用同步 Chat()

result, err := ag.Chat(ctx, "创建 hello.txt 文件")
if err != nil {
    log.Fatal(err)
}

fmt.Println(result.Message.Content)
// Agent 会自动调用工具并返回最终结果

相关资源