上一篇:Transcript Logging:Agent 执行日志与可观测性
下一篇:Context Explorer:调试 Prompt 与 Token 使用
English version: Context Builder for AI Coding Agents
文章介绍
Day 07 我们把 agent run 的关键事件写成了 JSONL transcript。现在已经能回答“运行时发生了什么”。
Day 08 要解决另一个更靠前的问题:模型到底看到了什么?
coding agent 的效果很大程度取决于上下文组装。上下文不是把所有字符串拼起来,而是有选择地组织这些材料:
- system prompt
- user request
- history summary
- tool definitions
- project snippets
今天实现一个最小 Context Builder,把这些材料变成结构化 ContextPart,同时生成真正发给模型的 messages。

今天要解决什么
今天完成四个交付:
- 新增
context/builder.ts。 - 让 builder 组装 system prompt、用户请求、历史摘要、工具定义和项目片段。
- 给
ContextPart增加source,让 context report 能显示来源。 - 让
agent/run.ts使用 builder,而不是手写 prompt 和 context parts。
Demo 命令:
npm run dev -- --context-report "build context for this repo"
输出里会出现类似结构:
System prompt system ~1,023 tokens (context-builder)
User request conversation ~7 tokens (argv)
History summary conversation ~11 tokens (context-builder)
Tool definitions tools ~391 tokens (tool-registry)
Project snippets files ~492 tokens (README.md, package.json)
Conversation conversation ~2,394 tokens (agent-loop)
Agent steps tool-results ~1,701 tokens (agent-loop)
它在 Cursor/Codex 里对应哪一层
今天实现的是 context assembly layer。
在 Cursor、Codex、Claude Code 这类 coding agent 中,模型请求前通常会经过一个上下文构建阶段:
User task
-> system instructions
-> project rules
-> selected files
-> tool schemas
-> conversation summary
-> recent messages
-> model request
这层的质量直接影响 agent 行为:
- 上下文太少,模型会猜。
- 上下文太多,关键信息会被稀释。
- 工具定义不清楚,模型会调用错工具。
- 文件片段选错,模型会围绕错误模块推理。
- 历史摘要不可靠,模型会带着错误状态继续。
Day 08 的实现还很小,但它把“上下文”从散落字符串升级成了可检查的数据结构。
设计思路
1. Context Builder 返回两类结果
新增文件:apps/mini-harness/src/context/builder.ts
builder 返回:
export type BuiltRunContext = {
messages: ChatMessage[];
contextParts: ContextPart[];
systemPrompt: string;
};
messages 是真正发给 model provider 的输入。
contextParts 是给 context report、transcript、debug UI 使用的结构化视图。
这两个结果来自同一套构建逻辑,避免“模型实际看到的内容”和“报告展示的内容”不一致。
2. ContextPart 增加 source
Day 08 给共享类型加了一个可选字段:
export type ContextPart = {
label: string;
kind: ContextKind;
content: string;
source?: string;
};
kind 说明材料类别,source 说明材料来源。例如:
Tool definitions -> kind: tools, source: tool-registry
Project snippets -> kind: files, source: README.md, package.json
User request -> kind: conversation, source: argv
这样 Day 09 做 Context Explorer 时,不只是显示 token 数,还能解释“这些 token 是从哪里来的”。
3. 先用保守的项目片段选择
今天不做复杂检索,也不做 embedding。Context Builder 默认读取两个稳定文件:
const DEFAULT_SNIPPET_FILES = ["README.md", "package.json"];
它们通常能提供项目目标、脚本、workspace 结构和包信息。每个文件最多读 4KB:
const MAX_SNIPPET_BYTES = 4_000;
路径仍然经过 workspace guard,避免 context builder 读取工作区外的文件。
4. agent loop 不再手写 prompt
Day 07 的 run.ts 里直接拼 system prompt、tool definitions 和 context parts。
Day 08 改成:
const builtContext = await buildRunContext({
task: input.task,
tools: input.tools,
workspaceRoot: input.workspaceRoot,
});
const messages = [...builtContext.messages];
返回 summary 时再追加运行后的动态部分:
- full conversation
- agent steps
这样静态输入由 Context Builder 负责,运行时过程由 Agent Loop 负责。
实现步骤
1. 新增 context builder
文件:apps/mini-harness/src/context/builder.ts
核心入口:
export async function buildRunContext(input: BuildRunContextInput): Promise<BuiltRunContext>
输入包括:
task
tools
workspaceRoot
historySummary
selectedFiles
当前默认 history summary 是:
No prior conversation summary for this run.
后续如果实现长期会话或 transcript replay,可以把历史摘要接进这里。
2. 组装 system prompt
system prompt 包含:
- agent 身份
- Day08 行为边界
- tool call 文本协议
- history summary
- available tools
- selected project snippets
这里刻意把 tool definitions 和 project snippets 放进 system prompt,是为了维持当前最小 ChatMessage 类型。真实 provider adapter 可以进一步映射成模型原生 tool schema 或 tool role。
3. 生成 context parts
builder 输出五个基础 parts:
System prompt
User request
History summary
Tool definitions
Project snippets
agent loop 运行结束后再补两个动态 parts:
Conversation
Agent steps
这让 context report 能区分“模型请求前的输入”和“运行后的观察结果”。
4. 更新 context report
文件:apps/mini-harness/src/context/context-report.ts
原来只显示 label 和 token 数:
System prompt ~484 tokens
现在显示 label、kind、token 和 source:
System prompt system ~1,023 tokens (context-builder)
Project snippets files ~492 tokens (README.md, package.json)
Demo
See Day 08 demo.
核心命令:
npm run dev -- --context-report "build context for this repo"
输出摘要:
Context Explorer
System prompt system ~1,023 tokens (context-builder)
User request conversation ~7 tokens (argv)
History summary conversation ~11 tokens (context-builder)
Tool definitions tools ~391 tokens (tool-registry)
Project snippets files ~492 tokens (README.md, package.json)
Conversation conversation ~2,394 tokens (agent-loop)
Agent steps tool-results ~1,701 tokens (agent-loop)
Total ~6,019 tokens
具体 token 数会随文章、工具和文件内容变化,但应该能看到 builder 产出的五个基础 context parts。
当前系统能力变化
到 Day 08,mini harness 的模型输入已经不再是临时拼接字符串:
- 上下文有
kind。 - 上下文有
source。 - system prompt、user request、tools、history、files 分开记录。
- agent loop 只消费 builder 产物。
- context report 可以显示每部分 token 估算。
这为 Day 09 的 Context Explorer 打好了基础。
遇到的问题
1. 文件片段选择仍然很粗糙
今天只是默认读取 README.md 和 package.json。这对 demo 足够,但离真实 coding agent 还差很远。
真实系统需要根据任务选择文件,例如:
- 用户提到某个路径时优先读取该文件。
- 搜索相关符号后加入匹配文件。
- 通过 git diff 加入当前改动。
- 根据 token budget 做排序和截断。
2. system prompt 变大了
把 tool definitions 和 project snippets 放进 system prompt 简单直接,但会让 system prompt token 增长。
后续可以把工具定义放到 provider 原生 tool schema,把文件片段作为单独 message 或 provider-specific context block。
3. history summary 还没有真实来源
当前 history summary 是占位文本。等后续支持 transcript replay 或长会话时,才会有真正的 history summarizer。
明天做什么
Day 09 会实现 Context Explorer:把上下文来源、token 估算、截断状态和调试信息做成更明确的命令行报告。
Day 08 负责“构建上下文”,Day 09 负责“解释上下文”。
Comments