Appearance
AI 工具对比分析
最近搞了一堆代码工具,不过我发现虽然都能实现AI编程,但是实现效果天差地别。大部分都是npm+开源。正好claude code最近泄露了一版,各个工具都算是开源了
我目前基本上就是在opencode及codex之间来回切,opencode主打基本预制好+兼容好,可以从web远程访问充当高级opencwebui、codex主打一个简单+自带GPT5.4轻便。然后偶尔用pi这种限制少的做测试。但是需要共享一大堆的配置文件,所以需要研究一下各自机制的不同看看如何共享
openclaw和herems主打一个配置复杂的一笔又麻烦,真的是神人了。而且目前需要大量汇总上下文的工作AI还是不行,注意力超级涣散
AI辅助部分:仅通过OPENCODE委派代理分析项目源码实现及制表,AI干这种脏活真的是有一手的
cli安装方式
bash
# js一把梭
npm install -g pm2 @anthropic-ai/claude-code @openai/codex opencode-ai @mariozechner/pi-coding-agent openclaw@latest
# claudecode 也要bash安装了,何意味
# hermes是一个异类,他是python的
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash特色
- claude code:Anthropic的官方vibe工具,最引领潮流的标准的最强工具。更新最频繁也是最黑盒(A/肆意妄为)的一个工具
- codex:openai的开源vibe工具,但是似乎不温不火,最大的优势就是适配了那个神人的官方有状态response
- opencode:算是开源届的标准,支持web界面,能力我会结合准官方插件omo插件进行的分析
- pi-mono:超级极简的框架,也是openclaw的底层框架。不支持mcp,就四个工具
- openclaw:最混沌(全球第一火热、灾难性的屎山)的工具,主打yolo+社交
- hermes agent:算是openclaw的优化版本,新星
内置插件情况
- 工具标准:工具调用、MCP、SKILL。基本都支持工具调用、MCP和Skill。内置工具基本都实现了websearch
- AGENTS.md标准:参考https://agents.md
- sub-agent标准:支持通过agents-name/AGENT.md来定义子智能体
| 对比项 | claude | codex | opencode | pi-mono | openclaw | hermes |
|---|---|---|---|---|---|---|
| 工具标准 | √ | √ | √ | X 不支持mcp | √ | √ |
| AGENTS.md标准 | CLAUDE.md | √ | √ | √ | O 兼容+自定义补充 | X 自定义yaml |
| sub-agent标准 | √ | X 自定义toml | √ | √ | O 兼容+自定义补充 | X 自定义yaml |
| web ui | √ | √ | √ | |||
| 远程控制 | app | web | IM | IM | ||
| 定时任务 | √ | √ | √ | |||
| 跨会话记忆 | 分层+自动整理 | 实验性 | 分层+自动整理 | 分层+自动整理 | ||
| 权限 | 可调可记忆 | 可调可记忆 | 可调可记忆 | YOLO | YOLO+可调 | 未知 |
| 上下文管理 | 自动裁剪+手动触发 | 自动触发+手动 | 手动 | 手动 | 自动管理 | 自动管理 |
AGENTS.md
AGENTS.md(Claude Code 为 CLAUDE.md)是各工具实现项目级指令注入的核心机制,但在发现策略、注入位置和继承规则上存在显著差异。
加载路径
| 工具 | 发现机制 | 文件名优先级 | 全局配置路径 |
|---|---|---|---|
| claude code | 向上遍历到 root,从 root→cwd 拼接 | CLAUDE.md > .claude/CLAUDE.md > .claude/rules/*.md > CLAUDE.local.md | /etc/claude-code → ~/.claude |
| codex | project_root_markers(.git) → 向上遍历 → 向下拼接 | AGENTS.override.md > AGENTS.md > fallback_filenames | ~/.codex/AGENTS.override.md → ~/.codex/AGENTS.md |
| opencode | findUp 向上搜索,First Match Wins | AGENTS.md > CLAUDE.md > CONTEXT.md(deprecated) | ~/.config/opencode → ~/.claude |
| pi-mono | 向上遍历祖先目录,unshift 保证顺序 | AGENTS.md > CLAUDE.md | ~/.pi/agent |
| openclaw | Workspace 目录集中管理 | AGENTS.md + SOUL.md + TOOLS.md + IDENTITY.md + ... (多文件并行) | ~/.openclaw/workspace |
| hermes | cwd 顶层单文件,无祖先遍历 | AGENTS.md > agents.md + .hermes.md(walk) | Profile 隔离: HERMES_HOME |
关键差异:Claude Code、Codex、pi-mono 采用"全部拼接"策略,祖先目录文件均被加载;OpenCode 采用"First Match Wins",找到第一个匹配文件即停止;openclaw 采用 Workspace 集中目录管理而非目录遍历;hermes 仅检查 cwd 顶层,不递归祖先目录。
提示词注入位置和模板
Claude Code 选择注入 User Message作为用第一条用户信息, 其余工具注入 System Prompt作为系统约束。(当然这也和anthropic的接口的system只有一条且只能是最顶上有关)
有趣的点是,除了A/,各家都使用的是md风格的hash tag而不是XML,我一直是倾向于XML的
| 工具 | 注入位置 | 格式包装 |
|---|---|---|
| claude code | User Context → prependUserContext (第一条 user message) | <system-reminder>\n# claudeMd\n{content}\n</system-reminder> |
| codex | ResponseItem::Message (user role) | # AGENTS.md instructions for {dir}\n<INSTRUCTIONS>\n{content}\n</INSTRUCTIONS> |
| opencode | System Prompt 数组元素 | Instructions from: {path}\n{content} |
| pi-mono | System Prompt 末尾 (# Project Context) | ## {path}\n\n{content} |
| openclaw | System Prompt (# Project Context) | ## {path}\n\n{content} (stable/dynamic 分离) |
| hermes | System Prompt Layer 5 (Context Files) | ## {name}\n\n{content} |
继承与覆盖策略
怎么说呢,各有各的idea吧,但是我觉得最有趣的应该就是anthropic的那个只读agent不需要继承写入规则吧,事确实是这么回事,那么语境这些该怎么注入呢?比如本地的文件索引。那就只能是任务的时候描述清楚了在·
| 工具 | 多文件策略 | 子代理继承 | 关键机制 |
|---|---|---|---|
| claude code | 全部拼接 (后加载优先级更高) | 默认省略 | omitClaudeMd: true,Explore/Plan 代理默认不继承 |
| codex | 全部拼接 (root→cwd) + HIERARCHICAL_AGENTS_MESSAGE | 可选继承 | ChildAgentsMd feature + TurnContext 持久化 |
| opencode | First Match Wins + Global 组合 | 动态加载 | Instruction.resolve() + claims Map 去重 |
| pi-mono | 全部拼接 (global → 祖先 → cwd) | 不继承 | 子进程独立加载,AgentScope 控制 agent 发现 |
| openclaw | MINIMAL_BOOTSTRAP_ALLOWLIST 过滤 | 部分继承 | 过滤后注入 AGENTS.md + TOOLS.md + SOUL.md + IDENTITY.md + USER.md |
| hermes | .hermes.md walk,AGENTS.md cwd only | 完全阻断 | skip_context_files=True + skip_memory=True 双重阻断 |
设计动机分析:
- Claude Code 的
omitClaudeMd设计基于效率考量:官方注释指出 "Read-only agents don't need commit/PR/lint guidelines — the main agent has full CLAUDE.md",此举节省约 5-15 Gtok/week - hermes 的完全阻断设计基于上下文隔离原则:
skip_memory=True确保子代理不读取/修改父代理的 MEMORY.md,Memory Provider 通过on_delegation()hook 在父代理层面接收结果 - openclaw 的部分继承保留指令(AGENTS.md)与工具指南(TOOLS.md),排除长期记忆(MEMORY.md)和心跳指令(HEARTBEAT.md),体现"功能性继承而非记忆继承"的设计思路
- OpenCode 的
resolve()动态加载机制在 read 工具执行时触发向上搜索,claims Map防止同一 message 内重复注入
子代理
各工具对子代理上下文传递的处理差异显著,从"完全阻断"到"动态继承"呈现出不同的架构哲学。核心问题在于:子代理是否继承父代理的对话历史?答案是一致的——不继承。
关键共识:所有工具均不传递父代理的对话记录历史。子代理始终以空白对话状态开始,仅接收任务描述和可选的指令文件。这一设计基于"上下文隔离"原则:避免父代理的大量对话历史"污染"子代理,同时节省 token 消耗。
这点上我其实挺担心的,只能说相信相信的力量了
对话记录传递机制
| 工具 | 子代理创建方式 | 父代理对话记录 | 传递的上下文内容 | 传递机制 |
|---|---|---|---|---|
| claude code | 同 Session 内调用 | ❌ 不传递 | 仅 currentDate + 任务描述 + agentDefinition.systemPrompt | 独立 messages 数组 |
| codex | TurnContext 继承 | ❌ 不传递 | user_instructions + 任务描述 + 层级提示 | TurnContext.user_instructions |
| opencode | 新 Session 创建 | ❌ 不传递 | system() 指令 + 任务 prompt | 新 sessionID,独立 messages |
| pi-mono | 子进程 spawn | ❌ 不传递 | 仅 agent.systemPrompt + 任务描述 | 独立进程,无上下文共享 |
| openclaw | Gateway + 新 Session | ❌ 不传递 | MINIMAL_BOOTSTRAP + 任务 system prompt | subagentSessionKey,独立 session |
| hermes | AIAgent 新实例 | ❌ 不传递 | 仅 ephemeral_system_prompt 任务描述 | skip_context_files=True |
继承内容对比
| 工具 | 继承策略 | 继承的文件/内容 | 被排除的内容 |
|---|---|---|---|
| claude code | 默认省略 | currentDate + agent.systemPrompt | 全部 CLAUDE.md 内容 |
| codex | 可选继承 | user_instructions + 层级提示 | 需启用 ChildAgentsMd feature |
| opencode | 动态加载 | system() 返回的 instructions + resolve() 加载邻近文件 | claims Map 控制去重 |
| pi-mono | 不继承 | agent.systemPrompt (via --append-system-prompt) | 全部上下文,子进程独立 |
| openclaw | 部分继承 | AGENTS.md, TOOLS.md, SOUL.md, IDENTITY.md, USER.md | MEMORY.md, HEARTBEAT.md, BOOTSTRAP.md |
| hermes | 完全阻断 | 无 | AGENTS.md + MEMORY.md + 外部 MemoryProvider |
设计模式分类
默认省略型(Claude Code):子代理上下文最小化,父代理负责解读子代理输出。适用于只读代理(Explore、Plan)场景。官方注释:节省约 5-15 Gtok/week。
可选继承型(Codex):通过 feature flag 控制是否继承,配合 HIERARCHICAL_AGENTS_MESSAGE 告知模型层级覆盖规则。灵活性高但需显式启用。TurnContext 可持久化用于 session resume/fork。
动态加载型(OpenCode):子代理在运行时通过 resolve() 动态发现邻近指令文件,而非静态继承。claims Map 机制确保同一消息内不重复注入。子代理获得独立的 sessionID。
完全阻断型(hermes):skip_context_files=True 阻断 AGENTS.md,skip_memory=True 阻断 MEMORY.md 和外部 MemoryProvider。子代理完全独立上下文,父代理通过 on_delegation() hook 接收结果。
子进程隔离型(pi-mono):通过 spawn 独立进程运行子代理,--no-session 禁用历史持久化。AgentScope 控制 agent 配置文件发现范围,而非 AGENTS.md 继承。
结果传递机制
子代理执行完成后,结果如何传递回父代理?
| 工具 | 结果传递方式 | 父代理处理机制 |
|---|---|---|
| claude code | 子代理 yield Message 对象 | 父代理通过 generator 接收并处理 |
| codex | TurnContext 持久化 | 父代理从 TurnContextItem 读取 |
| opencode | Task 工具返回 output 字符串 | 父代理解析 <task_result> 内容 |
| pi-mono | stdout 捕获 | 父进程解析 JSON 输出 |
| openclaw | Gateway response + spawnedBy lineage | 父代理通过 sessionDB 查询 lineage |
| hermes | MemoryProvider.on_delegation() hook | 父代理的 Memory Provider 接收结果 |
hermes 的 on_delegation() hook 设计独特:子代理结果不直接返回,而是通过父代理的 MemoryProvider 处理,可能写入 MEMORY.md 或触发外部 provider 更新。
MCP
由于MCP是一个比较复杂的工具,动态的将远程的服务转成本地的工具调用,替代原本的写到本地的函数插件。由于标准明确所以问题不算大
其实最重要的点是各家命名规则不一样,主打一个什么都有,千奇百怪。skill里是没法写死具体的函数名的,所以skill里必须做通用兼容性的考虑。
- 变量模板:采用bash规则的变量命名方式展示
- servername: mcp服务器的名字
- func: 具体函数名
| 工具 | 命名 | 说明 |
|---|---|---|
| claude code | mcp__${servername}__${func} | 双下划线分隔,servername 和 func 都经过 normalizeNameForMCP 处理 |
| codex | mcp__${servername}__${func} | 双下划线分隔,带 SHA1 hash 后缀防冲突,最大 64 字符 |
| opencode | ${servername}_${func} | 单下划线分隔,sanitize 处理([^a-zA-Z0-9_-] → _) |
| pi-mono | ${func} | 不支持mcp |
| openclaw | ${servername}__${func} | 双下划线分隔,sanitizeToolFragment 处理([^A-Za-z0-9_-] → -),最大 64 字符 |
| hermes | mcp_${servername}_${func} | 单下划线前缀,sanitize_mcp_name_component([^A-Za-z0-9_] → _) |
skill
虽然说配置格式就是YAML frontmatter且有标准的文档,必须字段就name和desc,但是实际上各家的配置不同,有很多神秘细节机制在里头。可以说基本上没有任何的通用设置,需要的时候补一下得了,关心这个不如关心正文
以opencode为基础模板,最多配置个model就行,tool这些也是以claude为主,其他的吃剩饭
具体的可以看 ai整理的各家frontmatter区别
一、AgentSkills.io 通用标准
所有工具都遵循的基础字段:
yaml
---
name: skill-name # 必需: 1-64字符,小写+数字+连字符
description: Description # 必需: 1-1024字符,用途+触发时机
license: MIT # 可选: SPDX许可证
compatibility: Requires... # 可选: 环境要求(max 500字符)
metadata: # 可选: 扩展元数据对象
---二、各家趋同的定义
该有的都有,但是很多的都没意思。考虑到苦
| 字段 | 趋同情况 | 说明 |
|---|---|---|
disable-model-invocation | Claude Code, pi-mono, OpenClaw | 阻止模型自动调用 |
allowed-tools / tools | 全部支持(格式不同) | 预授权/控制可用工具 |
model | Claude Code, OpenCode, pi-mono | 指定模型 |
user-invocable | Claude Code, OpenClaw | 控制菜单可见性 |
三、各家不同的定义字段
太多了,懒得说了,简而言之就是爱咋咋地,杂项拉倒
| 工具 | 独有字段 |
|---|---|
| Claude Code | when_to_use, argument-hint, effort, context, agent, hooks, paths, shell |
| OpenAI Codex | agents/openai.yaml 独立文件: interface.*, policy.allow_implicit_invocation, dependencies.tools[] |
| OpenCode | mode, temperature, top_p, permission, variant, color, hidden, steps (注: thinking/reasoningEffort 为 Provider 级参数,非 frontmatter 字段) |
| OpenClaw | metadata.openclaw.* (emoji, skillKey, primaryEnv, homepage, os, always, requires.*, install[]), command-dispatch, command-tool, command-arg-mode |
| pi-mono | 无独有字段(最简设计) |
| Hermes Agent | version, author, platforms, metadata.hermes.* (tags, config[], requires_toolsets, requires_tools, fallback_for_toolsets, fallback_for_tools), required_environment_variables, required_credential_files |
四、同一字段各家格式冲突
4.1 tools / allowed-tools
| 工具 | 格式 | 示例 |
|---|---|---|
| Claude Code | 空格分隔字符串或YAML列表 | allowed-tools: Read Grep Bash(git:*) |
| OpenAI Codex | 不支持 (仅模板文档提及) | — |
| OpenCode | YAML对象 | tools: { write: false, edit: false } |
| pi-mono | 逗号分隔字符串 | tools: bash,read,write,edit |
4.2 metadata 扩展
| 工具 | 扩展方式 | 示例 |
|---|---|---|
| Claude Code | 顶层字段直接扩展 | hooks:, paths: 与 metadata 同级 |
| OpenClaw | metadata.openclaw.* | metadata: { openclaw: { emoji: "🚀" } } |
| Hermes Agent | metadata.hermes.* | metadata: { hermes: { tags: [] } } |
| OpenCode | JSON配置分离 | opencode.json 中配置,非frontmatter |
4.3 requires 依赖声明
| 工具 | 字段路径 | 格式 |
|---|---|---|
| OpenClaw | metadata.openclaw.requires.* | 对象: { bins: [], env: [], config: [] } |
| Hermes Agent | required_environment_variables[] | 数组对象,带prompt/help |
| Hermes Agent | metadata.hermes.requires_toolsets | 简单数组 |
4.4 平台限制
| 工具 | 字段 | 值 |
|---|---|---|
| OpenClaw | metadata.openclaw.os | ["darwin", "linux", "win32"] |
| Hermes Agent | platforms | ["macos", "linux", "windows"] |
| Claude Code | shell | "bash" / "powershell"(间接平台控制) |
4.5 模型指定
| 工具 | 字段 | 格式 |
|---|---|---|
| Claude Code | model | 别名: best/sonnet/opus/haiku 或完整名 |
| OpenCode | model | provider/model-id: anthropic/claude-opus-4-7 |
| pi-mono | model | 完整模型ID: claude-sonnet-4-20250514 |
4.6 推理/变体控制
| 工具 | 字段 | 值范围 | 说明 |
|---|---|---|---|
| Claude Code | effort | low/medium/high/xhigh/max | frontmatter 字段 |
| OpenCode | variant | max/high/medium/low/xhigh | frontmatter 字段 |
| OpenCode | reasoningEffort | none/minimal/low/medium/high/xhigh | Provider 级参数,非 frontmatter |
五、关键冲突总结
| 冲突点 | 影响 | 建议 |
|---|---|---|
tools格式不一致 | 跨工具skill需要多套配置 | 使用metadata分别声明 |
requires路径不同 | 依赖检查逻辑不兼容 | 在metadata中同时声明两套 |
| 平台值命名差异 | darwin vs macos, win32 vs windows | 同时列出所有变体 |
metadata扩展方式 | 有的平铺、有的嵌套 | 优先使用嵌套格式避免冲突 |
插件自动管理机制
懒得喷了,基本上都是ts类型的插件了,自动update
记忆机制
先不写了,太复杂了。总之基本上都是以文件位置,写入本地文件,并且异步进行整理。有一些使用是sqlite+向量插件做RAG
附录:关键代码证据
本节汇总各工具处理 AGENTS.md 和子代理上下文传递的核心代码片段,供技术验证参考。
各工具关键实现代码路径
AGENTS.md
claude-code
- 加载路径:
/project/source/claude-code-leak/src/utils/claudemd.ts(getMemoryFiles 函数) - 提示词注入:
/project/source/claude-code-leak/src/utils/api.ts(prependUserContext 函数) - 子代理继承:
/project/source/claude-code-leak/src/tools/AgentTool/runAgent.ts(shouldOmitClaudeMd 逻辑)
- 加载路径:
codex
- 加载路径:
/project/source/codex/codex-rs/core/src/agents_md.rs(read_agents_md 函数) - 提示词注入:
/project/source/codex/codex-rs/instructions/src/user_instructions.rs(serialize_to_text) - 子代理继承:
/project/source/codex/codex-rs/core/hierarchical_agents_message.md(ChildAgentsMd feature)
- 加载路径:
opencode
- 加载路径:
/project/source/opencode/packages/opencode/src/session/instruction.ts(systemPaths, system 函数) - 提示词注入:
/project/source/opencode/packages/opencode/src/session/prompt.ts(instruction.system() 调用) - 子代理继承:
/project/source/opencode/packages/opencode/src/session/instruction.ts(resolve 函数)
- 加载路径:
pi-mono
- 加载路径:
/project/source/pi-mono/packages/coding-agent/src/core/resource-loader.ts(loadProjectContextFiles) - 提示词注入:
/project/source/pi-mono/packages/coding-agent/src/core/system-prompt.ts(buildSystemPrompt) - 子代理继承:
/project/source/pi-mono/packages/coding-agent/examples/extensions/subagent/agents.ts(discoverAgents)
- 加载路径:
openclaw
- 加载路径:
/project/source/openclaw/src/agents/workspace.ts(loadWorkspaceBootstrapFiles) - 提示词注入:
/project/source/openclaw/src/agents/system-prompt.ts(buildSystemPrompt) - 子代理继承:
/project/source/openclaw/src/agents/workspace.ts(filterBootstrapFilesForSession)
- 加载路径:
hermes
- 加载路径:
/project/source/hermes-agent/agent/prompt_builder.py(_load_agents_md 函数) - 提示词注入:
/project/source/hermes-agent/run_agent.py(_build_system_prompt 方法) - 子代理继承:
/project/source/hermes-agent/tools/delegate_tool.py(skip_context_files, skip_memory 参数)
- 加载路径:
MCP 命名
claude-code
- 命名规则:
mcp__${servername}__${func} - 实现:
/project/source/claude-code-leak/src/services/mcp/mcpStringUtils.ts(buildMcpToolName, mcpInfoFromString) - 标准化:
/project/source/claude-code-leak/src/services/mcp/normalization.ts(normalizeNameForMCP)
- 命名规则:
codex
- 命名规则:
mcp__${servername}__${func}(带 SHA1 hash 后缀) - 实现:
/project/source/codex/codex-rs/codex-mcp/src/mcp/mod.rs(qualified_mcp_tool_name_prefix) - 工具名生成:
/project/source/codex/codex-rs/codex-mcp/src/mcp_tool_names.rs(qualify_tools)
- 命名规则:
opencode
- 命名规则:
${servername}_${func} - 实现:
/project/source/opencode/packages/opencode/src/mcp/index.ts(sanitize 函数, tools 函数)
- 命名规则:
pi-mono
- 未找到 MCP 实现
openclaw
- 命名规则:
${servername}__${func} - 实现:
/project/source/openclaw/src/agents/pi-bundle-mcp-names.ts(buildSafeToolName, sanitizeToolName)
- 命名规则:
hermes
- 命名规则:
mcp_${servername}_${func} - 实现:
/project/source/hermes-agent/tools/mcp_tool.py(sanitize_mcp_name_component, _convert_mcp_schema)
- 命名规则:
Sub-Agent
claude-code
- 省略逻辑:
/project/source/claude-code-leak/src/tools/AgentTool/runAgent.ts(shouldOmitClaudeMd) - Agent 定义:
/project/source/claude-code-leak/src/tools/AgentTool/loadAgentsDir.ts(omitClaudeMd 字段) - Explore/Plan 代理:
/project/source/claude-code-leak/src/tools/AgentTool/built-in/exploreAgent.ts
- 省略逻辑:
codex
- Feature 定义:
/project/source/codex/codex-rs/features/src/lib.rs(ChildAgentsMd) - 层级消息:
/project/source/codex/codex-rs/core/hierarchical_agents_message.md - TurnContext:
/project/source/codex/codex-rs/core/src/session/turn_context.rs
- Feature 定义:
opencode
- 动态加载:
/project/source/opencode/packages/opencode/src/session/instruction.ts(resolve 函数) - Claims 去重:
/project/source/opencode/packages/opencode/src/session/instruction.ts(claims Map) - Task 工具:
/project/source/opencode/packages/opencode/src/tool/task.ts
- 动态加载:
pi-mono
- Subagent 实现:
/project/source/pi-mono/packages/coding-agent/examples/extensions/subagent/index.ts - Agent 发现:
/project/source/pi-mono/packages/coding-agent/examples/extensions/subagent/agents.ts - RPC 文档:
/project/source/pi-mono/packages/coding-agent/docs/rpc.md
- Subagent 实现:
openclaw
- Session key:
/project/source/openclaw/src/sessions/session-key-utils.ts(isSubagentSessionKey) - 文件过滤:
/project/source/openclaw/src/agents/workspace.ts(filterBootstrapFilesForSession) - Spawn 实现:
/project/source/openclaw/src/agents/subagent-spawn.ts
- Session key:
hermes
- 委托工具:
/project/source/hermes-agent/tools/delegate_tool.py(AIAgent 创建参数) - 上下文隔离:
/project/source/hermes-agent/tools/delegate_tool.py(skip_context_files, skip_memory) - Memory Provider:
/project/source/hermes-agent/agent/memory_provider.py(on_delegation hook)
- 委托工具:
Claude Code
- Skill 定义:
/project/source/claude-code-leak/src/skills/Skill.ts(Skill 接口, frontmatter 解析) - Hooks 定义:
/project/source/claude-code-leak/src/hooks/hooks.ts(hooks 字段) - Agent 工具:
/project/source/claude-code-leak/src/tools/AgentTool/runAgent.ts(context, agent 字段) - Agent 加载:
/project/source/claude-code-leak/src/tools/AgentTool/loadAgentsDir.ts(agent 定义) - Frontmatter 解析:
/project/source/claude-code-leak/src/skills/parseSkill.ts
OpenAI Codex
- AGENTS.md 解析:
/project/source/codex/codex-rs/core/src/agents_md.rs(frontmatter 提取) - Skill 验证:
/project/source/codex/codex-rs/core/src/skills/quick_validate.py(字段校验) - ChildAgentsMd Feature:
/project/source/codex/codex-rs/features/src/lib.rs(子代理配置) - TurnContext:
/project/source/codex/codex-rs/core/src/session/turn_context.rs(持久化)
OpenCode
- Skill 定义:
/project/source/opencode/packages/opencode/src/skill/index.ts(Skill 接口) - Agent 覆盖:
/project/source/opencode/packages/opencode/src/config/schema/agent-overrides.ts(Agent frontmatter) - 指令解析:
/project/source/opencode/packages/opencode/src/session/instruction.ts(动态加载) - Task 工具:
/project/source/opencode/packages/opencode/src/tool/task.ts(子代理配置)
OpenClaw
- Skill 类型:
/project/source/openclaw/src/agents/skills/types.ts(SkillFrontmatter 接口) - Metadata 扩展:
/project/source/openclaw/src/agents/skills/types.ts(OpenClawSkillMetadata) - Frontmatter 解析:
/project/source/openclaw/src/shared/frontmatter.ts(YAML 解析) - Skill 发现:
/project/source/openclaw/src/agents/skills/discovery.ts(加载逻辑) - Workspace 过滤:
/project/source/openclaw/src/agents/workspace.ts(bootstrap 文件过滤) - 子代理生成:
/project/source/openclaw/src/agents/subagent-spawn.ts(session key)
pi-mono
- Skill 定义:
/project/source/pi-mono/packages/coding-agent/src/core/skills.ts(SkillFrontmatter 接口) - Frontmatter 解析:
/project/source/pi-mono/packages/coding-agent/src/utils/frontmatter.ts(通用解析器) - Agent 配置:
/project/source/pi-mono/packages/coding-agent/examples/extensions/subagent/agents.ts(Agent frontmatter) - Prompt Template:
/project/source/pi-mono/packages/coding-agent/src/core/prompt-templates.ts(Template frontmatter) - 子代理实现:
/project/source/pi-mono/packages/coding-agent/examples/extensions/subagent/index.ts(AgentScope)
Hermes Agent
- Skill 加载:
/project/source/hermes-agent/skills/loader.py(SKILL.md 加载) - Skill 定义:
/project/source/hermes-agent/skills/skill.py(Skill 类) - 委托工具:
/project/source/hermes-agent/tools/delegate_tool.py(子代理配置) - Prompt 构建:
/project/source/hermes-agent/prompt_builder.py(AGENTS.md 加载)
A. Claude Code
AGENTS.md 加载路径 (claudemd.ts:850-934):
typescript
// 从 CWD 向上遍历到 root,然后从 root 向下处理
const dirs: string[] = []
let currentDir = originalCwd
while (currentDir !== parse(currentDir).root) {
dirs.push(currentDir)
currentDir = dirname(currentDir)
}
// Process from root downward to CWD (后加载优先级更高)
for (const dir of dirs.reverse()) {
// Try reading CLAUDE.md (Project)
// Try reading .claude/CLAUDE.md (Project)
// Try reading .claude/rules/*.md files (Project)
// Try reading CLAUDE.local.md (Local)
}子代理 omitClaudeMd 机制 (runAgent.ts:380-398):
typescript
// Read-only agents don't act on commit/PR/lint rules from CLAUDE.md
const shouldOmitClaudeMd =
agentDefinition.omitClaudeMd &&
!override?.userContext &&
getFeatureValue_CACHED_MAY_BE_STALE('tengu_slim_subagent_claudemd', true)
const { claudeMd: _omittedClaudeMd, ...userContextNoClaudeMd } = baseUserContext
const resolvedUserContext = shouldOmitClaudeMd
? userContextNoClaudeMd // 仅保留 currentDate
: baseUserContext
// 子代理 messages 独立,不继承父代理对话历史
const messages: Message[] = [
createUserMessage({ content: promptContent, isMeta: false }),
]AgentDefinition.omitClaudeMd 字段 (loadAgentsDir.ts:128-132):
typescript
/** Omit CLAUDE.md hierarchy from the agent's userContext. Read-only agents
* (Explore, Plan) don't need commit/PR/lint guidelines — the main agent has
* full CLAUDE.md and interprets their output. Saves ~5-15 Gtok/week across
* 34M+ Explore spawns. */
omitClaudeMd?: booleanB. OpenAI Codex
AGENTS.md 发现机制 (agents_md.rs:286-342):
rust
// 从 cwd 向上找 project_root (默认 .git)
for ancestor in dir.ancestors() {
for marker in &project_root_markers {
if marker_exists { project_root = Some(ancestor); break; }
}
}
// 从 project_root 到 cwd 拼接所有文件
let search_dirs: Vec<AbsolutePathBuf> = if let Some(root) = project_root {
let mut dirs = Vec::new();
let mut cursor = dir.clone();
loop {
dirs.push(cursor.clone());
if cursor == root { break; }
cursor = cursor.parent();
}
dirs.reverse(); // root → cwd 顺序
dirs
} else { vec![dir] };
// 每个目录只选择一个文件(按优先级)
for d in search_dirs {
for name in &["AGENTS.override.md", "AGENTS.md", ...fallbacks] {
if is_file { found.push(candidate); break; }
}
}ChildAgentsMd Feature (features/src/lib.rs:719-724):
rust
FeatureSpec {
id: Feature::ChildAgentsMd,
key: "child_agents_md",
stage: Stage::UnderDevelopment,
default_enabled: false,
}TurnContext 持久化 (protocol.rs:2922-2925):
rust
pub struct TurnContextItem {
#[serde(skip_serializing_if = "Option::is_none")]
pub user_instructions: Option<String>, // 可持久化用于 resume/fork
}C. OpenCode
FILES 数组与 First Match Wins (instruction.ts:17-21, 125-134):
typescript
const FILES = [
"AGENTS.md",
...(Flag.OPENCODE_DISABLE_CLAUDE_CODE_PROMPT ? [] : ["CLAUDE.md"]),
"CONTEXT.md", // deprecated
]
// The first project-level match wins
for (const file of FILES) {
const matches = yield* fs.findUp(file, ctx.directory, ctx.worktree)
if (matches.length > 0) {
matches.forEach((item) => paths.add(path.resolve(item)))
break // 找到第一个就停止
}
}resolve() 动态加载与 claims Map (instruction.ts:186-228):
typescript
const resolve = Effect.fn("Instruction.resolve")(function* (
messages: MessageV2.WithParts[],
filepath: string,
messageID: MessageID,
) {
const already = extract(messages) // 从历史消息提取已加载路径
const s = yield* InstanceState.get(state)
// claims Map 防止重复加载
let set = s.claims.get(messageID)
if (!set) { set = new Set(); s.claims.set(messageID, set) }
if (set.has(found)) { current = path.dirname(current); continue }
set.add(found)
const content = yield* read(found)
if (content) {
results.push({ filepath: found, content: `Instructions from: ${found}\n${content}` })
}
})D. pi-mono
AGENTS.md 加载流程 (resource-loader.ts:76-113):
typescript
export function loadProjectContextFiles(options): Array<{ path: string; content: string }> {
const resolvedAgentDir = options.agentDir ?? getAgentDir(); // ~/.pi/agent
// 1. 加载全局上下文
const globalContext = loadContextFileFromDir(resolvedAgentDir);
// 2. 从 cwd 向上遍历祖先目录
let currentDir = resolvedCwd;
while (true) {
const contextFile = loadContextFileFromDir(currentDir);
// unshift 保证祖先目录优先级更高
ancestorContextFiles.unshift(contextFile);
if (currentDir === root) break;
currentDir = resolve(currentDir, "..");
}
// 最终顺序:[global, ...祖先(从根到cwd)]
contextFiles.push(...ancestorContextFiles);
return contextFiles;
}子进程 spawn 与 AgentScope (subagent/index.ts:265-299):
typescript
// spawn 独立进程,不继承上下文
const args: string[] = ["--mode", "json", "-p", "--no-session"];
// 仅传递 agent.systemPrompt (通过临时文件)
if (agent.systemPrompt.trim()) {
const tmp = await writePromptToTempFile(agent.name, agent.systemPrompt);
args.push("--append-system-prompt", tmp.filePath);
}
const proc = spawn(invocation.command, invocation.args, {
cwd: cwd ?? defaultCwd,
shell: false,
});E. openclaw
MINIMAL_BOOTSTRAP_ALLOWLIST (workspace.ts:565-581):
typescript
const MINIMAL_BOOTSTRAP_ALLOWLIST = new Set([
DEFAULT_AGENTS_FILENAME, // AGENTS.md ✓
DEFAULT_TOOLS_FILENAME, // TOOLS.md ✓
DEFAULT_SOUL_FILENAME, // SOUL.md ✓
DEFAULT_IDENTITY_FILENAME, // IDENTITY.md ✓
DEFAULT_USER_FILENAME, // USER.md ✓
]);
// 排除: MEMORY.md, HEARTBEAT.md, BOOTSTRAP.md ✗
export function filterBootstrapFilesForSession(files, sessionKey): WorkspaceBootstrapFile[] {
// 非 subagent/cron session:注入全部文件
if (!sessionKey || (!isSubagentSessionKey(sessionKey) && !isCronSessionKey(sessionKey))) {
return files;
}
// Subagent/cron session:只注入 allowlist 文件
return files.filter((file) => MINIMAL_BOOTSTRAP_ALLOWLIST.has(file.name));
}子代理 Session Key 生成 (subagent-spawn.ts:495):
typescript
const childSessionKey = `agent:${targetAgentId}:subagent:${crypto.randomUUID()}`;F. hermes-agent
AGENTS.md 单文件加载 (prompt_builder.py:951-964):
python
def _load_agents_md(cwd_path: Path) -> str:
"""AGENTS.md — top-level only (no recursive walk)."""
for name in ["AGENTS.md", "agents.md"]:
candidate = cwd_path / name
if candidate.exists():
result = f"## {name}\n\n{content}"
return _truncate_content(result, "AGENTS.md")
return ""子代理完全阻断 (delegate_tool.py:265-426):
python
child = AIAgent(
...
ephemeral_system_prompt=child_prompt, # 仅任务描述
skip_context_files=True, # 阻断 AGENTS.md
skip_memory=True, # 阻断 MEMORY.md + MemoryProvider
parent_session_id=getattr(parent_agent, 'session_id', None),
)
# Blocked tools 禁止子代理使用
blocked_tools = ["delegate_task", "clarify", "memory", "send_message", "execute_code"]MemoryProvider.on_delegation() hook (memory_provider.py:175-186):
python
def on_delegation(self, task: str, result: str, *,
child_session_id: str = "", **kwargs) -> None:
"""Called on the PARENT agent when a subagent completes.
The parent's memory provider gets the task+result pair as an
observation. The subagent itself has no provider session."""待补充清单
- AGENTS.md:AGENTS.md的生效方式,子代理生效吗? ✓ 已补充
- 内置工具:内置了那些工具,什么等级
- sub agents
- 可配置参数
- 上下文传递方式 ✓ 已补充
- skill:支持那些skill
- mcp:
- 如何管理的
- lifecycle:比如有没有自动整理记忆
- memory
- 如何自动管理