01. Agent 入门与 Harness:Model 之外才是竞争力
最小循环能 Demo,约束验证纠正才撑得住生产
用 Cursor 改仓库、让 Deep Research 扫论文、让浏览器 Agent 填表、让语音 Agent 打电话改账单——形态差很远,共同点只有一个:系统不再是「你问一句、它答一句」,而是自己决定下一步、并能调用工具。
这一篇对应书的第 1 章:先把公式拆开,再看 ReAct 循环,最后落到 Harness——模型之外那一层工程为什么反而成了竞争力。
公式三件套:大脑、眼睛、手脚
Agent = LLM + 上下文 + 工具
| 直觉 | 实现 | 可选 RL 映射 | 含义 |
|---|---|---|---|
| 大脑 | LLM | Policy | 理解意图、规划、决定是否行动 |
| 眼睛 | 上下文 | Observation | 当前决策点能看见的全部信息 |
| 手脚 | 工具 | Action | 能对世界做的全部操作集合 |
三个词都要广义理解:
- LLM 不只是权重文件。它是决策内核:预训练给世界知识与语言,后训练(SFT / RL 等,第 7 章)固化「何时调工具、如何拆任务」一类策略。
- 上下文 不只是用户刚打的那句话。系统提示、工具 schema、记忆、检索片段、轨迹、状态栏……凡是进了本次请求窗口的,都是「眼睛」。
- 工具 不只是几个 JSON Function。预定义 API、Skills、动态写代码、子 Agent、事件入口、主动联系用户,都属于广义动作空间。
产品对照(只为建立直觉):
| 类型 | 主要「看见」什么 | 主要「动手」什么 |
|---|---|---|
| Coding Agent | 需求、代码库、终端输出 | 搜索、读写文件、跑命令/测试 |
| Research Agent | 网页、论文、本地资料 | 搜索、阅读、摘要、再搜索 |
| Computer Use | 屏幕、DOM/无障碍树 | 点击、输入、滚动、截图 |
| 办事类 Agent | 账户、账单、政策知识 | 电话、邮件、表单、与人确认 |
共同特征通常是:动作空间相对开放(自然语言 + 代码,而不是三四个按钮)、能内部思考、能根据反馈持续改策略。
工具调用四步:ReAct 的 API 地基
工具调用(Tool Calling / Function Calling)把「文本生成器」变成「可执行系统」的标准接口。一轮最小流程是:
- 在上下文里声明工具(名、描述、参数 schema)
- 模型决定是否调用、调哪个、参数是什么
- 运行时执行工具,把结果写成 tool 消息追加进上下文
- 模型基于结果继续推理或给出最终回答
用伪 API 形状写一遍(OpenAI 风格示意,逻辑通用于多数厂商):
# 可直接当阅读用骨架;接真实 API 时替换 client 与执行器即可
messages = [
{"role": "system", "content": "你是助手。需要实时天气时调用 get_weather。"},
{"role": "user", "content": "北京今天天气怎么样?"},
]
tools = [{
"type": "function",
"function": {
"name": "get_weather",
"description": "查询城市当前天气",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
},
},
}]
# 第 2 步:模型返回 tool_calls(此处用手写结果模拟)
assistant = {
"role": "assistant",
"content": None,
"tool_calls": [{
"id": "call_1",
"type": "function",
"function": {"name": "get_weather", "arguments": '{"city":"北京"}'},
}],
}
messages.append(assistant)
# 第 3 步:执行工具,结果回写
messages.append({
"role": "tool",
"tool_call_id": "call_1",
"content": '{"temp": 28, "sky": "晴"}',
})
# 第 4 步:模型再读完整 messages,生成自然语言回答
# final = client.chat.completions.create(model=..., messages=messages)
# 典型输出:"北京今天 28°C,晴。"
设计工具时,优先通用执行器而不是无限堆专用按钮:与其做一个「计算器」工具,不如给沙箱里的 Python;与其做一个「写工作日志」工具,不如给受控的文件系统。通用性把组合空间留给模型,专用性把确定性留给业务规则——第 4 章会细讲粒度权衡。
上下文五块:每次推理到底吃了什么
从 API 视角,一次调用的上下文大致由五部分构成:
- 系统提示词:岗位说明书——身份、权限、流程、不可违反的规则;也可挂用户记忆与环境元信息。
- 工具定义:有哪些手脚可用;没有定义,模型通常无法发起规范调用。
- 用户消息:本轮输入;也可夹 RAG 检索片段。
- 模型回复:可能含 reasoning(内部思考)、content(对用户文本)、tool_calls(行动请求)。
- 工具结果:执行层回写的观察,驱动下一轮决策。
前两项多是相对稳定的前缀,后三项是增长中的轨迹。第 2 章会从 KV Cache 角度解释:为什么前缀稳定、为什么乱改历史会打爆缓存。
消融思维很有用:拿掉工具定义,模型只剩「嘴炮」;拿掉工具结果,循环断在半空;拿掉系统提示,行为边界全靠模型脾气。构建系统时,缺哪一块,失败模式往往能对上号。
ReAct:把三件套拧成一个环
ReAct(Reasoning + Acting)是把「思考 → 行动 → 观察」迭代起来的核心循环。工程上最简实现就是:
def run_agent(user_text: str, tools: list, max_steps: int = 20) -> str:
"""最小 Agent 循环:模型决定是否调工具,直到给出最终文本或触顶。"""
messages = [
{"role": "system", "content": "逐步完成任务。需要时调用工具,完成后直接回答用户。"},
{"role": "user", "content": user_text},
]
for step in range(max_steps):
resp = llm_chat(messages, tools=tools) # 返回 assistant 消息
messages.append(resp)
if not resp.get("tool_calls"):
return resp.get("content") or ""
for tc in resp["tool_calls"]:
result = execute_tool(tc) # 你的运行时
messages.append({
"role": "tool",
"tool_call_id": tc["id"],
"content": result,
})
return "达到步数上限,未完成。"
注意三点反直觉:
- 循环主体在客户端(或编排层),直到「模型即 Agent」把部分循环收进服务端(内置 search / code interpreter 等)。
- 观察必须回写上下文,否则下一轮模型在「失明」状态下继续幻觉。
- 停止条件不能只信模型嘴上的「完成了」——假成功与过早放弃是生产高频病,要用验证层兜住(见下文 Harness)。
旧系列里有更展开的 ReAct 专篇,本篇只建立与公式、Harness 的接口。
三种学习范式:别一提学习就想到训模型
Agent「从经验变好」不只靠改权重:
| 范式 | 何时发生 | 改什么 | 特点 |
|---|---|---|---|
| 后训练 | 训练时 | 模型参数 | 通用、贵、慢(第 7 章) |
| 上下文学习 | 推理时 | 注意力里的临时模式 | 快、会话结束即失 |
| 外部化学习 | 运行时 | 知识库、Skills、工具代码 | 可审计、可更新、可验证 |
工程含义:能写进知识库或脚本的流程,不要硬塞进「再训一版模型」;能用评测驱动的后训练解决的通用能力,不要全靠超长提示词硬撑。三者时间尺度互补,第 8 章会回到自我进化时再拧紧。
Harness:模型之外的竞争力
公式描述内部组成;Harness 描述工程外壳——把 Model 绑进可靠任务执行的所有支撑代码。生产展开式:
Agent = Model + Harness
Harness ≈ 上下文 + 工具 + 约束 + 验证 + 纠正
例子帮助分界:
| 现象 | 更靠近哪一层 |
|---|---|
| 系统提示里写退款政策摘要 | 上下文 |
| 代码断言「退款额 ≤ 订单额」 | 约束 |
| 调用支付 API | 工具 |
| API 超时自动重试 / 换通道 | 纠正 |
| 提交前用第二模型或规则审交付件 | 验证 |
模型越强,自主决策面越大,出错半径也越大,对约束、验证、纠正的要求往往更高,而不是更低。Sutton 的 Bitter Lesson 提醒我们:长期看可扩展的方法会赢,模型会持续「吃掉」外围技巧。书里的务实立场可以记八个字:方向认同,节奏务实——今天模型还做不稳的,Harness 先补;模型每内化一层,Harness 卸一层,去兜下一道能力前沿。
编排光谱:工作流与自主不是二选一
一端是工作流:边由人定,模型只填节点。可控、可审计,适合合规硬、步骤固定的场景。
另一端是自主 Agent:边由模型在工具空间里长出来。适合开放问题、探索式任务。
中间大量是混合:关键节点人工或规则闸门,中间段落交给 ReAct。选型时问三句:
- 失败代价是「重答一遍」还是「真金白银 / 不可逆写操作」?
- 路径是否在事先可知、可穷举?
- 有没有客观验证器(测试、对账、schema)能当停止条件?
没有验证器的「全自主」,多半是把不确定性外包给运气。
护栏与安全:最小集合
第 1 章收束时常落在护栏上,这里只列工程最小集,细账在工具章与安全专文:
- 权限最小化:工具默认只读,写操作分工具、分路径、分审批。
- 参数校验:类型、范围、业务不变量在进真实副作用前检查。
- 人类在环:高风险动作前确认;超时与异常路径可中止。
- 轨迹可回放:messages + tool 结果落盘,否则无法评测与追责。
本篇收束
- 先用
LLM + 上下文 + 工具理解系统,再用Model + Harness理解生产。 - ReAct 是三件套的时间展开;观察回写与停止条件比「多写一句 chain-of-thought」更关键。
- 学习有后训练 / 上下文 / 外部化三条路,工程要会分流。
- 模型变强不会消灭 Harness,只会改变 Harness 的厚度与位置。
下一篇进入第 2 章主场:上下文工程——消息结构、KV Cache 友好设计、Skills、状态栏与压缩策略。那是全书最「日常」也最容易把系统拖死的一层。
版权声明: 如无特别声明,本文版权归 sshipanoo 所有,转载请注明本文链接。
(采用 CC BY-NC-SA 4.0 许可协议进行授权)
本文标题:01. Agent 入门与 Harness:Model 之外才是竞争力
本文链接:https://www.sshipanoo.com/blog/ai/ai-agent-indepth/01-Agent入门与Harness/
本文最后一次更新为 天前,文章中的某些内容可能已过时!