Sourcegraph工程师Thorsten Ball分享了How to Build an Agent - Amp,核心观点是Agent的构建就是让 LLM 像工程师一样“死磕问题”,不需要看一堆 Karpathy 的视频去理解代理,也不需要研究神经网络原理。只要了解 LLM 是怎么通过对话调用工具的,写点代码,跑一下,你就会恍然大悟。

以下是对文章的总结学习。

一、博客的核心观点

  1. Agent 其实没那么神秘:

    原文用不到 400 行的 Go 代码就构建了一个能读写、编辑文件的代码 Agent,有力说明了基础架构可以非常精简。核心三要素: 一个大语言模型 (LLM)、一个处理循环、再加上一套能让它操作外部环境的工具。这就是 Agent 的骨架。

2.工具是 Agent 的“手脚”:​​

read_file、list_files、edit_file 这些工具赋予了 LLM 感知和修改其运行环境(这里是文件系统)的能力。在​工具设计需要注意以下:​​

  • ​清晰定义:​​ 用 JSON Schema 明确告诉 LLM 工具需要什么输入,能做什么,返回什么。

  • ​功能单一:​​ 每个工具最好只专注做好一件事(比如 edit_file 就做字符串替换)。

  • ​安全边界:​​ 严格限制工具的操作范围(比如只允许操作相对路径下的文件)。

二、​构建 Agent 的关键步骤

1. 打造工具系统(核心引擎)​
  • 工具怎么表示?​

    type ToolDefinition struct {
        Name        string   // 工具名字,如 "edit_file"
        Description string   // 用自然语言告诉 LLM 这工具干嘛用、什么时候用
        InputSchema Schema   // 定义输入数据的格式和规则 (JSON Schema)
        Function    func()   // 工具实际执行的代码逻辑
    }

  • 必须做到位:​

    • 输入检查:​​ 在 Function 里一定要验证传入的参数是否合法、安全(比如文件路径是否在允许范围内)。

    • 明确反馈:​​ 工具执行失败时,要给 LLM 清晰的错误信息。

    • 无状态:​​ 工具本身不应该“记住”之前的状态,每次调用都是独立的。

2. 设计执行循环(控制中心)​
func (a *Agent) Run() error {
    for { // 持续运行的循环
        // (1) 获取用户输入
        userInput := getUserMessage()

        // (2) 调用 LLM (记得带上当前对话和可用工具列表)
        message := a.runInference(conversation, tools)

        // (3) 处理 LLM 的回复
        switch content.Type {
        case "text": // LLM 说了段话
            ... // 显示给用户
        case "tool_use": // LLM 想用某个工具!
            // 执行工具
            toolResults = executeTool(content)
            // **关键一步**:把工具执行结果作为一条新消息加入对话
            conversation.Append(toolResults)
        }
    }
}
  • 核心创新点:​​ 把工具的执行结果直接塞回对话历史 (conversation.Append(toolResults))。这让 LLM 能“看到”工具干了什么,并据此决定下一步行动。

3. LLM 与工具的协作方式
  • 工具描述清晰:​​ 工具描述 (Description) 必须写得准确易懂,让 LLM 明白什么时候该用哪个工具(比如 edit_file 强调 old_str 要能精确匹配且唯一)。

  • 触发机制:​​ LLM 通过返回一个特殊类型 ("tool_use") 来表示“我想用工具了”。

  • 无需训练:​​ Claude 3.7 这类现代 LLM 能直接理解工具描述并尝试使用,不需要特别教它例子。

三、​工程实践技巧

  1. ​如何节省 Token :​

    • 工具调用让 Agent 通过简洁的指令(如 edit_file({"path": "fizzbuzz.js", ...})) 操作复杂环境,避免了把大量文件内容塞进提示词。

  2. 让 Agent 更可靠:​

    • 权限管住:​​ 工具操作范围要小(比如只让动当前目录)。

    • 输入卡严:​​ 用 JSON Schema 严格校验工具输入格式。

    • 防死循环:​​ 限制工具链调用深度(比如最多连续调用 3 次工具,避免无限循环)。

    • 操作前检查:​​ 关键操作前可以加一步确认(比如 read_file 前先检查文件是否存在)。

    • 给工具更清晰的错误反馈机制,让 LLM 知道问题出在哪。

  3. 能力“涌现”:​

    • 当提供了几个基础工具(如读、列、写文件),像 Claude 3.7 这样的 LLM 能自发组合使用它们​(例如:先 list_files 找文件 -> 再 read_file 看内容 -> 最后 edit_file 做修改)。这种链条式调用不需要额外训练。

总结:Agent 构建的思路转变

传统 Agent的构建依赖复杂的规则引擎和硬编码逻辑,而当下则依靠LLM。核心是强大的 LLM(大脑),工具是它的四肢,执行循环是连接大脑和四肢的神经系统。​ 当工具系统和执行循环设计得当,​Agent 能力的上限主要取决于所用的 LLM 本身,而不是架构有多复杂

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐