完整 Harness
把前十九章接到同一个组合根,用跨功能场景证明边界一致。
先看它怎样跑起来
这一章不是几个孤立知识点,而是一条会产生结果的因果链。
完整 Harness
亮起的是当前动作,留下的是已经满足的前置条件。点击任意一步,可以从那里继续。
- 完整 Agent 的核心不是功能数量,而是边界一致。
- 不要复制第二套 AgentRunner。
- 模型提议动作,Harness 拥有真正控制权。
顺着原文把边界看清
01导读:问题背景与本章目标前十九章依次加入了 Agent Loop、工具、权限、Hook、TODO、Subagent、Skill、上下文压缩、记忆、动态 Prompt、模型恢复、Task DAG、后台任务、Cron、Teammate、协作协议、工作窃取、Worktree 和 MCP。⌄
前十九章依次加入了 Agent Loop、工具、权限、Hook、TODO、Subagent、Skill、上下文压缩、记忆、动态 Prompt、模型恢复、Task DAG、后台任务、Cron、Teammate、协作协议、工作窃取、Worktree 和 MCP。
第 20 章不再发明一个“终极框架”,也不复制第二套 Loop。它只做一件事:把已经实现的能力接到同一个组合根,并用跨功能场景证明边界同时成立。
021. 完整 Agent 的核心不是功能数量,而是边界一致模型只负责提出下一步动作。Harness 必须拥有真正的控制权:⌄
模型只负责提出下一步动作。Harness 必须拥有真正的控制权:
ToolRegistry决定当前能看到和调用哪些工具;PermissionPolicy在 handler 前执行硬权限判断;HookRegistry提供生命周期扩展,但不能放宽系统拒绝;MemorySession、CompactionManager和DynamicPromptProvider控制上下文;RecoveryManager处理 429、529、输出截断和输入过长;- SQLite Task、Protocol、Mailbox 和 Worktree 保存可恢复状态;
JobSupervisor、CronRuntime、TeammateRuntime和McpRuntime持有长期资源;AgentRunner.close()按逆序尝试关闭全部资源。
这意味着 Prompt 可以提示模型“不要写出工作区”,但真正阻止越界写入的必须是运行时权限和路径解析。MCP server 可以在 description 中声称自己只读,但权限只能来自本地可信策略。
032. 第 20 章仍然使用同一个 AgentRunner固定 Profile 位于 code/chapters/ch20/src/core/profiles.ts:⌄
固定 Profile 位于 code/chapters/ch20/src/core/profiles.ts:
// PROFILE_DELTAS 末尾追加 full_harness,P20 由 profileAt(20) 返回累计档案。
const PROFILE_DELTAS = [
// P1-P19 的增量能力,此处省略
["full_harness"],
] as const satisfies readonly (readonly Capability[])[];
export const P20 = profileAt(20);full_harness 是整合验收标记,不对应新的业务模块。它表示:P1-P19 的全部 Capability 已经在同一组合根中连接并通过交叉验证。
因此,第 20 章没有新增业务模块,但需要在四个代码位置把完整 Harness 标记、运行态状态、Prompt 尾部段落和固定入口连接起来。
第一处,在 profiles.ts 的 PROFILE_DELTAS 末尾追加 full_harness 增量,并让 profileForChapter(20) 返回累计出的 P20 固定对象。
第二处,在 prompting.ts 的渲染器末尾增加可选的 runtime_status 段落,并允许 Provider 用 statusProvider 每轮重新读取状态。
第三处,在 bootstrap.ts 汇总 MCP 连接与后台 pending work,并只给 P20 安装该状态 Provider。
第四处,提供固定章节入口 code/chapters/ch20/src/chapters/ch20.ts:
import { runProfile } from "../cli.js";
import { P20 } from "../core/profiles.js";
// 固定入口运行 P20 Full Harness,并由 CLI 负责结束后的资源释放与错误码返回。
process.exitCode = await runProfile(P20, process.argv.slice(2));入口不复制工具注册、恢复、调度或关闭逻辑。后续修复公共运行时,所有已引入该能力的章节会一起受益。
043. 组合根如何连接全部能力BuildDependencies 是第 20 章唯一的外部边界。离线测试可注入模型、时钟、命令执行器和各类持久化运行时;真实 CLI 则创建正式适配器。⌄
BuildDependencies 是第 20 章唯一的外部边界。离线测试可注入模型、时钟、命令执行器和各类持久化运行时;真实 CLI 则创建正式适配器。
关键依赖关系如下:
| 资源 | 必须共享的对象 | 原因 |
|---|---|---|
| Cron | JobSupervisor、EventInbox | 调度和后台完成事件必须进入同一 typed inbox |
| Teammate | Supervisor、Cron、Inbox、Mailbox | 队友生命周期、消息和事件由同一 owner 管理 |
| Protocol | Teammate、Mailbox | 请求状态与实际投递参与方必须一致 |
| Work stealing | SQLite Task store、Worktree claim service | 自动认领与手动认领必须使用同一租约边界 |
| Worktree | SQLite Task store、Git runner | Task、claim、binding 是独立状态线,但必须引用同一 Task |
| MCP | Lead 的 live ToolRegistry | 动态工具只进入 Lead,并在下一次模型请求可见 |
buildAgent() 会检查这些对象身份。依赖虽然类型正确,只要共享关系错误,也会在启动阶段明确失败。
054. 单一循环的真实执行顺序-> 渲染当前 system prompt,取得不可变 ToolRegistry Snapshot⌄
每个用户 turn 都遵守同一顺序:
UserPromptSubmit Hook
-> drain typed events
-> 选择相关 Memory,整理历史并压缩完整消息组
-> 渲染当前 system prompt,取得不可变 ToolRegistry Snapshot
-> RecoveryManager 调用 OpenAI Chat Completions
-> 追加规范化 assistant 消息
-> 对每个 tool call:
JSON + Zod schema 校验
-> 解析可信 ToolContext / Worktree cwd
-> PreToolUse Hook
-> PermissionPolicy / 人工审批
-> handler 或后台提交
-> PostToolUse Hook
-> 追加同 ID tool result
-> 无工具调用时运行 Stop Hook,最多强制续跑一次
-> 返回最终文本这里有三个不能破坏的不变量。
064.1 一次回复只使用一个 Registry Snapshot模型请求中的 tools 与该回复中全部 tool calls 使用同一个 sealed snapshot。即使回复里的第一个调用连接了 MCP,第二个调用也不能提前使用新工具;新工具只能出现在下一次模型请求。⌄
模型请求中的 tools 与该回复中全部 tool calls 使用同一个 sealed snapshot。即使回复里的第一个调用连接了 MCP,第二个调用也不能提前使用新工具;新工具只能出现在下一次模型请求。
074.2 一个 tool call 必须恰好配一个 tool result未知工具、坏 JSON、schema 错误、权限拒绝、超时、远端失败都必须形成相同 toolcallid 的错误结果。不能因为其中一个调用失败,就丢弃同一 assistant 消息里的其他调用。⌄
未知工具、坏 JSON、schema 错误、权限拒绝、超时、远端失败都必须形成相同 tool_call_id 的错误结果。不能因为其中一个调用失败,就丢弃同一 assistant 消息里的其他调用。
084.3 Prompt 和 Hook 都不是授权边界工作区外写入由 PermissionPolicy 拒绝。Teammate 的 effectful 工具由计划门控规则拒绝。MCP 权限由本地 McpToolPolicy 决定。Hook 只能在硬边界允许的范围内修改输入或输出。⌄
工作区外写入由 PermissionPolicy 拒绝。Teammate 的 effectful 工具由计划门控规则拒绝。MCP 权限由本地 McpToolPolicy 决定。Hook 只能在硬边界允许的范围内修改输入或输出。
095. 动态上下文:Skill、Memory、工具和工作区第 20 章的 system prompt 不是固定字符串。DynamicPromptProvider 每次请求按固定顺序渲染:⌄
第 20 章的 system prompt 不是固定字符串。DynamicPromptProvider 每次请求按固定顺序渲染:
- identity 与静态 context;
- 当前工具目录;
- 当前 workspace;
- Skill catalog;
- 本轮选中的 Memory;
- 可选的
runtime_status。
Skill 初始只公开名称和描述,正文通过 load_skill 按需读取。Memory 只注入与当前查询相关的记录。大工具结果和旧历史保存到 workspace artefact,再把有界引用放回对话。
动态 MCP 工具也使用同一个 live registry。因此,连接前 system prompt 不含远程工具;连接成功后的下一轮才同时更新 prompt 和 OpenAI tools schema。
P20 新加入的 runtime_status 不是普通对话文本,而是组合根在每轮渲染前读取的可同步状态:
function fullHarnessRuntimeStatus(dependencies: BuildDependencies): JsonObject {
const pendingWork =
dependencies.backgroundSupervisor?.hasPendingWork === true ||
dependencies.cronRuntime?.hasPendingWork === true ||
dependencies.teammateRuntime?.hasPendingWork === true;
const mcpConnections =
dependencies.mcpRuntime === undefined ? [] : dependencies.mcpRuntime.connectedAliases;
return Object.freeze({
mcp_connections: Object.freeze([...mcpConnections]),
pending_work: pendingWork,
});
}这段状态放在全部固定段落之后,例如:
10runtimestatus{"mcpconnections":["fake"],"pendingwork":false}⌄
{"mcp_connections":["fake"],"pending_work":false}
它不替代 `EventInbox`:typed event 仍在请求前消费,状态只回答“当前是否仍有异步工作、MCP 已连接哪些 alias”这两个模型决策问题。这里只读取 synchronous getter,不等待后台任务、不查询远端,也不把运行态 JSON 当作授权依据。这段固定在提示词最后并参与缓存键:只改 status、其余输入不变时 cacheHits 加一,之前的正文保持不变。
116. Task、Teammate 与 Worktree 是三条状态线完整 Harness 不把所有状态塞进一个 Task object。⌄
完整 Harness 不把所有状态塞进一个 Task object。
- Task 保存 DAG、状态、owner、claim token 和 lease;
- Protocol 保存计划或关机请求的 typed 状态机;
- Worktree binding 保存 Task 与隔离 Git 工作区的绑定和审计事件。
典型流程是:
Lead 创建 A -> B DAG
-> B 因依赖保持 blocked
-> A completed 后 B 变为 pending
-> Teammate 提交计划
-> Lead 批准计划
-> Teammate 原子 claim B
-> claim token 绑定 Worktree execution scope
-> 每次工具调用重新解析可信 cwd
-> 文件只写入对应 Worktree计划未批准时,effectful handler 和后台提交次数必须为零。批准计划不会绕过其他权限:工作区边界和人工审批仍然生效。
127. Background、Cron 和 typed event耗时工具可以由 JobSupervisor 接管,当前 tool call 立即得到 job 占位结果。任务完成或失败后,Supervisor 向 EventInbox 发布稳定 ID 的 typed event。⌄
耗时工具可以由 JobSupervisor 接管,当前 tool call 立即得到 job 占位结果。任务完成或失败后,Supervisor 向 EventInbox 发布稳定 ID 的 typed event。
CronRuntime 使用相同 Supervisor 和 Inbox。调度到期时,它提交后台工作;事件在下一轮由 Runner drain。事件采用至少一次投递,但相同 event ID 只注入一次,确认后再次 poll 必须为空。
测试使用 FakeClock 和显式释放的 worker,不依赖真实 sleep。关闭时 Supervisor 会 await 或取消所有受管任务,不能遗留无主后台任务或无人持有的 Promise。
138. 模型恢复与上下文压缩RecoveryManager 把供应商错误转换为明确恢复路径:⌄
RecoveryManager 把供应商错误转换为明确恢复路径:
| 情况 | 行为 |
|---|---|
| 429 | 解析 Retry-After,在总时限内退避 |
| 连续 529 | 达到阈值后切换显式配置的 fallback model |
finish_reason="length" | 先提升输出预算;仍截断时使用 continuation prompt |
ModelPromptTooLongError | 对完整消息组做一次响应式压缩后重试 |
| 第二次输入过长 | 明确失败,不无限压缩 |
未完成的 length 片段不会先写进正式会话历史。压缩不能拆开 assistant tool calls 与对应 tool results。
149. MCP 是动态能力边界真实 MCP 客户端使用官方 TypeScript SDK 的 stdio transport:⌄
真实 MCP 客户端使用官方 TypeScript SDK 的 stdio transport:
StdioClientTransport
-> Client.connect
-> listTools / callTool模型只能提交本地 allowlist 中的 alias,不能提供 command、args 或 cwd。每个 connection 由独立 owner task 持有;远端 schema 先做安全检查,再由 Ajv 在 handler 前验证参数。
远端业务错误保留健康连接。timeout、进程退出或 transport failure 会原子撤销该 alias 的全部工具。MCP management 工具和远程工具只安装到 Lead,Subagent 与 Teammate 不继承。
1510. 关闭和重建也是业务行为JobSupervisor -> CronRuntime -> TeammateRuntime -> McpRuntime⌄
完整 Harness 的资源注册顺序为:
JobSupervisor -> CronRuntime -> TeammateRuntime -> McpRuntimeAgentRunner.close() 逆序关闭:
McpRuntime -> TeammateRuntime -> CronRuntime -> JobSupervisor某个资源关闭失败时,Runner 仍会尝试关闭剩余资源;一个异常原样抛出,多个异常组成 AggregateError。失败状态允许再次调用 close 完成收尾。
重建 Harness 后,SQLite Task、Memory、Cron pending event、Mailbox/Protocol 和 Worktree binding 从各自权威存储恢复。已经确认消费的事件不能重放,未知外部副作用也不能因进程重启被盲目重试。事件去重共两层:进程内 #seenEventIds 防同一轮重投,store 里的 ack 防跨重启重放——至少一次投递加 eventId 去重,对模型表现成恰好一次;恢复矩阵的中间过程一条都不进 canonical history。
1611. 离线整合验收第 20 章测试从 buildAgent(P20, BuildDependencies(...)) 进入,不导入真实凭据,也不访问公网。当前组合测试直接验证:⌄
第 20 章测试从 buildAgent(P20, BuildDependencies(...)) 进入,不导入真实凭据,也不访问公网。当前组合测试直接验证:
- UserPrompt Hook 执行;
- 初始 prompt 同时包含 Skill、相关 Memory 与完整内置工具;
- 初始
runtime_status为{"mcp_connections":[],"pending_work":false}; - 未连接的 MCP 工具不泄漏到 prompt 或 schema;
- 同一回复连接 MCP 并请求工作区外写入时,连接成功,越界写入被硬拒绝;
- 两个 tool call 都得到相同 ID 的配对结果;
- 下一轮远程 MCP 工具同时进入 prompt 和 tools,且
runtime_status.mcp_connections更新为["fake"]; - 最终关闭 MCP、Teammate、Cron 和 Supervisor,无活跃 worker。
新增的 ch20-full-harness.test.ts 覆盖上述跨功能场景,ch20-entry.test.ts 覆盖 P20 固定入口、有效配置、缺失配置和非 Git 根目录的启动边界;其余测试文件继承前十九章聚焦套件。
P20 聚焦套件现在直接覆盖以下场景:固定入口在有效配置下拒绝非 Git 根目录且不创建状态;大 MCP 结果与 TODO/A→B DAG;计划审批后的 Worktree claim 路由;Background/Cron typed event 各一次;429/529/length/prompt-too-long 恢复与单次摘要;Stop 单次续跑;以及 Task/Memory/Cron pending event/Worktree binding 重建和已确认事件不重放。 第 1-19 章聚焦测试仍负责各状态机的细粒度失败分支;P20 只从同一个 buildAgent(P20, BuildDependencies(...)) 组合根证明跨能力接缝,不复制第二套 Loop。
运行 P20 聚焦测试:
Set-Location F:\笔记\Agent实操\code
npm run test:ch20运行全量离线门禁:
Set-Location F:\笔记\Agent实操\code
npm run typecheck
npm test
npm run lint
npm run format:check
npm run build1712. 第 20 章源码讲解地图code/chapters/ch20/src 是 P1-P20 的累计快照,不是只包含 P20 新文件。下面的地图覆盖该目录中的全部源码位置;P1-P19 已经引入的模块沿用其原始章节讲解,第 20 章正文负责新增标记、完整组合、运行态状态、MCP 生命周期和入口收束。⌄
code/chapters/ch20/src 是 P1-P20 的累计快照,不是只包含 P20 新文件。下面的地图覆盖该目录中的全部源码位置;P1-P19 已经引入的模块沿用其原始章节讲解,第 20 章正文负责新增标记、完整组合、运行态状态、MCP 生命周期和入口收束。
| 源码位置 | 责任 | 本章讲解位置 |
|---|---|---|
core/commands.ts、core/filesystem.ts、core/events.ts | Command、文件系统与 typed event 的稳定契约 | 第 3 节组合根、第 7 节事件 |
core/hooks.ts、core/permissions.ts | Hook 生命周期与硬权限策略,两个边界不合并 | 第 4 节,尤其 4.3 |
core/loop.ts、core/messages.ts、core/tools.ts | 唯一 Loop、消息配对和 Registry Snapshot | 第 4 节全部 |
core/model.ts | 供应商无关 Model 请求、回复、错误与恢复契约 | 第 8 节 |
core/profiles.ts | P1-P20 Capability 增量与 full_harness | 第 2 节 |
features/builtin-tools.ts、features/todos.ts、features/skills.ts | 标准工具、TODO 快照、Skill 渐进披露 | 第 3、4、5 节 |
features/subagents.ts、features/tasks.ts | Subagent 最小工具面与 Task DAG 状态机 | 第 6 节及第 6/12 章 |
features/worktrees.ts、features/work-stealing.ts | 可信 Worktree cwd、claim token 与自动认领 | 第 6 节及第 17/18 章 |
features/memory.ts、features/compaction.ts、features/recovery.ts | 选中记忆、上下文压缩、供应商故障恢复 | 第 5、8 节 |
features/prompting.ts | 固定顺序 Prompt 渲染、缓存键、尾部 runtime_status | 第 5 节 |
features/background.ts、features/cron.ts | 受管后台任务与定时调度 | 第 7 节及第 13/14 章 |
features/teammates.ts、features/mailbox.ts、features/protocol.ts | 队友生命周期、持久 Mailbox、审批/关机协议 | 第 6、7 节及第 15/16 章 |
features/mcp-tools.ts | MCP alias、本地策略、动态发布、原子撤销与关闭 | 第 9 节及第 19 章 |
adapters/mcp-client.ts、adapters/mcp-schema.ts | 官方 SDK stdio transport 与远端 JSON Schema 校验 | 第 9 节及第 19 章 |
adapters/background-json.ts、adapters/cron-json.ts、adapters/mailbox-json.ts、adapters/protocol-json.ts | 后台、Cron、Mailbox、Protocol 的 JSON 持久化 | 第 6、7 节 |
adapters/task-json.ts、adapters/task-sqlite.ts | Task JSON/SQLite 持久化,后者持有 claim token 与 lease | 第 6 节及第 12/17 章 |
adapters/git.ts、adapters/filesystem.ts、adapters/powershell.ts | Git、Node 文件系统和 PowerShell 边界实现 | 第 3、6 节 |
adapters/openai-chat.ts | OpenAI wire format 与响应规范化,供应商细节隔离 | 第 8 节 |
mcp-servers/demo.ts | 可运行的双 alias 演示 MCP server | 第 9 节 |
bootstrap.ts、cli.ts、config.ts | 组合根、命令行入口、环境配置装配 | 第 2、3、12/13 节 |
chapters/ch01.ts、chapters/ch02.ts、chapters/ch03.ts、chapters/ch04.ts、chapters/ch05.ts、chapters/ch06.ts、chapters/ch07.ts、chapters/ch08.ts、chapters/ch09.ts、chapters/ch10.ts、chapters/ch11.ts、chapters/ch12.ts、chapters/ch13.ts、chapters/ch14.ts、chapters/ch15.ts、chapters/ch16.ts、chapters/ch17.ts、chapters/ch18.ts、chapters/ch19.ts、chapters/ch20.ts | 每章固定入口,其中 ch20.ts 只转发 P20 给 runProfile | 第 2 节和第 13 节 |
这个地图也是验收清单:不能只确认文件存在,必须确认每个位置都有对应职责、所属章节说明和直接测试。若后续修改某一行,必须先回到该行的原始章节契约,再检查 P20 是否因此产生新的跨能力假设。
1813. 运行第 20 章config.ts 只负责把四项显式 OpenAI 配置读取成冻结的普通配置对象,不会在缺失配置时创建 .agenttutorial 或 MCP 状态。cli.ts 的 runProfile() 再校验当前目录是目标 Git 仓库根,根据 P20 与配置构造真实 BuildDependencies,最后统一交给 buildAgent()。固定入口 ch20.ts 与通用 CLI 没有第二套装配逻辑。⌄
config.ts 只负责把四项显式 OpenAI 配置读取成冻结的普通配置对象,不会在缺失配置时创建 .agent_tutorial 或 MCP 状态。cli.ts 的 runProfile() 再校验当前目录是目标 Git 仓库根,根据 P20 与配置构造真实 BuildDependencies,最后统一交给 buildAgent()。固定入口 ch20.ts 与通用 CLI 没有第二套装配逻辑。
第 18 章起必须从目标 Git 仓库根目录运行。假设教程代码在 F:\笔记\Agent实操\code,目标仓库在 F:\workspace\demo-repo:
Set-Location F:\workspace\demo-repo
npm exec --prefix F:\笔记\Agent实操\code -- tsx F:\笔记\Agent实操\code\chapters\ch20\src\chapters\ch20.ts --prompt "分析仓库并先给出计划"通用入口等价:
Set-Location F:\workspace\demo-repo
npm exec --prefix F:\笔记\Agent实操\code -- tsx F:\笔记\Agent实操\code\chapters\ch20\src\cli.ts run --chapter 20 --prompt "分析仓库并先给出计划"没有四项 OpenAI 配置时,入口会在模型或 MCP 状态创建前列出缺失字段。cwd 不是 Git 仓库根目录时,也会在创建 .agent_tutorial 状态前失败。
19与 Claude Code 的差异参照 learn-claude-code/s20comprehensive/README.md 中深入 CC 源码的分析,P20 的完整 Harness 在教学简化上与 Claude Code 的真实机制存在以下差异:⌄
参照 learn-claude-code/s20_comprehensive/README.md 中深入 CC 源码的分析,P20 的完整 Harness 在教学简化上与 Claude Code 的真实机制存在以下差异:
工具面。 CC 的 s20 教学代码列出 27 个内置工具,包含 compact、list_crons、cancel_cron、check_inbox、request_plan 等。P20 的固定 Lead 工具面是 23 个教学工具。compact 不暴露为模型工具,由 CompactionManager 和 RecoveryManager 在请求前或恢复期自动执行。Cron 只保留 schedule_cron。队友消息通过 typed EventInbox 自动注入,不提供 check_inbox。协议把 request_plan 归入 shutdown/plan_approval 状态机,并由 review_plan 与 submit_plan 表达。额外提供 disconnect_mcp 用于显式断开连接。
循环信号。 CC 教学代码以 has_tool_use(response.content) 作为是否继续工具轮的信号,而不是直接信任 stop_reason。P20 使用 OpenAI tool_calls 字段,并在组合根中强制一个 assistant tool call 恰好配对一个同 ID 的 tool result。没有工具调用时,由 Stop Hook 做至多一次续跑检查。
组装位置。 CC 用 assemble_tool_pool() 与 assemble_system_prompt(context) 分别组装每轮工具和 Prompt。P20 在 buildAgent(P20, BuildDependencies(...)) 统一组合,并对 CronRuntime、TeammateRuntime、ProtocolRuntime、WorkStealingRuntime、WorktreeRuntime 做对象身份检查。类型相同但共享关系错误会在启动阶段失败,而不是到运行时才暴露出错。
权限架构。 CC 把权限、日志和审计都挂在 PreToolUse hook 上:blocked = trigger_hooks("PreToolUse", block) 直接决定是否执行工具。P20 将 HookRegistry 与 PermissionPolicy 分离。Hook 只记录、转换和拦截输入输出,不能放宽 PermissionPolicy、计划门控或 McpToolPolicy 的硬拒绝;这是第 4.3 节不变量在组合根上的具体体现。
执行者边界。 CC 的 MCP 工具对主 Agent 和子 Agent 都可用。P20 明确 MCP 管理工具和远程工具只安装到 Lead 的 live registry,Subagent 与 Teammate 不继承;Teammate 默认只获得受限文件、消息、协议和任务工具面。
教学收束。 CC 用“机制很多,循环一个”总结:所有组件仍挂在同一个 while True 上。P20 用“模型提议,Harness 决策”收束:循环结构相同,但每个状态和权限边界都必须在组合根中可验证、可重建、可关闭。
这些简化让本章能聚焦于“分章能力如何收束成同一个 Harness”。真实场景中还应关注 CC 的成熟 harness 细节:工具池排序与缓存断点、MCP 重连/OAuth/反向通知、后台任务通知优先级,以及更细的恢复与压缩策略。详情见前十九章的差异说明与参考快照。
2014. 最后的架构结论一个可运行的 Agent 不是“模型加几十个工具”。它是一组可以验证的所有权和状态边界:⌄
一个可运行的 Agent 不是“模型加几十个工具”。它是一组可以验证的所有权和状态边界:
- 模型提议,Harness 决策;
- Prompt 指导,Policy 授权;
- Hook 扩展,硬边界优先;
- 消息成组,调用与结果严格配对;
- 状态各有权威存储,重建不猜测;
- 长期任务都有 owner,关闭能回收;
- 动态能力下一轮生效,不污染当前快照;
- Subagent 和 Teammate 默认只获得裁剪后的最小工具面。
第 20 章因此没有第二个 Agent。它只有一个被前十九章逐步加固、现在可以整体证明的 Agent Harness。
至此,20 章教程形成完整闭环:每章有固定入口、累进能力、离线行为测试和真实 OpenAI 兼容运行路径;最终章复用同一实现完成整合验收。
换个场景,你还会判断吗?
每题只测一个边界。先做决定,再看解释。
准备开始