前 8 篇我们都在解决"如何让模型答得好"这个问题。第 9 篇开始换主角:从 “答” 到 “"。一个能用 bash 改文件、能跑 test、能在 test 跑红时改代码再跑的 AI——这就是 Agent。本章把"Agent 是什么"和"它和 chat 的真实区别"讲透。

9.1 Chatbot vs Agent:从被动到主动

Chatbot            ┌────────────────────────────────┐
(被动回答)          │ user msg → model → 回答 → 结束   │
                   └────────────────────────────────┘

Agent              ┌────────────────────────────────┐
(主动执行 + 循环)   │ user msg → model → 工具调用 →         │
                   │   工具输出 → model → 又一个工具调用 →  │
                   │   ... → 最终回答 → 结束                │
                   └────────────────────────────────┘

核心区别:能不能在"思考 → 行动 → 观察 → 再思考"的循环里待足够久。Agent 的"待"不是时长,是这个 agent 里有几次转弯、能不能纠错

9.2 Agent 的三件套

任何 Agent 系统必含三件:

作用 类比
大脑(LLM) 思考与决策 实习生的脑子
工具(Tools) 读写文件 / 执行命令 / 检索数据 实习生的手 + 浏览器
循环(Loop) 让模型一次次推进,直到任务结束或失败 实习生 “再做一稿” 的耐心

这三件缺任何一件就不是 agent:只有大脑叫 LLM、加工具不循环叫 “tool-using LLM”、加循环了才是 Agent。

9.3 ReAct:Agent 的最小心智

ReAct = Reason + Act,是 2022 年提出、现在仍是大多数 Agent 内核的方法。一次 ReAct 拆为:

Step k:
  Thought:我接下来应该 ...
  Action:调某工具(name, args)
  Observation:工具输出 ...
  ↓
Step k+1: ...
...
Final Answer

实战:把它写成最简 Python 吧(去掉所有花哨):

import json, anthropic

client = anthropic.Anthropic()
tools  = [{"name": "bash", "description": "run shell", "input_schema": {}}]

def react_step(history: list, user_msg: str) -> str:
    msg = client.messages.create(
        model="claude-3-5-sonnet-latest",
        max_tokens=4096,
        tools=tools,
        system=("You are an agent. Output a tool_use for action; "
                "wait for user_msg with tool_result, then continue. "
                "When done, no more tool_use."),
        messages=history + [{"role": "user", "content": user_msg}],
    )
    return msg

def run_agent(goal: str, budget: int = 20) -> str:
    history, user_msgs = [], [goal]
    for _ in range(budget):
        msg = react_step(history, user_msgs.pop())
        history.append({"role": "assistant", "content": msg.content})
        if msg.stop_reason == "end_turn":
            return msg.content[-1].text
        tool_use = next(b for b in msg.content if b.type == "tool_use")
        result   = run_bash(**tool_use.input)           # 你的工具实现
        history.append({"role": "user", "content": [{
            "type": "tool_result",
            "tool_use_id": tool_use.id,
            "content": result,
        }]})
        user_msgs.append("")
    return "budget reached"

不要被几百行的 Claude Code / OpenCode 吓到——它们里层就是这个。Loop 篇 10 章 把这个最小骨架加上"预算 / 反思 / 重试”——剩下的都是工程细节。

9.4 自治的光谱:从"提示给个菜单"到"自己安排"

把 Agent 按自治度排序:

级别 名字 形态 例子
0 Tool-using LLM 你给 prompt,模型文中可选调工具一次 Copilot 自动改一段
1 Single-Step Agent 模型决定调工具,工具运行后用户接着问 Cursor chat “改一下这里”
2 Multi-Step Agent 模型自己循环多步直到任务结束 Claude Code “把所有 go test 跑一遍,全红的修了”
3 Self-Planning Agent 模型自己列计划 → 计划再循环执行 OpenCode 的 Plan / Momus
4 Multi-Agent Swarm 多个 Agent 协作、互审 task subagent / Oracle 后续展开

| “你是否在场” —— 你 step 1 必须每步按 yes;level 4 你只要发起任务。Slack 上近来反反复复的"feels-like-magic"魔法,都是跳级 (响到) level 4 然后被打回 level 2 的"自主幻觉"。

9.5 使用 Agent 的两条心法

9.5.1 Trust Gradient

越高自治度的 Agent,越要按"信任曲线"调权:

agent level ↑    trust threshold ↑    permission scope ↓
   ─────────────────────────────────────────────
   level 2 你时刻看 token,最多放开 "edit ask"
   level 4 你只放 sandbox,"auto" 模式要严格 white-list

OpenCode 的 permission 系统就是这条曲线的工具化:

"permission": { "edit": "ask", "bash": "ask" }   // 默认保守
"permission": { "edit": "auto","bash": "ask"  }  // 重构任务期间
"permission": { "edit": "auto","bash": "auto" }  // 仅在 sandbox 镜像内
"permission": { "edit": "ask", "bash": "deny" }  // 安全审查任务

9.5.2 Task 到 Agent 边界的"对齐"

一个 effective 单 Agent task 满足 S.M.A.R.T (一个 prompt 能搞定) 时才能交给 level 2 以上。三段 prompt alignment:

GOAL    : 一句话产出,例如"diff 加新校验"
SCOPE   : 一句话范围,例如"只动 lib/validators.py,不写 test"
DONE    : 一句话答"成功为何",例如"test_validators.py 通过且无新增 type warn"

如果三个空格答不上,不要交给 Agent——这句应做拆分。

9.6 一个真实例子:自动补单元测试

[USER]
对 lib/validators.py 里 5 个没 test 的函数加 unit test。
scope: 只在 tests/test_validators.py 加文件,不动 lib/missions.py
done : pytest tests/test_validators.py -v 输出 0 failures,all 函数 covered

[AGENT 内部轨迹]
Thought 1: 先看 lib/validators.py 列出 5 个无 test 的函数
Action 1: bash run `rg "^def " lib/validators.py | head -20`
Obs    1: def is_email / is_phone / is_cents / is_url / is_handle
Thought 2: 看 tests/test_validators.py 已有,避免重写
Action 2: bash run `cat tests/test_validators.py | head -100`
Obs    2: 已有 is_email 测试,其他没有
Thought 3: 为剩下 4 个加 unit test,分别测 2 正 + 2 负
Action 3: edit add  `def test_is_phone_valid / test_is_phone_invalid / ...`
Obs    3: file written, no syntax error
Thought 4: 跑 test
Action 4: bash run `pytest tests/test_validators.py -v`
Obs    4: 12 passed
Final: 给你 diff

15 分钟内自动跑出来——这就是从"被动答"到"主动做"的能量差异。但前提是你 scope 给得清楚。

9.7 何时不要用 Agent

诚实清单:

  • ★ 任务有"不可逆副作用"(删数据、上 prod、向真实用户发邮件) → 单步给工具调用就够,不要让模型"自己看着办"
  • ★ 任务跨多个boundary时(数据库迁移 + 部署脚本 + 通知用户) → 拆成多个小 Agent 串起来,不要让一个 Agent 全包
  • ★ 范围需要"判断力"(“这个产品该不该加这个 feature”) → 让 Agent 给你"诊断信息",决策给你

9.8 小结

  • 三件套:大脑 / 工具 / 循环
  • ReAct 心智:Thought → Action → Observation → next
  • 自治 5 级:Tool-using LLM → Self-Planning → Multi-Agent Swarm
  • Trust Gradient:自治度越高 → 默认权限越小
  • 不可逆副作用 / 跨 boundary / 判断力 / 都要拆,不要全包

下一篇:《10 Loop 机制:自循环任务执行》——把 ReAct 心智变成长跑的执行引擎。

Summary: Agent = 大脑 + 工具 + 循环,ReAct 是最小心智,自治五级匹配权限梯度。