架构总览
相关源文件
本页面内容基于以下源文件生成:
- crates/openfang-kernel/src/lib.rs
- crates/openfang-runtime/src/lib.rs
- crates/openfang-api/src/lib.rs
- crates/openfang-channels/src/lib.rs
- crates/openfang-memory/src/lib.rs
- crates/openfang-types/src/lib.rs
- docs/architecture.md
- crates/openfang-runtime/src/tts.rs
- crates/openfang-runtime/src/mcp.rs
- crates/openfang-runtime/src/a2a.rs
- sdk/python/setup.py
- sdk/javascript/index.js
- packages/whatsapp-gateway/index.js
- Cargo.toml
- Dockerfile
- docker-compose.yml
- xtask/Cargo.toml
- sdk/javascript/package.json
- crates/openfang-api/Cargo.toml
- crates/openfang-cli/Cargo.toml
OpenFang 是一个用 Rust 编写的开源 Agent 操作系统,采用 Cargo workspace 组织 14 个 crate,依赖关系从上层到底层单向流动。系统核心由内核协调器、运行时执行引擎、类型系统、存储底座和通道层构成,支持 51 个 LLM 模型、40 个消息通道、MCP/A2A 协议以及多语言 SDK。
系统架构总览
OpenFang 采用分层架构设计,通过 Cargo workspace 组织 14 个 crate(13 个代码 crate + xtask 构建任务)。依赖关系严格单向流动:上层 crate 依赖下层,下层不依赖上层,确保了模块边界清晰和可测试性(docs/architecture.md:27-48)。
正在加载图表渲染器...
架构要点说明:
- 接口层:CLI 提供命令行交互和守护进程自动检测,桌面应用基于 Tauri 2.0 实现跨平台原生体验(docs/architecture.md:61-62)
- API 层:基于 Axum 0.8 构建,提供 76 个 REST 端点、WebSocket 实时聊天、SSE 流式响应,以及 OpenAI 兼容接口(docs/architecture.md:58)
- 核心层:内核作为中央协调器,组装 AgentRegistry、Scheduler、CapabilityManager、EventBus、WorkflowEngine 等子系统(docs/architecture.md:57)
- 运行时层:包含 Agent 执行引擎、通道适配器、P2P 网络协议和技能系统,支持 MCP/A2A 协议扩展(docs/architecture.md:56)
- 基础层:内存底座提供三层存储抽象,类型系统定义跨 crate 共享的核心数据结构(docs/architecture.md:54-55)
核心内核子系统
内核(openfang-kernel)是 OpenFang 的中央协调器,负责组装和管理所有子系统。通过 OpenFangKernel::boot_with_config() 启动时,内核按序初始化配置、内存底座、LLM 驱动、模型目录、计量引擎、核心子系统、RBAC、技能注册表和 Web 工具上下文(docs/architecture.md:71-139)。
子系统组成
内核模块声明展示了 20 个子系统组件(crates/openfang-kernel/src/lib.rs:6-27):
| 子系统 | 职责边界 | 关键数据结构 |
|---|---|---|
| AgentRegistry | Agent 实例的注册、查找、生命周期管理 | DashMap<AgentId, AgentEntry> |
| AgentScheduler | 配额跟踪、每小时窗口重置 | DashMap<AgentId, QuotaState> |
| CapabilityManager | 能力授予、继承验证、权限检查 | DashMap<AgentId, CapabilitySet> |
| EventBus | 异步事件广播、触发器评估 | async_broadcast::Sender<Event> |
| WorkflowEngine | 工作流注册、执行、运行驱逐(上限 200) | HashMap<WorkflowId, Workflow> |
| TriggerEngine | 事件模式匹配、触发器调度 | Vec<TriggerRule> |
| Supervisor | 健康监控、panic/重启计数 | DashMap<AgentId, HealthState> |
| WasmSandbox | Wasmtime 引擎、双重 fuel+epoch 计量 | Engine, Store |
启动序列
内核启动流程包含 14 个步骤(docs/architecture.md:73-139):
- 配置加载:读取
~/.openfang/config.toml,应用#[serde(default)]默认值,验证并记录警告 - 数据目录创建:确保
~/.openfang/data/存在 - 内存底座初始化:打开 SQLite 数据库(
openfang.db),运行 schema 迁移(至 v5),设置内存衰减率 - LLM 驱动初始化:从环境变量读取 API 密钥,创建配置 provider 的驱动,验证驱动配置
- 模型目录初始化:构建包含 51 个内置模型、20+ 别名、20 个 provider 的 ModelCatalog,运行
detect_auth()检测环境变量存在性(不读取密钥) - 计量引擎初始化:创建带有成本目录(20+ 模型家族)的 MeteringEngine,连接模型目录作为定价源
- 模型路由器初始化:创建带有 TaskComplexity 评分的 ModelRouter,验证配置模型并解析别名
- 核心子系统初始化:初始化 AgentRegistry、CapabilityManager、EventBus、AgentScheduler、Supervisor、WorkflowEngine、TriggerEngine、BackgroundExecutor、WasmSandbox
- RBAC 认证管理器初始化:创建带有 UserRole 层级的 AuthManager,设置通道身份解析
- 技能注册表初始化:通过
parse_bundled()加载 60 个捆绑技能,从磁盘加载用户安装的技能,将技能工具接入 tool_runner 回退链 - Web 工具上下文初始化:创建 WebSearchEngine(4-provider 级联:Tavily→Brave→Perplexity→DDG)和 WebFetchEngine(SSRF 保护)
- 持久化 Agent 恢复:从 SQLite 加载所有 Agent,在内存中重新注册(registry、capabilities、scheduler),设置状态为 Running
- 发布 KernelStarted 事件
- 返回内核实例
Agent 生命周期
Agent 状态机包含三个状态(docs/architecture.md:176-178):
- Running:Agent 活跃,可接收消息
- Suspended:Agent 暂停(如守护进程关闭期间),持久化到 SQLite 以便下次启动恢复
- Terminated:Agent 已被杀死,从注册表和持久存储中移除
Spawn 流程(docs/architecture.md:180-192):
- 生成新
AgentId(UUID v4)和SessionId - 在内存底座创建会话
- 解析 manifest 并提取能力
- 验证能力继承(
validate_capability_inheritance()防止权限提升) - 通过
CapabilityManager授予能力 - 向
AgentScheduler注册(配额跟踪) - 创建
AgentEntry并在AgentRegistry注册 - 通过
memory.save_agent()持久化到 SQLite - 如果 Agent 有父级,更新父级的子级列表
- 注册主动触发器(如果调度模式为
Proactive) - 发布
Lifecycle::Spawned事件并评估触发器
Kill 流程(docs/architecture.md:219-228):
- 检查调用者具有
AgentKill(target_name)能力 - 从
AgentRegistry移除 - 通过
BackgroundExecutor停止后台循环 - 从
AgentScheduler注销 - 撤销所有能力
- 从
EventBus取消订阅 - 移除触发器
- 从持久存储(SQLite)移除
运行时与类型系统
运行时执行引擎
运行时(openfang-runtime)是 Agent 执行引擎,包含 Agent 循环、3 个原生 LLM 驱动、23 个内置工具、WASM 沙箱、MCP 客户端/服务器、A2A 协议实现(docs/architecture.md:56)。
LLM 驱动抽象(docs/architecture.md:331-355):
rust1#[async_trait] 2pub trait LlmDriver: Send + Sync { 3 async fn send_message( 4 &self, 5 model: &str, 6 system_prompt: &str, 7 messages: &[Message], 8 tools: &[ToolDefinition], 9 ) -> Result<LlmResponse, OpenFangError>; 10 11 async fn send_message_streaming( 12 &self, 13 model: &str, 14 system_prompt: &str, 15 messages: &[Message], 16 tools: &[ToolDefinition], 17 tx: mpsc::Sender<StreamEvent>, 18 ) -> Result<LlmResponse, OpenFangError>; 19 20 fn key_required(&self) -> bool; 21}
三个原生驱动实现覆盖 20 个 provider 和 51 个模型(docs/architecture.md:359-366):
- AnthropicDriver:原生 Anthropic Messages API,处理 Claude 特性(内容块包括图像、工具使用块、流式 delta),支持
ContentBlock::Image及媒体类型验证和 5MB 上限 - GeminiDriver:原生 Google Gemini API(v1beta),使用
x-goog-api-key认证、systemInstruction、functionDeclarations、streamGenerateContent?alt=sse - OpenAiCompatDriver:OpenAI 兼容 Chat Completions API,适用于任何实现 OpenAI API 格式的 provider,覆盖 18+ provider 包括 OpenAI、DeepSeek、Groq、Mistral、Together 和本地运行器
Provider 配置表(docs/architecture.md:369-391):
| Provider | 驱动 | Base URL | 密钥要求 |
|---|---|---|---|
anthropic | Anthropic | https://api.anthropic.com | Yes |
gemini | Gemini | https://generativelanguage.googleapis.com | Yes |
openai | OpenAI-compat | https://api.openai.com | Yes |
deepseek | OpenAI-compat | https://api.deepseek.com | Yes |
groq | OpenAI-compat | https://api.groq.com/openai | Yes |
ollama | OpenAI-compat | http://localhost:11434 | No |
vllm | OpenAI-compat | http://localhost:8000 | No |
lmstudio | OpenAI-compat | http://localhost:1234 | No |
Per-Agent 驱动解析:每个 Agent 可覆盖内核默认 provider(docs/architecture.md:393-402):
toml1[model] 2provider = "openai" # 不同于内核默认 3model = "gpt-4o" 4api_key_env = "OPENAI_API_KEY" # 自定义密钥环境变量 5base_url = "https://custom.api.com" # 可选自定义端点
类型系统
类型系统(openfang-types)定义跨内核、运行时、内存底座和线协议共享的所有数据结构,不包含业务逻辑(crates/openfang-types/src/lib.rs:1-5)。
核心类型模块(crates/openfang-types/src/lib.rs:6-23):
| 模块 | 职责 | 关键类型 |
|---|---|---|
agent | Agent 定义 | AgentManifest, AgentId |
capability | 能力系统 | Capability 枚举 |
config | 配置结构 | KernelConfig |
error | 错误类型 | OpenFangError |
event | 事件系统 | Event 枚举 |
memory | 内存类型 | Memory trait |
message | 消息结构 | Message, ContentBlock |
tool | 工具定义 | ToolDefinition |
taint | 污点追踪 | TaintLabel, TaintSet |
model_catalog | 模型目录 | ModelCatalogEntry, ProviderInfo, ModelTier |
安全特性:
- Ed25519 manifest 签名:确保 Agent manifest 完整性
- 污点追踪:
TaintLabel和TaintSet跟踪数据来源和信任级别 - 工具兼容性映射:21 个 OpenClaw 到 OpenFang 的工具名映射
- 前向兼容配置:所有配置结构使用
#[serde(default)]支持 TOML 解析
Agent 循环稳定性
Agent 循环包含多层硬化以防止失控行为(docs/architecture.md:232-277):
- 工具执行超时:所有工具执行包装在 60 秒
tokio::time::timeout中,超限返回超时错误而非无限挂起 - 最大继续次数:
MAX_CONTINUATIONS = 3防止无限"请继续"循环,3 次继续尝试后 Agent 返回部分响应 - Agent 间调用深度限制:
MAX_AGENT_CALL_DEPTH = 5通过tokio::task_local!在 tool runner 中强制执行 - 稳定性指南:
STABILITY_GUIDELINES追加到每个 Agent 的系统提示,包含反循环和反重试行为规则 - 块感知压缩:会话压缩器处理所有内容块类型(Text、ToolUse、ToolResult、Image),当会话超过配置阈值(默认上下文窗口 80%)时触发自动压缩,保留最近消息(默认 20 条)
存储与通道层
内存底座
内存底座(openfang-memory)提供三层存储后端的统一抽象(crates/openfang-memory/src/lib.rs:1-8):
- 结构化存储(SQLite):键值对、会话、Agent 状态
- 语义存储:基于文本的搜索(Phase 1: LIKE 匹配,Phase 2: Qdrant 向量)
- 知识图谱(SQLite):实体和关系
Agent 通过单一 Memory trait 与所有三层存储交互(crates/openfang-memory/src/lib.rs:8)。
存储模块(crates/openfang-memory/src/lib.rs:10-16):
| 模块 | 职责 |
|---|---|
structured | 结构化 KV 存储 |
semantic | 语义搜索 |
knowledge | 知识图谱 |
session | 会话管理 |
consolidation | 记忆整合 |
usage | 使用事件持久化 |
migration | Schema 迁移 |
六层存储(docs/architecture.md:282-322):
- 结构化 KV 存储:Per-agent 键值存储,键为字符串,值为 JSON,由
memory_store和memory_recall工具使用。共享内存命名空间(固定 Agent ID00000000-...01)启用跨 Agent 数据共享 - 语义搜索:基于文本的搜索,Phase 1 使用 LIKE 匹配,Phase 2 使用 Qdrant 向量嵌入
- 知识图谱:实体和关系存储,支持复杂知识推理
- 会话管理:对话历史持久化,支持会话修复和压缩
- 任务板:多 Agent 协作的共享任务队列,支持
task_post、task_claim、task_complete、task_list操作 - 使用追踪和规范会话:
usage_events表持久化 token 计数、成本估算和模型使用;CanonicalSession跟踪用户跨通道对话上下文
SQLite 架构(docs/architecture.md:323-326):
所有内存操作通过 Arc<Mutex<Connection>> 配合 Tokio 的 spawn_blocking 进行异步桥接,确保线程安全而无需异步 SQLite 驱动。Schema 迁移自动运行五个版本(V1 核心、V2 协作、V3 嵌入、V4 使用、V5 canonical_sessions)。
通道层
通道层(openfang-channels)提供 40 个可插拔消息集成,将平台消息转换为统一的 ChannelMessage 事件供内核处理(crates/openfang-channels/src/lib.rs:3-5)。
通道适配器模块(crates/openfang-channels/src/lib.rs:6-42):
| 类别 | 通道 |
|---|---|
| 即时通讯 | Telegram, Discord, Slack, WhatsApp, Signal, Matrix, IRC, XMPP, LINE, Viber, Messenger |
| 企业协作 | Teams, Mattermost, Google Chat, Rocket.Chat, Zulip, Feishu, Nextcloud, Guilded, Keybase, Threema, Pumble, Flock, Twist, Mumble, DingTalk, Gitter |
| 社交媒体 | Twitch, Reddit, Mastodon, Bluesky, Revolt, Nostr, LinkedIn, Discourse |
| 通知服务 | Email, Webhook, Ntfy, Gotify, Webex |
核心组件(docs/architecture.md:59):
- ChannelAdapter trait:每个适配器实现的统一接口
- AgentRouter:消息路由
- BridgeManager:生命周期协调
- ChannelRateLimiter:Per-user DashMap 跟踪的限流器
- formatter.rs:Markdown 到 TelegramHTML/SlackMrkdwn/PlainText 的格式转换
- ChannelOverrides:model/system_prompt/dm_policy/group_policy/rate_limit/threading/output_format 覆盖
DM/Group 策略执行:ChannelBridgeHandle.authorize_channel_user() 强制执行 DM/group 策略(docs/architecture.md:197)。
协议与扩展生态
MCP 协议
MCP(Model Context Protocol)支持 stdio 和 SSE 两种传输类型(crates/openfang-runtime/src/mcp.rs:39-51):
rust1pub enum McpTransport { 2 /// Subprocess with JSON-RPC over stdin/stdout. 3 Stdio { 4 command: String, 5 #[serde(default)] 6 args: Vec<String>, 7 }, 8 /// HTTP Server-Sent Events. 9 Sse { url: String }, 10}
McpConnection 结构(crates/openfang-runtime/src/mcp.rs:57-71):
| 字段 | 类型 | 职责 |
|---|---|---|
config | McpServerConfig | 连接配置 |
tools | Vec<ToolDefinition> | 通过 tools/list 发现的工具 |
original_names | HashMap<String, String> | 命名空间工具名到原始工具名的映射 |
transport | McpTransportHandle | 传输句柄(stdio 子进程或 HTTP) |
next_id | u64 | 下一个 JSON-RPC 请求 ID |
连接流程(crates/openfang-runtime/src/mcp.rs:127-156):
- 根据传输类型建立连接(stdio 或 SSE)
- 执行初始化握手
- 发现工具
- 存储命名空间工具(
mcp_{server}_{tool}格式)
安全特性:SSE 连接执行 SSRF 检查,拒绝私有/localhost URL 除非显式配置(crates/openfang-runtime/src/mcp.rs:134-135)。
A2A 协议
A2A(Agent-to-Agent)协议实现 Agent 间通信,定义任务状态、消息和工件结构。
A2aTaskStatusWrapper(crates/openfang-runtime/src/a2a.rs:136-154):
支持两种序列化形式(Object 和 Enum),提供 state() 方法获取任务状态,实现 From<A2aTaskStatus> 和 PartialEq<A2aTaskStatus> trait。
A2aMessage 结构(crates/openfang-runtime/src/a2a.rs:156-163):
| 字段 | 类型 | 描述 |
|---|---|---|
role | String | 消息角色("user" 或 "agent") |
parts | Vec<A2aPart> | 消息内容部分 |
A2aPart 枚举(crates/openfang-runtime/src/a2a.rs:165-182):
| 变体 | 字段 | 描述 |
|---|---|---|
Text | text: String | 文本内容 |
File | name, mime_type, data | 文件内容(base64 编码) |
Data | mime_type, data | 结构化数据 |
A2aArtifact 结构(crates/openfang-runtime/src/a2a.rs:184-190): 任务产生的工件,包含可选名称、必需的描述和内容部分。
SDK 生态
Python SDK(sdk/python/setup.py:1-14):
- 包名:
openfang - 版本:0.1.0
- 描述:OpenFang Agent OS REST API 的官方 Python 客户端
- 模块:
openfang_sdk,openfang_client - Python 要求:>=3.8
JavaScript SDK(sdk/javascript/index.js:467-479):
- 导出:
OpenFang类和OpenFangError错误类 - 提供完整的 REST API 封装,包括 Agent、Workflow、Trigger、Memory、Channel、Schedule 等资源管理
数据流与调用链
消息处理流程
以下时序图展示从用户消息到 Agent 响应的完整数据流:
正在加载图表渲染器...
流程要点说明(docs/architecture.md:194-217):
- RBAC 检查:
AuthManager解析通道身份并检查用户角色权限 - 通道策略检查:
ChannelBridgeHandle.authorize_channel_user()强制执行 DM/group 策略 - 配额检查:
AgentScheduler验证 Agent 未超过 token-per-hour 限制 - 模块分发:基于
manifest.module分发到 LLM agent 循环、WASM 沙箱或 Python 子进程 - LLM agent 循环:加载会话、规范上下文、追加稳定性指南、解析驱动、收集工具、初始化循环守卫、运行迭代循环、自动压缩会话
- 成本估算:
MeteringEngine.estimate_cost_with_catalog()计算美元成本 - 使用记录:更新配额跟踪的 token 计数,持久化使用事件
核心设计决策与取舍
1. 单向依赖架构
决策:采用严格的单向依赖流,下层 crate 不依赖上层。
理由:
- 确保模块边界清晰,避免循环依赖
- 提高可测试性,下层模块可独立测试
- 支持增量编译,减少构建时间
限制:上层模块无法直接访问下层模块的内部状态,必须通过公开 API 交互。
2. SQLite 作为统一存储后端
决策:使用 SQLite 作为所有存储层的后端,通过 Arc<Mutex<Connection>> + spawn_blocking 实现异步桥接。
理由:
- 零配置、嵌入式、单文件部署简单
- ACID 事务保证数据一致性
- 足够支撑中小规模部署场景
替代方案:PostgreSQL(更强的并发能力,但增加部署复杂度)、RocksDB(更高性能,但缺乏 SQL 查询能力)。
限制:写入并发受限于 SQLite 的单写者模型,高并发场景需要考虑连接池优化。
3. 三驱动覆盖 20+ Provider
决策:实现三个原生驱动(Anthropic、Gemini、OpenAI-compat)覆盖 20+ provider。
理由:
- 减少维护负担,避免为每个 provider 维护独立驱动
- OpenAI API 已成为事实标准,大多数 provider 提供兼容接口
- 原生驱动针对特定 provider 优化(如 Anthropic 的内容块、Gemini 的系统指令)
限制:无法利用某些 provider 的独特特性(如 OpenAI 的 function calling 高级功能)。
4. 能力继承验证
决策:通过 validate_capability_inheritance() 防止权限提升。
理由:
- Agent 可能由不可信来源创建
- 子 Agent 不应获得比父 Agent 更高的权限
- 能力系统提供细粒度访问控制
实现:在 Agent spawn 流程中强制执行,拒绝违反继承规则的创建请求。
5. 多层循环防护
决策:实现工具超时、最大继续次数、Agent 间调用深度限制、稳定性指南等多层防护。
理由:
- LLM 可能陷入重复行为模式
- 工具执行可能无限挂起
- Agent 间调用可能形成无限递归
限制:某些复杂任务可能需要更多迭代次数,需要通过配置调整限制。
技术选型表格
| 技术 | 用途 | 选型理由 | 替代方案 |
|---|---|---|---|
| Rust | 系统编程语言 | 内存安全、零成本抽象、异步支持、编译时保证 | Go(GC 停顿)、C++(内存安全风险) |
| Tokio | 异步运行时 | 生态成熟、性能优异、社区活跃 | async-std(生态较小) |
| Axum 0.8 | HTTP 框架 | 类型安全、与 Tower 生态集成、性能优异 | Actix-web(API 设计差异)、Warp(学习曲线) |
| SQLite | 存储后端 | 零配置、嵌入式、ACID 事务、单文件部署 | PostgreSQL(部署复杂)、RocksDB(无 SQL) |
| Wasmtime | WASM 运行时 | 安全沙箱、fuel+epoch 双重计量、WASI 支持 | Wasmer(生态差异) |
| Mermaid | 架构图 | 文本定义、GitHub 原生渲染、版本控制友好 | PlantUML(需要 Java)、Draw.io(二进制) |
| Tauri 2.0 | 桌面应用 | 轻量、跨平台、系统托盘支持、移动就绪 | Electron(体积大)、Flutter Desktop(生态差异) |
| Clap | CLI 框架 | derive 宏、子命令支持、自动补全生成 | StructOpt(已合并到 Clap) |
| Serde | 序列化 | 零成本抽象、derive 宏、格式无关 | 手动实现(维护负担) |
| tracing | 日志/追踪 | 结构化日志、span 支持、订阅者灵活 | log(功能较少) |
| DashMap | 并发 Map | 无锁读取、细粒度锁、性能优异 | RwLock<HashMap>(写锁阻塞) |
| Ed25519 | Manifest 签名 | 快速验证、小签名、安全可靠 | RSA(性能差)、ECDSA(实现复杂) |
模块依赖关系图
正在加载图表渲染器...
依赖要点说明(docs/architecture.md:29-48):
- 基础层(openfang-types):被所有其他 crate 依赖,定义共享类型,无外部依赖
- 数据层(openfang-memory):依赖 types,提供存储抽象,被 runtime 和 channels 依赖
- 执行层:依赖 memory 和 types,提供具体实现(runtime、channels、wire、skills、migrate)
- 协调层(openfang-kernel):依赖执行层所有 crate,组装子系统
- 服务层(openfang-api):依赖 kernel,暴露 HTTP 接口
- 应用层:依赖 api 和 kernel,提供用户界面(CLI、Desktop)
关键配置与启动流程
配置文件结构
主配置文件位于 ~/.openfang/config.toml,使用 #[serde(default)] 支持前向兼容(docs/architecture.md:74-77)。
Per-Agent 配置覆盖(docs/architecture.md:396-402):
toml1[model] 2provider = "openai" # 覆盖内核默认 provider 3model = "gpt-4o" # 指定模型 4api_key_env = "OPENAI_API_KEY" # 自定义密钥环境变量 5base_url = "https://custom.api.com" # 可选自定义端点
守护进程启动
当守护进程包装内核时,额外执行以下步骤(docs/architecture.md:141-150):
- 设置自句柄:弱 Arc 引用用于触发器分发
- 连接 MCP 服务器:后台连接到配置的 MCP 服务器(stdio/SSE),命名空间工具为
mcp_{server}_{tool},存储连接到kernel.mcp_connections - 启动心跳监控:监控 Agent 健康状态
CLI 守护进程检测
CLI 实现守护进程自动检测(docs/architecture.md:61):
- 检查
~/.openfang/daemon.json - 执行健康 ping
- 如果守护进程运行,使用 HTTP 通信
- 否则启动进程内内核作为回退
