如何构建AGENT? OR 皇帝的新装
Sourcegraph工程师Thorsten Ball分享了,核心观点是Agent的构建就是让 LLM 像工程师一样“死磕问题”,不需要看一堆 Karpathy 的视频去理解代理,也不需要研究神经网络原理。只要了解 LLM 是怎么通过对话调用工具的,写点代码,跑一下,你就会恍然大悟。以下是对文章的总结学习。原文用不到 400 行的 Go 代码就构建了一个能读写、编辑文件的代码 Agent,有力说明
Sourcegraph工程师Thorsten Ball分享了How to Build an Agent - Amp,核心观点是Agent的构建就是让 LLM 像工程师一样“死磕问题”,不需要看一堆 Karpathy 的视频去理解代理,也不需要研究神经网络原理。只要了解 LLM 是怎么通过对话调用工具的,写点代码,跑一下,你就会恍然大悟。
以下是对文章的总结学习。
一、博客的核心观点
-
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 能直接理解工具描述并尝试使用,不需要特别教它例子。
三、工程实践技巧
-
如何节省 Token :
-
工具调用让 Agent 通过简洁的指令(如
edit_file({"path": "fizzbuzz.js", ...})
) 操作复杂环境,避免了把大量文件内容塞进提示词。
-
-
让 Agent 更可靠:
-
权限管住: 工具操作范围要小(比如只让动当前目录)。
-
输入卡严: 用 JSON Schema 严格校验工具输入格式。
-
防死循环: 限制工具链调用深度(比如最多连续调用 3 次工具,避免无限循环)。
-
操作前检查: 关键操作前可以加一步确认(比如
read_file
前先检查文件是否存在)。 -
给工具更清晰的错误反馈机制,让 LLM 知道问题出在哪。
-
-
能力“涌现”:
-
当提供了几个基础工具(如读、列、写文件),像 Claude 3.7 这样的 LLM 能自发组合使用它们(例如:先
list_files
找文件 -> 再read_file
看内容 -> 最后edit_file
做修改)。这种链条式调用不需要额外训练。
-
总结:Agent 构建的思路转变
传统 Agent的构建依赖复杂的规则引擎和硬编码逻辑,而当下则依靠LLM。核心是强大的 LLM(大脑),工具是它的四肢,执行循环是连接大脑和四肢的神经系统。 当工具系统和执行循环设计得当,Agent 能力的上限主要取决于所用的 LLM 本身,而不是架构有多复杂。
更多推荐
所有评论(0)