AI AGENT 开发 · 从入门到实战 · #02

解剖一个 Agent:LLM 大脑、工具、记忆与规划四大件

2026-09-17 QBnewb 约 9 分钟读完 约 3200 字
TL;DR
  • 四大件 = 模型(大脑)、工具(手脚)、记忆(状态)、规划(总监);业内拆法已经收敛:核心积木是「增强型 LLM(augmented LLM)」,其余都是挂件与编排。
  • 模型是唯一「会思考」的件,按难度分层路由;工具是 Agent 的能力边界,「少而精」胜过「多而全」。
  • 记忆分短期(循环里的 messages)与长期(循环外的存储):一次性任务型 Agent 根本不需要长期记忆。
  • 规划是可选项,透明度是必选项;每加一件都要付延迟与成本的税——先问它替你赚回了什么。

上篇回顾:上一篇我们用「目标、工具、循环」三问定义了 Agent,并留下一个二十行的最小循环骨架。本篇把那个骨架放上解剖台——看看挂在循环上的四大件各自负责什么、怎么设计,以及什么时候你可以不装。

一、解剖图:先积木,后编排

把两大厂的官方文档摆在一起,会发现他们对 Agent 的拆法已经收敛。Anthropic 的说法是:一切的核心积木是增强型 LLM(augmented LLM)——「一个被检索、工具、记忆所增强的 LLM」,再往上才是各种编排模式 [1];OpenAI 的《A Practical Guide to Building Agents》则把 agent 拆成三个基础——模型、工具(经函数调用定义)、指令,并主张从「带工具的单 Agent」起步,不够用再升级为编排者模式 [2]。

两种拆法互相印证,而且给了我们一张干净的解剖图:

四大件角色对应到代码是否必需
模型大脑:理解、决策、生成循环里那次 LLM 调用必需
工具手脚:读写文件、调 API、操作环境tools 注册 + 执行器要「办事」就必需
记忆状态:记住发生过什么循环里的 messages;跨会话才需要外部存储短期必需,长期可选
规划总监:先拆解再执行循环外(或内)的一次额外 LLM 调用可选

注意后两行:记忆和规划不是一开始就在的,它们是「按需加装」的配件。四大件里只有模型是那个真正「会思考」的器官,其余三件都是围绕它的工程。

把这张表套回上一篇的代码,你会发现一个关键事实:messages 列表同时扮演着「喂给大脑的输入」和「短期记忆」两个角色。这正是理解四大件关系的钥匙——它们不是四个并列的模块,而是同一个循环的四个切面:模型件决定每次调用的质量,工具件决定循环能触达多大的世界,记忆件决定循环能记住多久之前的事,规划件决定循环是直奔目标还是先画路线图。理清了这个从属关系,后面四节的取舍逻辑会变得非常自然。

二、大脑:模型件——按难度分层,别一把梭

很多团队纠结「Agent 该用哪个模型」,但更有价值的问题是「每一步该用哪个模型」。Anthropic 给出的做法是路由式选模:常规问题发给更小、更省钱的模型(如 Claude Haiku 4.5),真正困难的步骤才上旗舰 [1]。OpenAI 的指南同样把「按任务难度分层用模型」作为控制成本的第一手段 [2]。所以模型路由本身就是一个工程决策点——写进循环里,而不是写死在配置文件里选一次完事。

另一个容易被低估的事实:工具调用能力是模型之间的真实差异,而且对设计很敏感。Anthropic 工程团队的实测结论是,工具命名加不加前缀(namespacing)有「不可忽视的影响」,而且「因模型而异」;模型总是更擅长处理与其训练数据匹配的格式——JSON、XML 还是 Markdown,要用评测实测,不能靠感觉 [4]。这条的工程推论很硬:换模型 ≠ 免费复用同一套工具定义,工具层必须有评测兜底(评测怎么做,第 9 篇展开)。

落地时我常用的路由粒度有三档:机械的抽取、格式转换类步骤,交给小模型;需要理解上下文做判断的中间步骤,用中档模型;面向用户的汇总、定稿与关键决策,才动用旗舰模型。另一个实用技巧是「模型升级即重试」:某一步用小模型连续失败两次,自动切到更强的模型再试一次(以工具报错或格式违约判定失败;「结果好不好」的自动判定需要评测,第 9 篇细说)——比全局换大模型便宜得多,也比原地死磕重试有效得多。路由逻辑写进循环只是几行 if,但它省下的真金白银,随调用量线性增长。

三、手脚:工具件——Agent 的能力边界

模型的上限由它自己决定,Agent 的上限几乎由工具决定。Anthropic 为此专门造了一个词:智能体-计算机接口(Agent-Computer Interface, ACI)——像对待人机界面(HCI)一样对待工具设计,甚至建议对工具做防呆(Poka-yoke)[1]。落到写代码,我把官方建议压缩成四条军规:

  • 参数无歧义:别叫 user,叫 user_id;描述工具要像「给新入职同事写交接文档」[4];
  • 少而精:「更多工具不一定带来更好的结果」,重叠的工具会让 Agent 分心;要把多个底层 API 合并成语义完整的高层工具——一个 schedule_event 胜过 list → check → create 三连 [4];
  • 返回值 token 友好:只返回高信号信息。Anthropic 实测精简版响应 72 tokens 对详细版 206 tokens(省约三分之二),Claude Code 默认把工具响应截断到 25,000 tokens;把 UUID 解析成语义化名称还能减少幻觉 [4];
  • 防呆:能在代码里钉死的就不要交给模型自由发挥(比如钉死根目录、只让模型传文件名,再对拼接结果做穿越校验——下面代码里就有现成例子)。

把这四条军规装进代码,对比上一篇的骨架,注意注释里的设计决策:

import json
from pathlib import Path
from openai import OpenAI   # pip install openai;需先设置环境变量 OPENAI_API_KEY

client = OpenAI()

# —— 工具层:设计决策写在注释里 ——
def list_notes() -> str:
    """列出 notes/ 目录下所有 .txt 笔记的文件名,每行一个。"""
    names = sorted(p.name for p in Path("notes").glob("*.txt"))
    return "\n".join(names) if names else "(空目录)"

def read_note(note_name: str) -> str:
    """按文件名读取单篇笔记,返回前 2000 字。"""
    root = Path("notes").resolve()
    path = (root / note_name).resolve()
    if path.parent != root:              # 防呆(Poka-yoke):拦截 ../ 与绝对路径穿越
        return f"非法路径:{note_name}"
    return path.read_text(encoding="utf-8")[:2000]   # 截断:token 友好

def save_report(content: str) -> str:
    """把最终报告保存为 notes/report.md。"""
    path = Path("notes/report.md")
    path.write_text(content, encoding="utf-8")
    return f"已保存 report.md(共 {len(content)} 字符)"   # 短确认,不回显全文

TOOLS = {"list_notes": list_notes, "read_note": read_note, "save_report": save_report}

TOOL_SCHEMAS = [
    {"type": "function", "function": {
        "name": "list_notes", "description": "列出 notes/ 下所有 .txt 笔记的文件名",
        "parameters": {"type": "object", "properties": {}, "required": []}}},
    {"type": "function", "function": {
        "name": "read_note", "description": "按文件名读取单篇笔记,返回前 2000 字",
        "parameters": {"type": "object",
                       "properties": {"note_name": {"type": "string",
                                                    "description": "笔记文件名,如 2026-09-01.txt"}},
                       "required": ["note_name"]}}},
    {"type": "function", "function": {
        "name": "save_report", "description": "把最终报告保存为 notes/report.md",
        "parameters": {"type": "object",
                       "properties": {"content": {"type": "string",
                                                  "description": "报告全文(Markdown)"}},
                       "required": ["content"]}}},
]

def run(goal: str, max_steps: int = 12) -> str:
    messages = [
        {"role": "system", "content": "你是笔记整理员:先 list_notes 看清单,再按需 read_note,最后 save_report 交报告;同一篇笔记最多读一次。"},
        {"role": "user", "content": goal},
    ]
    for _ in range(max_steps):          # 循环:第 1 篇讲过的那颗心脏
        msg = client.chat.completions.create(
            model="gpt-4o-mini", messages=messages, tools=TOOL_SCHEMAS
        ).choices[0].message
        if not msg.tool_calls:
            return msg.content
        messages.append(msg)
        for call in msg.tool_calls:
            result = TOOLS[call.function.name](**json.loads(call.function.arguments))
            messages.append({"role": "tool", "tool_call_id": call.id, "content": str(result)})
    return "步数耗尽,任务未完成。"

# 预期输出:模型的收尾汇报(含「已保存 report.md」确认),notes/report.md 落盘
print(run("通读 notes/ 下所有笔记,写一份主题摘要报告"))

注意 system 提示里那句「同一篇笔记最多读一次」——它是写给模型的防呆,和代码里的路径校验互为补充:代码防的是物理错误,提示防的是行为浪费。

四、状态:记忆件——多数项目只需要一半

「给 Agent 加个记忆」是需求列表里出现频率最高、也最容易被过度设计的一项。主流分法其实很朴素:LangGraph 的官方口径是短期记忆用检查点(Checkpointer),长期记忆用存储(Store)——前者是同一会话线程内、可随 thread_id 恢复的状态;后者是跨线程持久化的「用户偏好、事实与共享知识」[3]。翻译成纯 Python:短期记忆就是你循环里那个 messages 列表,长期记忆是循环之外的持久化存储。

什么时候才需要长期记忆?判据同样朴素:Agent 需要「继续一段对话、中断后恢复、故障后重跑、或跨会话记住信息」中的至少一条,才引入持久化 [3]。一次性任务型 Agent(比如上一篇整理发票的那个)跑完即弃,只有短期记忆。别为了架构图好看给 Agent 挂向量库。

还有一类容易被忽略的中间形态:任务级工作记忆(scratchpad)——把「已处理过哪些文件、当前进行到第几步」这类进度显式写到一个任务文件里,循环每轮先读它再行动。它不跨会话,却能治长任务里最常见的两种病:重复劳动和迷失方向。上一节代码里那句「同一篇笔记最多读一次」,就是它最朴素的替身——当提示约束开始不够用时,就该让它升级成真正的外部状态。至于上下文窗口本身怎么精打细算,第 4 篇上下文工程专门讲;跨会话记忆的写入与遗忘,留给第 7 篇。

长期记忆是带运维成本的:官方明确提醒,生产环境不要用内存保存器(进程一重启全部丢失);检查点会不断累积,推高延迟与存储成本,需要定期修剪 [3]。把记忆当成「带租约的数据」来管,而不是 append-only 日志。

五、总监:规划件——可选项,但透明度必选

规划(Planning)是四大件里最可选的一件。两种风格:

  • 先规划后执行(plan-then-execute):开跑前先把目标拆成步骤清单,然后逐条执行。适合步骤可预测的结构化任务;
  • 边走边看(interleaved):不预先拆解,循环里每一步现场决定下一步。开放性任务用它——Agent 的适用域本来就是「难以预测所需步骤数的问题」[1]。

显式规划有一个常被忽略的副产品价值:它给了人一个天然的审查卡点。计划在执行前先过一遍人眼,错误的目标拆解就不会被循环放大。规划件本身不需要什么黑科技,往往就是同一个模型的又一次调用:

import json
from openai import OpenAI   # 依赖:pip install openai;run_agent 沿用第 1 篇的循环骨架

client = OpenAI()

PLANNER_PROMPT = """你是规划员。把目标拆成不超过 5 步的清单,
每步一句话、以动词开头、能独立完成。只输出 JSON:{"steps": ["...", "..."]}"""

def make_plan(goal: str) -> list:
    resp = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[{"role": "system", "content": PLANNER_PROMPT},
                  {"role": "user", "content": goal}],
        response_format={"type": "json_object"})
    return json.loads(resp.choices[0].message.content)["steps"]

plan = make_plan("对比三款主流笔记软件,写一份选型报告存为 report.md")
print(plan)                    # 卡点:先人审计划,再放行执行
for i, step in enumerate(plan, 1):
    print(f"[{i}/{len(plan)}]", run_agent(step))   # run_agent:第 1 篇的循环骨架,每步当小目标

与「要不要规划」相比,更值得坚持的原则是 Anthropic 说的透明:"explicitly showing the agent's planning steps"——把规划步骤显式展示出来 [1]。不管你选哪种风格,让用户看得见 Agent 打算干什么,是排障与信任的共同基础。

再补一个实战判断:计划是允许被改的。执行到第 3 步发现第 1 步的假设错了,好的做法是把「修订计划」也变成一次显式动作——把新发现喂回给规划员,重新出一份剩余步骤的清单,而不是让执行者硬着头皮按废纸走。这个模式到了多智能体场景(第 8 篇)会升级成编排者的核心职责,但它的种子在单 Agent 阶段就该种下:计划服务于目标,而不是目标服务于计划。

六、三个最贵的误区

最后把踩坑成本最高的三个误区钉在墙上:

  • 误区一:四大件全都要上。Anthropic 的提醒值得贴在工位上:"finding the simplest solution possible, and only increasing complexity when needed"——很多应用把单次 LLM 调用配上检索和示例就足够了;而「Agentic 系统常用延迟与成本换任务表现」[1]。每加一件之前,先回答:它替你赚回了多少延迟和成本?
  • 误区二:把工作流当 Agent。上一篇划过界,这里补一个新的观察角度:误称的代价是真的——你会为「Agent」这个名字付延迟税、成本税和调试税,而你的 if/else 流水线其实一分钱都不用付。
  • 误区三:工具越多越好。「重叠的工具会让 Agent 偏离高效策略」[4];工具列表每多一行,模型的选择空间和犯错概率就多一分。给内部 REST 端点一比一包皮是最常见的反模式。

小结

  • 四大件的官方收敛拆法:核心是增强型 LLM,工具与记忆是积木挂件,规划属于编排层;只有模型必需,记忆取一半,规划按需;
  • 模型件:按步骤难度分层路由;工具调用能力因模型而异,工具层要有评测兜底;
  • 工具件四条军规:参数无歧义、少而精、返回 token 友好、能防呆就防呆;
  • 记忆件判据:跨会话/中断恢复/故障恢复才要长期记忆;规划件判据:步骤可预测才先拆解——但透明度永远必选。

下一篇预告:四大件都挂在同一颗「心脏」上——那个循环。下一篇《ReAct 与循环工程》专讲怎么把循环写好:思考-行动-观察的节拍、停止条件的设计、工具失败后的恢复,以及为什么「质量来自迭代回路,而不是单次生成」。

参考来源

  1. Building Effective Agents, Anthropic, 2024-2025,anthropic.com
  2. A Practical Guide to Building Agents, OpenAI, 2025,openai.com
  3. LangGraph Persistence 官方文档, LangChain, 2025,docs.langchain.com
  4. Writing Tools for Agents, Anthropic Engineering, 2025,anthropic.com
Q
QBnewb
相信「AI 是杠杆」的独立开发者。这个博客由多智能体流水线调研、写作、评审与排版——用 AI 做内容,也是 AI Agent 实战的一部分。