# NanoClaw 架构图 ## 系统概览 ```mermaid flowchart TB subgraph Platforms["消息平台"] P1[Discord] P2[Telegram] P3[Slack] P4[GitHub / Linear] P5[WhatsApp / iMessage / Teams / GChat / Matrix / Webex / Email] end subgraph Host["宿主机进程 (Node)"] direction TB Bridge["Chat SDK 桥接
(src/channels/chat-sdk-bridge.ts)"] Router["路由器
(src/router.ts)
platformId + threadId -> messaging_group -> agent_group -> session"] SessMgr["Session 管理器
(src/session-manager.ts)
创建 inbound.db + outbound.db"] Runner["容器运行器
(src/container-runner.ts)
OneCLI ensureAgent + 启动"] Delivery["投递轮询器
(src/delivery.ts)
活跃时 1s / sweep 时 60s"] Sweep["宿主机 Sweep
(src/host-sweep.ts)
心跳、重试、重复执行"] Central[("中央库
data/v2.db
agent_groups
messaging_groups
messaging_group_agents
sessions
pending_approvals")] end subgraph OneCLI["OneCLI 网关 (0.3.1)"] Vault["Agent Vault
秘密 + OAuth"] Approvals["configureManualApproval
-> pending_approvals"] end subgraph Session["每个 Session 的容器 (Docker / Apple Container)"] direction TB PollLoop["轮询循环
(container/agent-runner)"] Provider["Agent 提供程序
(claude、opencode、mock;待办: codex)"] MCP["MCP 工具
send_message, send_file, edit_message,
add_reaction, send_card, ask_user_question,
schedule_task, create_agent,
install_packages, add_mcp_server"] Skills["容器技能
(container/skills/)"] InDB[("inbound.db
宿主机写入
偶数 seq
messages_in
destinations
processing_ack")] OutDB[("outbound.db
容器写入
奇数 seq
messages_out
心跳文件")] end subgraph Groups["Agent Group 文件系统 (groups/*)"] Folder["CLAUDE.md
记忆
每个 group 的技能
container_config"] end P1 & P2 & P3 & P4 & P5 --> Bridge Bridge --> Router Router --> Central Router --> SessMgr SessMgr --> InDB SessMgr --> Runner Runner --> OneCLI Runner --> PollLoop PollLoop --> InDB PollLoop --> Provider Provider --> MCP Provider --> Skills MCP --> OutDB OutDB --> Delivery Delivery --> Central Delivery --> Bridge Bridge --> P1 & P2 & P3 & P4 & P5 Sweep --> InDB Sweep --> OutDB Sweep --> Central Runner -.挂载.-> Folder MCP -.审批.-> Approvals Approvals --> Central Provider -.API 调用.-> Vault ``` ## 消息流程 (入站 -> agent -> 出站) ```mermaid sequenceDiagram participant P as 平台 (例如 Telegram) participant B as Chat SDK 桥接 participant R as 路由器 participant SM as Session 管理器 participant IDB as inbound.db participant C as 容器 (agent-runner) participant ODB as outbound.db participant D as 投递轮询器 P->>B: 新消息 B->>R: routeInbound(platformId, threadId, msg) R->>R: 解析 messaging_group -> agent_group -> session
(agent-shared | shared | per-thread) R->>SM: 确保 session + DB 存在 R->>IDB: INSERT messages_in (偶数 seq) R->>C: 唤醒容器 (docker run / 已在运行) C->>IDB: 轮询 messages_in C->>C: 格式化 xml, 流式传输到选定的 provider C->>ODB: INSERT messages_out (奇数 seq)
解析 块 D->>ODB: 1s 轮询(活跃)/ 60s(sweep) D->>D: hasDestination() 重新验证 D->>B: 通过适配器投递 B->>P: 发送消息 / 编辑 / 反应 / 文件 / 卡片 ``` ## 命名目的地 + Agent 到 Agent ```mermaid flowchart LR subgraph AgentA["Agent Group A (主agent)"] A_out["输出:
<message to='slack'>...</message>
<message to='browser-agent'>...</message>
<internal>scratchpad</internal>"] end subgraph Dests["inbound.db.destinations (每个 agent)"] D1["slack -> messaging_group 42"] D2["browser-agent -> agent_group 7
(双向行)"] D3["github -> messaging_group 13"] end subgraph AgentB["Agent Group B (浏览器子agent)"] B_session["自己的 inbound.db / outbound.db
继承了返回到 A 的目的地"] end Slack[Slack 频道] GitHub[GitHub PR 线程] A_out -->|解析 + 查找| Dests D1 -->|投递| Slack D2 -->|写入 B 的 inbound.db| B_session D3 -->|投递| GitHub B_session -.通过 'parent' 回复.-> Dests ``` ## 实体模型 + 隔离级别 ```mermaid erDiagram agent_groups ||--o{ messaging_group_agents : 已连接 messaging_groups ||--o{ messaging_group_agents : 已连接 agent_groups ||--o{ sessions : 运行 messaging_groups ||--o{ sessions : 上下文 agent_groups ||--o{ agent_destinations : 拥有 agent_groups ||--o{ pending_approvals : 请求 agent_groups { int id string name string folder string agent_provider json container_config } messaging_groups { int id string channel_type string platform_id string name bool is_group string unknown_sender_policy "strict | request_approval | public" } users { string id PK "命名空间 :" string kind string display_name } user_roles { string user_id FK string role "owner | admin" string agent_group_id FK "null = 全局" } agent_group_members { string user_id FK string agent_group_id FK } user_dms { string user_id FK string channel_type string messaging_group_id FK } messaging_group_agents { int messaging_group_id int agent_group_id string session_mode "agent-shared | shared | per-thread" json trigger_rules int priority } sessions { int id int agent_group_id int messaging_group_id string sdk_session_id string status } ``` ### 隔离级别速查表 | 级别 | `session_mode` | 共享内容 | 示例 | |---|---|---|---| | 1. 共享 session | `agent-shared` | 工作区 + 记忆 + 对话 | Slack + GitHub webhooks 在同一线程 | | 2. 相同 agent,独立 session | `shared` / `per-thread` | 仅工作区 + 记忆 | 一个 agent 跨 3 个 Telegram 聊天 | | 3. 独立的 agent group | (不同的 `agent_group_id`) | 无 | 个人 vs 工作频道 | ## 双库拆分(为什么) ```mermaid flowchart LR subgraph Mount["/workspace (挂载到容器中的卷)"] In[("inbound.db")] Out[("outbound.db")] HB["/.heartbeat (文件 touch)"] end Host[宿主机进程] -->|"仅写入
(偶数 seq)"| In Host -->|读取| Out Container[agent-runner] -->|读取| In Container -->|"仅写入
(奇数 seq)"| Out Container -->|每次轮询 touch| HB HostSweep[宿主机 sweep] -->|stat mtime| HB HostSweep -->|读取 processing_ack| In note1["每个文件有且仅有一个写入者。
消除了 SQLite 跨进程写入竞争。
无冲突的 seq 编号。"] ```