diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..19bedd1 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,65 @@ +# AGENTS.md + +Behavioral guidelines to reduce common LLM coding mistakes. Merge with project-specific instructions as needed. + +**Tradeoff:** These guidelines bias toward caution over speed. For trivial tasks, use judgment. + +## 1. Think Before Coding + +**Don't assume. Don't hide confusion. Surface tradeoffs.** + +Before implementing: +- State your assumptions explicitly. If uncertain, ask. +- If multiple interpretations exist, present them - don't pick silently. +- If a simpler approach exists, say so. Push back when warranted. +- If something is unclear, stop. Name what's confusing. Ask. + +## 2. Simplicity First + +**Minimum code that solves the problem. Nothing speculative.** + +- No features beyond what was asked. +- No abstractions for single-use code. +- No "flexibility" or "configurability" that wasn't requested. +- No error handling for impossible scenarios. +- If you write 200 lines and it could be 50, rewrite it. + +Ask yourself: "Would a senior engineer say this is overcomplicated?" If yes, simplify. + +## 3. Surgical Changes + +**Touch only what you must. Clean up only your own mess.** + +When editing existing code: +- Don't "improve" adjacent code, comments, or formatting. +- Don't refactor things that aren't broken. +- Match existing style, even if you'd do it differently. +- If you notice unrelated dead code, mention it - don't delete it. + +When your changes create orphans: +- Remove imports/variables/functions that YOUR changes made unused. +- Don't remove pre-existing dead code unless asked. + +The test: Every changed line should trace directly to the user's request. + +## 4. Goal-Driven Execution + +**Define success criteria. Loop until verified.** + +Transform tasks into verifiable goals: +- "Add validation" → "Write tests for invalid inputs, then make them pass" +- "Fix the bug" → "Write a test that reproduces it, then make it pass" +- "Refactor X" → "Ensure tests pass before and after" + +For multi-step tasks, state a brief plan: +``` +1. [Step] → verify: [check] +2. [Step] → verify: [check] +3. [Step] → verify: [check] +``` + +Strong success criteria let you loop independently. Weak criteria ("make it work") require constant clarification. + +--- + +**These guidelines are working if:** fewer unnecessary changes in diffs, fewer rewrites due to overcomplication, and clarifying questions come before implementation rather than after mistakes. \ No newline at end of file diff --git a/CLAW_AGENT_ARCH_ANALYSIS.md b/CLAW_AGENT_ARCH_ANALYSIS.md new file mode 100644 index 0000000..9fffe25 --- /dev/null +++ b/CLAW_AGENT_ARCH_ANALYSIS.md @@ -0,0 +1,933 @@ +# 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` 列表,见 `src/gui/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 或 `` 包装内容 + +##### 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 成一个 `` 给模型,见: + +- `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` 主循环的前提下增量演进。 diff --git a/data_agent_v0.md b/data_agent_v0.md new file mode 100644 index 0000000..3f5fd1e --- /dev/null +++ b/data_agent_v0.md @@ -0,0 +1,553 @@ +文档结构 +1. 数据迭代Agent架构 + + + + + +- 1-2周MVP方案 +- badcase反馈渠道接入、自动收集分析 + +- 1-2周MVP方案 +1. 定义一个最小的任务流程,整理流程中AI需要具备的能力 + - 工具 + - 记忆 + - 环境 + - 技术选型 + + Badcase 反馈渠道接入与自动收集分析:数据挖掘Agent设计方案 + +Router Data Agent Workbench 方案文档 +1. 背景 +当前快慢系统路由的数据开发流程,主要围绕以下任务展开: + - 分析需求 / badcase + - 明确快慢系统边界 + - 构建评测集 + - 构建训练集 + - 挖掘线上样本 + - 人工标注与复核 + - 模型训练与回放评估 + - 根据结果继续补齐数据 +现有流程本质上仍然是 人驱动的数据开发 + 人理解需求 +→ 人拆解边界 +→ 人写 prompt / 规则 +→ 人捞数据 +→ 人筛样本 +→ 人整理评测集 +→ 人分析模型问题 +→ 人沉淀经验 +这个流程可以用 AI 做局部提效,但如果只是把每一步变成一个 LLM 节点,本质上仍然是旧框架。 +本项目希望重构的不是某几个节点,而是整个数据开发范式。 + +--- +1.1 业务尝试:快慢系统评测集构建 +当前路由标签空间包括: +FAST_DIRECT +SLOW_FILTER_RANK +SLOW_DISAMBIGUATE +SLOW_GOAL_STATE +SLOW_WORKFLOW +SLOW_CONTEXT_DEPENDENT +SLOW_UNCLEAR +SLOW_ADVANCED_CAPABILITY +这些标签不是普通分类标签,而是路由系统的 能力边界定义。 +评测集构建的核心目标也不是简单判断 fast / slow,而是判断: +这个请求为什么复杂? +complexity reason 是什么? +例如: +导航到附近停车场 +→ FAST_DIRECT + +导航到附近最大的停车场 +→ SLOW_FILTER_RANK +真正困难的不是打标签本身,而是持续维护这些边界: +- 哪些请求快系统可以稳定承接? +- 哪些请求必须交给慢系统? +- 哪些 case 是边界混淆? +- 哪些标签定义不清? +- 哪些线上 badcase 暴露了新的边界问题? +- 哪些模型错误值得转成训练集 / 评测集? +2. 数据迭代Agent架构 +建设一个面向快慢路由系统的数据开发 Agent 环境:Router Data Agent Workbench +它的目标是: +让 Agent 能够围绕一个需求 / badcase,自主理解问题、探索数据、发现边界冲突、提出人工裁决问题、生成评测集候选、沉淀长期经验,从而显著提升路由评测 / 训练数据构建效率。 +目标不是做一个固定流程平台,而是做一个 Agent-native 的数据开发工作台。 + +--- +2.1 Agent定位 +- 不做传统 workflow+LLM节点提效 +[图片] +2.1.1 不做传统 workflow +不采用这种模式: +需求理解节点 +→ 边界分析节点 +→ 样本挖掘节点 +→ 预打标节点 +→ 人工审核节点 +→ 评测集生成节点 +这种方式的问题是: +- 还是人预先设计流程 +- LLM 只是填充节点 +- Agent 没有真正自主决策 +- 新问题仍然需要人调整流程 / prompt +- 长期价值有限 +这不是 AI 原生,而是旧流程自动化。 + +--- +2.1.2 做 Agent-native workbench +目标模式是: +给 Agent 一个目标、工作区、资料、工具、经验、权限和评价标准; +Agent 自己决定下一步做什么; +系统负责提供环境、边界、记录、校验和人工裁决入口。 +核心区别: +传统 Workflow +Agent-native Workbench +人提前画流程 +Agent 根据任务自主推进 +LLM 填节点 +Agent 自己选择资料、工具和行动 +prompt 是核心 +workspace / skills / memory / tools 是核心 +人负责执行大量步骤 +人只负责关键业务裁决 +每次任务从头开始 +经验持续沉淀,下一次复用 +输出一个结果 +输出结果 + 过程 + 经验 + 可复用资产 + +--- +2.2 系统定位 +Router Data Agent Workbench 应该承担以下职责: +输入: +- 需求文档 +- badcase +- 线上 session +- 当前标签定义 +- 历史评测集 +- 模型预测结果 +- 人工裁决记录 + +输出: +- 边界分析 +- open questions +- 人工裁决问题 +- 候选样本池 +- 标注任务 +- 专项评测集候选 +- 训练集候选 +- 回放评估报告 +- 标签定义修订建议 +- 可复用经验 +它不是一个“评测集生成器”,而是一个 路由数据开发 Agent 工作环境。 + +--- +2.3 核心架构 +Router Data Agent Workbench 由 6 个核心要素组成: + - Workspace:任务工作区 + - Skills:领域经验包 + - Tools:可执行工具 + - Memory:Agent 外部认知状态 + - Policy:权限与人工裁决边界 +[图片] + +--- +2.4 Workspace:任务工作区 +每个需求 / badcase 启动后,系统创建一个独立 workspace。 +示例结构: +[图片] +Workspace 的作用: +- 承载任务上下文 +- 记录 Agent 中间理解 +- 保存探索过程 +- 支持人机协作 +- 沉淀可复用经验 +- 保证过程可追溯 +Agent 不是在一个固定流程里跑,而是在 workspace 中像研究员一样工作。 + +--- +2.5 MD First:以 Markdown 作为 Agent 工作语言 +[图片] +Agent 工作过程优先使用 Markdown +适合用 Markdown 的内容: +需求理解 +边界分析 +open questions +人工裁决记录 +挖掘策略 +失败尝试 +经验总结 +效果报告 +标签定义说明 +原因: +- MD 更适合人读 +- MD 更适合 Agent 自然读写 +- MD 更适合沉淀讨论和判断过程 +- MD 更接近真实工作台,而不是状态机 +但不是完全不要结构化。 +原则是: +MD 是 Agent 的工作语言; +JSONL / CSV / DB 是数据资产的交换格式。 +也就是: +内容 +推荐格式 +需求理解 +MD +边界分析 +MD +人工裁决 +MD +经验沉淀 +MD +候选样本池 +CSV / JSONL +评测集 +JSONL +训练集 +JSONL +回放结果 +表格 + MD 报告 +工具调用参数 +schema / JSON +最终原则: +Agent 工作过程 MD first; +系统边界 schema when needed。 + +--- +2.6 Skills:领域经验包,而不是流程节点 +[图片] +Skills 不应该被设计成固定节点。 +错误理解: +Skill 1:需求理解 +Skill 2:边界分析 +Skill 3:数据挖掘 +Skill 4:预打标 +Skill 5:评测生成 +这还是 workflow。 +正确理解: +Skill 是 Agent 可发现、可按需加载、可组合的领域经验包。 +示例: +/skills/ + router-label-boundary/ + SKILL.md + examples.md + known-confusions.md + decision-principles.md + + online-session-mining/ + SKILL.md + query-patterns.md + sampling-strategies.md + badcase-mining.md + + eval-set-construction/ + SKILL.md + golden-set-rules.md + boundary-set-rules.md + anti-patterns.md + + active-learning-router/ + SKILL.md + disagreement-mining.md + hard-negative-mining.md + recall-gap-analysis.md +Agent 在运行中根据问题自主选择是否读取某个 skill。 +例如: +发现 FAST_DIRECT 和 SLOW_FILTER_RANK 边界不清 +→ 读取 router-label-boundary skill + +需要从线上 session 挖相关样本 +→ 读取 online-session-mining skill + +发现模型离线准确率高但线上效果差 +→ 读取 active-learning-router skill +Skill 的价值不是定义流程,而是沉淀经验。 + +--- +2.7 Resources:可检索资料 +Resources 是 Agent 可读取的业务上下文。 +包括: +当前标签定义 +历史标签定义版本 +历史 badcase +历史人工裁决 +已有评测集 +已有训练集 +线上 session 索引 +topquery 集合 +模型预测结果 +模型误判样本 +历史回放报告 +Agent 不应该一次性把所有资料塞进上下文。 +更合理的方式是: +Agent 先读任务目标 +→ 判断需要什么资料 +→ 按需检索相关资源 +→ 只把当前需要的内容纳入上下文 +这样可以避免上下文污染,也能让 Agent 更像真实研究员一样探索。 + +--- +2.8 Tools:可执行能力 +Tools 是 Agent 可以调用的实际能力。 +示例: +search_online_sessions() +sample_top_queries() +find_similar_cases() +mine_by_pattern() +mine_by_embedding() +mine_by_model_disagreement() +cluster_and_dedup() +run_router_eval() +run_online_replay() +create_annotation_queue() +read_human_review_result() +train_router_model() +compare_model_versions() +Agent 不应该直接写复杂 SQL 或手工操作数据表。 +系统应该提供稳定、可控、可审计的工具接口。 +Agent 自己决定: +什么时候查线上 session +什么时候找历史裁决 +什么时候跑模型分歧 +什么时候构造混淆样本 +什么时候创建标注任务 +什么时候请求人工裁决 + +--- +2.9 Memory:Agent 外部认知状态 +Memory 不是简单存几个结构化字段。 +错误理解: +{ + "status": "running", + "target_label": "SLOW_FILTER_RANK" +} +正确理解: +Memory 是 Agent 为了完成长期任务而主动维护的外部认知状态。 +建议形式: +memory/current_understanding.md +memory/open_questions.md +memory/human_decisions.md +memory/failed_attempts.md +memory/reusable_lessons.md +其中: +current_understanding.md +记录 Agent 当前对任务的理解。 +open_questions.md +记录尚未解决的边界问题。 +human_decisions.md +记录人工裁决及其理由。 +failed_attempts.md +记录无效挖掘策略,避免重复踩坑。 +reusable_lessons.md +记录可复用经验,供后续任务调用。 +长期看,系统要沉淀: +哪些标签容易混淆 +哪些边界已有裁决 +哪些挖掘策略有效 +哪些关键词误伤高 +哪些样本适合评测集 +哪些样本只适合训练集 +哪些模型错误模式反复出现 +判断系统是否真正 Agent-native 的关键标准之一: +下一次遇到类似问题,Agent 是否明显更聪明。 + +--- +2.10 Policy:权限与人工裁决边界 +[图片] +Agent 可以自主推进任务,但不能无限自由。 +需要明确哪些事情 Agent 可以自动做,哪些必须人类确认。 +暂时无法在小米办公Pro文档外展示此内容 +核心原则: +Agent 负责探索和建议; +人负责业务边界裁决。 + +--- +3. 人的角色 +人不再是流程执行者。 +人不应该做: +手写 prompt +手动拼关键词 +手动捞数据 +手动合并 Excel +大量刷 easy case +手动维护所有边界记忆 +人应该做: +裁决业务边界 +确认标签定义变更 +审核 golden set 入库 +处理高分歧样本 +处理高流量低置信样本 +确认模型回放结论 +一句话: +人是边界裁判,不是数据流水线工人。 + +--- +4. Agent 应该如何向人提问 +Agent 不应该问: +下一步怎么办? +而应该提出可裁决问题。 +示例: +边界裁决问题: + +“导航到最近的停车场”应该标为 FAST_DIRECT 还是 SLOW_FILTER_RANK? + +候选判断: + +A. FAST_DIRECT +理由:最近可以视为导航系统默认距离排序,快系统可以直接执行。 + +B. SLOW_FILTER_RANK +理由:最近也是排序条件,请求涉及候选集合选择。 + +Agent 建议:A + +原因: +当前快系统导航 POI 默认支持距离优先,因此“最近的停车场”不应等同于“最大的停车场 / 评分最高的停车场”这类优化筛选请求。 + +请确认: +1. 接受 A +2. 改为 B +3. 补充新的边界规则 +人工裁决后,Agent 写入: +memory/human_decisions.md +长期标签边界知识库 +相关 skill 的 known-confusions.md +以后类似问题直接复用。 + +--- +5. 典型运行方式 +[图片] + +用户输入: +一批 badcase + 需求说明 + 当前标签定义 +Agent 启动任务 workspace。 +然后 Agent 自主推进: +1. 读取需求和 badcase +2. 写 goal.md +3. 写 current_understanding.md +4. 检索相关标签定义 +5. 检索历史类似裁决 +6. 判断当前问题涉及哪些边界 +7. 自主选择数据挖掘策略 +8. 查询线上 session / topquery / 模型误判样本 +9. 聚类、去重、找代表样本 +10. 发现标签冲突或定义不清 +11. 生成 open_questions.md +12. 向人提出高价值裁决问题 +13. 根据裁决继续挖掘和修正 +14. 生成候选评测集 +15. 生成回放报告 +16. 沉淀 reusable_lessons.md +注意:这不是预设流程,而是一个典型任务可能自然形成的行动轨迹。 + +--- +6. 关键产物 +第一版系统建议产出以下文件: +goal.md +current_understanding.md +boundary_analysis.md +open_questions.md +human_decisions.md +failed_attempts.md +reusable_lessons.md +candidate_pool.csv +annotation_queue.csv +eval_set_candidate.jsonl +label_definition_patch.md +replay_report.md +trace.md +skills_used.md +这些产物分为三类: +6.1 Agent / 人类协作产物 +goal.md +current_understanding.md +boundary_analysis.md +open_questions.md +human_decisions.md +reusable_lessons.md +6.2 数据资产产物 +candidate_pool.csv +annotation_queue.csv +eval_set_candidate.jsonl +6.3 审计与复盘产物 +trace.md +skills_used.md +failed_attempts.md +replay_report.md + +--- +7. MVP 建议 +第一版不要做大而全平台。 +先验证一个最小闭环: +输入 badcase,Agent 能否自主探索并产出高质量边界问题和候选评测集。 +MVP 输入 +1. 一批 badcase +2. 当前标签定义 +3. 可查询的线上 session / topquery +4. 现有评测集 +5. 模型预测结果,可选 +MVP 输出 +1. boundary_analysis.md +2. open_questions.md +3. human_decisions.md +4. candidate_pool.csv +5. eval_set_candidate.jsonl +6. replay_report.md +7. reusable_lessons.md +MVP 验收标准 +1. Agent 能自己识别涉及的标签边界 +2. Agent 能自己查找相关历史定义 / 样本 +3. Agent 能自己提出挖掘策略 +4. Agent 能找出一批有效候选样本 +5. Agent 能提出高质量人工裁决问题 +6. 人工裁决后,Agent 能继续修正结果 +7. 最终候选评测集可被人工抽检使用 +8. 本次经验能被后续任务复用 + +--- +8. 成功标准 +项目成功不看是否跑通一个固定流程,而看以下能力: +1. Agent 是否能自主理解新需求 / badcase? +2. Agent 是否能主动寻找相关历史定义和裁决? +3. Agent 是否能判断当前问题属于哪些标签边界? +4. Agent 是否能自主决定挖哪些数据? +5. Agent 是否能发现标签定义冲突? +6. Agent 是否能提出高质量人工裁决问题? +7. Agent 是否能生成可用候选评测集? +8. Agent 是否能根据人工裁决修正自己的判断? +9. Agent 是否能沉淀经验? +10. 下一次遇到类似问题,Agent 是否明显更聪明? +最重要的是第 10 点。 +如果每次任务都像第一次一样重新开始,那就不是经验驱动。 + +--- +9. 最终结论 +[图片] +本项目不应该定义为: +用 Agent 编排快慢系统评测集构建流程 +而应该定义为: +给路由数据开发建设一个 Agent-native 工作环境。 +最终形态是: +Router Data Agent Workbench +它的核心不是流程,而是: +Workspace +Skills +Resources +Tools +Memory +Policy +它要实现的能力是: +需求 / badcase +→ Agent 自主探索 +→ 发现边界问题 +→ 挖掘候选数据 +→ 提出人工裁决 +→ 生成评测 / 训练资产 +→ 回放验证 +→ 沉淀经验 +→ 下次复用 +一句话总结: +不是让 AI 跑数据流程,而是让 Agent 拥有一个可以自主完成数据开发工作的环境。 + + + diff --git a/r.txt b/r.txt new file mode 100644 index 0000000..ab1388e --- /dev/null +++ b/r.txt @@ -0,0 +1,15 @@ +annotated-doc==0.0.4 +annotated-types==0.7.0 +anyio==4.13.0 +-e git+https://github.com/HarnessLab/claw-code-agent.git@30de15b6d52dd4942924e92f3fffdee0063cc9d4#egg=claw_code_agent +click==8.3.2 +exceptiongroup==1.3.1 +fastapi==0.136.0 +h11==0.16.0 +idna==3.12 +pydantic==2.13.3 +pydantic_core==2.46.3 +starlette==1.0.0 +typing-inspection==0.4.2 +typing_extensions==4.15.0 +uvicorn==0.45.0