5 min read
Day 14:Mini Harness Recap:14 天架构复盘

上一篇:AGENTS.md:把项目规则注入 Agent 上下文
English version: How to Build a Mini AI Coding Agent Harness in TypeScript

文章介绍

14 天前,这个项目只有一个问题:Cursor、Codex、Claude Code 这类 coding agent 到底是怎样工作的?

现在我们得到的不是一个完整 IDE,也不是一个通用 autonomous agent,而是一个可运行、可检查的 TypeScript CLI harness。它把模型调用、上下文、工具、执行循环、patch、安全边界、项目规则和可观测性拆成了清晰的模块。

这正是第一阶段的目标:先理解 harness 层,再决定哪些产品能力值得继续投入。

Mini AI coding agent harness architecture recap

今天要解决什么

Day 14 不再引入一个孤立功能,而是完成四件事:

  1. 新增 --overview,直接从当前工具注册表展示 harness 能力边界。
  2. 运行 context、rules、file tools、Git、patch、approval 与 transcript 的完整 CLI demo。
  3. 复盘 14 天各模块如何组成一次 agent run。
  4. 明确 Phase 2 的 Skills、MCP、IDE 与 subagents 边界。

先运行能力概览:

npm run dev -- --overview

输出会列出当前 workspace、已注册工具、执行生命周期、安全策略和还没有实现的扩展能力。

最终架构

完整链路可以归纳为:

user task + AGENTS.md + project snippets + tool definitions
  -> context builder
  -> model provider
  -> agent loop
  -> tool registry
  -> approval gate + workspace sandbox
  -> tool result
  -> transcript + context report

这条链路里的每一层都有不同职责:

当前实现 负责什么
Context system prompt、rules、snippets、tools 给模型足够且可解释的输入
Model mock 或 OpenAI-compatible provider 根据 messages 决定回答或工具调用
Agent loop bounded observe-decide-act loop 驱动多步执行、超时和最终答案
Tools files、Git、patch 把模型意图转换为受控操作
Safety approval + sandbox 决定是否执行、限制可达路径
Observability JSONL transcript + context report 回放行为、定位 token 与错误

14 天能力地图

Day 01-04:先定义边界与协议

前四天没有急着写复杂功能,而是建立最小运行骨架:

  • Day 01:区分 model、agent 和 harness。
  • Day 02:建立 TypeScript npm workspace 与 CLI。
  • Day 03:定义 messages 和 provider 边界。
  • Day 04:建立 schema 驱动的 tool registry。

最关键的判断是:模型不是 harness。模型只生成下一步意图;harness 才负责注入上下文、验证工具输入、执行副作用和记录结果。

Day 05-07:让 agent 观察、循环与回放

Day 05 的 list_filesread_filesearch_text 让 agent 能观察 workspace。Day 06 的 bounded loop 把单轮聊天变成:

observe -> decide -> act -> observe -> final

Day 07 的 JSONL transcript 让每一次 model request、tool call、tool result、耗时与错误都可以被回放。

没有 transcript 的 agent 很难调试。你无法判断问题来自模型、上下文、工具参数、超时,还是循环本身。

Day 08-09:把上下文变成工程对象

Day 08 将 system prompt、用户任务、历史摘要、工具定义和文件片段集中到 context builder。Day 09 将这些来源转换成可检查的 token report。

这使上下文不再是散落在字符串拼接里的隐形状态:

Context Explorer
  -> source
  -> kind
  -> estimated tokens
  -> budget percentage

Day 10-11:从观察代码到提出并验证修改

Day 10 的 git_statusgit_diff 让模型可以看见工作区变化。Day 11 使用成熟的 diff 库解析和应用 unified diff,不手写 hunk 匹配。

apply_patch 的重要设计是先准备所有文件内容,再执行写入;解析失败或 hunk 不匹配会返回可恢复错误,而不是让进程崩溃或只写入一半。

Day 12-13:加入真实产品必须面对的约束

Day 12 将真实写入与 dry-run 分开。默认模式拒绝 write-class action,只有显式 --allow-writes 才能执行;workspace guard 会拒绝 ../、绝对路径和 symlink escape。

Day 13 从根目录加载 AGENTS.md,把 durable project guidance 作为独立 rules context part 注入,并纳入 token report。

到这里,agent 具备了一个最小但合理的工程闭环:知道项目约定、能读取和检查 diff、能提出 patch、并且不能绕过安全边界。

Day 14 新增:Harness Overview

文件:apps/mini-harness/src/overview.ts

Day 14 增加的不是新的 agent 能力,而是一个与实现保持同步的运行时概览:

npm run dev -- --overview

它从默认 tool registry 读取实际注册的工具:

Registered tools (7):
echo, list_files, read_file, search_text, git_status, git_diff, apply_patch

同时输出当前生命周期:

context -> model -> tool call -> approval -> sandbox -> tool result -> transcript

这个命令很小,但它避免了文档和代码脱节,也给 demo、教学和后续检查提供了一个稳定入口。

完整 CLI Demo

文件:demos/day-14/README.md

1. 查看当前能力边界

npm run dev -- --overview

2. 加载项目规则并检查 context

npm run dev -- --workspace demos/day-13/workspace --context-report "load project rules"

输出应包含:

Project rules      rules  ...  source: AGENTS.md

3. 让 agent 读取项目结构

npm run dev -- --context-report "inspect repository structure"

mock provider 会依次调用 list_filesread_file

4. 检查 Git 工作区

npm run dev -- --context-report "inspect git diff"

mock provider 会调用 git_statusgit_diff,返回原始 unified diff 与解析后的文件统计。

5. 验证 patch,不写入文件

npm run dev -- "apply a small patch to a fixture file"

这个 demo 只运行 dryRun: true,可重复执行。

6. 验证审批门禁

npm run dev -- "show approval sandbox for a write"

模型会请求真实 patch,但默认策略会拒绝:

Tool failed: apply_patch
The harness denied the write because this run did not include explicit approval.

7. 保存一次可回放运行

npm run dev -- --transcript logs/runs/day-14.jsonl "inspect git diff"

transcript 是追加式 JSONL;敏感字段被 redaction,过长字符串会被截断。

当前能力边界

这个项目已经实现:

CLI entrypoint
  + structured context
  + project rules
  + local file tools
  + Git inspection
  + unified patch validation/application
  + bounded agent loop
  + write approval
  + workspace sandbox
  + transcript logging
  + context token reporting

但它仍然是教学 harness,不应该被误认为生产级 coding agent。

还没有实现的部分

能力 当前状态 为什么未在 Phase 1 实现
Shell command runner 未实现 需要命令 allowlist、环境隔离、输出流与更严格审批
Native function calling 未实现 当前用文本 TOOL_CALL 协议保持协议最小化
Skills 未实现 需要发现、版本、权限与按需加载设计
MCP 未实现 需要 transport、server 生命周期与授权模型
IDE integration 未实现 需要编辑器状态、诊断、diff UI 与交互确认
Subagents 未实现 需要任务分解、隔离 context、预算与结果合并
Evaluation suite 未实现 需要任务集、断言、回归与成本质量指标

关键设计原则

1. 先做边界,再做能力

读取文件、查看 Git diff、应用 patch 和运行命令的风险不同。越早把 tool registry、approval、sandbox 和 transcript 建立起来,后续能力越不容易变成无法审计的脚本集合。

2. 所有副作用都经过 harness

模型永远不直接写磁盘。模型只返回 tool call;实际执行必须经过:

schema validation
  -> approval decision
  -> workspace path guard
  -> tool handler
  -> structured tool result

3. Context 是预算,不是垃圾桶

更多上下文不一定更好。项目 snippets、Git diff、rules 和 transcript 都会消耗 token,Context Explorer 的价值就在于使这种成本可见。

4. 错误需要对模型可见

patch conflict、approval denial、timeout 和未知工具都应成为 tool result 或明确错误,而不是隐藏的控制流。下一轮模型才能理解限制、尝试恢复或给用户说明。

5. Demo 必须可重复

默认 patch demo 用 dry-run,默认写入被拒绝,fixture workspace 与主仓库规则隔离。可重复性比“看起来像做了修改”更重要。

Phase 2 建议

下一阶段不建议同时接入所有能力。更合理的顺序是:

  1. Native function calling 与 command policy:先替换文本 tool-call 协议,并把命令执行纳入 approval/sandbox。
  2. Evaluation 与 replay:基于 JSONL transcript 建立固定任务集、结果断言、耗时和 token 指标。
  3. Skills 与 MCP:引入外部能力前,先定义发现、最小权限和生命周期。
  4. IDE integration:把上下文报告、patch preview、审批确认和 diff 放进用户可见界面。
  5. Subagents:最后再解决任务拆分、共享规则、并行工具预算与结果收敛。

这个顺序的核心是:先稳住执行协议和评估,再扩大能力表面。

结论

Mini Coding Agent Harness 的第一阶段到这里完成。

它没有试图复刻任何单一产品,而是把现代 coding agent 共同拥有的 harness 骨架拆成可运行的最小模块:

context + tools + loop + patch + safety + rules + observability

理解这条链路后,无论后续接入哪个模型、IDE、MCP server 或 skill,都能清楚判断新能力应该放在哪一层、受什么边界约束、如何被测试和观测。

Comments

  • Loading comments…

Comments are posted immediately and emailed to the site owner. No account needed.