Skill、流式执行优化与系统架构全面升级
本次提交对标 Claude Code 与 Hermes-Agent 的工程细节,在安全、可靠性、
会话管理、自我进化四个维度进行了系统性加固,变更总量 48 文件 / +12680 -2292 行。
═══════ 安全纵深防御 ═══════
1. Hardline 硬阻止层 (src/agent/runtime/hardline.rs, +534 行)
- 不可绕过的危险命令拦截(关重启、磁盘擦除、Fork 炸弹、rm -rf /、kill -1)
- 反规避标准化管线: ANSI 序列剥离 → Unicode NFKC → shell 反斜杠还原 → 空字面量清理
- 在 PermissionChecker 之前执行,YOLO/Bypass 模式下同样生效
- 集成到 executor Phase 2,被拒绝工具直接注入错误结果
2. Permission 优先级裁决器 (src/agent/runtime/permission.rs, +200 行)
- 7 层正式优先级规则 (P0 Deny → P7 Allow),带冲突日志
- explain() 方法支持审计追溯
- Hook PermissionRequired 与 Checker 结果的正确叠加逻辑
═══════ Checkpoint 文件快照系统 ═══════
3. git2 原生快照 (src/agent/runtime/checkpoint.rs, +920 行)
- 基于 git2 bare repo,内容寻址自动去重
- 文件变更操作前自动触发 (file_write/file_edit/run_bash)
- 每目录每 turn 最多一次快照,防止同一轮重复
- 支持 list/diff/restore API + pre-rollback 安全快照
- 旧快照自动 prune(保留最近 N 个)+ 按目录隔离 ref
- 排除规则自动过滤 node_modules/target/.git/*.pdf 等
- 集成到 executor: 文件操作前 ckpt.ensure_checkpoint()
═══════ 错误恢复系统大升级 ═══════
4. 21 种 FailoverReason 分类 (src/agent/runtime/error_recovery.rs, +1200 行)
- 参考 Hermes-Agent error_classifier.py
- 8 步分类管线: provider-specific → HTTP status → text pattern → error body → fallback
- is_retryable / should_compress / should_failover / is_permanent 方法
- Context Overflow 自动修复: 从错误消息提取 token 限制,自动下调预算
- RecoveryStep::AdjustMaxTokens 实现 (参考 Claude Code 自动修复)
- 向后兼容 ErrorKind 别名
═══════ 会话 Rewind / Branch / Retry 体系 ═══════
5. 完整 undo 栈 (src/agent/runtime/session.rs, +800 行 + 2 迁移脚本)
- Rewind (软删除): active=0 标记,审计 trail 保留,LLM 不可见
- Restore (撤销回退): 冲突检测——回退后有新消息则拒绝,引导使用 Branch
- Branch: 分叉会话,复制所有 active=1 消息到新会话
- Retry: 硬删除最后一轮对话,返回原消息文本供前端重提交
- 数据库: agent_messages.active 列 + agent_sessions.rewind_count + parent_session_id
- API: 4 个新端点 (/branch, /retry, /rewind, /rewind/restore)
- load_history_for_agent 全面使用 active=1 过滤
═══════ Hooks 系统模块化重构 ═══════
6. 单文件 → 7 模块体系 (src/agent/hooks/)
hooks.rs (994 行) 拆分为:
- mod.rs — 入口 + HookRegistry + SessionHookManager
- types.rs — 类型定义 (Context, TaggedContext, PermissionRequestAction 等)
- traits.rs — AgentHook + AsyncAgentHook + 15 种生命周期事件
- matcher.rs — 工具名/参数匹配 + session 作用域过滤
- dispatch.rs — 并行调度引擎 (run_pre/post_tool_use 等)
- registry.rs — 注册/注销/查询
- builtins.rs — CancellationHook + MetricsHook + AuditLogHook + ContextDeduplicator
关键改进:
- run_pre_tool_use 并行执行所有匹配 hooks,聚合 Block/MutateInput/Continue
- TaggedContext 带完整来源标记的上下文注入 (hook_name + event)
- ContextDeduplicator 单 dispatch cycle 内内容哈希去重
- AsyncAgentHook 支持 fire-and-forget 异步 hooks
═══════ Executor 并发执行升级 ═══════
7. 三阶段管道重写 (src/agent/runtime/executor.rs, +600 行)
- Phase 1: 死循环检测 + 参数解析 (不变)
- Phase 2: Hardline 预检查 (新增) → PermissionChecker (改进)
- Phase 3: ToolPartitioner 分区 → 逐批次执行 (重写)
- 并行批次内 FuturesUnordered 并发
- 串行批次确保非并发安全工具独占执行
- Checkpoint 预触发集成
- Hook 上下文注入: system-reminder 格式 + ContextDeduplicator 去重
- Hook 阻塞错误详细记录
═══════ 流式执行真正的流式调度 ═══════
8. StreamingExecutor 重写 (src/agent/runtime/streaming_executor.rs, ~400 行变更)
- on_tool_use 中对并发安全工具立即 tokio::spawn,不等待 flush
- executing_non_concurrent 标志阻塞后继工具直到独占工具完成
- JoinHandle 管理替代自定义 cancel channel
- completed_queue 按流顺序 yield
- Sibling Abort 通过 broadcast channel + tokio::select! 竞速
- ToolContext 实现 Clone (支持 per-task 上下文复制)
═══════ 自改进 Skill 系统 ═══════
9. PatternDetector + SkillCreator + Curator (src/agent/skills/, +1500 行)
- PatternDetector: 扫描 agent_messages 表,检测跨 session 重复工具调用模式
- SkillCreator: 将高置信度模式自动生成 SKILL.md (YAML frontmatter + 工作流步骤)
- SelfImprovePipeline: 一站式 模式检测 → 创建 → 质量审查
- Curator: 分析 skill 使用统计,标记 stale/deprecated,建议清理
- Skill frontmatter 新增 pinned 字段 (禁止 Curator 自动清理)
═══════ 基础设施优化 ═══════
10. 系统提示词缓存 (src/agent/runtime/system_prompt.rs + mod.rs)
- SystemPromptCache: 首次计算后永久复用,/clear 时失效
- 新增 SAFETY / SYSTEM_CONTEXT / TOOL_USAGE 静态 section
- 环境/tools/skills/memory 动态 section 通过 get_or_compute 缓存
11. ToolRegistry schema 缓存 (src/agent/tools/mod.rs)
- schema_cache + schema_generation 版本号
- 工具变更/过滤器变更时自动失效
- precompute_definitions() 预计算 (AgentRuntime 初始化时调用)
12. 迭代摘要融合 (src/agent/compact.rs, +100 行)
- 参考 Hermes context_compressor.py
- CollapseLog 追踪压缩历史,支持溢出合并
- extract_prior_summary: 提取已有摘要融入新压缩
13. SubAgent 系统提示词模块化 (src/agent/tools/subagent.rs)
- 复用 5 个标准 section + 子代理专有上下文 section
- 独立 ToolRegistry 构建工具列表
═══════ 前端 — CSS 变量主题系统 ═══════
14. 全新主题变量体系 (dashboard/src/index.css + App.tsx + 各面板)
- CSS 自定义属性: --bg-card, --text-main, --text-muted, --border-precision
- 语义化颜色: --accent-blueprint, --accent-star
- 全面替换硬编码 Tailwind 颜色 (slate-xxx → var(--xxx))
- 文献入库提示优化 ("核心知识节点" 替代 "向量块")
- ReaderPanel 样式变量化
39 KiB
Claude Code / Hermes-Agent 参考分析
对 Claude Code (/home/fmq/program/claudecode/src/) 和 Hermes-Agent (libs/hermes-agent/)
源码的全面架构分析,记录对 AstroResearch Agent 系统的参考价值与改进方向。
分析日期: 2026-06-22 | 最后更新: 2026-06-22
实施状态
| 优先级 | 改进项 | 状态 | 涉及文件 |
|---|---|---|---|
| P0 | Context Overflow 自动修复 | ✅ 已完成 | error_recovery.rs (+150 行) |
| P0 | StreamingExecutor 真正流式调度 | ✅ 已完成 | streaming_executor.rs (重写 ~400 行) |
| P0 | Executor 集成分区器(批次串行/并行) | ✅ 已完成 | executor.rs (Phase 3 重写 + 2 个提取函数) |
| P1 | 工具并发分区 partition_tool_calls |
✅ 已完成 | partitioner.rs (+2 测试) |
| P1 | PermissionRequest / PermissionDenied Hooks | ✅ 已完成 | hooks/types.rs, traits.rs, dispatch.rs, mod.rs |
| P1 | Auto-mode Classifier | ⏳ 待定 | — |
| P2 | Self-improving Skills(模式检测 + 自动创建 + Curator) | ✅ 已完成 | skills/pattern_detector.rs + curator.rs + SkillCreator |
| P2 | Coordinator Mode | ⏳ 待定 | — |
| P2 | UserPromptSubmit / PreCompact / PostCompact Hook | ⏳ 待定 | — |
| P3 | FTS5 跨 session 搜索 | ⏳ 待定 | — |
| P3 | Tool defer_loading / classifier_summary |
⏳ 待定 | — |
| P3 | 模型回退策略 | ⏳ 待定 | — |
| P3 | Session Memory Compaction | ⏳ 待定 | — |
目录
- 总体评估
- 工具并发执行模型
- Permission 系统
- Hooks 系统
- Error Recovery / 重试系统
- Tool 定义系统
- Memory 持久化
- Coordinator / Multi-Agent
- Hermes-Agent 的独特贡献
- 优先级排序 —— 建议实施路线
1. 总体评估
1.1 参考项目概览
| 维度 | Claude Code | Hermes-Agent | AstroResearch |
|---|---|---|---|
| 语言 | TypeScript (Node.js) | Python (3.11+) | Rust (Axum) |
| 定位 | 终端 IDE 编程助手 | 通用 AI 个人助手 | 天文科研 Agent |
| Agent 循环 | 流式 query() generator |
同步 while 循环 |
流式 ReAct 循环 |
| 工具注册 | 手动 import + getAllBaseTools() |
文件系统自动发现 | 手动 ToolRegistry::new() |
| 工具接口 | Tool<T> — ~70 个方法 |
handler(args) -> JSON string |
AgentTool trait — ~10 个方法 |
| 权限系统 | 6 层优先级 + Classifier + 沙箱 | 无内置 | 3 层规则 + PermissionChecker |
| Hooks | 27 种事件,6 种 hook 类型 | PluginManager 生命周期 | 15 种事件,2 种 hook 类型 |
| 子代理 | AgentTool + Fork + Worktree 隔离 |
delegate_task + 子 AIAgent |
SubAgentTool + 独立 ReAct |
| 多 Agent | Coordinator 模式 + Swarm/Team | Kanban 工作队列 | Team 系统 (lead/teammate) |
| 持久化 | 文件系统 Markdown + cost tracker | SQLite (FTS5) + SessionDB | SQLite + MEMORY.md |
| 上下文压缩 | 微压缩 + 自动压缩 + 手动压缩 | ContextCompressor | 4 层压缩 (微/snip/auto/aggro) |
1.2 核心结论
AstroResearch 的 Agent 系统架构本身就是对标 Claude Code 设计的——StreamingToolExecutor、
PermissionChecker、HookRegistry 都明确标注了参考来源。当前差距主要是实现深度而非设计方向。
Claude Code 的参考价值在工程细节:流式调度的时机选择、Overflow 的自动修复、Classifier 的并行化设计。Hermes-Agent 的独特价值在自我进化(Self-improving Skills)和多 Profile 隔离。
2. 工具并发执行模型
2.1 对比
| 特性 | Claude Code | AstroResearch (当前) |
|---|---|---|
| 流式调度 | tool_use 到达立即开始执行 | tool_use 全部收集,flush() 批量执行 |
| 并发分区 | partitionToolCalls() 自动分组连续只读工具并行 |
ToolPartitioner 存在但基本未使用 |
| Sibling Abort | Bash 错误 → 级联取消兄弟工具,有专用 siblingAbortController |
AbortReason::SiblingError + 广播通道存在,取消逻辑不完整 |
| Progress 流式 | pendingProgress 即时 yield,progressAvailableResolve 唤醒等待 |
execute_with_progress 有通道,getCompletedResults 未检查 |
| 中断行为 | interruptBehavior() 区分 cancel vs block |
InterruptBehavior 枚举存在但未在 Executor 中使用 |
2.2 Claude Code 的分区逻辑
// src/services/tools/toolOrchestration.ts
// 自动将连续只读工具分组并行,写工具独立串行
function partitionToolCalls(toolUseMessages, toolUseContext): Batch[] {
return toolUseMessages.reduce((acc, toolUse) => {
const tool = findToolByName(toolUseContext.options.tools, toolUse.name)
const parsedInput = tool?.inputSchema.safeParse(toolUse.input)
const isConcurrencySafe = parsedInput?.success
? (() => { try { return Boolean(tool.isConcurrencySafe(parsedInput.data)) } catch { return false } })()
: false
if (isConcurrencySafe && acc[acc.length - 1]?.isConcurrencySafe) {
acc[acc.length - 1].blocks.push(toolUse) // 合并到当前批次
} else {
acc.push({ isConcurrencySafe, blocks: [toolUse] }) // 新批次
}
return acc
}, [])
}
关键点:
- 输入感知的并发安全判断:同一工具可能因参数不同而安全属性不同
- 并发安全的工具连续分组——不打断写入顺序
- 非并发安全的工具独占执行——等上一个完成后才启动下一个
2.3 Claude Code 的 StreamingToolExecutor 核心逻辑
文件: src/services/tools/StreamingToolExecutor.ts (531 行)
状态机: Queued → Executing → Completed → Yielded
生命周期:
1. addTool(block) — LLM 流产生 tool_use 时立即调用
2. processQueue() — 检查 concurrency 条件,启动可执行工具
3. executeTool(tool) — 创建子 AbortController,调用 runToolUse generator
4. getCompletedResults() — 按序 yield 结果(非阻塞)
5. getRemainingResults() — 等待未完成工具(async generator)
关键设计:
- siblingAbortController: 父 AbortController 的子节点
Bash 错误 → siblingAbortController.abort('sibling_error') → 取消所有兄弟
但 toolAbortController 的 abort 会向上冒泡到父 AbortController
- progressAvailableResolve: Promise resolver 用于唤醒等待 progress 的 getRemainingResults
- 中断行为: 'cancel' 工具被用户中断时生成 REJECT_MESSAGE; 'block' 工具不受影响
2.4 AstroResearch 的现状(2026-06-22 更新)
文件: src/agent/runtime/streaming_executor.rs (~400 行,已重写)
已实现:
✅ TrackedTool 状态机 (Queued/Executing/Completed/Yielded)
✅ Sibling Abort 广播通道(broadcast::channel + tokio::select! 竞速)
✅ on_tool_use / flush / next_result 接口
✅ 输出截断
✅ 真正的流式调度 — on_tool_use 中对并发安全工具立即 spawn tokio task
✅ 非并发安全工具独占执行 — executing_non_concurrent 标志阻塞后续启动
✅ 并发取消 — tokio::select! 在工具执行和 Sibling Abort 之间竞速
✅ 输入感知的并发安全判断 — 通过 tool_registry.get().is_concurrency_safe(&args)
✅ ToolContext 实现 Clone(支持 per-task 复制上下文)
与 Claude Code 的对齐:
- 核心理念一致:addTool → 立即 processQueue
- Sibling Abort 机制等效:broadcast::Sender + subscribe
- collectCompletedTasks 使用 JoinHandle::is_finished() 做非阻塞检查
2.5 已实施改进(2026-06-22)
✅ P0: 真正的流式调度 — 已完成
on_tool_use 中对并发安全工具立即 tokio::spawn,非并发安全工具标记 executing_non_concurrent
并阻塞后续启动,直到独占工具完成。
✅ P0: Executor 集成分区器 — 已完成
src/agent/runtime/executor.rs Phase 3 从「所有非拒绝工具单一 FuturesUnordered 无差别并发」
改为「ToolPartitioner 分区 → 逐批次执行」:
- 并行批次内
FuturesUnordered并发 - 串行批次内逐个执行(非并发安全工具独占)
- 提取
execute_single_tool()和process_single_result()两个辅助函数
✅ P1: 并发分区器 — 已完成
src/agent/runtime/partitioner.rs 新增 2 个测试(run_bash、file_write 打断并发批)。
2.6 原始建议(已过时)
// 建议在 on_tool_use 中对并发安全的工具立即 spawn
pub fn on_tool_use(&mut self, call_id: String, name: String, args: Value) -> bool {
let is_concurrency_safe = /* 判断 */
let idx = self.tracked.len();
self.tracked.push(tool);
if is_concurrency_safe && self.can_execute_now() {
let handle = tokio::spawn(/* 执行 */);
self.tracked[idx].handle = Some(handle);
true
} else {
false
}
}
P1: 并发分区
/// 将 tool_use 列表分区为 (并发安全批次, 非并发安全单例)
fn partition_tool_calls(calls: &[PreparedCall], registry: &ToolRegistry) -> Vec<Batch> {
calls.iter().fold(Vec::new(), |mut acc, call| {
let is_safe = registry.get(&call.tool_name)
.map(|t| t.is_concurrency_safe(&call.args))
.unwrap_or(false);
if is_safe && acc.last().map_or(false, |b: &Batch| b.concurrent) {
acc.last_mut().unwrap().calls.push(call.clone());
} else {
acc.push(Batch { concurrent: is_safe, calls: vec![call.clone()] });
}
acc
})
}
3. Permission 系统
3.1 对比
| 特性 | Claude Code | AstroResearch (当前) |
|---|---|---|
| 规则来源分层 | 6 层优先级:policy > project > user > plugin > flag > command | 单一规则列表 |
| 规则行为 | Allow / Deny / Ask | Allow / Deny / Ask ✅ |
| Classifier 自动模式 | 两阶段(快速 + 思考),并行于 hooks 启动 | 无 |
| 拒绝追踪 | 带时间窗口的限流回退 (DenialTracker) | 简单计数 |
| 沙箱集成 | shouldUseSandbox() + sandbox-adapter |
无沙箱概念 |
| 决策溯源 | 每条 PermissionDecisionReason 记录完整来源链 | 只返回 Allow/Deny/Ask |
| 权限模式 | 5 种:default, acceptEdits, bypassPermissions, dontAsk, plan | 4 种 ✅ |
3.2 Claude Code 的 Permission 决策管道
1. validateInput() — Zod schema 验证
2. runPreToolUseHooks() — Session hooks(用户配置的)
3. canUseTool — 检查 deny 规则
4. resolveHookPermissionDecision() — Allow 规则
5. [auto mode] Classifier — 两阶段分类器(Haiku)
6. [default mode] 用户弹窗 — 交互式确认
7. PermissionDecisionReason — 记录决策来源
每个决策都烙印 PermissionDecisionReason:
rule | mode | subcommandResults | permissionPromptTool |
hook | asyncAgent | sandboxOverride | classifier |
workingDir | safetyCheck | other
3.3 Classifier 系统(最值得借鉴)
Claude Code 的 auto-mode classifier 是一个独立的小模型调用(Haiku),在后台并行运行:
Auto Mode 决策流程:
┌──────────────────────────────────────────────┐
│ 1. startSpeculativeClassifierCheck() │
│ └─ 并行于 PreToolUse hooks 启动 │
│ 2. 两阶段分类: │
│ ├─ Fast: 简单模式匹配(秒级) │
│ └─ Thinking: 深度分析(复杂命令时) │
│ 3. 结果: Allow / Deny / Ask + confidence │
│ 4. DenialTracker: 连续 Deny 后 fallback 用户 │
└──────────────────────────────────────────────┘
AstroResearch 目前没有 auto-mode——所有非白名单工具都需要用户交互确认。
3.4 建议改进
P1: Auto-mode Classifier
/// Auto-mode 分类器 — 使用廉价模型在后台预分类工具调用
pub struct AutoClassifier {
llm: LlmClient, // 使用廉价模型(如 Haiku 级别 provider)
cache: LruCache<String, ClassificationResult>,
}
#[derive(Debug)]
pub struct ClassificationResult {
pub decision: PermissionResult,
pub confidence: f64,
pub reason: String,
}
impl AutoClassifier {
/// 在工具执行前异步预分类(不阻塞用户)
pub async fn preclassify(
&self,
tool_name: &str,
args: &Value,
context: &str, // 从 CLAUDE.md 和当前对话提取
) -> ClassificationResult {
// 构建精简 prompt:
// "You are a security classifier. Evaluate this tool call:
// Tool: {tool_name}
// Args: {args}
// Context: {context}
// Respond: ALLOW|DENY|ASK <confidence 0-100> <reason>"
todo!()
}
}
P1: PermissionRequest / PermissionDenied Hook 事件
这两个事件对科研场景的审计至关重要:
// 在 hooks/types.rs 中添加
pub enum HookEvent {
// ... 现有事件 ...
/// 权限请求前触发(可阻止或修改)
PermissionRequest,
/// 权限被拒绝后触发(审计日志)
PermissionDenied,
}
4. Hooks 系统
4.1 对比
| 特性 | Claude Code | AstroResearch (当前) |
|---|---|---|
| Hook 类型 | 6 种:command, prompt, agent, http, callback, function | 2 种:sync AgentHook + async AsyncAgentHook |
| 匹配器 | simple / pipe-separated / regex | glob + 精确匹配 |
| if 条件 | preparePermissionMatcher() — Bash 上有 tree-sitter |
无 |
| 输出协议 | JSON {continue, decision, reason, suppressOutput, hookSpecificOutput} |
直接返回值 |
| 超时 | 每个 hook 独立超时(默认 10min) | 统一 DEFAULT_HOOK_TIMEOUT |
| 事件数量 | 27 种 | ~15 种 |
| 来源 | config + plugin + SDK + session + function | registry + session |
4.2 Claude Code 的 27 种 Hook 事件
生命周期类:
SessionStart, Setup, SubagentStart, SubagentStop, SessionEnd, Stop, StopFailure
用户交互类:
UserPromptSubmit, Elicitation, ElicitationResult, PermissionRequest, PermissionDenied
工具执行类:
PreToolUse, PostToolUse, PostToolUseFailure
上下文类:
PreCompact, PostCompact, InstructionsLoaded
环境监控类:
FileChanged, CwdChanged, ConfigChange
Swarm/Team 类:
TeammateIdle, TaskCreated, TaskCompleted
UI 类:
Notification, StatusLine, FileSuggestion
4.3 AstroResearch 缺失的关键事件
| 缺失事件 | 用途 | 优先级 | 状态 |
|---|---|---|---|
UserPromptSubmit |
用户提交 prompt 前拦截(自动上下文注入) | P2 | ⏳ |
Notification |
长时间操作完成通知 | P1 | ⏳ |
PermissionRequest |
权限弹窗前触发 | P1 | ✅ 已实现 |
PermissionDenied |
权限被拒绝后记录审计 | P1 | ✅ 已实现 |
PreCompact |
上下文压缩前机会(保存重要信息) | P2 | ⏳ |
PostCompact |
上下文压缩后通知(更新外部状态) | P2 | ⏳ |
4.4 已实施改进(2026-06-22)
✅ P1: PermissionRequest / PermissionDenied 事件 — 已完成
新增类型(src/agent/hooks/types.rs):
HookEvent::PermissionRequest/HookEvent::PermissionDeniedPermissionRequestContext— 携带current_decision、permission_mode、is_subagentPermissionDeniedContext— 携带reason、source(Rule/Classifier/User/Timeout)PermissionRequestAction— Continue / Override / InjectContextPermissionDecision/PermissionDenialSource枚举
新增 trait 方法(src/agent/hooks/traits.rs):
AgentHook::on_permission_request()→PermissionRequestActionAgentHook::on_permission_denied()→ void (审计日志)
新增调度方法(src/agent/hooks/dispatch.rs):
HookRegistry::run_on_permission_request()— 并行调用,第一个 Override 生效HookRegistry::run_on_permission_denied()— fire-and-forget 审计
4.5 原始建议(部分已过时)
原建议的 context 设计已被更完善的实现替代: }
**P2: 支持 command 类型 hook**
```rust
/// Command 类型 hook — 执行外部 shell 命令处理事件
pub struct CommandHook {
command: String, // 如 "python3 audit.py"
timeout: Duration, // 默认 10min
shell: HookShell, // Bash | PowerShell
}
5. Error Recovery / 重试系统
5.1 对比
| 特性 | Claude Code | AstroResearch (当前) |
|---|---|---|
| 重试结构 | Generator 模式,yield 系统消息直到不可重试 | ErrorRecovery 枚举 + 简单决策 |
| 退避算法 | 指数 + 25% jitter,可配置上限(32s 默认,5min 持久) | 固定退避 |
| 错误分类 | shouldRetry() 检查 15+ 种错误,每种不同策略 |
8 步分类管线 |
| 529 Overloaded | 3 次重试 → 模型回退(Opus→Sonnet)→ 持久化重试 | 无模型回退 |
| Context Overflow | 解析 "X + Y > Z",自动调整 max_tokens + 1000 安全缓冲 | 只分类不修复 |
| 持久化重试 | 无限重试 + 30s 心跳 | 无 |
| Fast Cooldown | 429/529 在 fast mode → retry-after <20s → 10min cooldown | N/A |
5.2 Context Overflow 自动修复(最值得借鉴)
Claude Code 的做法:
// src/services/api/withRetry.ts
// 解析 Anthropic API 的错误消息:
// "input length and max_tokens exceed context limit: 180000 + 32000 > 200000"
// → 计算安全的 max_tokens = 200000 - 180000 - 1000(safety) = 19000
function parseContextOverflowError(errorMessage: string) {
const match = errorMessage.match(
/input length and max_tokens exceed context limit: (\d+) \+ (\d+) > (\d+)/
);
if (match) {
const [, inputLen, maxTokens, contextLimit] = match.map(Number);
const newMaxTokens = contextLimit - inputLen - SAFETY_MARGIN;
if (newMaxTokens > MIN_TOKENS) {
return { shouldRetry: true, adjustedMaxTokens: newMaxTokens };
}
}
return { shouldRetry: false };
}
5.3 已实施改进(2026-06-22)
✅ P0: Context Overflow 自动修复 — 已完成
新增公共 API(src/agent/runtime/error_recovery.rs):
ContextOverflowInfo— 从错误消息解析的数值结构体parse_context_overflow()— 支持 Anthropic/OpenAI/通用三种格式calculate_safe_max_tokens()—context_limit - input_length - SAFETY_MARGIN(1000)RecoveryStep::AdjustMaxTokens { new_max_tokens }— 恢复管线第 0 步extract_three_numbers()— 正则匹配 "A + B > C" 模式(使用已有regexcrate)
AgentRuntime 集成(src/agent/runtime/mod.rs):
let overflow_info = error_recovery::parse_context_overflow(&e_str);
while let Some(recovery_step) = recovery.try_recover(&error_kind, overflow_info.as_ref()) {
// AdjustMaxTokens 优先于 AggressiveCompact,仅无空间时才回退到压缩
}
12 个新增测试覆盖 Anthropic/OpenAI/Generic 格式、边界条件、恢复优先级。
5.4 原始建议(部分已过时)
P1: 模型回退策略
/// 模型回退链 — 529/Overloaded 时自动降级
pub struct ModelFallback {
chain: Vec<ModelTier>,
}
#[derive(Debug, Clone)]
pub enum ModelTier {
Primary(String), // 如 "claude-opus-4-8"
Fallback(String), // 如 "claude-sonnet-4-6"
Emergency(String), // 如 "claude-haiku-4-5"
}
6. Tool 定义系统
7.1 对比
| 特性 | Claude Code Tool<T> |
AstroResearch AgentTool trait |
|---|---|---|
| 并发安全 | isConcurrencySafe(input) — 输入感知 ✅ |
is_concurrency_safe(args) — ✅ |
| 语义标记 | isReadOnly() / isDestructive() / isConcurrencySafe() |
causes_sibling_abort() / interrupt_behavior() |
| 权限逻辑 | checkPermissions() — 工具自己决定权限 |
集中在 PermissionChecker |
| 分类器输入 | toAutoClassifierInput() — 精简信息 |
无 |
| 延迟加载 | shouldDefer / alwaysLoad — 减小 prompt |
无 |
| 搜索提示 | searchHint — 帮助 ToolSearch 匹配 |
无 |
| UI 渲染 | renderToolUseMessage/Result/Progress/Error (6 种) |
前端独立处理 |
| 中断行为 | interruptBehavior() — cancel vs block |
interrupt_behavior() ✅ |
| 输出大小 | maxResultSizeChars — 超限存磁盘 |
env var 全局配置 |
| 权限匹配器 | preparePermissionMatcher() — 工具级模式匹配 |
HookMatcher |
7.2 Claude Code 的 buildTool() Factory
// 每个工具通过 buildTool 创建,自动填充安全默认值
const myTool: Tool = buildTool({
name: 'MyTool',
inputSchema: z.object({ ... }),
async call(input, context, toolUseId) { ... },
// 以下都有安全默认值,按需覆盖:
// isEnabled: true (可根据 permission mode 禁用)
// isConcurrencySafe: false
// isReadOnly: false
// isDestructive: false
// checkPermissions: {behavior: 'allow'} (最宽松)
// toAutoClassifierInput: '' (不参与分类)
// shouldDefer: false (立即加载)
// interruptBehavior: 'block' (不可中断)
})
7.3 建议改进
P2: 为 AgentTool trait 添加方法
pub trait AgentTool: Send + Sync {
// ... 现有方法 ...
/// 返回用于 auto-mode 分类器的精简摘要
fn classifier_summary(&self, args: &Value) -> String {
format!("{}", self.name())
}
/// 是否是只读操作(与并发安全不同——glob 是 readonly 但不能和 bash 并发)
fn is_readonly(&self) -> bool { false }
/// 是否需要延迟加载工具描述(大工具可延迟以减小 prompt)
fn defer_loading(&self) -> bool { false }
}
P3: 工具 allow/deny 列表
参考 Claude Code 的做法,AstroResearch 已有 subagent_allowed_tools,可扩展:
// 为子代理/异步代理定义工具过滤策略
pub struct ToolFilterPolicy {
/// 全局禁止(不计代理类型)
pub all_agent_disallowed: Vec<String>,
/// 自定义代理禁用(不能 spawn 子代理 + 编辑文件的代理)
pub custom_agent_disallowed: Vec<String>,
/// 异步代理白名单(只读子集)
pub async_agent_allowed: Vec<String>,
}
7. Memory 持久化
8.1 对比
AstroResearch 与 Claude Code 在 Memory 设计上高度相似(都是文件系统 frontmatter markdown +
MEMORY.md 索引),差距很小。
Claude Code 多了:
- Team Memory: 共享给团队的记忆(AstroResearch 有 team 系统但无 team memory)
- Session Memory compaction: 压缩时自动通过 LLM 提取记忆到文件
8.2 建议改进
P3: Session Memory Compaction
压缩时自动提取记忆:
/// 在 compact.rs 的 auto_compact 过程中提取 session memory
pub async fn extract_session_memory(
llm: &LlmClient,
messages: &[ChatMessage],
) -> Vec<MemoryExtraction> {
// 用专门的小 prompt 让 LLM 从对话中提取可持久化的记忆
// 返回候选记忆列表,由 MemoryManager 做 dedup + 衰减
}
8. Coordinator / Multi-Agent
9.1 Claude Code 的 Coordinator Mode
Coordinator Mode 架构:
┌─────────────────────────────────────────────────┐
│ Coordinator (Coordinator System Prompt) │
│ Tools: Agent, SendMessage, TaskStop, │
│ SyntheticOutput (仅 4 个) │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Worker 1 │ │ Worker 2 │ │ Worker 3 │ │
│ │ (async) │ │ (async) │ │ (async) │ │
│ │ standard │ │ standard │ │ standard │ │
│ │ tools │ │ tools │ │ tools │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │
│ Worker 结果以 <task-notification> 返回 │
│ Coordinator 做 Synthesis → 下一轮 Workers │
└─────────────────────────────────────────────────┘
9.2 关键设计点
- Coordinator 只看到 4 个工具——它不能直接读文件或执行 bash,只能编排 Workers
- Workers 全异步——Coordinator 不等待,结果以
<task-notification>XML 注入 - Continue-vs-Spawn 决策矩阵:
- 新任务与已有 Worker 上下文重叠 <30% → 创建新 Worker
- 新任务是对已有 Worker 的跟进 →
SendMessage继续
- Worker prompt 写法规范:自包含(self-contained),包含完整 spec,明确交付物
9.3 AstroResearch 的现状
AstroResearch 有 SubAgentTool + TeamManager,但没有 Coordinator 的概念。Team
是平级的(lead ↔ teammates),不是层级编排。
9.4 建议改进
P2: Coordinator Mode 原型
当 Agent 检测到复杂多步骤任务时,自动切换为 Coordinator 模式:
用户请求
→ Coordinator 做任务分解
→ 并行子代理执行 (SubAgentTool, async)
→ 结果综合
→ 减少单 Agent 的步骤数和 token 消耗
关键实现:
1. Coordinator system prompt: 类似 Claude Code coordinatorMode.ts
2. 仅暴露 SubAgentTool + 少量管理工具
3. 子代理结果以结构化格式注入
4. 综合阶段由 Coordinator 处理
9. Hermes-Agent 的独特贡献
10.1 文件位置
/home/fmq/program/AstroResearch/libs/hermes-agent/
10.2 Hermes-Agent vs Claude Code 架构对比
| 关注点 | Hermes-Agent | Claude Code |
|---|---|---|
| 语言 | Python 3.11+ | TypeScript (Node.js 20+) |
| Agent 循环 | 同步 while 循环 |
异步 query() generator |
| 工具注册 | 文件系统自动发现 (tools/*.py) |
手动 import + getAllBaseTools() |
| 工具接口 | handler(args) -> JSON string |
Tool<T> — ~70 方法 |
| 状态管理 | SQLite (SessionDB + FTS5) | 内存 AppState React store |
| Plugin 系统 | PluginManager + 生命周期 hooks | Plugin loader + MCP 集成 |
| Profile 隔离 | 多 profile + 独立 HERMES_HOME |
单 profile |
| 子代理 | 子 AIAgent 实例 |
LocalAgentTask + runAgent() |
| Swarm/Team | Kanban 工作队列 | InProcessTeammateTask + coordinator |
| 上下文压缩 | ContextCompressor |
compact/ 服务 |
| MCP 支持 | mcp_tool.py + catalog |
完整的 services/mcp/ |
| 定位 | 个人 AI 助手(自我改进、记忆、跨平台) | 编程 AI 助手(终端集成、文件操作) |
10.3 Hermes-Agent 的核心架构
hermes-agent/
├── run_agent.py # AIAgent 类 (~11k LOC) — 核心入口
├── model_tools.py # 工具编排层 (~2.7k LOC)
├── toolsets.py # 工具集定义
├── hermes_state.py # SessionDB — SQLite + FTS5
├── cli.py # HermesCLI 类 (~11k LOC)
│
├── agent/ # Agent 内部
│ ├── conversation_loop.py # 主循环
│ ├── turn_context.py # 每轮上下文 dataclass
│ ├── system_prompt.py # 三层 System Prompt
│ ├── prompt_builder.py # Prompt 片段构建
│ ├── memory_manager.py # 记忆编排
│ ├── context_compressor.py # 上下文压缩
│ ├── tool_executor.py # 工具执行分发
│ ├── tool_guardrails.py # 安全 guardrails
│ └── curator.py # 后台 Skill 生命周期管理
│
├── tools/ # 工具实现(自动发现)
│ ├── registry.py # ToolRegistry(discover_builtin_tools)
│ ├── delegate_tool.py # 子代理 spawn
│ ├── skills_tool.py # Skill 管理
│ └── cronjob_tools.py # Cron 调度
│
└── hermes_cli/ # CLI 子系统
├── plugins.py # PluginManager + 生命周期 hooks
└── profiles.py # 多 Profile 隔离
10.4 最值得借鉴的 Hermes 特性
Self-improving Skills
工作流:
1. Agent 在科研中反复使用某流程
(如: 搜索某类天体 → 下载论文 → RAG → 总结)
2. Agent 自动检测重复模式
3. Agent 创建 Skill 保存该流程
4. Curator 管理 Skill 生命周期
5. 下次相似查询直接加载 Skill,无需重新探索
AstroResearch 已有 Skills 系统 (skills.rs),缺少:
- 自动检测重复模式
- Agent 自主创建 Skill
- Curator 管理 Skill 质量
Session FTS5 搜索
# Hermes 的 SessionDB 使用 SQLite FTS5 实现跨 session 搜索
class SessionDB:
def search_sessions(self, query: str) -> List[Session]:
"""全文本搜索所有历史会话"""
return self.db.execute(
"SELECT * FROM sessions WHERE sessions MATCH ?", (query,)
)
AstroResearch 的 agent_sessions 表有基本的 title/status 字段,但没有全文搜索。
10.5 建议改进
P2: Self-improving Skills 原型
1. Pattern Detector (自动检测)
- 监控 N 个 session 中的工具调用序列
- 使用简单的子序列匹配识别重复模式
- 阈值: 3 次相似序列 → 候选 Skill
2. Skill Creator (Agent 自主创建)
- 将候选 Skill 展示给用户确认
- 生成 SKILL.md 文件(含 when_to_use, steps)
- 注册到 SkillRegistry
3. Curator (管理生命周期)
- 跟踪 Skill 使用频率
- 长时间未用的 Skill 标记为 stale
- 提示用户审查或删除
10. 优先级排序 —— 建议实施路线
按价值/投入比排序:
| 优先级 | 改进项 | 来源 | 状态 | 价值 | 预估投入 | 依赖 |
|---|---|---|---|---|---|---|
| P0 | Context Overflow 自动修复 | Claude Code | ✅ | 减少 ~50% LLM 调用失败 | ~30 行 | 无 |
| P0 | StreamingExecutor 真正的流式调度 | Claude Code | ✅ | 减少 30-50% 工具执行延迟 | ~200 行 | 无 |
| P0 | Executor 集成分区器(批次串行/并行) | Claude Code | ✅ | 修复非安全工具错误并发 | ~300 行 | ToolPartitioner |
| P1 | 工具并发分区 partition_tool_calls |
Claude Code | ✅ | 批量只读操作 3-5x 加速 | ~100 行 | 无 |
| P1 | PermissionRequest / PermissionDenied Hook 事件 | Claude Code | ✅ | 安全审计能力 | ~100 行 | 无 |
| P1 | Auto-mode Classifier(廉价模型预分类) | Claude Code | ⏳ | 消除 80%+ 权限弹窗 | ~300 行 | LLM client 支持 |
| P2 | Self-improving Skills(Agent 保存成功流程) | Hermes | ✅ | 科研场景独特价值 | ~500 行 | Skills 系统 |
| P2 | Coordinator Mode(层级多 Agent 编排) | Claude Code | ⏳ | 复杂任务效果提升 | ~800 行 | SubAgent + Team |
| P2 | UserPromptSubmit / PreCompact / PostCompact Hook | Claude Code | ⏳ | Hook 系统完善 | ~200 行 | 无 |
| P3 | FTS5 跨 session 搜索 | Hermes | ⏳ | 历史研究可复用 | 中 | SQLite 迁移 |
| P3 | Tool defer_loading / classifier_summary |
Claude Code | ⏳ | 减小 tool schema prompt | ~50 行 | 无 |
| P3 | 模型回退策略 (Model Fallback) | Claude Code | ⏳ | 提高可用性 | ~200 行 | ErrorRecovery |
| P3 | Session Memory Compaction | Claude Code | ⏳ | 自动化记忆提取 | ~300 行 | MemoryManager + Compact |
实施进度(2026-06-22)
- P0 项 — 全部完成 ✅
- Context Overflow 自动修复(
error_recovery.rs) - StreamingExecutor 真正流式调度(
streaming_executor.rs重写) - Executor 集成分区器(
executor.rsPhase 3 重写)
- Context Overflow 自动修复(
- P1 项 — 部分完成
- ✅ 工具并发分区
- ✅ PermissionRequest / PermissionDenied Hook 事件
- ⏳ Auto-mode Classifier — 需要设计讨论
- P2 项在下一个大版本规划:需要设计讨论和更多测试
- P3 项作为 backlog:长期优化方向
附录 A: Claude Code 关键源码索引
| 文件 | 用途 | 与 AstroResearch 对应 |
|---|---|---|
src/Tool.ts |
Tool 类型 + buildTool factory | src/agent/tools/mod.rs |
src/tools.ts |
工具注册 + assembleToolPool | ToolRegistry::new() |
src/services/tools/toolExecution.ts |
工具执行管道 | executor.rs |
src/services/tools/toolOrchestration.ts |
并发分区 + 批量执行 | partitioner.rs + executor.rs |
src/services/tools/StreamingToolExecutor.ts |
流式工具执行 | streaming_executor.rs |
src/services/api/withRetry.ts |
错误重试 + 退避 | error_recovery.rs |
src/services/api/claude.ts |
API 流式调用 | streaming.rs |
src/constants/prompts.ts |
System Prompt 构建 | system_prompt.rs |
src/utils/hooks.ts |
Hook 执行引擎 (5022 行) | hooks/dispatch.rs |
src/utils/permissions/permissions.ts |
权限逻辑 | permission.rs |
src/utils/permissions/yoloClassifier.ts |
Auto-mode 分类器 | 无 (建议新增) |
src/tools/AgentTool/runAgent.ts |
子代理执行引擎 | subagent.rs |
src/tools/AgentTool/AgentTool.tsx |
子代理编排 | tools/subagent.rs |
src/coordinator/coordinatorMode.ts |
Coordinator 模式 | 无 (建议参考) |
src/memdir/memdir.ts |
Memory 文件系统 | memory/mod.rs |
src/skills/loadSkillsDir.ts |
Skill 加载 | skills.rs |
附录 B: Hermes-Agent 关键源码索引
| 文件 | 用途 | 与 AstroResearch 对应 |
|---|---|---|
run_agent.py |
AIAgent 核心类 | runtime/mod.rs |
agent/conversation_loop.py |
Agent 主循环 | runtime/mod.rs (ReAct loop) |
agent/system_prompt.py |
三层 System Prompt | system_prompt.rs |
agent/context_compressor.py |
上下文压缩 | compact.rs |
agent/memory_manager.py |
记忆编排 | memory/mod.rs |
agent/curator.py |
Skill 生命周期管理 | 无 (建议参考) |
tools/registry.py |
工具自动发现 | tools/mod.rs |
tools/delegate_tool.py |
子代理 | subagent.rs |
hermes_state.py |
SessionDB + FTS5 | api/agent.rs (sessions) |
hermes_cli/plugins.py |
PluginManager | 无 |
hermes_cli/profiles.py |
多 Profile 隔离 | 无 |
model_tools.py |
工具编排 | executor.rs |
附录 C: 变更日志
2026-06-22 — 首轮实施
P0: Context Overflow 自动修复
src/agent/runtime/error_recovery.rs: +150 行- 新增
ContextOverflowInfo、parse_context_overflow()、calculate_safe_max_tokens() - 新增
RecoveryStep::AdjustMaxTokens、extract_three_numbers() - 12 个新增测试(Anthropic/OpenAI/Generic 格式 + 边界 + 恢复优先级)
- 新增
src/agent/runtime/mod.rs: AgentRuntime 集成调用点Cargo.lock: 无新增依赖(使用已有regexcrate)
P0: StreamingExecutor 真正流式调度
src/agent/runtime/streaming_executor.rs: 重写 ~400 行(原 316 行)on_tool_use中对并发安全工具立即tokio::spawntokio::select!在工具执行和 Sibling Abort 之间竞速collect_completed_tasks()使用JoinHandle::is_finished()非阻塞检查executing_non_concurrent标志实现独占执行
src/agent/tools/mod.rs:ToolContext添加Clonederive
P0: Executor 集成分区器
src/agent/runtime/executor.rs: Phase 3 重写 + 2 个提取函数- Phase 3a: 构建非拒绝工具的 (原索引, PreparedCall) 映射
- Phase 3b:
ToolPartitioner::partition()分区 - Phase 3c: 逐批次执行(并行批次
FuturesUnordered,串行批次逐个执行) - 提取
execute_single_tool()和process_single_result()辅助函数
src/agent/runtime/partitioner.rs: +2 测试(run_bash、file_write打断并发批)
P1: PermissionRequest / PermissionDenied Hook 事件
src/agent/hooks/types.rs: +80 行- 新增
HookEvent::PermissionRequest、HookEvent::PermissionDenied - 新增
PermissionRequestContext、PermissionDeniedContext - 新增
PermissionRequestAction、PermissionDecision、PermissionDenialSource
- 新增
src/agent/hooks/traits.rs: +20 行AgentHook::on_permission_request()、AgentHook::on_permission_denied()
src/agent/hooks/dispatch.rs: +120 行run_on_permission_request()(并行调用,第一个 Override 生效)run_on_permission_denied()(fire-and-forget 审计)
src/agent/hooks/mod.rs: 更新 re-exports
2026-06-22 — Self-improving Skills
P2: Self-improving Skills(模式检测 + 自动创建 + Curator)
src/agent/skills/pattern_detector.rs: +420 行PatternDetector— 从agent_messagesDB 表扫描工具调用序列DetectedPattern— 跨 session 重复模式(携带出现次数、置信度、指纹)- 滑动窗口子序列提取 + Jaccard 相似度去重 + 超序列包含检测
- 8 个单元测试(子序列提取、指纹、去重、Jaccard 计算)
src/agent/skills/curator.rs: +700 行Curator— Skill 生命周期管理(Active → Inactive → Stale → Deprecated)SkillQuality— 基于调用次数和新鲜度的质量评分(对数 + 指数衰减)CuratorReport— 分析报告 + 清理建议列表archive_stale_skills()— 将过期 skill 移动到归档目录CuratorRunner— 后台空闲触发审查(should_run_now()+record_activity()心跳)- 12 个单元测试(5 种生命周期状态 + 质量评分 + 清理候选 + pinned + runner)
src/agent/skills.rs: +230 行SkillCreator— 将DetectedPattern转为 SKILL.md 文件(kebab-case 命名 + YAML frontmatter)SelfImprovePipeline— 一站式管道(检测 → 创建 → 质量审查)SelfImproveResult— 管道结果(patterns_found + skills_created + curator_report)SkillFrontmatter+SkillMeta增加pinned字段
2026-06-22 — Hermes Curator 特性补齐
Pinned Skills(不可清理)
src/agent/skills.rs:SkillFrontmatter.pinned+SkillMeta.pinned— YAMLpinned: truesrc/agent/skills/curator.rs:evaluate_quality(pinned)— 强制 Active + min_score 0.8;analyze过滤 pinned 不进入 cleanup_candidates
Seed Record(新 Skill 锚定时钟)
src/agent/skills/curator.rs:evaluate_quality对无统计记录 skill 设置days_since_last_use=Some(0)(等效刚创建),NEW_SKILL_GRACE_PERIOD_DAYS=7防止立即 stale
CuratorRunner(后台空闲触发审查)
src/agent/skills/curator.rs:CuratorRunner结构体 +should_run_now()(paused/idle/interval 三重检查)+record_activity()心跳 +run_once()+spawn()tokio 后台任务 +pause()/resume()- 5 个新增测试(pinned_always_active、pinned_not_in_cleanup、seed_record、runner_paused、runner_idle)