
1. 从能聊到能干活Pi Harness 到底解决了什么问题很多人第一次接触 Agent脑子里想的都是我给它一句话它帮我把活干完。但真上手写过几行代码之后就会发现模型本身再聪明它也只是个只会输出文本的脑子。它没有手没有眼睛记不住上一秒干了什么更不知道什么时候该停下来。Pi Harness 要解决的恰恰就是这层把脑子接上手脚的工程问题。我先把结论摆在这Harness 不是模型不是框架里那个花哨的编排层它是夹在大模型和真实世界之间的一层运行时。你可以把它理解成给 Agent 装的一副外骨骼——模型负责思考决策Harness 负责把决策翻译成真实动作、把动作结果再喂回给模型并且管住它别乱来。标题里说的让 Agent 跑起来这个跑字很关键不是能回答而是能持续地、有状态地、安全地执行任务。为什么现在大家都在聊这个因为过去一年 Agent 的讨论基本集中在两头一头是模型能力上下文长度、推理、工具调用格式另一头是上层框架LangChain、Dify、CrewAI 这类编排工具。中间这层真正决定能不能稳定跑起来的运行时反而被严重低估了。你去看那些 Agent 项目翻车的案例十有八九不是模型不行而是 Harness 没写好——循环停不下来、工具调用参数错乱、上下文越滚越大最后爆掉、出错之后整个流程直接崩死。这篇序篇我想干的事是把 Pi Harness 这套东西拆开揉碎讲清楚它由哪些部件组成、每个部件为什么这么设计、TypeScript 在这个场景里扮演什么角色、Agent Loop 和 Context Engineering 这两个核心概念到底怎么落地。适合谁看写过一点 TypeScript、想自己动手搭 Agent 但被各种框架绕晕的人或者已经在用现成框架、但总觉得黑盒太多、控制不住的人。如果你连 Agent 是什么都还没概念也能看我会尽量用生活化的例子把底层逻辑讲明白。提示这篇是序篇重点在建立心智模型和整体架构认知具体的代码实现、参数调优、工具注册细节会在后续篇章里逐个展开。先把地图看清楚再动手写代码能少走很多弯路。2. 先厘清概念Harness、Agent、框架三者到底啥关系2.1 一句话区分 Harness 和 Agent网上关于harness 和 agent 区别的搜索量一直很高说明这个概念确实容易混。我用一个类比说清楚Agent 是司机Harness 是车。司机负责看路、判断、决定往哪开车负责把方向盘的动作变成轮子的转动负责刹车、供油、仪表盘反馈。司机再厉害没有车也跑不起来车再好没有司机也只是一堆铁。具体到技术层面Agent指的是具备自主决策能力的智能体核心是那个决策循环——观察、思考、行动、再观察。它本质上是模型 提示词 决策逻辑的组合。Harness指的是承载 Agent 运行的执行环境它管的是怎么调用模型、怎么解析模型的输出、怎么执行工具、怎么维护对话历史、怎么处理错误、怎么控制循环的终止。框架LangChain 这类通常是更高层的封装它可能同时包含 Harness 的能力还额外提供了编排、多 Agent 协作、可视化等东西。所以你会发现很多框架内部其实都藏着一个 Harness。Pi Harness 的思路是把这个 Harness 单独拎出来做成一个轻量、可控、可替换的运行时而不是把它埋在厚厚的抽象层里。这样做的好处是你能清楚地知道每一步发生了什么出问题的时候知道去哪查。2.2 为什么不用现成框架非要自己搞 Harness这个问题我被问过很多次。现成框架开箱即用为什么要费劲自己写 Harness我的经验是框架适合快速验证想法但一旦你要做生产级的 Agent框架的抽象反而会变成负担。原因有三第一调试成本。框架把模型调用、工具执行、上下文管理都封装起来了出问题的时候你只能看到结果不对但看不到中间发生了什么。自己写 Harness每一步的输入输出你都能打日志排查起来快得多。第二控制粒度。框架的循环逻辑是写死的你想改一下什么时候该重试上下文超过多少该压缩工具调用失败几次该放弃往往要跟框架的设计对抗。自己写 Harness这些策略都是你的代码想怎么调怎么调。第三依赖负担。一个成熟的 Agent 框架动辄几十个依赖版本冲突、安全更新、打包体积都是问题。Pi Harness 用 TypeScript 从零构建核心依赖极少你能完全掌控整个技术栈。当然这不是说框架一无是处。我的建议是先用框架跑通一个最小 Demo理解 Agent 的基本运作方式然后再用 Pi Harness 这样的轻量运行时替换掉框架把控制权拿回自己手里。这个路径比一上来就啃框架源码要高效得多。2.3 TypeScript 在 Agent 运行时里的独特价值标题里带了 TypeScript这不是随便选的。Agent 运行时的核心难点之一是数据在多个部件之间流转——模型输出要变成工具调用参数工具返回要变成上下文消息上下文要变成下一次模型调用的输入。这个流转过程里类型错了就是运行时崩溃。TypeScript 在这里的价值体现在几个方面。第一是工具参数的类型安全。你定义一个工具它的输入参数是什么结构用 TypeScript 的 interface 描述清楚模型输出的 JSON 在解析时就能做校验参数不对直接拦下来而不是等执行到一半才发现。第二是消息结构的统一。Agent 的上下文是一串消息每条消息有角色、内容、可能的工具调用信息用类型把这些结构固定下来能避免大量字段名写错结构对不上的低级错误。第三是重构友好。Agent 的逻辑经常要调整类型系统能在你改代码的时候立刻告诉你哪里受影响了。我踩过的一个坑早期用纯 JavaScript 写 Harness工具调用的参数结构全靠约定结果模型偶尔返回一个字段名大小写不对的 JSON整个流程就静默失败了查了半天才发现。换成 TypeScript 之后这类问题在编译期或者解析期就被拦住了。这个教训很值钱。3. Agent Loop让 Agent 跑起来的心脏3.1 循环的本质一个不断收敛的 whileAgent Loop 是整个 Harness 的心脏。说白了它就是一个循环把当前上下文发给模型模型返回一个动作要么是最终答案要么是要调用某个工具Harness 执行这个动作把结果追加到上下文然后再发给模型如此往复直到模型给出最终答案或者触发终止条件。用伪代码表达大概是这样async function agentLoop(task: string): Promisestring { const messages: Message[] [{ role: user, content: task }]; while (true) { const response await callModel(messages); messages.push(response); if (response.type final_answer) { return response.content; } if (response.type tool_call) { const result await executeTool(response.toolName, response.args); messages.push({ role: tool, content: result }); } if (shouldStop(messages)) { throw new Error(Agent loop exceeded limits); } } }看起来简单但魔鬼全在细节里。这个循环能不能稳定跑取决于几个关键决策什么时候停、上下文怎么管、工具调用失败了怎么办、模型输出格式不对怎么办。每一个都是坑。3.2 终止条件Agent 最容易失控的地方新手写 Agent 最常见的翻车方式就是循环停不下来。模型一直调用工具工具一直返回结果上下文越滚越大最后要么爆 token要么无限循环烧钱。所以终止条件必须设计得足够严谨。我一般会设置多重保险最大迭代次数。这是最硬的保险比如设成 20 次超过就直接终止。这个数字怎么定看你的任务复杂度简单任务 5 到 10 次够了复杂任务可以到 30 次。但绝不能设成无限。最大 token 预算。整个循环消耗的 token 总量设个上限超过就停。这个比迭代次数更精确因为有些工具返回的内容特别长一次就能吃掉大量 token。无进展检测。如果连续几次迭代模型都在调用同一个工具、传相似的参数、拿到相似的结果说明它卡住了这时候应该主动打断。显式终止信号。模型输出里包含明确的任务完成或者无法完成标记时正常退出。注意终止条件不是设一个就够要组合使用。我见过只设最大迭代次数的项目结果模型每次迭代都返回超长内容迭代次数还没到token 先爆了。多重保险才能兜住各种意外。3.3 工具调用的执行与错误处理工具调用是 Agent 的手。模型决定调用哪个工具、传什么参数Harness 负责真正执行。这里有几个实操要点。参数校验必须做。模型输出的参数是 JSON但 JSON 合法不代表参数正确。字段可能缺失、类型可能不对、值可能超出范围。我习惯在工具执行前做一层校验用 TypeScript 的类型守卫或者 zod 这类库校验不过就把错误信息返回给模型让它重新生成参数。这比直接执行然后崩溃要好得多。执行要有超时。工具可能是网络请求、可能是文件操作、可能是外部命令任何一个都可能卡住。给每个工具调用设超时超时就返回错误让模型决定下一步。没有超时的工具调用是定时炸弹。错误要结构化返回。工具执行失败时不要直接抛异常中断整个循环而是把错误信息作为工具结果返回给模型。模型看到这个工具报错了错误是 XXX它可能会换个方式重试或者换一个工具。这比整个流程崩掉要健壮得多。副作用工具要谨慎。有些工具是只读的查资料、读文件有些是有副作用的写文件、发请求、执行命令。有副作用的工具我建议加一层确认机制或者在 Harness 层面做权限控制避免模型误操作造成不可逆的后果。3.4 循环中的状态管理Agent Loop 是有状态的这个状态就是不断增长的上下文消息列表。状态管理做得好不好直接决定 Agent 能跑多久、跑多稳。我的经验是把状态分成两类必须保留的和可以压缩的。必须保留的是任务目标、关键决策、最终结论可以压缩的是中间过程的细节、冗长的工具返回、重复的尝试。Context Engineering 的核心工作就是在这两者之间做权衡。一个实用的技巧是给消息打标签。每条消息除了角色和内容额外标记它的类型任务、思考、工具调用、工具结果、结论和重要性。当上下文接近预算上限时优先压缩低重要性的消息保留高重要性的。这样即使循环跑了很多轮核心信息也不会丢。4. Context Engineering决定 Agent 上限的隐形战场4.1 上下文不是越多越好很多人有个误区觉得上下文窗口越大越好把所有信息都塞进去模型就能做出更好的决策。实际恰恰相反。上下文越长模型的注意力越分散关键信息越容易被淹没而且成本和延迟都线性上升。Context Engineering 这个词最近很火但它的核心思想其实很朴素在正确的时机把正确的信息以正确的形式放进上下文。不是塞得越多越好而是塞得越准越好。我做过一个对比实验同一个任务一个版本把所有历史消息原封不动地保留另一个版本做了上下文压缩和筛选。结果压缩版本不仅 token 消耗少了 60%任务成功率还更高。原因就是模型在干净的上下文里更容易抓住重点。4.2 上下文的四个组成部分一个设计良好的 Agent 上下文通常包含四块内容我按重要性排序第一块是系统提示词。它定义了 Agent 的角色、能力边界、行为规范、输出格式要求。这块内容相对固定但极其重要。系统提示词写得好不好直接决定 Agent 的行为是否可控。我见过太多项目系统提示词就一句话你是一个助手然后抱怨 Agent 不听话。第二块是任务描述。用户到底要干什么这是整个循环的锚点。任务描述要清晰、具体、可验证。模糊的任务描述会让 Agent 在循环里迷失方向。第三块是工具定义。有哪些工具可用、每个工具干什么、参数是什么。这块内容会占用不少 token所以工具不能注册太多只注册当前任务真正需要的。工具太多不仅浪费 token还会让模型选择困难。第四块是执行历史。之前发生了什么、调用了哪些工具、得到了什么结果。这块是动态增长的也是最需要管理的部分。4.3 上下文压缩的几种实用策略当执行历史越来越长就需要压缩。我常用的策略有这么几种各有适用场景。滑动窗口是最简单的只保留最近 N 轮的消息更早的直接丢弃。优点是实现简单缺点是可能丢掉早期的重要信息。适合任务步骤之间相对独立的场景。摘要压缩是把早期的消息用模型总结成一段简短的摘要替换掉原始消息。这样既保留了核心信息又大幅减少了 token。缺点是摘要本身要消耗一次模型调用而且摘要可能丢失细节。适合长任务。关键信息提取是只保留消息里的关键字段比如工具调用的名称和结果状态丢掉冗长的原始返回。这个需要针对不同工具定制提取逻辑但效果最好。分层记忆是把信息分成短期记忆当前几轮和长期记忆整个任务的关键节点短期记忆完整保留长期记忆只保留摘要。这是最复杂但最强大的方案。实际操作中我通常是组合使用滑动窗口兜底摘要压缩处理中期历史关键信息提取处理工具返回。具体比例根据任务特点调整。4.4 上下文工程里的常见陷阱这块我想重点说说踩过的坑因为 Context Engineering 的坑特别隐蔽往往要跑很久才暴露。陷阱一工具返回内容不裁剪。有些工具返回一大坨 JSON 或者 HTML直接塞进上下文一次就能吃掉几千 token。正确做法是在工具层面就做裁剪只返回模型真正需要的字段。陷阱二错误信息重复堆积。工具调用失败时错误信息会进上下文。如果模型反复重试同一个失败的工具错误信息就会堆积把上下文撑爆。要在 Harness 层面检测重复错误做去重或者提前终止。陷阱三系统提示词和任务描述被挤掉。当执行历史很长时如果压缩策略不当可能把系统提示词或者任务描述也压缩掉了导致 Agent 忘记自己是谁、要干什么。这两块内容应该始终保留不参与压缩。陷阱四上下文顺序混乱。消息的顺序很重要模型对最近的消息注意力更高。如果把关键信息放在很靠前的位置模型可能忽略。重要的指令和约束要么放系统提示词要么在每轮循环里重新强调。提示Context Engineering 没有一劳永逸的方案它需要根据你的具体任务、模型特性、成本预算反复调优。建议在 Harness 里把上下文管理做成可配置的策略方便快速实验不同的方案。5. Pi Harness 的整体架构拆解5.1 核心模块划分把前面讲的东西串起来Pi Harness 的架构大致可以分成这么几个模块我用一张表说清楚每个模块的职责和关键设计点。模块职责关键设计点模型适配层封装不同模型的调用接口统一输入输出格式屏蔽模型差异循环控制器驱动 Agent Loop 运转终止条件、错误处理、状态管理工具注册表管理可用工具及其定义类型安全、参数校验、权限控制上下文管理器维护和压缩对话历史压缩策略、重要性标记、预算控制执行沙箱安全地执行工具调用超时、隔离、副作用控制可观测层记录和追踪运行过程日志、指标、链路追踪这个划分不是绝对的不同项目可以合并或者拆分。但核心思想是关注点分离模型调用、循环控制、工具执行、上下文管理各自独立通过清晰的接口交互。这样任何一个模块出问题都能快速定位和替换。5.2 数据流一次完整的循环长什么样理解架构最好的方式是跟着一次完整的循环走一遍。假设用户给了一个任务帮我查一下这个项目的依赖有没有安全漏洞。第一步Harness 初始化上下文把系统提示词、任务描述、可用工具定义组装进去。第二步循环控制器把上下文发给模型适配层适配层调用模型拿到模型的响应。第三步响应解析出来是一个工具调用要调用读取 package.json这个工具。第四步工具注册表校验参数执行沙箱执行工具拿到依赖列表。第五步结果经过裁剪追加到上下文。第六步循环控制器检查终止条件没到继续下一轮。第七步模型看到依赖列表决定调用查询漏洞数据库工具如此往复直到模型给出最终结论。这个流程里每一步都有明确的输入输出都可以打日志、做校验、加钩子。这就是自己写 Harness 的好处——整个过程是透明的、可控的。5.3 为什么选择 TypeScript 实现前面提了 TypeScript 的价值这里再具体说说在 Pi Harness 里的体现。类型定义贯穿始终。消息类型、工具定义、模型响应、配置项全部用 TypeScript 的 interface 或者 type 描述。这不仅是为了编译期检查更是为了代码即文档——看类型定义就知道数据结构长什么样。异步流程天然契合。Agent Loop 本质上是异步的模型调用、工具执行都是异步操作。TypeScript 的 async/await 让异步代码写起来像同步代码逻辑清晰。而且 Promise 的组合能力让超时控制、并发执行、错误处理都变得优雅。生态成熟。Node.js 生态里有大量现成的库可以用HTTP 请求、JSON 校验、日志、测试应有尽有。不用像某些语言那样什么都自己造轮子。部署灵活。TypeScript 编译成 JavaScript 之后可以跑在 Node.js、Deno、Bun 上也可以打包进各种运行时环境。部署选择多不被单一平台绑定。5.4 与其他方案的对比为了让你更清楚 Pi Harness 的定位我把它和几种常见方案做个对比。方案优势劣势适用场景Pi Harness轻量、可控、透明需要自己实现部分能力生产级、需要精细控制重型框架开箱即用、功能全抽象层厚、调试难快速原型、简单任务纯手写完全自由重复造轮子、易出错学习、特殊需求平台托管免运维、易上手定制受限、数据在外非核心业务、快速验证我的建议是如果你的 Agent 是核心业务、需要长期维护、对稳定性和成本敏感那自己搞一套 Pi Harness 这样的轻量运行时是值得的。如果只是验证想法用现成框架或者托管平台更快。6. 从零跑通第一个 Agent 的实操路径6.1 环境准备与项目初始化理论讲完了来点实在的。这一节我带你走一遍从零搭建的最小路径让你能真正把 Agent 跑起来。首先是环境。你需要 Node.js建议 18 以上因为要用到较新的 API和包管理器npm、pnpm、yarn 都行我个人偏好 pnpm快且省空间。初始化项目mkdir pi-harness-demo cd pi-harness-demo pnpm init pnpm add typescript tsx types/node pnpm add zod npx tsc --inittsx是用来直接运行 TypeScript 文件的省去编译步骤开发时很方便。zod用来做参数校验后面工具定义会用到。tsconfig.json里我建议开启这几个选项strict打开严格模式target设成 ES2022module设成 NodeNextmoduleResolution设成 NodeNext。这样能获得最好的类型检查和模块支持。6.2 定义核心类型先把核心类型定义好这是整个 Harness 的地基。// types.ts export type Role system | user | assistant | tool; export interface Message { role: Role; content: string; toolCallId?: string; toolName?: string; } export interface ToolDefinition { name: string; description: string; parameters: Recordstring, unknown; execute: (args: Recordstring, unknown) Promisestring; } export interface ModelResponse { type: final_answer | tool_call; content?: string; toolName?: string; toolArgs?: Recordstring, unknown; } export interface HarnessConfig { maxIterations: number; maxTokens: number; modelCall: (messages: Message[]) PromiseModelResponse; }这几个类型定义了 Harness 的核心数据结构。Message是上下文的基本单位ToolDefinition描述一个工具ModelResponse是模型返回的标准化格式HarnessConfig是运行时的配置。注意modelCall是个函数这样模型适配层就可以替换测试的时候可以注入 mock。6.3 实现最小可用的 Agent Loop有了类型实现循环就水到渠成了。// harness.ts import { Message, ToolDefinition, HarnessConfig } from ./types; export class Harness { private tools: Mapstring, ToolDefinition new Map(); private messages: Message[] []; private config: HarnessConfig; constructor(config: HarnessConfig) { this.config config; } registerTool(tool: ToolDefinition) { this.tools.set(tool.name, tool); } async run(task: string): Promisestring { this.messages [ { role: system, content: 你是一个能调用工具的助手。 }, { role: user, content: task }, ]; for (let i 0; i this.config.maxIterations; i) { const response await this.config.modelCall(this.messages); if (response.type final_answer) { return response.content ?? ; } if (response.type tool_call) { const tool this.tools.get(response.toolName ?? ); if (!tool) { this.messages.push({ role: tool, content: 错误工具 ${response.toolName} 不存在, }); continue; } try { const result await tool.execute(response.toolArgs ?? {}); this.messages.push({ role: tool, content: result }); } catch (err) { this.messages.push({ role: tool, content: 工具执行失败${(err as Error).message}, }); } } } throw new Error(达到最大迭代次数任务未完成); } }这段代码虽然短但包含了 Harness 的核心逻辑循环、工具查找、错误处理、终止条件。你可以直接拿去跑然后逐步往里加东西——上下文压缩、token 统计、日志、超时都是在这个骨架上长出来的。6.4 注册第一个工具并跑通来注册一个最简单的工具验证整个流程。// index.ts import { Harness } from ./harness; import { z } from zod; const calculatorSchema z.object({ expression: z.string(), }); const harness new Harness({ maxIterations: 10, maxTokens: 100000, modelCall: async (messages) { // 这里替换成真实的模型调用 // 返回格式参考 ModelResponse return { type: final_answer, content: 模拟回答 }; }, }); harness.registerTool({ name: calculator, description: 计算数学表达式输入一个字符串表达式, parameters: { type: object, properties: { expression: { type: string, description: 要计算的表达式 }, }, required: [expression], }, execute: async (args) { const parsed calculatorSchema.parse(args); // 实际项目里用安全的表达式求值库不要用 eval return 计算结果${parsed.expression}; }, }); harness.run(帮我算一下 123 乘以 456).then(console.log);跑起来之后你会看到整个流程走通。虽然模型调用是模拟的但 Harness 的骨架已经完整了。接下来你要做的就是把modelCall换成真实的模型 API 调用把工具换成真实的功能然后不断调优。6.5 实操中的几个关键决策在真正把 Harness 用到项目里之前有几个决策点我想提醒你。模型调用的重试策略。模型 API 可能因为网络、限流、服务波动失败。要有重试机制但重试要区分错误类型——网络错误可以重试参数错误重试也没用。重试要带退避别一失败就立刻重试容易雪上加霜。工具执行的并发控制。有些场景下模型会一次返回多个工具调用这时候可以并发执行提高效率。但要注意有副作用的工具不能随便并发可能产生竞态。我的做法是给工具标记是否可并发可并发的才并发执行。日志的粒度。日志太粗出问题查不到日志太细噪音太大。我的经验是记录这几个关键点每次模型调用的输入输出摘要、每次工具调用的名称和参数、每次循环的 token 消耗、终止原因。这些信息足够定位绝大多数问题。配置的外部化。最大迭代次数、token 预算、超时时间这些参数不要写死在代码里做成配置文件或者环境变量。不同任务、不同环境需要不同的配置硬编码会让你改起来很痛苦。7. 常见问题与排查技巧实录7.1 Agent 跑不起来的典型症状我把实际项目中遇到的高频问题整理成一张速查表方便你对照排查。症状可能原因排查方向循环停不下来终止条件缺失或太宽松检查 maxIterations 和 token 预算模型不调用工具工具描述不清或系统提示词没引导优化工具 description明确要求使用工具工具参数总是错参数 schema 定义不清晰检查 parameters 定义加参数校验上下文爆掉工具返回太长或历史未压缩裁剪工具返回启用上下文压缩结果不稳定温度参数过高或提示词模糊降低温度明确输出格式要求执行很慢串行调用或工具本身慢检查并发策略优化慢工具7.2 几个我踩过的深坑坑一模型返回的 JSON 格式不稳定。早期我直接让模型返回 JSON然后JSON.parse结果模型偶尔会在 JSON 外面加一段解释文字解析直接失败。后来改成让模型用特定的标记包裹 JSON解析前先提取标记之间的内容稳定多了。再后来用上了模型的原生工具调用能力这个问题基本消失。坑二工具描述写得太简略。工具描述是模型选择工具的唯一依据。我一开始写工具描述就一句话结果模型经常选错工具或者传错参数。后来把描述写详细包括什么时候用、参数什么含义、有什么限制准确率大幅提升。工具描述值得花时间打磨。坑三忽略了 token 计数的准确性。不同模型的 token 计算方式不一样我一开始用估算结果经常超出预算。后来接入了准确的 token 计数预算控制才靠谱。如果你的模型提供商有 token 计数接口一定要用。坑四错误处理太粗暴。一开始工具执行失败我就直接抛异常整个循环崩掉。后来改成把错误作为工具结果返回给模型让模型自己决定重试还是换方案健壮性好了很多。Agent 的容错能力很大程度上取决于 Harness 怎么处理错误。7.3 性能与成本的平衡技巧Agent 跑起来之后下一个问题就是跑得好不好、贵不贵。几个实用技巧缓存重复的模型调用。如果同样的上下文反复出现可以缓存模型响应。这在测试和调试阶段特别有用能省不少钱。用小模型做简单决策。不是所有决策都需要最强的模型。工具选择、参数生成这类相对简单的任务可以用小模型把大模型留给真正需要推理的环节。批量处理工具调用。如果模型一次返回多个独立的工具调用并发执行比串行快很多。但要注意前面说的副作用问题。监控 token 消耗。给每次运行记录 token 消耗定期分析哪些环节最费 token针对性优化。很多时候优化上下文比换更便宜的模型效果更好。8. 后续篇章的路线图序篇到这里Pi Harness 的整体框架和核心概念应该讲清楚了。你手里现在有了一个能跑的最小实现也有了排查问题的思路。接下来可以往几个方向深入。模型适配层的完整实现包括如何对接不同提供商的 API、如何处理流式响应、如何做重试和降级。工具系统的进阶包括工具的动态注册、权限控制、执行沙箱、结果缓存。上下文工程的实战包括各种压缩策略的具体实现、重要性评估、预算分配。多 Agent 协作包括 Agent 之间怎么通信、任务怎么分解、冲突怎么解决。可观测性建设包括日志、指标、链路追踪、可视化。我个人在实际操作中的体会是Agent 这个东西看再多文章不如自己动手跑一遍。Pi Harness 的价值就在于它足够轻、足够透明你能看到每一行代码在干什么。先把最小版本跑通然后遇到什么问题解决什么问题比一上来就啃大框架的源码要高效得多。踩过的坑都是经验跑通的流程都是资产。