作者:互联网搜索团队-Wang Wenqian
本文通过对OpenClaw,Claude Code等主流Agent产物的筹划举行分析,给出Agent架构筹划的关键决议,分析各方案的利弊。 1分钟看图把握核心观点
图 1 VS 图 2,您更倾向于哪张图来辅助明白全文呢?
一、弁言
构建一个 Agent 必要做一系列架构决议:上下文怎么管理?工具怎么加载?工具怎么查找?Agent 的主循环围绕什么来筹划?
这些决议没有标准答案,但每个选择都有明白的代价。本文从 OpenClaw、Claude Code 等主流 Agent 产物的实现出发,拆解四个关键的筹划决议,分析各种方案的利弊。
二、上下文管理
2.1 追加式上下文
OpenClaw 和 Claude Code 接纳了同一种模式:追加式上下文(Append-only Context)。Agent 维护一个一连增长的对话汗青,每次调用 LLM 时将完备汗青作为 prompt 发送,每轮交互的效果追加到同一个数组中。- 第1轮 LLM 调用:
- ┌──────────────────────────────────────────────┐
- │ System Prompt │ User: "帮我重构登录模块" │ → LLM → 回复 + 工具调用
- └──────────────────────────────────────────────┘
- ~2K tokens
- 第2轮 LLM 调用(工具结果返回后):
- ┌──────────────────────────────────────────────────────────────────┐
- │ System Prompt │ User │ Assistant │ Tool Call │ Tool Result │ ... │ → LLM
- └──────────────────────────────────────────────────────────────────┘
- ~8K tokens
- ... 经过 20 轮工具调用 ...
- 第N轮 LLM 调用:
- ┌─────────────────────────────────────────────────────────────────────────────┐
- │ System │ U │ A │ T │ R │ A │ T │ R │ A │ T │ R │ ... │ User: "你好" │
- └─────────────────────────────────────────────────────────────────────────────┘
- │◄──────────────── 80K tokens 历史 ──────────────────────►│◄─ 2 tokens ──►│
- 全部重新发送 实际新内容
复制代码 这种模式运行在一个范例的 Agent Loop 中:- 用户输入
- │
- ▼
- ┌─────────────────────────────────────────────────────────┐
- │ Agent Loop │
- │ │
- │ ┌───────────────────────────────────────────────┐ │
- │ │ messages = [system, ...history, user_input] │ │
- │ └───────────────────┬───────────────────────────┘ │
- │ │ │
- │ ▼ │
- │ ┌─────────────────┐ │
- │ │ 调用 LLM API │◄────────────┐ │
- │ │ (全量上下文) │ │ │
- │ └────────┬────────┘ │ │
- │ │ │ │
- │ ▼ │ │
- │ 有工具调用? │ │
- │ ╱ ╲ │ │
- │ 是 否 │ │
- │ │ │ │ │
- │ ▼ ▼ │ │
- │ ┌────────────┐ ┌──────────┐ │ │
- │ │ 执行工具 │ │ 输出回复 │ │ │
- │ │ 追加结果 │ │ (结束) │ │ │
- │ │ 到 messages │ └──────────┘ │ │
- │ └─────┬──────┘ │ │
- │ │ 追加到 messages │ │
- │ └──────────────────────────────────┘ │
- │ │
- │ messages 只增不减,直到会话结束或达到上下文窗口上限 │
- └─────────────────────────────────────────────────────────┘
复制代码 上风:
- 缓存利用率高——每次哀求的前缀高度重叠,prompt cache 掷中率极高
- 实现简单——一个数组,只追加不修改,不必要复杂的上下文选择或裁剪逻辑
- 上下文连贯——模子始终能看到完备的交互汗青,对单一使命的恒久推理非常理想
题目:
当用户在同一个会话中切换话题时,全部汗青被无差别地塞入同一个上下文窗口。用户上午讨论了一个复杂的代码重构(斲丧 80K token),下战书返来说了句"你好"——这句"你好"必要携带 80K token 的完备汗青一起发送给模子。即便掷中缓存,以 Opus 定价盘算也要 $0.30。
上下文只增不减,无关信息干扰模子推理,资本与当前哀求的复杂度完全脱钩。
2.2 压缩计谋
追加式模式终究会撞上上下文窗口的天花板。Claude Code 和 OpenClaw 各自筹划了压缩机制。
Claude Code 在上下文利用率到达约 83.5% 时自动触发压缩——优先裁剪工具输出,LLM 天生结构化择要前置到新会话开头,迩来几轮对话原样生存。- 压缩前:
- ┌─────────────────────────────────────────────────────────────────┐
- │ System │ U │ A │ T │ R │ ... │ U │ A │ T │ R │ U │ A │ U │ A │
- └─────────────────────────────────────────────────────────────────┘
- │◄──────────────────── ~167K tokens ─────────────────────────────►│
- 压缩后:
- ┌─────────────────────────────────────────────────────────────────┐
- │ System │ [压缩摘要: 已完成X, 正在做Y, │ 最近几轮 │ 新输入 │
- │ │ 修改了哪些文件, 关键决策...] │ 原样保留 │ │
- └─────────────────────────────────────────────────────────────────┘
- │◄─ 固定 ─►│◄──── ~10-20K ──────────────►│◄─ 近期 ─►│
复制代码 OpenClaw 接纳更复杂的多层计谋:在压缩之前先举行影象落盘(让模子把紧张信息写入磁盘上的 .md 文件),然后分阶段渐进压缩。落盘的影象文件跨会话存活,下次可加载。
压缩机制是须要的安全网,但它是对上下文膨胀的缓解而非办理:压缩本身必要额外的 LLM 调用,择要是有损的,而且压缩后的择要仍旧混淆了全部话题。
这引出了另一个思绪:与其在上下文膨胀之后想办法缩小,可否从源头克制不相干的内容进入同一个上下文?
2.3 使命隔离:另一种思绪
除了压缩,另有一种更直接的应对方式:以使命为单元隔离上下文。这并不是什么新概念——传统的使命队列、工单体系早就是这么做的,只是在 Agent 范畴,对话驱动模式的盛行让这种思绪被忽略了。- 对话驱动(当前主流模式):
- ┌──────────────────────────────────────────────────────────────┐
- │ 重构登录模块(80K) │ "你好"(2) │ 查询用户数据(30K) │ ... │
- │ 所有内容挤在同一个上下文中 │
- └──────────────────────────────────────────────────────────────┘
- 每次调用都携带全部历史,无论是否相关
- 任务隔离:
- ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
- │ 任务1: 重构登录 │ │ 任务2: 查询数据 │ │ 任务3: 部署服务 │
- │ 上下文: 80K │ │ 上下文: 30K │ │ 上下文: 15K │
- │ (只含相关内容) │ │ (只含相关内容) │ │ (只含相关内容) │
- └──────────────────┘ └──────────────────┘ └──────────────────┘
- 每个任务只为自己的上下文付费
复制代码 以使命为单元隔离上下文,每个使命拥有独立的上下文窗口。使命内部仍旧利用追加式上下文——这完全公道,一个使命内的全部交互纪录天然相干。但使命之间的上下文是隔离的,互不干扰。
这种方式要求用户创建一个简单的意识:差别的题目,在差别的使命中办理。 就像步调员知道差别的功能应该在差别的分支上开发一样。好的筹划应该让这种隔离天然发生——新题目自动创建新使命,上下文跟着使命走,用户不必要手动管理 prompt。
使命隔离的上风是彻底消除了话题稠浊题目,每个使命的上下文资本与其自身的复杂度成正比。代价是放弃了跨使命的上下文连贯性——如果两个使命之间有关联,必要额外的机制(如使命间共享择要、会话关联)来通报信息。
对话驱动模式屏蔽了使命概念,换来的是入门门槛低;使命隔离模式引入了使命边界,换来的是更高的服从和更低的资本。两者的弃取取决于目的用户和利用场景。
三、工具加载
3.1 tools 字段与缓存机制的辩论
LLM API 的哀求中,tools 是独立于 messages 的顶层字段。模子针对这种结构化格式专门微调过,包管了工具调用的高准确率息争析确定性。
但 Anthropic 的 Prompt Cache 按严酷次序构建缓存前缀: system → tools → messages。 tools位于前端,缓存从第一个 token 开始逐一比对,任何位置出现差别,该位置及之后的全部内容全部失效。- 请求 A(5 个工具):
- ┌──────────────────────────────────────────────────────────┐
- │ system prompt │ tools(5个) │ msg1 │ msg2 │ ... │ msg100 │
- └──────────────────────────────────────────────────────────┘
- ✅ 全部命中
- 请求 B(加了1个新工具,变成6个):
- ┌───────────────────────────────────────────────────────────┐
- │ system prompt │ tools(6个) │ msg1 │ msg2 │ ... │ msg100 │
- └───────────────────────────────────────────────────────────┘
- ↑ tools 变了,整条链全部失效
- ❌ 100K token 的 messages 缓存失效(即使内容完全没变)
复制代码 MCP 的核心代价在于动态工具发现和加载,但每切换一次工具集,就要为整个对话汗青全额付费。Claude Code 陈诉的 92% 缓存掷中率,很洪流平上靠的就是永久不改变 tools 列表。- 当前架构的矛盾:
- 动态工具(MCP 的核心价值)
- ↕ 不可调和
- 缓存稳定性(成本控制的关键)
复制代码 3.2 工具形貌从 tools 字段移入 prompt
一种替换方案是将工具形貌嵌入 messages 而非 tools 字段:- 当前方式(tools 字段注入):
- ┌──────────────────────────────────────────────────┐
- │ system │ tools [A,B,C] │ messages... │
- └──────────────────────────────────────────────────┘
- ↑ 改这里 → 后面全部失效
- 替代方式(工具描述嵌入 prompt):
- ┌──────────────────────────────────────────────────┐
- │ system │ messages... │ [工具 A 描述] [工具 B 描述] │
- └──────────────────────────────────────────────────┘
- ↑ 追加新工具 → 前面的缓存全部保留 ✅
复制代码 上风是增长工具不粉碎缓存,按需加载,与追加式上下文兼容。代价是离开了 tools 字段的结构化包管,必要自行实现工具结构的剖析和调用逻辑,模子从纯文本形貌中明白自界说 API schema 的可靠性大概降落。
3.3 本地用控制台,长途用 MCP
工具形貌移入 prompt 后,格式可靠性取决于工具范例。
如果工具是终端—— execute: 实行 shell 下令,返回 stdout/stderr ——险些不必要"教"模子任何东西。curl、grep、psql、docker 这些是模子在预训练中已经把握的天下知识,不是必要通过 JSON Schema 界说的生疏 API。- MCP 方式:需要 N 个工具定义
- ┌─────────────────────────────────────────────────────────┐
- │ tools: [get_weather, query_db, send_email, read_file, │
- │ write_file, search_web, translate, ...] │
- └─────────────────────────────────────────────────────────┘
- 每增加一个 → 缓存全部失效
- 控制台方式:始终只需要 1 个工具定义
- ┌───────────────────────────┐
- │ tools: [execute] │ ← 永远不变,永远命中缓存
- └───────────────────────────┘
- 需要查天气? → execute: curl wttr.in/Beijing
- 需要查数据库?→ execute: psql -c "SELECT ..."
- 需要发邮件? → execute: sendmail ...
复制代码 控制台的上风:零学习资本、格式剖析题目消散、工具数目无穷、与缓存完全兼容。
但控制台不能覆盖全部场景——必要 OAuth 认证的第三方 API、必要维持长毗连的服务等,终端下令并非最佳选择,这类长途服务仍旧必要 MCP 提供标准化的接口结构和鉴权机制。
实际的工具计谋是:本地本领用控制台,长途本领用 MCP,二者组合覆盖绝大部门场景。 少数必要恒久毗连或复杂状态管理的场景(如 WebSocket 订阅、毗连池维护)仍旧是开放题目。
3.4 渐进式工具加载
团结控制台和 MCP,理想的工具加载方式是渐进式的:- 任务开始(轻量上下文):
- ┌────────────────────────────────────────────┐
- │ system │ 任务目标 │ 基础工具(execute) │
- └────────────────────────────────────────────┘
- ~3K tokens
- Agent 判断需要远程搜索工具:
- ┌────────────────────────────────────────────────────────────┐
- │ system │ 任务目标 │ 基础工具 │ 对话... │ + mcp_search 描述 │
- └────────────────────────────────────────────────────────────┘
- │◄────────── 缓存命中 ──────────────►│◄─ 新增 ─►│
- Agent 发现并加载数据库工具:
- ┌──────────────────────────────────────────────────────────────────────┐
- │ system │ 任务目标 │ 基础工具 │ 对话... │ mcp_search │ + query_db 描述 │
- └──────────────────────────────────────────────────────────────────────┘
- │◄─────────────── 缓存命中 ──────────────────────►│◄── 新增 ──►│
复制代码 每次只追加新工具的形貌,已有的上下文缓存完全生存——工具跟着对话流走,而不是钉死在缓存前缀的头部。
3.5 两种加载方式的对比
两种方式可以混淆利用:高频、核心的工具(如 execute)放在 tools 字段包管可靠性和缓存稳固;低频、动态发现的长途工具通过 prompt 渐进式加载,克制粉碎缓存前缀。
四、工具查找
当可用工具到达数百以致上千个时,Agent 怎样高效地找到办理当前题目所需的工具?
4.1 四种方式及其弃取
- 全量注入 tools 字段。 最简单,模子路由正确率高。但工具列表变更导致缓存失效,工具数目多时固定 token 开销巨大。
- 追加上下文加载。 不粉碎缓存,但工具形貌一旦追加就永久留在上下文中,几轮搜索下来上下文堆满已用完的工具形貌。
- 子 Agent 查找。 不污染主上下文,但子 Agent 缺乏主对话的上下文明白,大概选择不敷精准的工具。
- 向量搜索 / 关键词检索。 零 LLM token 斲丧,但语义暗昧时不敷正确,工具库大时噪声严厉。
这四种方式面临一个共同的抵牾:我们在接口维度上查找工具(一个 API 一个工具),但实际需求是在功能维度上查找本领。
4.2 Skill:按功能维度构造工具
Skill 的本质是:将多个工具的调用方法内聚在一起,按功能维度构造,而非按接口维度摆列。- 接口维度(传统工具列表):
- ┌────────────────────────────────────────────────────────────┐
- │ pg_connect │ pg_query │ pg_insert │ pg_update │
- │ pg_delete │ pg_schema │ pg_export │ pg_import │
- │ redis_get │ redis_set │ redis_del │ redis_scan │
- │ s3_upload │ s3_download│ s3_list │ s3_delete │
- └────────────────────────────────────────────────────────────┘
- 20 个工具定义,搜索空间:20 个选项
- 功能维度(Skill):
- ┌──────────────────────────────────────────────┐
- │ 数据库管理 │ 缓存操作 │ 文件存储 │
- │ (内含 8 个 │ (内含 4 个 │ (内含 4 个 │
- │ pg_* 工具的 │ redis_* │ s3_* 工具的 │
- │ 组合用法) │ 工具用法) │ 组合用法) │
- └──────────────────────────────────────────────┘
- 3 个技能,搜索空间:3 个选项
复制代码 一个 Skill 不是一个工具,而是一份"怎样组合利用多个工具完成某类使命"的分析书:- # 数据库管理技能
- ## 能力描述
- 管理 PostgreSQL 数据库:查询、写入、schema 管理、数据导入导出。
- ## 可用工具
- - psql:命令行客户端,支持 SQL 查询和管理
- - pg_dump / pg_restore:备份与恢复
- ## 常见用法
- ### 查询数据
- > psql -h $HOST -d $DB -c "SELECT * FROM users WHERE active = true"
- ### 导出为 CSV
- > psql -h $HOST -d $DB -c "\COPY (SELECT ...) TO STDOUT CSV HEADER" > output.csv
- ### 查看表结构
- > psql -h $HOST -d $DB -c "\d+ tablename"
- ## 注意事项
- - 写操作前先确认,避免误修改
- - 大查询加 LIMIT
复制代码 4.3 Skill 是工具调用知识的 Cache
就像 CPU 缓存把频仍访问的内存数据放在更快的存储中一样,Skill 把频仍利用的工具调用知识预先构造好,克制每次都重新搜索和学习。- 没有 Skill(每次从头探索):
- 任务: "导出用户数据为 CSV"
- Agent 第1次做:搜索工具 → 阅读文档 → 尝试执行 → 调试 → 成功
- Agent 第2次做:同样的探索过程再来一遍
- 每次都消耗大量 token 在"重新发现"已知的方法
- 有 Skill(知识已缓存):
- 任务: "导出用户数据为 CSV"
- Agent 任意次做:匹配技能 → 加载 → 直接执行
- 1 次搜索 + 加载技能文本 ≈ 几百 token
复制代码 技能不愿定必要人工编写。Agent 可以在初次完成新范例使命后,将探索过程中学到的工具组合自动整理成 Skill,下次遇到同类使命直接加载。这形成了一个自我优化的循环:Agent 利用工具越多,积聚的 Skill 越丰富,将来的服从越高。
4.4 综合对比
Skill 不是替换其他方式,而是在它们之上提供了一个缓存层。 底层仍旧可以用搜索检索来匹配 Skill,用追加上下文来加载 Skill 内容,但搜索空间和加载量都被功能聚合大幅压缩了。
五、主循环筹划
前三章讨论了 Agent 的上下文、工具加载和工具查找机制,此中第一章已经提到了使命隔离作为上下文管理的一种思绪。本章从更上层的视角睁开这个话题:Agent 的主循环围绕什么来筹划?
5.1 对话驱动
当前险些全部 Agent 产物——OpenClaw、ChatGPT、Claude——都围绕对话框筹划:用户在对话框里输入,Agent 在对话框里复兴,对话框既是输入源、输出目的,也是维系上下文的容器。
这种模式的上风是交互门槛极低——和谈天没有区别,不必要明白任何抽象概念。但它也意味着 Agent 的齐备举动都被包裹在对话交互中,上下文管理、工具调用、效果输出全部绑定在对话框这个载体上。
5.2 使命驱动
另一种思绪是围绕使命来筹划主循环:- 对话驱动:
- ┌─────────────────────────────────────────────┐
- │ 对话框 = Agent 的世界 │
- │ │
- │ 用户输入 → Agent 思考 → Agent 回复 │
- │ 用户输入 → Agent 思考 → 调用工具 → 回复 │
- │ │
- │ 对话框既是输入源,也是输出目标, │
- │ 更是维系上下文的容器 │
- └─────────────────────────────────────────────┘
- 任务驱动:
- ┌─────────────────────────────────────────────┐
- │ Agent 主循环:感知→思考→行动 │
- │ │
- │ 感知: │
- │ ├─ 聊天框(工具)→ 读取用户消息 │
- │ ├─ Cron 定时器 → 触发定期检查 │
- │ ├─ Webhook → 接收外部事件 │
- │ └─ 自身推理 → fork 新子任务 │
- │ │
- │ 思考:(Agent 的核心输出) │
- │ 分析任务 → 制定方案 → 选择工具 │
- │ │
- │ 行动: │
- │ ├─ 控制台(工具)→ 执行本地操作 │
- │ ├─ MCP(工具)→ 调用远程服务 │
- │ ├─ 聊天框(工具)→ 回复用户 │
- │ └─ 任务队列 → 创建后续任务 │
- └─────────────────────────────────────────────┘
复制代码 在使命驱动筹划中,谈天框被降格为一个工具——Agent 通过它读取用户消息,也通过它复兴用户,和 execute(控制台)、MCP 长途调用没有本质区别。谈天框的特别之处在于它同时充当输入源和输出工具,但它是 Agent 浩繁可调用本领中的一个,不是 Agent 运行的容器。
5.3 思索过程作为核心输出
如果谈天框只是工具之一,Agent 的核心输出就不是对话复兴,而是思索过程:- 对话驱动:Agent 的输出 = 对话回复
- ┌────────────────────────────────────────────┐
- │ User: 帮我查一下线上报错 │
- │ │
- │ Assistant: 我来查一下。 │ ← 主要输出:对话文本
- │ [调用工具: grep error.log] │ ← 附带动作
- │ Assistant: 找到了,是数据库连接超时... │ ← 主要输出:对话文本
- └────────────────────────────────────────────┘
- 任务驱动:Agent 的输出 = 思考链
- ┌────────────────────────────────────────────┐
- │ 任务: 排查线上报错 │
- │ │
- │ 思考: 需要先查看错误日志 │
- │ 行动: execute("grep -n ERROR app.log") │
- │ 思考: 发现数据库连接超时,需要检查连接池配置 │
- │ 行动: execute("cat config/db.yaml") │
- │ 思考: 连接池 max_idle 设置过低, │
- │ 需要告知用户结果 │
- │ 行动: chat.send("问题定位到了:...") │ ← 回复用户只是其中一个动作
- │ 任务完成 │
- └────────────────────────────────────────────┘
复制代码 当思索过程成为核心输出时,Agent 的举动变得可观测——用户可以看到 Agent 在想什么、为什么选择某个工具、为什么放弃某个方案。当 Agent 犯错时,可以追溯到具体哪一步思索出了题目,这种可追溯性是 Agent 一连改进的根本。
Claude Code 在这个方向上做了故意义的实行——它展示了思索过程、工具调用和实行效果。固然如今的情势更像是 Agent 在自问自答,但核心理念值得鉴戒:让思索过程成为一等公民。
5.4 实际束缚:模子的对话训练倾向
使命驱动筹划面临一个实际停滞:当前的大语言模子是以对话模式训练的。
- RLHF 优化的是"复兴满足度" ——直接给出答案险些总是比"我先调用工具"得到更高的评分,模子的本能是直接答复
- 工具调用是后天习得的 ——function calling 本领通过后期微调加入,没有明白触发信号时模子会 fallback 到对话模式
- 复兴和工具调用是竞争关系 ——训练数据中"语言"的样本远多于"调用工具"的样本
要让 Agent 真正以"思索→工具调用"为主循环,不但必要 system prompt 层面的引导,更必要模子厂商在训练阶段针对 agent 模式专门优化。从 GPT-4 到 Claude 到 Gemini,每一代模子的工具调用本领都在提拔,但间隔"模子天然就是使命实行器"的状态另有间隔。
5.5 两种模式的弃取
两种模式并非非此即彼。对话驱动可以作为使命驱动的前端——用户通过对话提交需求,体系自动将其转化为使命,在背景以使命驱动模式实行。关键是在架构层面生存使命隔离的本领,而不是将全部东西绑定在一个对话框上。
六、总结
构建 Agent 的四个关键筹划决议:
①上下文管理。
追加式上下文简单高效但资本与哀求复杂度脱钩,压缩机制可以缓解膨胀但无法消除话题稠浊。使命隔离从源头克制了这个题目,代价是必要额外机制处置处罚跨使命的上下文关联。
②工具加载。
tools 字段包管了调用可靠性但与动态加载存在缓存辩论,工具形貌移入 prompt 兼容了缓存但捐躯了格式包管,两者可以混淆利用。本地本领用控制台、长途本领用 MCP 的组合是当前的务实选择。
③工具查找。
接口维度的查找在工具规模增长时服从降落,Skill 通过功能维度的聚合压缩了搜索空间,并形成了可复用的履历沉淀,但必要前期投入来构建和维护技能库。
④主循环筹划。
对话驱动门槛低、模子兼容性好,使命驱动机动、可观测性强,但受制于模子的对话训练倾向。两者可以团结——对话作为前端,使命作为后端。
这些决议之间并非独立。使命隔离影响上下文管理计谋,工具加载方式决定了 Skill 的构造情势,主循环筹划决定了 Agent 能从哪些泉源获取使命。明白这些决议的关联和弃取,是筹划一个高效 Agent 的条件。
免责声明:如果侵犯了您的权益,请联系站长及时删除侵权内容,谢谢合作!qidao123.com:ToB企服之家,中国第一个企服评测及软件市场,开放入驻,技术点评得现金. |