附录 B:关键执行流程图
本附录收录 6 个关键流程的 Mermaid 图,覆盖从单次对话到系统级防御的核心路径。每个图标注了对应的源码文件和章节引用。
B.1 单次对话流程
对应章节:第 3 章(请求旅程)、第 4 章(AIAgent 内核)
sequenceDiagram
participant U as 用户
participant E as 入口层<br/>(CLI / Gateway)
participant A as AIAgent<br/>(run_agent.py)
participant L as LLM API
participant T as 工具系统<br/>(model_tools.py)
participant S as SessionDB<br/>(hermes_state.py)
U->>E: 发送消息
E->>A: run_conversation(user_message)
A->>A: _build_system_prompt()<br/>(identity + memory + skills + context)
A->>S: 加载会话历史
A->>A: 检查 IterationBudget
loop 工具调用循环
A->>L: API 调用(messages + tools schema)
L-->>A: 流式响应(text + tool_calls)
A-->>E: stream_delta_callback(token)
alt 模型返回 tool_call
A->>A: budget.consume()
A->>T: handle_function_call(name, args)
T->>T: registry.get(name) → handler
T-->>A: 工具执行结果
A->>A: 追加 tool_result 到 messages
Note over A: 检查 budget 压力<br/>70% → caution<br/>90% → warning
else 模型返回纯文本
Note over A: 退出循环
end
end
A->>S: 保存会话(messages + metadata)
A->>A: 检查 nudge 计数器<br/>(memory / skill)
opt nudge 触发
A->>A: _spawn_background_review()<br/>(后台线程)
end
A-->>E: 返回最终响应
E-->>U: 显示响应
B.2 工具发现与调度
对应章节:第 6 章(工具系统)、第 7 章(工具剖面)
graph TB
subgraph "启动时:工具发现"
A["model_tools._discover_tools()"] --> B["导入 tools/*.py 模块"]
B --> C["每个模块执行 registry.register()"]
C --> D["ToolRegistry 单例<br/>存储 ToolEntry 列表"]
end
subgraph "初始化时:工具过滤"
D --> E["get_tool_definitions()"]
E --> F{"enabled_toolsets /<br/>disabled_toolsets"}
F -->|匹配| G["生成 tool schema<br/>(JSON Schema 格式)"]
F -->|排除| H["跳过"]
G --> I["AIAgent.tools 列表"]
end
subgraph "运行时:工具调度"
I --> J["LLM 返回 tool_call"]
J --> K{"name 在<br/>valid_tool_names 中?"}
K -->|是| L["handle_function_call()"]
K -->|否| M["返回错误提示"]
L --> N{"entry.is_async?"}
N -->|是| O["_run_async()<br/>async→sync 桥接"]
N -->|否| P["直接调用 handler"]
O --> Q["返回工具结果"]
P --> Q
end
subgraph "特殊路径"
L --> R{"是 MCP 工具?"}
R -->|是| S["mcp_tool.py<br/>MCP 协议调用"]
L --> T{"是 Memory Provider 工具?"}
T -->|是| U["MemoryManager<br/>路由到 provider"]
end
style D fill:#f96,stroke:#333,stroke-width:2px
B.3 Memory Provider 生命周期
对应章节:第 11 章(Memory Provider 架构)
stateDiagram-v2
[*] --> 加载: load_memory_provider(name)
加载 --> 可用性检查: is_available()
state 可用性检查 <<choice>>
可用性检查 --> 注册: 可用
可用性检查 --> 跳过: 不可用(缺少 API key 等)
注册 --> 初始化: MemoryManager.add_provider()
初始化 --> 就绪: initialize_all(session_id, platform, user_id)
state 就绪 {
[*] --> 等待调用
等待调用 --> 工具注册: get_tool_schemas() → 追加到 AIAgent.tools
等待调用 --> 系统提示: system_prompt_block() → MemoryManager.build_system_prompt()
等待调用 --> 上下文注入: prefetch() / queue_prefetch() → 注入 recalled context
等待调用 --> 每轮开始: on_turn_start()
每轮开始 --> 等待调用
等待调用 --> 每轮同步: sync_turn()
每轮同步 --> 等待调用
等待调用 --> 会话结束: on_session_end()
会话结束 --> 等待调用
end
就绪 --> 清理: shutdown()
清理 --> [*]
跳过 --> [*]
B.4 Gateway 会话管理
对应章节:第 14 章(Gateway)
graph TB
subgraph "消息到达"
A["平台消息<br/>(Telegram / Discord / ...)"] --> B["BasePlatformAdapter<br/>.handle_message()"]
B --> C["提取 SessionSource<br/>(platform + user_id + chat_id)"]
end
subgraph "会话路由"
C --> D["SessionStore.get_or_create()"]
D --> E{"会话存在?"}
E -->|是| F{"过期?"}
E -->|否| G["创建新会话"]
F -->|是| H["重置会话<br/>保留记忆"]
F -->|否| I["复用会话"]
G --> J["分配 session_id"]
H --> J
I --> J
end
subgraph "Agent 调用"
J --> K["复用或构造 AIAgent<br/>(注入平台回调)"]
K --> L["agent.run_conversation()"]
L --> M["响应"]
end
subgraph "响应投递"
M --> N{"响应长度"}
N -->|短| O["单条消息"]
N -->|长| P["分段发送<br/>(Telegram 4096 字符限制)"]
N -->|含代码| Q["代码块格式化"]
O --> R["platform.send()"]
P --> R
Q --> R
end
subgraph "并发控制"
S["同一用户连续消息"] --> T["队列化处理<br/>防止 race condition"]
U["不同用户并行消息"] --> V["独立 session<br/>并行处理"]
end
style D fill:#9cf,stroke:#333,stroke-width:2px
B.5 上下文压缩流程
对应章节:第 12 章(上下文管理)
graph TB
A["run_conversation() 每轮循环开始"] --> B["估算当前 messages 的 token 数"]
B --> C{"token 数 > threshold?<br/>(默认 50% context window)"}
C -->|否| D["正常继续"]
C -->|是| E["触发压缩"]
E --> F["标记保护区域"]
F --> G["protect_first_n = 3<br/>(system prompt + 初始消息)"]
F --> H["protect_last_n = 20<br/>(最近的对话)"]
G --> I["中间区域:可压缩"]
H --> I
I --> J["对可压缩区域生成摘要"]
J --> K["使用同一模型<br/>或轻量模型"]
K --> L["替换:多条消息 → 1 条摘要消息"]
L --> M["重新计算 token 数"]
M --> N{"仍然超过阈值?"}
N -->|是| O["降低 protect_last_n<br/>再次压缩"]
N -->|否| P["压缩完成"]
P --> Q["注入压缩标记<br/>[CONTEXT COMPRESSED]"]
style E fill:#fc9,stroke:#333,stroke-width:2px
B.6 四层稳定性防御
对应章节:第 10 章(SessionDB)、第 19 章(并发模型)、第 20 章(进程生命周期)、第 21 章(运行时容错)
graph TB
subgraph "第 1 层:进程生命周期 (Ch20)"
A1["信号处理<br/>SIGTERM → 优雅关停"]
A2["Process Registry<br/>追踪子进程"]
A3["清理守护线程<br/>回收资源"]
A4["atexit 注册<br/>最终清理"]
end
subgraph "第 2 层:运行时防御 (Ch21)"
B1["SafeWriter<br/>broken pipe 保护"]
B2["API 重试 + 指数退避<br/>429/500/timeout"]
B3["Fallback Provider 链<br/>主模型不可用时切换"]
B4["Gateway 断线重连<br/>自动恢复连接"]
B5["平台消息投递重试<br/>send() 失败重试"]
end
subgraph "第 3 层:数据安全 (Ch10)"
C1["SQLite WAL 模式<br/>读写并发"]
C2["BEGIN IMMEDIATE<br/>写锁定"]
C3["Jitter Retry × 15<br/>锁竞争退避"]
C4["事务回滚<br/>部分写入恢复"]
end
subgraph "第 4 层:架构防御 (Ch19)"
D1["IterationBudget<br/>防无限循环"]
D2["70% / 90% 压力预警<br/>budget 消耗提醒"]
D3["async→sync 桥接<br/>线程隔离"]
D4["daemon 线程<br/>background review 自动终止"]
end
EXT["外部故障"] --> B1
EXT --> B2
EXT --> B4
INT["内部风险"] --> D1
INT --> D2
SYS["系统事件"] --> A1
SYS --> A2
DATA["数据竞争"] --> C1
DATA --> C3
style A1 fill:#fc9
style B2 fill:#f96
style C3 fill:#9cf
style D1 fill:#9f9
以上流程图使用 Mermaid 格式,可在 mdbook 中直接渲染。图中的行号和文件引用基于 Hermes Agent v0.8.0。