news 2026/5/28 16:31:25

Agent Harness 架构真相:Prompt Cache 如何决定 Skill、MCP 与 SubAgent 设计

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Agent Harness 架构真相:Prompt Cache 如何决定 Skill、MCP 与 SubAgent 设计

拆解 Agent Harness 的上下文分层、Skill 延迟加载与 SubAgent 隔离设计。
原文链接:AI 小老六

很多人第一次看 Claude Code、Codex CLI 或类似 Coding Agent 的实现,注意力会落在 Skill、MCP、SubAgent 这些新名词上。它们看起来像一组彼此独立的能力:Skill 像插件,MCP 像外部工具协议,SubAgent 像多智能体协作。

真正把代码和请求链路翻开之后,结论会朴素很多:这些机制大多不是模型侧的新能力,而是 ​Agent Harness 在 ​systemtoolsmessages​三个输入面上做的工程编排​。难点不在于“能不能塞进去”,而在于​什么时候塞、塞到哪里、怎样不把 Prompt Cache 打碎​。

Prompt Cache 这件事很容易被低估。Agent 每轮请求都可能带上系统提示词、工具定义、历史消息、文件片段、运行时提醒和工具结果。如果​前缀稳定​,缓存命中能明显降低延迟和成本;如果动态内容插得太靠前,从变化位置之后的内容就会失去缓存价值。Claude Code 很多看似绕的设计,本质上是在守这条边界。

Harness 的输入面:三块上下文决定了所有扩展点

图:Agent Harness 把稳定规则、工具能力与动态消息分层管理

一次 LLM 调用通常不神秘。无论是 Anthropic Messages API,还是 OpenAI Chat Completions 风格的接口,核心输入都绕不开三类内容:

{"model":"claude-opus-4.7","system":"You are a helpful coding assistant.","messages":[{"role":"user","content":"..."}],"tools":[{"name":"read_file","description":"...","input_schema":{}}]}

这三个字段对应 ​Harness 的三条主线​。

输入面适合放什么不适合放什么
system稳定身份、全局规则、安全边界高频变化的项目状态、动态 skill 列表
tools相对稳定的工具名、参数 schema、权限边界大段文档、可变 agent 列表、临时状态
messages用户输入、历史对话、工具结果、运行时注入需要长期稳定缓存的大块静态规则

Agent Harness 的大部分能力都可以落回这张表。Skill 是把一段 prompt 延后放进上下文;SubAgent 是通过一个工具调用开出一套新的上下文;MCP 是把外部能力包装成工具 schema;attachment 是把运行时生成的信息变成额外 message。概念变多了,底层入口没有变。

Agent Loop:模型只决定下一步,Harness 负责把世界接回来

Agent 不是一次请求给出完整答案,而是在“模型决策”和“工具执行”之间来回切换。模型输出tool_use,Harness 调用真实工具,再把tool_result写回 messages,下一轮继续请求模型。

图:Agent Loop 在模型决策与工具执行之间循环

真实系统会在这条循环外再加很多护栏,比如最大轮次、token 上限、工具超时、权限过滤、错误重试、上下文压缩。但这些护栏不改变主结构:​LLM 负责判断下一步,Harness 负责执行下一步​。

Skill 和 SubAgent 的差别,也可以放进这条循环里看。Skill 不会自己执行代码,它只是改变下一轮模型能看到的指令。SubAgent 则更重:一次外层工具调用会启动另一个独立的 Agent Loop,外层只拿最终结果。

Prompt Cache 是架构约束,不是性能小优化

如果把所有内容一股脑塞进system或工具描述,功能也许能跑,但缓存会很快变差。原因是 ​Prompt Cache 依赖前缀稳定​。​越靠前的 token 越应该稳定,越动态的内容越应该靠后​。

可以把一次请求粗略拆成这样:

图:稳定上下文靠前,动态信息靠后

这解释了 Claude Code 里一些不直觉的选择:动态列表不一定塞进system,而是作为额外 message 注入;工具 schema 尽量保持稳定;某些工具定义可以 defer-loading,先暴露搜索入口,命中后再加载完整定义。

这不是洁癖。一个可扩展 Agent 会不断遇到新文件、新 skill、新 MCP server、新 agent 配置和用户临时指令。只要其中一类内容频繁变化,放错位置就会拖累后面的缓存命中。

Skill:不要把它想成插件,先把它看成延迟加载的提示词

Skill 的核心价值不是“多一个工具”,而是把某类任务的做法沉淀成一个可按需加载的 prompt​。它通常有SKILL.md,也可能带参考资料、示例和脚本。

my-skill/ ├── SKILL.md ├── reference.md ├── examples/ └── scripts/

SKILL.md本身不具备执行能力。它会告诉 Agent:遇到这类任务时应该怎么读文件、怎么调用 bash、怎么编辑代码、怎么验收。真正干活的仍然是 Harness 已经提供的工具。

更合理的 Skill 系统一般分两步:

图:Skill 从短描述到完整指令的按需加载

这样做有两个好处。第一,初始上下文只放很短的 ​**name/description**​,不会把所有 skill 内容都塞进去。第二,skill 可以渐进加载,真正命中后再读 body,缓存压力小很多。

Slash Command 是另一个入口,但不是 Skill 的本质。Command 更像用户主动点名:“把这段 prompt 展开后送进 Agent Loop”。Skill 更重要的部分,是 Harness 能让模型先感知有哪些能力,再决定是否加载完整说明。

Command 和 Skill 的关系可以这么看:

机制入口放进上下文的内容典型用途
Slash Command用户显式输入/xxx展开后的 command prompt快速触发固定流程
Skill MetaHarness 自动注入namedescription让模型知道可选能力
Skill Tool模型按需调用完整SKILL.md与资源复杂任务的过程约束

Claude Code 将 Skill 注册进 CommandRegistry,是一个产品和工程上的复用选择。用户可以像调用命令一样主动触发 Skill;模型也可以在看到 skill 列表后,按需把完整指令加载进来。

Attachment:把动态清单放到消息层,而不是污染稳定前缀

Skill 列表、SubAgent 列表、运行时提醒​,这些内容有一个共同点:它们有用,但变化频率高。项目里新增一个 Skill、插件更新一个 Agent、会话中临时挂载一个能力,都会改变这部分内容。

把它们写死在system里会很省事,但会破坏稳定前缀。更稳的做法是把这类内容变成 attachment,作为额外 user message 注入,常见形式是包一层类似<system-reminder>的标签,让模型知道它是系统级提醒,但又不把它放进最前面的静态 system prompt。

<system-reminder>Available skills: - code-review: inspect diffs and report risks - explain-code: explain implementation and call chain</system-reminder>

这层设计解决的是“动态信息如何被模型感知”的问题。它不负责执行,也不保证模型一定调用,只是把运行时状态以较低缓存代价送进上下文。

可以把它理解成 Harness 的上下文公告栏:不稳定的信息贴在公告栏上,稳定规则留在前缀里。

SubAgent:一次工具调用,换来一条隔离的执行链

图:父 Agent 保持主线干净,子 Agent 消化高噪声探索过程

SubAgent 很容易被说成“多个智能体协作”。这个说法没错,但会遮住实现重点。工程上更准确的说法是:父 Agent 调用一个Agent工具,Harness 为子任务创建新的 system、tools 和 messages,然后在这个新上下文里再跑一条 Agent Loop。

constAgentTool={name:"Agent",description:"Run a subagent in an isolated context.",asynccall(input:{subagent_type:string;prompt:string}){constagent=resolveAgent(input.subagent_type)constchildContext=createContext({systemPrompt:agent.prompt,tools:filterTools(agent.allowedTools),})constchildMessages=[{role:"user",content:input.prompt},]returnAgentLoop({context:childContext,messages:childMessages,})},}

这条链路和普通工具不同。普通工具返回的是文件内容、命令结果或 API 数据;​SubAgent 返回的是另一个 Agent Loop 压缩后的结论​。父 Agent 不需要消费子 Agent 的每一步探索,也不需要把子 Agent 查过的所有文件、失败尝试、临时推理都塞回主上下文。

图:父 Agent 通过工具调用获得隔离子任务结果

它解决的不是“让系统显得更智能”,而是​上下文隔离​。复杂任务里,探索过程经常很脏:搜索范围大、失败路径多、噪声高。把这部分放到子 Agent 里,父 Agent 只拿整理后的结果,主线会干净很多。

SubAgent 的感知层也有类似取舍。agent list 可以内联进Agent工具描述,也可以走 attachment。前者简单,后者更利于缓存,因为工具 schema 会更稳定,动态 agent 清单留在消息层。

方案优点代价
agent list 写进 tool description实现直接,模型看到工具时也看到 agent 类型agent 增删会改变工具 schema,影响前缀稳定性
agent list 走 attachment工具定义稳定,动态清单靠后注入Harness 需要多维护一层上下文注入逻辑

如果系统规模很小,第一种方案够用。Agent 类型一多,或者用户、项目、插件都能贡献 Agent,第二种更抗变化。

MCP、defer-loading 与 tool_search:同一类问题的另一种解法

MCP 也可以放进同一套框架理解。它把外部系统能力变成工具,供模型在 Agent Loop 中调用。问题是工具一多,tools字段会膨胀,工具描述本身也会吃掉上下文。

defer-loading 和tool_search的思路与 Skill 渐进加载很接近:先给模型一个轻量入口,让它搜索或选择需要的工具;命中后再加载完整定义。它牺牲了一点直接性,换来更小的初始上下文和更稳定的缓存前缀。

图:大量工具先搜索再加载,减少初始上下文压力

这和 Skill 系统里的name/description -> 完整 SKILL.md是同一个工程套路:​不要在一开始把所有可能性都展开​。Agent Harness 越大,这条原则越重要。

写 Harness 时真正要做的取舍

如果从实现角度落地,重点不是先定义一堆漂亮概念,而是把上下文分层做清楚。

设计问题更稳的处理方式
全局规则放哪里system,尽量稳定,少混运行时状态
工具 schema 怎么管理工具名和参数保持稳定,大工具考虑延迟加载
Skill 怎么暴露初始只暴露 meta,命中后再读完整 body
动态能力清单怎么注入用 attachment 放进 messages,避免污染前缀
子任务怎么隔离用 Agent tool 创建子上下文,父 Agent 只接收结果
探索噪声怎么处理让 SubAgent 消化过程,回传压缩后的判断

Claude Code 这类产品真正值得学的地方,不是某个名词的包装,而是它对上下文经济性的敏感:​稳定内容放前面,动态内容放后面;短描述先出现,长内容按需加载;高噪声探索放进隔离 loop​,主上下文只保留有用结论。

这套设计不复杂,但很容易被做坏。最常见的错误是把所有东西都塞进系统提示词,短期看功能全了,长期看缓存差、上下文脏、工具列表膨胀、模型注意力被稀释。Agent Harness 的工程质量,往往就体现在这些“不显眼”的放置位置上。

推荐阅读

Claude Code 如何压缩上下文:Microcompact、Prompt Cache 与 cache_edits 工程拆解

平台智能化到了分水岭:为什么配置代码化才是 AI Coding 的下一代接口

为什么 AI Coding 难进生产环境?深入了解 Everything-Claude-Code!

Agent Harness Runtime 架构深度解析:工具循环、状态外置与长程任务调度

OpenClaw Dreaming 记忆流水线底层架构:状态分层、证据留痕与检索回流

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/28 16:29:45

猫抓插件终极使用手册:5步快速掌握网页资源抓取

猫抓插件终极使用手册&#xff1a;5步快速掌握网页资源抓取 【免费下载链接】cat-catch 猫抓 浏览器资源嗅探扩展 / cat-catch Browser Resource Sniffing Extension 项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch 你是否曾遇到过这样的困境&#xff1f;…

作者头像 李华
网站建设 2026/5/28 16:27:07

AI Agent的自动采集和报表功能好用吗?深度拆解2026企业级自动化实践路径

进入2026年&#xff0c;全球电商市场已全面步入以数据为核心驱动力的存量博弈阶段。对于品牌方而言&#xff0c;竞品分析不再是简单的价格监控&#xff0c;而是涵盖了商业结构、动态库存、内容营销策略及用户体验的多维度深度对标。然而&#xff0c;主流电商平台的“数据孤岛”…

作者头像 李华
网站建设 2026/5/28 16:22:34

DIY便携音箱全流程:从DSP调音到箱体制作的实战指南

1. 项目概述&#xff1a;打造一台属于自己的“沙滩伴侣”如果你和我一样&#xff0c;是个对声音有点“挑剔”的DIY爱好者&#xff0c;总想鼓捣点能带出去、声音又够劲的东西&#xff0c;那这个便携音箱项目可能就是你的菜。我给它起了个名字叫“沙滩盒”&#xff08;Beach-Box&…

作者头像 李华
网站建设 2026/5/28 16:22:34

长序列推理中的 FlashAttention 调优实录——从 Profiling 数据到 Kernel 级优化

前言 随着大语言模型在各类应用场景中的广泛落地&#xff0c;长序列推理性能已成为制约服务能力的关键瓶颈。以 128K 上下文窗口的模型为例&#xff0c;注意力机制的计算复杂度随序列长度呈二次方增长&#xff0c;传统的注意力实现方式在处理超长序列时会面临显存占用过高、计…

作者头像 李华
网站建设 2026/5/28 16:22:07

【力扣100题】72.括号生成

题目描述 数字 n 代表生成括号的对数&#xff0c;请你设计一个函数&#xff0c;用于生成所有可能并且有效的括号组合。 示例 1&#xff1a; 输入&#xff1a;n 3 输出&#xff1a;["((()))","(()())","(())()","()(())","()()()…

作者头像 李华