2026年7月2日 2 分钟阅读

150 行代码搭建 AI Agent CLI:拆解工具调用的四个核心组件

tinyash 0 条评论

背景

Go Micro 团队最近发布了一篇技术博客,展示如何用约 150 行代码构建一个能与微服务通过自然语言交互的 AI Agent CLI。项目的核心承诺听起来像魔法:你只需说「创建用户 Alice」,Agent 就能自动找到正确的服务端点并完成调用,全程不需要手写任何「if 用户请求 email 则调用 email 服务」这样的逻辑判断。

但这背后没有魔法。整个系统的核心只有四个组件——工具发现、模型创建、对话记忆、主循环——每个组件的代码量都小得令人惊讶。本文将这些组件逐一拆解,用 Go 代码(原文语言)展示每个部分,并提供框架无关的分析,让你能在任意技术栈中复现这个模式。

组件一:工具发现(Discover the Tools)

LLM 在做工具调用之前,首先需要知道有哪些工具可用。这是整个系统的基础。

原文中,Go Micro 利用了自己的服务注册表(Registry)来实现自动发现:每个部署的服务都会注册它的端点、请求类型和字段元数据。注册表将这些信息转为一个工具列表——每个服务端点对应一个工具,工具名就是端点名,描述来自 handler 的 doc comment,参数 schema 来自请求结构体的字段定义。

// 从注册表自动发现工具列表(Go Micro 专用)
tools := ai.NewTools(reg, ai.ToolClient(client))
discovered, err := tools.Discover()

这段代码之所以简洁,完全得益于 Go Micro 的自描述服务机制:每个服务都公开自己的元数据。doc comment 自动成为工具描述,@example tag 为 LLM 提供参数格式示例。

框架无关分析:如果你不用 Go Micro,你需要手动枚举你的函数/端点并构建一个 {name, description, parameters} 列表。可以是一个 JSON 配置文件,也可以是一个中心化的函数注册表。关键是——没有一个额外的「智能调度层」去解析用户意图——你只是把本地的 API 清单格式化成了 LLM 能理解的 Schema。

组件二:模型创建(Create the Model)

有了工具列表,Agent 需要与 LLM 交互。Go Micro 的 ai.New() 接受提供商名(如 anthropic)和配置选项。

// 一行代码创建模型 + 绑定工具集
m := ai.New("anthropic",
    ai.WithAPIKey(os.Getenv("ANTHROPIC_API_KEY")),
    ai.WithTools(tools),
)

这里的核心设计是 m 对象做了两件事:推理面执行面。推理面构建工具列表并发送给模型;执行面在模型说「调用 X 工具的 Y 参数」时,将调用路由到正确的 RPC 端点并返回结果。

框架无关分析ai.New() 对多个提供商(Anthropic、OpenAI、Gemini、Groq、Mistral、Together、Atlas Cloud)使用了统一接口,切换提供商只需要修改第一个参数(如 "openai""gemini")。如果你自己实现,你需要选择一个 LLM SDK,并为每个提供商实现一个 Model 接口——但核心逻辑是一样的:构建 messages + tools 的请求,解析 tool_use 响应,路由到 handler 执行,将结果返回。

组件三:对话记忆(Track the Conversation)

AI Agent 能理解上下文的关键在于「记住前面说了什么」。原文的实现出人意料的简洁——用 ai.NewHistory() 创建一个带大小限制的消息累加器:

// 一个带滑动窗口的消息历史
hist := ai.NewHistory(50)
// 使用时只需追加消息
hist.Add("user", prompt)
// 获取当前所有消息(自动限制在窗口大小内)
msgs := hist.Messages()

它本质上就是一个消息列表 + 滑动窗口。用户的消息和模型的回复在每次交互后被追加进来,下次调用时一起传入 LLM。这个简单结构支持的却是多轮对话自然语言追问——你可以说「创建用户 Alice」→ 系统执行 →「再给她发一封欢迎邮件」,而不需要手动拼接上下文。需要重置对话时,调用 hist.Reset() 清空即可。

框架无关分析:对话记忆是所有 AI Agent 中最容易被低估的组件。很多实现倾向于加入「记忆压缩」「语义摘要」「向量检索」等复杂机制,但 90% 的场景下,一个简单的消息累加器就足够了。滑动窗口大小(传递给 NewHistory 的参数)可以根据模型的最大上下文长度设定——例如 128K 上下文的模型可以设置更大的窗口,64K 的模型则需要更紧凑。关键原则:先做对的,再做快的。

组件四:主循环(The Core Loop)

有了前面三个组件,主循环就是将一切串联起来的胶水。原文的核心代码只有约 40 行:

func ask(ctx context.Context, m ai.Model, hist *ai.History, tools []ai.Tool, prompt string) error {
    hist.Add("user", prompt)

    resp, err := m.Generate(ctx, &ai.Request{
        Prompt:       prompt,
        SystemPrompt: systemPrompt,
        Tools:        tools,
        Messages:     hist.Messages(),
    })
    if err != nil {
        return err
    }

    if resp.Reply != "" {
        hist.Add("assistant", resp.Reply)
        fmt.Println(resp.Reply)
    }

    // 显示调用了哪些工具
    for _, tc := range resp.ToolCalls {
        args, _ := json.Marshal(tc.Input)
        fmt.Printf("  → called %s(%s)\n", tc.Name, args)
    }

    if resp.Answer != "" {
        hist.Add("assistant", resp.Answer)
        fmt.Println(resp.Answer)
    }
    return nil
}

func main() {
    scanner := bufio.NewScanner(os.Stdin)
    for {
        fmt.Print("> ")
        if !scanner.Scan() { return nil }
        line := strings.TrimSpace(scanner.Text())
        switch line {
        case "exit", "quit": return nil
        case "reset": hist.Reset(); continue
        default:
            if err := ask(ctx, m, hist, discovered, line); err != nil {
                fmt.Printf("error: %v\n", err)
            }
        }
    }
}

m.Generate() 是核心——它内部实现了「模型决定 → 调用工具 → 获取结果 → 再次询问模型是否需要继续」的循环。我们从来没有写过一句「if 用户想要 email,调用 email 服务」的逻辑。LLM 根据工具描述自己做了这个推理。

框架无关分析:主循环模式是一个生成 → 执行 → 反馈的迭代过程。即使你不用 Go Micro,在任何语言中都可以实现同样的循环:读取 prompt → 构造请求(含 tools)→ 调用 LLM API → 解析响应(检查是否有 tool_use)→ 如果有工具调用则执行并反馈结果 → 继续循环直到模型返回纯文本答案。这个模式的通用性使其成为所有 tool-calling Agent 的基座。

扩展方向

原文提出了六个从原型走向生产级的方向:

  • 确认步骤:对危险操作(删除记录、修改权限)加入人工确认
  • 审计日志:所有工具调用记录到审计追踪或可观测性栈
  • 作用域限制:基于角色的工具可见性,让 Agent 只能看到权限范围内的服务
  • 切换到 Slack Bot:将 stdin/stdout 替换为 Slack 消息循环
  • 预加载系统提示:注入领域知识(如业务规则、命名约定)
  • 事件驱动:从 stdin 循环改为 cron 或 Webhook 触发

其中审计日志和确认步骤两个方向对生产级部署尤其关键——前者解决合规需求,后者防止意外操作。

核心启示

Go Micro 这篇博客展示了一个重要的工程认知:构建工具调用的 AI Agent 不是需要学习复杂框架的任务——它是一个可复制的、约 150 行的设计模式。四个组件的职责清晰、边界明确,每个组件都可以独立替换或升级。工具发现可以用配置文件代替注册表;模型创建可以换 SDK;对话记忆可以加持久化;主循环可以接不同的输入源。

对于正在搭建 Agent 系统的开发者来说,这个架构的启示是:不要急于引入框架,先用 150 行理解系统的本质,再根据实际需要逐步添加复杂性。

原文:Build Your Own AI Agent CLI in 150 Lines(Go Micro Blog, May 30, 2026)

发表评论

你的邮箱地址不会被公开,带 * 的为必填项。