Files
zk-data-agent/README.md
T
2026-05-06 12:01:22 +08:00

934 lines
27 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Claw Code Agent 架构逆向分析报告
本文基于只读分析仓库源码撰写,目标不是介绍如何使用,而是回答这个项目作为一个 Agent 系统是如何被构造出来的。
---
## 1. 总体定位
### 1.1 这个项目本质上是什么
这个项目本质上是一个 **agentic coding runtime**,而不是单纯的 workflow engine,也不只是一个 tool harness。
更准确地说,它处在三者交叉区:
- **最核心身份**Claude Code / Codex 风格的本地 coding agent runtime
- **承载方式**:以 Python 实现的 agent loop + tool harness
- **扩展方式**:外挂了大量 runtime 子系统,例如 search、MCP、plan、task、team、workflow、worktree、plugin、hook policy
因此它不是一个“纯工作流系统”。workflow 在这里是一个被 agent 调用的能力域,而不是系统唯一中心。系统中心仍然是 `LocalCodingAgent` 的多轮模型-工具循环,见 `src/agent_runtime.py:103``src/agent_runtime.py:358`
### 1.2 核心抽象是什么
这个项目有几个关键抽象:
- **Agent**`LocalCodingAgent`,真正的 orchestrator,负责 prompt 构建、loop、工具调用、budget、session 持久化,见 `src/agent_runtime.py:103`
- **Session**`AgentSessionState`,维护系统消息、用户上下文、assistant/tool transcript 以及 mutation lineage,见 `src/agent_session.py:89`
- **Tool**`AgentTool` + `ToolExecutionContext`,以 OpenAI function calling 风格对工具进行 schema 化和执行,见 `src/agent_tools.py:44``src/agent_tools.py:73`
- **Prompt Context**`PromptContext` / `AgentContextSnapshot`,把工作目录、git 状态、CLAUDE.md、各种 runtime 状态拼进模型上下文,见 `src/agent_prompting.py:15``src/agent_context.py:40`
- **StoredAgentSession`**:把完整 transcript、tool_calls、usage、file_history、plugin_state 持久化到 `.port_sessions/agent/*.json`,见 `src/session_store.py:53`
换句话说,它不是围绕“任务节点图”来设计的,而是围绕:
1. 当前 session 里有哪些上下文
2. 当前模型要不要发起 tool call
3. tool result 如何再次喂回模型
4. 何时 compact / stop / persist
### 1.3 与 Claude Code / Codex 的相似点与差异
#### 相似点
- 典型 **LLM-driven tool loop**:模型产出 tool call,runtime 执行工具,再把结果作为 `tool` message 回灌
-**workspace / repository** 为中心,强依赖文件系统、git 状态、shell、搜索
- 支持 **系统提示词 + repo memory** 注入,尤其是 `CLAUDE.md`
-**多轮对话 session**、resume、context compaction、权限 gating
- 支持 **Agent 子代理 / delegation**
#### 差异点
- 比 Claude Code / Codex 更“runtime platform 化”:这里塞了大量本地 runtime 子系统,如 `task_runtime``plan_runtime``team_runtime``workflow_runtime``remote_runtime``mcp_runtime`
- “skills” 实现较轻:当前更像 prompt-template / slash-command bridge,而不是成熟的按需 markdown 技能系统
- 权限模型相对简化:主要是 CLI 启动时布尔权限 + policy deny,而不是更细粒度的人机交互审批流
- 可观测性是“有 transcript / event / file_history 基础设施,但 UI 和诊断链条尚未完全产品化”
结论上,这个项目像是:
> 一个以 coding agent loop 为中心、向外扩张成通用本地 agent runtime 平台的 Python 实现。
---
## 2. Agent Loop
### 2.1 主循环入口
真实入口是 `LocalCodingAgent.run()`,它生成 `session_id`、scratchpad 目录,然后进入 `_run_prompt()`,见:
- `src/agent_runtime.py:358`
- `src/agent_runtime.py:413`
恢复会话则走 `resume()`,它把持久化 session 反序列化成 `AgentSessionState`,并补充 file history replay 与 compaction replay,见 `src/agent_runtime.py:376`
### 2.2 每轮如何观察当前状态
Agent 的“观察”不是通过一个单独的 observe() 函数完成,而是在 loop 外预构建 session,并在每轮前做上下文压力处理:
1. **启动时构建 prompt context**
- `build_prompt_context()` -> `build_context_snapshot()`
- 汇总 cwd、platform、git status、scratchpad、CLAUDE.md bundle、各 runtime summary
-`src/agent_runtime.py:240` 左右、`src/agent_prompting.py:30``src/agent_context.py:71`
2. **构建初始 session**
- `build_session()` 使用 system prompt parts + user_context/system_context 生成 session
- `AgentSessionState.create()` 会插入:
- `system` message
- `user_context reminder`
- 当前用户 prompt
-`src/agent_runtime.py:255` 左右、`src/agent_session.py:97`
3. **每轮前的状态整理**
- `_microcompact_session_if_needed()`
- `_snip_session_if_needed()`
- `_compact_session_if_needed()`
- `_preflight_prompt_length()`
-`src/agent_runtime.py:527-547`
因此,“观察当前状态”既包括文件系统 / git / runtime summary,也包括自身历史 transcript 的压缩后视图。
### 2.3 如何构造上下文
上下文构造分两层:
#### 第一层:环境与 memory 采样
`src/agent_context.py` 负责采样:
- cwd、shell、platform、date
- git status snapshot,见 `src/agent_context.py:279`
- scratchpad directory,见 `src/agent_context.py:197`
- `CLAUDE.md` / `.claude/CLAUDE.md` / `CLAUDE.local.md` / `.claude/rules/*.md` bundle,见 `src/agent_context.py:313-372`
- plugin / hook policy / MCP / remote / search / account / ask_user / config / LSP / plan / task / team / workflow / worktree 的 runtime summary,见 `src/agent_context.py:205-275`
#### 第二层:系统提示词装配
`build_system_prompt_parts()` 会拼接:
- system instructions
- doing tasks guidance
- tool usage guidance
- agent guidance
- plugin / MCP / search / account / ask-user / config / LSP / plan / task / team / hook policy guidance
- session-specific permission guidance
- simple env info
`src/agent_prompting.py:75-119`
也就是说,这个项目的上下文不是“只把聊天记录喂给模型”,而是:
> transcript + injected local memory + runtime summaries + environment facts + permissions hints
### 2.4 如何决定下一步行动
行动选择主要由模型驱动。
每轮中 runtime 做的事情是:
1.`session.to_openai_messages()``tool_specs` 发给模型,见 `src/agent_runtime.py:1153-1157`
2. 从返回中解析:
- 普通 assistant content
- tool calls
- finish_reason
- usage
3. 若无 tool call,则视作模型选择直接回答
4. 若有 tool call,则 runtime 执行这些工具,再把工具结果回灌到 session
真正的“决策”是模型自己通过 OpenAI tool calling 选择的,而不是 runtime 用规则树规划下一步。
因此 loop 属于:
- **外层固定流程**
- **内层模型驱动的动态行动选择**
### 2.5 如何调用工具
工具定义为 `AgentTool`,带:
- `name`
- `description`
- JSON Schema 参数定义 `parameters`
- `handler`
`src/agent_tools.py:73-111`
每轮把所有工具变成 OpenAI function spec
- `tool_specs = [tool.to_openai_tool() for tool in self.tool_registry.values()]`
-`src/agent_runtime.py:463`
模型返回 tool call 后,主循环在 `src/agent_runtime.py:808-1119` 中执行:
- 创建一个 tool message 占位 `session.start_tool(...)`
- 记录 `tool_start` event
- 应用 plugin / hook policy preflight
- 执行 delegate / Skill / 普通 tool
-`serialize_tool_result()` 将结果序列化成 JSON 字符串写回 transcript
### 2.6 工具结果如何回到模型上下文
工具结果通过 `session.finalize_tool(...)` 变成一个 `role='tool'` 的 message,内容是:
```json
{
"tool": "...",
"ok": true/false,
"content": "...",
"metadata": {...}
}
```
见:
- `src/agent_tools.py:1248`
- `src/agent_runtime.py:1037-1047`
下一轮模型调用时,`session.to_openai_messages()` 会把这些 tool messages 一并送回模型。因此工具结果不是旁路状态,而是标准 transcript 的一部分。
### 2.7 什么时候停止
停止条件有多类:
- **模型正常回答且无 tool_calls**:结束,见 `src/agent_runtime.py:764-806`
- **finish_reason = length/max_tokens**:自动注入 continuation prompt,再继续一轮,见 `src/agent_runtime.py:766-783`
- **budget exceeded**:停止,见 `src/agent_runtime.py:500-525``552-581``733-762`
- **prompt too long / preflight fail**:停止或先 compact 再试,见 `src/agent_runtime.py:543-605`
- **backend error**:停止,见 `src/agent_runtime.py:703-725`
- **达到 `max_turns`**:停止,见 `src/agent_runtime.py:1121-1146`
### 2.8 loop 是固定流程还是模型驱动
结论:
- **loop 骨架是固定的 runtime state machine**
- **每轮内的动作内容是模型驱动的**
固定部分是:
1. 整理上下文
2. 预算检查
3. 调模型
4. 若 tool_calls 则执行工具
5. 把工具结果写回 transcript
6. 进入下一轮或停止
动态部分是:
- 调什么工具
- 调多少个工具
- 是继续观察、修改还是直接回答
---
## 3. Context / Memory
### 3.1 是否有短期上下文
有。短期上下文就是当前 `AgentSessionState.messages`
其中包含:
- system prompt
- user context reminder
- user / assistant / tool messages
- mutation metadata
`src/agent_session.py:89-148`
### 3.2 是否有长期记忆
有,但不是向量数据库式长期记忆,而是 **文件化长期记忆**
- `~/.claude/CLAUDE.md`
- 向上目录搜索的 `CLAUDE.md`
- `.claude/CLAUDE.md`
- `CLAUDE.local.md`
- `.claude/rules/*.md`
这些文件会在 session 创建时被 bundle 进 `user_context['claudeMd']`,见 `src/agent_context.py:205-207``313-372`
因此它支持“repo memory / instruction memory”,但不支持自动写回、检索式 memory store 或 embedding memory。
### 3.3 是否有 conversation history
有,而且比较完整:
- 运行时 transcript`AgentSessionState.messages`
- 持久化 transcript`StoredAgentSession.messages`
- resume 后会恢复完整历史,见 `src/session_store.py:53-115`
工具调用、usage、message metadata 也一起保存。
### 3.4 是否有压缩 / summarize / compaction
有,而且这是一个比较成熟的部分。
机制分三层:
- **microcompact**:时间驱动的小型压缩,清理旧 tool results,见 `src/agent_runtime.py:113-115 import``src/agent_runtime.py:527-533`
- **snip**:把早期消息 tombstone 化为短摘要,见 `src/agent_runtime.py:533-537``_snip_session_pass`
- **compact**:调用 `compact_conversation()` 生成更正式的压缩摘要,见 `src/agent_runtime.py:538-547``src/agent_runtime.py:1240` 前后逻辑
此外还有:
- prompt too long 时的 **reactive compaction retry**
- resume 时的 **compaction replay**
`src/agent_runtime.py:3042-3142`
### 3.5 是否有外部文件作为 memory
有,且非常明显:
- `CLAUDE.md` 系列
- `.claude/rules/*.md`
- 各类 workspace state 文件:config、plan、task、team、workflow、worktree 等 runtime manifest/state 文件
不过严格说,后者更多是 “runtime state injection”,不是纯 memory。
### 3.6 是否支持类似 CLAUDE.md / AGENTS.md / skills 的持久知识
#### CLAUDE.md
支持,且是当前唯一成熟的一类持久知识注入。
#### AGENTS.md
**不原生支持 `AGENTS.md` 作为 memory bundle**。当前 memory 发现逻辑只搜索 `CLAUDE.md``CLAUDE.local.md``.claude/rules/*.md`,见 `src/agent_context.py:355-372`
#### skills
只支持“bundled skills”:
- 在 Python 代码里硬编码 skill 元数据和 prompt builder
- 通过 `Skill` 工具或 `/skills` 暴露
不支持从工作区扫描 markdown skill 文档并按需加载。
### 3.7 当前设计局限
1. **长期记忆是纯文件注入,不是检索式 memory**
- 规模大时容易塞满 prompt
- 没有 relevance ranking
2. **只识别 CLAUDE.md 家族,不识别 AGENTS.md**
- 对多代理协作约束不够统一
3. **resume 依赖 transcript replay,不是真正的 semantic memory**
- 历史很多时仍然会发生 compaction 丢失细节
4. **runtime summaries 很多,但上下文管理是“全量摘要注入”**
- 不是 query-time selective loading
5. **task / plan / workflow 已有,但未形成强约束的 workspace memory layout**
- 更像多个离散 runtime,而不是统一的 task-memory 文件系统
---
## 4. Tools / Actions
### 4.1 工具能力概览
核心工具能力包括:
- **文件系统**
- `list_dir`
- `read_file`
- `write_file`
- `edit_file`
- `notebook_edit`
- **搜索与代码理解**
- `glob_search`
- `grep_search`
- `LSP`
- `tool_search`
- **Shell**
- `bash`
- **Web / Search**
- `web_fetch`
- `web_search`
- search provider 管理工具
- **计划 / 任务**
- `update_plan`
- `plan_get`
- task runtime 相关工具
- **Human gate**
- `ask_user_question`
- **扩展 runtime**
- `mcp_*`
- `remote_*`
- `workflow_*`
- `worktree_*`
- `account_*`
- `config_*`
- **Agent 特有**
- `Agent` / `delegate_agent`
- `Skill`
tool registry 定义入口在 `src/agent_tools.py:210`
### 4.2 工具 schema 怎么定义
每个工具是一个 `AgentTool`
- `name`
- `description`
- `parameters`JSON Schema
- `handler`
`src/agent_tools.py:73-111`
它通过 `to_openai_tool()` 转成 OpenAI-compatible function calling schema,见 `src/agent_tools.py:80-88`
### 4.3 工具调用怎么执行
模型返回 tool call 后,runtime 会:
1. 解析 tool call,见 `src/openai_compat.py:273-298`
2. 在 loop 中逐个消费,见 `src/agent_runtime.py:808-1119`
3. 普通工具走 `execute_tool_streaming()``tool.execute()`,见 `src/agent_tools.py:181-207`
4. 特殊工具:
- `Agent` / `delegate_agent` 走子代理执行,见 `src/agent_runtime.py:2214`
- `Skill``_execute_skill()`,见 `src/agent_runtime.py:2059`
### 4.4 工具结果如何返回
工具结果统一封装为 `ToolExecutionResult`
- `name`
- `ok`
- `content`
- `metadata`
然后 `serialize_tool_result()` 把它转成 JSON 字符串,塞入 tool message,见 `src/agent_tools.py:1248-1255`
这意味着:
- 对模型来说,工具结果是 transcript 中的标准 `tool` message
- 对 runtime 来说,工具结果又带 `metadata`,可用于 file_history、policy event、plugin hook
### 4.5 是否有安全边界
有,但不是特别细粒度。
#### 文件边界
`_resolve_path()` 会强制路径位于 workspace root 内,防止越界,见 `src/agent_tools.py:1277-1288`
#### 写权限边界
`write_file` / `edit_file``allow_file_write` 控制,见 `src/agent_tools.py:1291-1295`
#### shell 权限边界
`bash` 受两层控制:
- `allow_shell_commands`
- `allow_destructive_shell_commands`
并有 destructive regex 阻断,比如 `rm``git reset --hard``git clean -fd` 等,见 `src/agent_tools.py:1298-1324`
#### policy / hook deny
workspace 可以通过 `.claw-policy.json` / `.codex-policy.json` / `.claw-hooks.json` 配置 deny_tools、deny_tool_prefixes 以及 hook message,见 `src/hook_policy.py:160-256`
#### CLI 层 deny context
还有一个更轻的 `ToolPermissionContext`,可按名字或前缀过滤工具,见 `src/permissions.py:7-17`
### 4.6 这一层的架构评价
这个项目的 tools 层已经不是“几个本地 IO 工具”,而是:
> 一个围绕 workspace 资源、外部 runtime 状态和 agent orchestration 展开的统一 action surface。
优点是扩展性强,缺点是工具域越来越大后,模型对何时该用哪个工具会变得更依赖 prompt guidance。
---
## 5. Markdown / Workspace
### 5.1 是否支持 workspace-first
是,明显是 workspace-first 设计。
证据:
- `ToolExecutionContext.root` 是工作区根,见 `src/agent_tools.py:45`
- 所有文件工具都围绕 workspace root 做相对路径解析,见 `src/agent_tools.py:1277-1288`
- context 注入围绕 cwd、git repo、worktree、scratchpad、additional_working_directories 展开,见 `src/agent_context.py:71-99`
- 很多 runtime 都是 `from_workspace(cwd)` 初始化的
### 5.2 是否适合让 Agent 维护 `.md` 文件作为任务记忆
适合,而且比很多 agent 框架更适合。
原因:
- 已经原生支持 markdown 记忆文件注入(CLAUDE.md / rules
- 文件读写/编辑能力完整
- 有 plan / task runtime,可作为结构化状态
- 有 scratchpad directory,可作为会话级临时区
不足是它没有约定一个统一的 task-memory 目录布局。
### 5.3 是否有任务目录 / workspace 概念
有 workspace 概念,但没有强约定的任务目录结构。
已有元素:
- workspace root
- additional working directories
- scratchpad root / scratchpad directory
- `.claude/` 作为本地 agent/runtime 元数据目录
但没有默认的:
- `/tasks/{task_id}/...`
- `/artifacts/...`
- `/memory/...`
### 5.4 能否改造成 task directory layout
完全可以,而且改造成本不高。
一个可行布局:
```text
/tasks/{task_id}/goal.md
/tasks/{task_id}/memory/open_questions.md
/tasks/{task_id}/memory/working_notes.md
/tasks/{task_id}/artifacts/report.md
/tasks/{task_id}/artifacts/commands.md
/tasks/{task_id}/artifacts/findings.md
```
最小改造方式:
1.`task_runtime` 中给 task 增加 `task_root`
2.`agent_context._load_memory_bundle()` 中把 `/tasks/{active_task}/memory/*.md` 纳入 memory discovery
3. 在 prompt context 中注入 `active task root`
4.`update_plan` / task 工具增加 task-root 绑定
这样不需要重写 loop,只是增强 workspace memory layout。
---
## 6. Skills
### 6.1 当前是否支持 skill
支持,但属于 **弱 skill 系统**
当前 skill 机制分两部分:
1. **Bundled skills**
- `BundledSkill` 定义 name / description / when_to_use / aliases / allowed_tools / get_prompt
-`src/bundled_skills.py:22-32`
2. **Skill tool**
- `_execute_skill()` 优先查 bundled skill
- 查不到再退回 slash command
-`src/agent_runtime.py:2059-2142`
### 6.2 是否有技能发现机制
有,但只对 bundled skill 生效:
- `format_skills_for_system_prompt()` 把 skill 列表渲染进系统提示,帮助模型“知道”有哪些 skill,见 `src/bundled_skills.py:268-289`
- GUI 也有 `/api/skills` 列表,见 `backend/api/server.py`
但它没有:
- 从工作区扫描 skill 文件
- 从 skill 文档按需加载正文
- skill-level semantic retrieval
### 6.3 是否支持 progressive disclosure
**严格说不支持。**
当前 bundled skill 更像:
- 用户 / 模型选中 skill
- skill 生成一段 prompt
- prompt 立即进入模型上下文
并不是:
- 先列 metadata
- 决定是否需要 skill
- 再按需读取 skill markdown 正文
- 只展开相关片段
因此它缺乏真正的 progressive disclosure。
### 6.4 如果没有,应该如何扩展
建议做一个最小可行版 workspace skill system,不破坏现有 loop。
#### 最小改造方案
##### 目录结构
```text
.claude/skills/
review/
skill.json
SKILL.md
data-agent/
skill.json
SKILL.md
python-debug/
skill.json
SKILL.md
```
##### metadata
`skill.json` 示例:
```json
{
"name": "data-agent",
"description": "Analyze datasets and produce structured markdown reports.",
"when_to_use": "When the task involves CSV/JSON/table exploration, metric comparison, or report writing.",
"aliases": ["data", "analysis"],
"allowed_tools": ["read_file", "write_file", "edit_file", "glob_search", "grep_search", "bash"],
"entry_markdown": "SKILL.md"
}
```
##### loading 时机
建议两阶段:
1. **session 初始化时只加载 metadata**
- 像 bundled skill 一样列进 system prompt
- 不把 `SKILL.md` 正文直接注入
2. **当模型选择 Skill 工具时再加载正文**
- `Skill(skill="data-agent")`
- runtime 读取对应 `SKILL.md`
- 返回 skill prompt 或 `<system-reminder>` 包装内容
##### Agent 如何决定读取哪个 skill
沿用现有机制,最小改造即可:
- 在 system prompt 里暴露 `name + description + when_to_use`
- 模型自己决定是否调用 `Skill`
- `Skill` 工具负责延迟读取 skill 正文
##### 代码落点
最小改造建议:
- 扩展 `src/bundled_skills.py` 为“bundled + discovered skills”
- 或新建 `workspace_skills.py`
-`_execute_skill()` 中优先:
1. bundled skill
2. workspace discovered skill
3. slash command fallback
这个改法不会触碰 loop 主干,只是在 skill lookup 阶段增加一个来源。
---
## 7. Policy / Human Gate
### 7.1 如何处理权限
当前权限机制主要有三层。
#### 第一层:启动时权限布尔开关
`AgentPermissions`
- `allow_file_write`
- `allow_shell_commands`
- `allow_destructive_shell_commands`
`src/agent_types.py:147-150`
这是最直接的 runtime gate。
#### 第二层:workspace hook / policy
`HookPolicyRuntime` 支持:
- `trusted`
- `managed_settings`
- `safe_env_names`
- `deny_tools`
- `deny_tool_prefixes`
- `before_prompt`
- `after_turn`
- `before_tool`
- `after_tool`
- `budget_overrides`
`src/hook_policy.py:10-22`
#### 第三层:ask_user runtime
并不是所有危险动作都会自动弹确认框。当前“人工确认”更像一个工具能力:
- `ask_user_question`
也就是说,模型可以选择向用户提问,但 runtime 本身不会像桌面 Codex 那样对每个危险动作自动出现审批 UI。
### 7.2 哪些动作会请求用户确认
严格来说,**默认没有统一的自动确认拦截器**。
当前模式更像:
- 文件写:如果没开 `allow_write`,直接拒绝
- shell:如果没开 `allow_shell`,直接拒绝
- destructive shell:如果没开 `--unsafe`,直接拒绝
- policy deny:直接拒绝
- ask-user:模型显式调用 `ask_user_question` 才会走人工澄清
因此它偏向:
> hard gate / deny-first,而不是 ask-on-demand 审批流。
### 7.3 哪些动作默认允许
默认允许的是安全读类能力,例如:
- read
- list
- search
- tool discovery
- runtime status inspection
默认不允许的是:
- 写文件
- shell
- destructive shell
具体提示也被写进 system prompt,见 `src/agent_prompting.py:388-401`
### 7.4 是否有 deny / allow / ask 策略
`allow``deny`,但 `ask` 不是系统级统一策略。
- **allow**CLI flag / runtime permissions
- **deny**hook policy deny_tools / deny_tool_prefixes
- **ask**:只通过 `ask_user_question` 工具实现,非自动策略
### 7.5 是否支持项目级规则
支持。
项目级规则来自:
- `.claw-policy.json`
- `.codex-policy.json`
- `.claw-hooks.json`
并且会沿 cwd 向上目录发现,见 `src/hook_policy.py:160-187`
### 7.6 对数据 Agent 的不足
如果你们要做数据 Agent,这套 human gate 还有几个明显缺口:
1. **缺少按数据源级别的权限模型**
- 没有“允许读 CSV 但不允许发网络请求”这种更细粒度策略
2. **没有结构化审批流**
- 例如“将执行 SQL / 访问线上表 / 导出结果集”的 ask approval 缺位
3. **没有数据脱敏/泄露策略**
- safe_env 只管环境变量,不管输出内容
4. **没有审计级 action classification**
- tool 结果有 metadata,但没有“高风险数据出站/高风险变更”的统一标签体系
5. **policy 更偏 workspace engineering,而不是 data governance**
如果面向数据 Agent,建议增加:
- data source allowlist
- query approval policy
- outbound redaction hook
- result size limits
- table/column sensitivity policy
---
## 8. Trace / Observability
### 8.1 是否记录每一轮模型输入输出
有记录,但“模型输入原文”不单独存为一条日志,而是可由 session transcript 和 system/user context 还原。
保存内容包括:
- `messages` transcript
- `system_prompt_parts`
- `user_context`
- `system_context`
- `usage`
- `turns`
- `tool_calls`
`src/session_store.py:53-115``src/agent_runtime.py:3269-3345`
模型输出则直接进入 `assistant` messages。
### 8.2 是否记录工具调用
有,而且记录得比较细:
- transcript 中的 assistant tool_calls
- transcript 中的 tool result message
- `events` 中的 `tool_start` / `tool_delta` / `tool_result`
- `file_history` 中的摘要化变更记录
`src/agent_runtime.py:852-1119`
### 8.3 是否记录文件变更
有,`file_history` 是一个重要机制。
resume 时会把 file_history replay 成一个 `<system-reminder>` 给模型,见:
- `src/agent_runtime.py:2914-3040`
持久化时也会一起保存到 session json,见:
- `src/session_store.py:66`
- `src/agent_runtime.py:3333`
它不是完整 patch log,但已经记录:
- action
- path / changed_paths
- snapshot ids
- before/after preview
- result preview
### 8.4 是否有 replay/debug 能力
有基础能力:
- `agent-resume`
- transcript 持久化
- file_history replay
- compaction replay
- GUI 可以展示 transcript 和 tool calls
但没有一个真正成熟的“调试控制台”或统一 trace viewer。
### 8.5 现有 observability 的优点
优点:
- 数据结构已经齐全:transcript、events、file_history、budget_state、plugin_state
- session 是 JSON 文件,易于离线分析
- message metadata 里保留了 mutation lineage / revision 信息
这意味着系统已经具备做更强 observability 的底座。
### 8.6 还缺什么
目前还缺:
1. **完整 prompt snapshot**
- 现在有 system/user context 和 transcript,但缺“每轮实际发给模型的最终 payload”落盘
2. **turn-level structured trace**
- 比如 `turn_03.json`
- 包含 prompt size、tool candidates、selected tool calls、latency、errors
3. **统一 replay viewer**
- 现在 resume 偏“继续工作”
- 不是“回放调试”
4. **tool latency / error taxonomy**
- 有 event,但缺统计聚合
5. **compaction provenance**
- 已有 replay,但缺图形化 lineage/summary mapping
### 8.7 如果要补,怎么加
最小建议:
#### 建议新增 trace 目录
```text
.port_sessions/traces/{session_id}/
turn_001.request.json
turn_001.response.json
turn_001.events.json
turn_001.tools.json
```
#### 每轮保存这些内容
- request
- rendered messages
- tool specs
- token budget snapshot
- response
- raw model response
- parsed tool calls
- finish_reason
- tools
- tool args
- tool result
- latency
- events
- 当前 turn 的 event list
#### 代码落点
最合适挂点在:
- `_query_model()` 前后
- tool loop `for tool_call in turn.tool_calls`
- `_persist_session()`
这样能复用现有 `session_id``turn_index`
---
## 总结判断
这个项目已经具备一个完整 coding agent runtime 的主要骨架:
- 有明确的 session 与 transcript 模型
- 有模型驱动的动态工具循环
- 有 context injection 与 memory bundle
- 有 compaction / replay / resume
- 有较丰富的本地工具和 runtime 子系统
但从“下一代 workspace-native agent platform”的角度看,它还有几个明显缺口:
- skills 仍是 prompt-template 级,未形成 markdown-native progressive disclosure
- policy 偏 deny/allow,不是强审批流
- memory 已经文件化,但没有统一 task directory layout
- observability 有底座,缺一层真正可用的 trace 产品化视图
如果目标是把它改造成更强的“任务型数据 Agent / 文档驱动 Agent / workspace-memory-first Agent”,最值得优先补的不是 loop,而是三件事:
1. **workspace skill discovery + on-demand markdown loading**
2. **任务目录结构与 memory layout 约定**
3. **turn-level trace 持久化与 replay viewer**
这三项都可以在不重写 `LocalCodingAgent` 主循环的前提下增量演进。