第 01 章 · Agent 到底是什么
本章目标:把“Agent 很聪明”改写成一张可以检查的数据流图。学完后,你应该能指出模型、宿主程序、工具和真实世界分别负责什么。
1. 从聊天模型到行动系统
普通聊天只有一条短链:用户输入文字,模型预测下一段文字。模型即使说“我已经打开文件”,也不代表电脑上真的发生了任何事情。Agent 多出了一层宿主程序:它把模型的结构化意图解释成真实操作,再把操作结果送回模型。于是系统从“一次回答”变成“观察、决定、行动、再观察”的循环。
可以用一个严格但朴素的公式理解:
Agent = 模型决策 + 工具执行 + 循环控制 + 状态与边界。
模型负责在不确定信息下选择下一步;工具负责确定性动作;循环负责让上一步的结果影响下一步;状态负责保存目标、历史、预算和中间进度;边界负责阻止模型做超出授权的事情。四者缺一,系统就会退化成聊天、脚本或失控自动化。
2. 四个角色不要混在一起
假设用户说:“运行测试并修复失败。”模型可能返回一个工具调用,要求执行 pytest。模型没有执行 pytest,它只是填出工具名称和参数。Executor 检查命令是否被允许,在指定工作目录创建进程,收集退出码和输出。Runtime 把这些结果包装成工具结果消息。模型下一轮看到 AssertionError,才决定读取哪个文件。
这段流程里有四种责任:
| 角色 | 输入 | 输出 | 不能假装负责的事 |
|---|---|---|---|
| 模型 | 任务、历史、工具说明 | 文本或工具意图 | 不能宣称真实动作已经发生 |
| Runtime | 会话状态、模型响应 | 下一轮请求、事件 | 不应该替模型猜业务决定 |
| Executor | 通过校验的工具参数 | 真实结果、错误、退出码 | 不应该无限制相信参数 |
| 人类 | 目标、边界、验收标准 | 审批、反馈、最终判断 | 不必亲手编写每一行代码 |
把责任分开以后,很多神秘问题会变成普通工程问题:为什么读错文件,是上下文检索问题;为什么执行了危险命令,是权限问题;为什么跑了十轮还没结束,是停止条件问题。
3. Agent 与固定工作流的区别
固定脚本提前写死步骤:先读取 A,再调用 B,最后生成 C。Agent 只预先给出目标、工具和规则,具体路径由模型根据观察动态选择。两者不是互相替代。可靠产品通常让确定性骨架管理权限、状态和验证,让模型只处理真正需要判断的岔路。
例如发布流程不应让模型自由发明:构建、测试、签名、上传这些步骤适合固定脚本。模型可以判断失败日志属于依赖、代码还是环境,并选择调用哪条诊断工具。好的 Agent 设计不是“所有事都交给模型”,而是准确区分确定性部分和判断性部分。
4. 对照当前代码
在 minimal_swe_agent.py 中,run_agent 是循环控制器,build_prompt 组装模型能看到的现场,call_llm 是模型边界,execute_tool 是真实世界边界,history 是本次任务状态。先不要逐行读实现,只需要用这五个名字在脑中搭出地图。
一次运行的最小事件序列是:
user_task
→ model_request
→ function_call
→ executor_result
→ model_request
→ final_answer
如果中间任何箭头没有记录,你就很难调试;如果 executor_result 没有回填,模型只能猜刚才发生了什么;如果 final_answer 没有完成证据,Agent 可能只是自信地提前结束。
5. 本章检查
遇到一个新功能时,先回答四个问题:新信息由谁提供?下一步由谁决定?真实动作由谁执行?成功由什么外部证据证明?能回答这四问,才算从“把 AI 当魔法”进入“把 Agent 当系统”。
思考题
如果模型输出“测试已经通过”,但 executor 从未运行测试,错误属于模型能力、工具能力、验证策略,还是界面表达?试着用本章四角色重新描述。