前两篇讲了 Agent 是什么、模型怎么工作。这一篇看最具体的东西:调用模型时,到底发送了什么数据。理解消息结构之后,后面讲 Agent Loop 和工具调用就很直观了。
一、一次调用长什么样
各家 API 细节不同,但结构都差不多:一个系统提示,加一个按顺序排列的消息列表,每条消息有一个角色和内容。一个简化示例:
{
"system": "你是一名网站运维助手,回答要简洁,给出排查步骤。",
"messages": [
{"role": "user", "content": "网站首页打开很慢,但接口响应正常,可能是什么原因?"}
]
}
模型返回一条 assistant 消息。就这么简单,没有任何隐藏的会话状态。
二、四种角色
| 角色 | 谁写的 | 作用 |
|---|---|---|
| system | 开发者 | 设定身份、规则、可用能力和输出要求,对整个会话生效 |
| user | 用户 | 提出问题或任务 |
| assistant | 模型 | 模型的回答,也可能是一个工具调用请求 |
| tool | 你的程序 | 工具执行的结果,回填给模型 |
注意:有的 API 把工具结果作为独立的 tool 角色消息,有的放在 user 消息里的一个 tool_result 内容块中。形式不同,含义一样:告诉模型「你刚才要求执行的工具,结果是这个」。
三、模型是无状态的
这是本篇最重要的一点:模型本身不保存任何会话状态。每次调用,都要把完整的历史重新发一遍。
所谓「多轮对话」,其实是客户端在不断拼接消息列表。第二轮对话时发出去的是:
[
{"role": "user", "content": "网站首页打开很慢,可能是什么原因?"},
{"role": "assistant", "content": "常见原因是静态资源加载慢,先检查图片和脚本的加载时间……"},
{"role": "user", "content": "首页有几张图片超过 5MB,怎么办?"}
]
模型之所以「记得」上一轮说过什么,只是因为你把上一轮的内容又发给了它。这带来几个直接后果:
- 对话越长,每次请求越大,费用和延迟越高。
- 你可以任意修改历史:删掉过时的内容、把长段落替换成摘要。这正是上下文工程的基础。
- 换一台服务器、换一个进程处理下一轮请求完全没问题,状态都在消息列表里。
四、工具调用在消息里是什么样子
当模型决定调用工具时,assistant 消息里不再是普通文字,而是一个结构化的调用请求,包含工具名、参数和一个调用 ID。你的程序执行工具后,把结果连同同一个 ID 追加回消息列表,再次调用模型:
[
{"role": "user", "content": "查一下最近一小时的下单量"},
{"role": "assistant", "tool_call": {"id": "call_1", "name": "query_orders",
"arguments": {"minutes": 60}}},
{"role": "tool", "tool_call_id": "call_1", "content": "{\"orders\": 135, \"vs_yesterday\": -0.68}"}
]
(字段名各家不同,这里只示意结构。)模型看到工具结果后,继续生成:要么再调用别的工具,要么给出最终回答。这个「请求 → 执行 → 回填 → 再调用」的过程,就是下一篇要讲的 Agent Loop。
五、System Prompt 怎么写
System Prompt 是你对 Agent 行为最直接的控制手段。一个好的 System Prompt 通常回答这几个问题:
- 你是谁:角色和专业领域。
- 要做成什么:任务目标,什么算完成。
- 能用什么:有哪些工具,各自什么时候用。
- 边界在哪:什么不能做,什么需要先确认。
- 怎么输出:格式、长度、语言。
一个运维助手的示例:
你是网站运维助手,负责分析业务指标异常。
目标:找出下单量、转化率等指标异常的原因,并给出可执行的处理建议。
工具:query_orders 查询订单数据;query_api_errors 统计接口错误。先看整体数据,再看细节。
边界:只能查询,不能修改任何配置。涉及切换服务或回滚的建议,需注明「需人工确认」。
输出:先给结论,再列证据,最后给建议,使用中文。
两个实用经验:
- 规则附带理由。「不要一次查询超过 1 小时的明细,因为数据量太大会拖慢系统」比单纯的「不要查超过 1 小时」效果更好,模型能据此处理没写到的情况。
- 具体胜过抽象。「回答要专业」不如「先给结论,再列证据」。
本篇小结
- 一次调用 = System Prompt + 按顺序排列的消息列表。
- 四种角色:system、user、assistant、tool。
- 模型无状态,多轮对话靠客户端每次重发完整历史。
- 工具调用是 assistant 发出的结构化请求,结果带着同一个 ID 回填。
- System Prompt 讲清身份、目标、工具、边界、输出格式,规则附上理由。
思考与练习
- 如果历史越来越长,每次都重发全量消息会带来什么问题?你能想到哪些处理办法?
- 为一个你熟悉的业务场景写一份 System Prompt,覆盖上面五个问题。
上一篇:AI Agent原理篇02:大模型基础:Token、上下文窗口与采样
下一篇:AI Agent原理篇04:Agent Loop:感知-思考-行动循环与 ReAct
返回系列总目录