AstroResearch/docs/architecture/agent/overview.md
Asfmq cec4b8cf7b feat: Docker 容器化、Cookie 鉴权、Coordinator 编排、FTS5 搜索与 P1-P3 全面收尾
Docker 容器化部署
  - 提供 Mode A (Alpine musl, ~23MB) 和 Mode B (Distroless glibc, ~87MB)
    两种镜像,Docker Compose 一键启动
  - build.rs 支持 SKIP_DASHBOARD_BUILD 跳过前端构建
  - 国内镜像加速 (npm/apt/apk) 通过 USE_MIRRORS build-arg 控制

  安全:Cookie-Based 鉴权系统
  - HttpOnly/SameSite=Strict Cookie 会话管理(24h 过期自动清理)
  - 登录/登出/验证接口 + 中间件注入
  - 前端登录页面 + 退出按钮
  - 三层 CORS:localhost 鉴权 / 全放通 bookmarklet / 受保护路由
  - 书签脚本 fetch 添加 credentials:'include'

  Coordinator 模式 (P2)
  - 4 个 meta-tool (delegate_task/check_task/task_stop/synthesize)
  - WorkerPool + Semaphore 并发控制 + 超时保护
  - 前端协调者模式开关

  Hook 系统:UserPromptSubmit 事件 (P2)
  - 第 13 个生命周期事件,fire-and-forget 审计

  FTS5 全文搜索 (P3)
  - agent_sessions_fts + agent_messages_fts 虚拟表
  - search_history Agent 工具 + /api/search/history HTTP 接口
  - 前端防抖搜索框 + 仅当前会话筛选

  工具加载优化 (P3)
  - defer_loading 延迟加载 (7 个重型工具)
  - is_readonly 只读标记 (9 个查询工具)
  - classifier_summary 工具目录供 LLM 按需判断

  模型回退策略 (P3)
  - LLM_FALLBACK_MODEL 优先回退 + LLM_FALLBACK_CHAIN 链式轮换
  - LlmClient model 改为 Arc<RwLock> 支持运行时切换
  - 连续 3 次过载后自动切换

  压缩记忆桥接 (P3)
  - 压缩丢弃消息 → 子代理提取持久记忆 (extract_memories_from_compaction)

  git2 依赖修复
  - 切换到 vendored-libgit2,消除 OpenSSL 系统依赖
2026-06-23 20:22:06 +08:00

7.1 KiB
Raw Blame History

Agent 架构概览

AstroResearch 内置了一个基于 ReAct (Thought → Action → Observation) 范式的科研智能体引擎 (src/agent/),参考 Claude Code 的分层设计。以下对各子系统的架构、数据流和内部逻辑进行完整说明。

整体架构

graph TD
    subgraph API["API 层"]
        SSE["SSE /api/chat/agent"]
        Sessions["Session CRUD"]
        Metrics["GET /api/chat/metrics"]
        Audit["GET /api/chat/sessions/:id/audit"]
        AskUser["问答 /api/chat/questions + /api/chat/answer"]
    end

    subgraph Runtime["AgentRuntime — ReAct 引擎"]
        RunTurn["run_turn() 主入口"]
        SP["SystemPrompt 组装器"]
        CtxBuild["Context Builder 上下文构建"]
        ReAct["ReAct 主循环"]
        Streaming["streaming.rs 流式处理"]
        Executor["executor.rs 并行执行"]
        Finalize["finalize.rs 会话收尾"]
        TokenBudget["token_budget.rs"]
        CircuitBreaker["circuit_breaker.rs"]
    end

    subgraph Tools["工具系统 (tools/)"]
        AgentTool["AgentTool trait"]
        Registry["ToolRegistry"]
        FS["filesystem/ (6 工具)"]
        Astro["astro/ (7 工具)"]
        AskUserT["ask_user"]
        SubAgentT["subagent/delegate_research"]
        TeamT["team/ (4 工具)"]
        BG["background (2 工具)"]
    end

    subgraph CrossCutting["横切关注点"]
        Hooks["HookRegistry (13 事件)"]
        Skills["SkillRegistry (两层加载)"]
        Memory["MemoryManager (项目记忆)"]
        Permission["PermissionChecker"]
        FileCache["FileStateCache (Read 去重)"]
        Coordinator["Coordinator Mode (协调者编排)"]
    end

    subgraph DB["持久化"]
        AgentSessions["agent_sessions"]
        AgentMessages["agent_messages"]
        AgentTasks["agent_tasks"]
        AgentAudit["agent_audit_log"]
    end

    SSE --> RunTurn
    RunTurn --> SP
    RunTurn --> CtxBuild --> DB
    RunTurn --> ReAct
    ReAct --> Streaming --> Tools
    ReAct --> Executor --> Tools
    ReAct --> TokenBudget
    ReAct --> CircuitBreaker
    ReAct --> Finalize

    Hooks -.-> ReAct
    Hooks -.-> Tools
    Skills -.-> Tools
    Memory -.-> SP
    Permission -.-> Tools
    FileCache -.-> Tools

ReAct 运行循环 (runtime/)

主循环由 AgentRuntime::run_turn() 驱动,分为 4 个阶段:

完整生命周期

sequenceDiagram
    participant FE as 前端 SSE
    participant RT as AgentRuntime
    participant DB as SQLite
    participant LLM as LLM API
    participant Tools as ToolRegistry

    FE->>RT: POST /api/chat/agent { question, session_id? }

    Note over RT: Phase 1 — 会话管理
    RT->>DB: create_or_resume_session()
    alt 新会话
        DB-->>RT: session_id = uuid, turn_index = 0
    else 恢复会话
        DB-->>RT: 验证存在 + 计算 turn_index
    end
    RT->>RT: 触发 OnSessionStart hook
    RT->>RT: 触发 UserPromptSubmit hook (用户输入审计)
    RT-->>FE: SSE session { session_id, title }

    opt 协调者模式 (coordinator_mode: true)
        RT->>RT: run_coordinator_turn() → CoordinatorAgent
        Note over RT: Coordinator 委托 Worker → 合成结果
    end

    Note over RT: Phase 2 — 上下文构建
    RT->>RT: build_initial_context()
    RT->>RT: ① 组装 SystemPrompt (静态 section + 记忆注入)
    RT->>DB: ② 加载历史消息 load_history_for_llm()
    RT->>DB: ③ 恢复未完成任务 (agent_tasks)
    RT->>RT: ④ 检查压缩/清理上下文
    RT->>DB: ⑤ 保存用户消息
    RT->>RT: ⑥ 运行 PreToolUse hooks 过滤

    Note over RT: Phase 3 — ReAct 循环
    loop 每步迭代 (step ≤ max_steps)
        RT->>LLM: chat_stream(messages + tool_defs)
        LLM-->>RT: ReasoningDelta / TextDelta / ToolCallsComplete
        RT-->>FE: SSE thought / text_delta / tool_call

        alt 无工具调用 → 最终答案
            RT->>DB: 保存 assistant 消息
            RT-->>FE: SSE text_delta → usage → done
            Note over RT: break 循环
        else 有工具调用
            RT->>RT: 检查 token 预算 + 熔断器
            RT->>RT: validate_and_prepare() — 去重 + 过滤
            RT->>Tools: execute_parallel() — 并行执行
            Tools-->>RT: (tool_call_id, name, output)
            RT-->>FE: SSE tool_result { tool_call_id, name, output }
            RT->>DB: 保存 tool 消息 + 审计日志
            RT->>RT: 运行 PostToolUse hooks
            RT->>RT: 检测压缩需求 (auto_compact)
        end
        RT->>RT: 检测循环终止条件
    end

    Note over RT: Phase 4 — 会话收尾
    RT->>DB: 更新 turn_count + updated_at
    RT->>DB: calculate_and_persist_metrics()
    RT->>RT: 运行 OnSessionStop hook
    RT-->>FE: SSE done

并行工具执行模型

sequenceDiagram
    participant ReAct as ReAct 循环
    participant Val as validate_and_prepare
    participant Exec as execute_parallel
    participant T1 as Tool A
    participant T2 as Tool B
    participant FE as 前端 SSE

    ReAct->>Val: LLM 返回 [tool_call_a, tool_call_b]
    Val->>Val: 去重检测 + 权限验证
    Val-->>ReAct: prepared_calls[] + has_duplicate 标志
    ReAct->>FE: 发送 tool_call SSE (逐一)
    ReAct->>Exec: 启动 execute_parallel()
    par 并行执行
        Exec->>T1: tool_a.execute(args_a)
        Exec->>T2: tool_b.execute(args_b)
    end
    T1-->>Exec: ToolOutput { content, is_error }
    Exec-->>FE: SSE tool_result (立即推送)
    T2-->>Exec: ToolOutput { content, is_error }
    Exec-->>FE: SSE tool_result (立即推送)
    Exec-->>ReAct: Vec<(tool_call_id, name, args, output, cancelled)>
    ReAct->>ReAct: PostToolUse hooks + 审计日志 + 持久化
  • 并发上限:由 max_concurrent_tools 环境变量控制,默认不限制
  • Sibling Abort:仅 causes_sibling_abort() = true 的工具(如 download_paper)能在出错时中断兄弟任务
  • InterruptBehaviorBlock 工具(如 ask_user)不可被用户取消;Cancel 工具可在取消信号时中断
  • 超时控制:每个工具有独立超时,默认 120sAGENT_TOOL_TIMEOUT_SECS

Coordinator Mode协调者模式, P2

graph TD
    User["用户请求"] --> API["POST /api/chat/agent\n{ coordinator_mode: true }"]
    API --> RT["AgentRuntime::run_coordinator_turn()"]
    RT --> CA["CoordinatorAgent (仅元工具)"]
    CA --> Tool["delegate_task / check_task / task_stop / synthesize"]
    Tool --> WP["WorkerPool (Semaphore 并发控制)"]
    WP --> W1["Worker 1 (SubAgentRunner)"]
    WP --> W2["Worker 2 (SubAgentRunner)"]
    WP --> W3["Worker N (SubAgentRunner)"]
    W1 --> Synth["synthesize 收集结果"]
    W2 --> Synth
    W3 --> Synth
    Synth --> Answer["最终答案"]

Coordinator 仅拥有 4 个元工具,将实际研究工作委托给拥有完整工具访问权限的 Worker 子代理。Worker 通过 SubAgentRunner + Semaphore 实现并发控制(默认最大 4 并发)。

  • 委托 → 检查 → 合成 三步工作流
  • 前端通过 coordinator_mode: true 字段启用
  • 源码: src/agent/coordinator/{agent,tools,worker,mod}.rs