AstroResearch/docs/architecture/agent/overview.md
Asfmq f6df9d8136 feat: Agent 思考模式前端可控、子代理全链路持久化、权限系统、工具 ID 追踪体系、前端面板与文档架构重构
- AgentConfig/LlmClient 新增 enable_thinking 参数,前端 SSE 请求传递 thinking
  开关,仅千问/DashScope 时启用
  - 完善权限系统,支持细粒度的权限控制和用户权限申请
  - delegate_research 工具重命名为 subagent,SubAgentTool/SubAgentRunner 重构
  - 子代理消息(system/user/assistant/tool)持久化到 agent_messages 表,带 agent_name 标识
  - 子代理活动日志(工具调用列表+思考摘要)注入返回结果,Hooks 获得正确 session_id 和 subagent_name
  - LLM 工具调用 ID 回退生成 UUID(llm.rs),ToolCall/ToolResult SSE 事件增加 id/tool_call_id 双字段
  - ToolContext 扩展 session_id/sse_tx/enable_thinking 字段,executor 统一注入而非构造函数传参
  - agent_messages 新增 metadata+raw_json 列,agent_sessions 暴露 summary 字段
  - 删除文件级 transcript 快照(compact.rs),改为依赖 DB 持久化
  - ResearchAgentPanel 重写:TimelineItem 类型替代 StreamStep,支持会话历史回放
  - 新增 AgentMetricsPanel/AskUserQuestionCard/AuditLogViewer 三个前端组件,types.ts 完整类型定义
  - docs/architecture/ 分层重组:概览/核心模块/核心工作流 + agent/ 子目录 11 篇专题文档
  - docs/api.md 补充 RAG/Target/Agent 接口,docs/development.md 新建开发指南
  - .env.example 完全重写,补充 FALLBACK_MODEL 等变量说明
2026-06-18 01:21:02 +08:00

175 lines
5.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Agent 架构概览
AstroResearch 内置了一个基于 **ReAct** (Thought → Action → Observation) 范式的科研智能体引擎 (`src/agent/`),参考 Claude Code 的分层设计。以下对各子系统的架构、数据流和内部逻辑进行完整说明。
### 整体架构
```mermaid
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 (9 事件)"]
Skills["SkillRegistry (两层加载)"]
Memory["MemoryManager (项目记忆)"]
Permission["PermissionChecker"]
FileCache["FileStateCache (Read 去重)"]
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 个阶段:
#### 完整生命周期
```mermaid
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-->>FE: SSE session { session_id, title }
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
```
#### 并行工具执行模型
```mermaid
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`)能在出错时中断兄弟任务
- **InterruptBehavior**`Block` 工具(如 `ask_user`)不可被用户取消;`Cancel` 工具可在取消信号时中断
- **超时控制**:每个工具有独立超时,默认 120s`AGENT_TOOL_TIMEOUT_SECS`
---