2026年6月8日 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 专用)
reg := registry.DefaultRegistry
services, _ := reg.ListServices()
for _, svc := range services {
    for _, ep := range svc.Endpoints {
        tool := &llmtool.Tool{
            Name:        svc.Name + "." + ep.Name,
            Description: ep.Metadata["description"],
            Parameters:  buildSchema(ep.Request),
        }
        tools = append(tools, tool)
    }
}

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

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

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

有了工具列表,Agent 需要与 LLM 交互。Go Micro 的 llmtool.New() 接受一个模型名(如 claude-sonnet-4-20250514)并自动选择对应的提供商。

// 一行代码创建模型 + 工具调用 handler
m, _ := llmtool.New(
    llmtool.WithModel(os.Getenv("MICRO_LLM_MODEL")),
    llmtool.WithProvider(os.Getenv("MICRO_LLM_PROVIDER")),
)

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

// m.Init() 返回 (推理工具, 执行 handler)
tools, handler, _ := m.Init(services)

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

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

AI Agent 能理解上下文的关键在于「记住前面说了什么」。原文的实现出人意料的简洁:

// 一个带大小限制的消息累加器
type Conversation struct {
    Messages []llm.Message
    MaxSize  int
}

func (c *Conversation) Add(msg llm.Message) {
    c.Messages = append(c.Messages, msg)
    if len(c.Messages) > c.MaxSize {
        c.Messages = c.Messages[1:]
    }
}

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

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

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

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

func chat(ctx context.Context, m *llmtool.Model, conv *Conversation) error {
    // 从 stdin 读取用户输入
    scanner := bufio.NewScanner(os.Stdin)
    for scanner.Scan() {
        input := scanner.Text()
        if input == "exit" { break }

        conv.Add(llm.Message{Role: "user", Content: input})

        // 调用 LLM:工具调用自动执行,最终答案返回
        response, _ := m.Run(ctx, conv.Messages, tools)
        
        // 显示调用了哪些工具
        for _, tc := range response.ToolCalls {
            fmt.Printf("→ [%s] %s(%v)\n", tc.Name, tc.Name, tc.Args)
        }
        // 打印最终答案
        fmt.Println(response.Content)
        conv.Add(llm.Message{Role: "assistant", Content: response.Content})
    }
    return nil
}

m.Run() 是核心——它内部实现了「模型决定 → 调用工具 → 获取结果 → 再次询问模型是否需要继续」的循环。我们从来没有写过一句「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)

发表评论

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