刚刚在社区开源了我的个人agent项目,今天就来扒开里边看看我是怎么一步一步架构设计实现到现在这样的开源的帖子地址在这里后续我会不断分享细节设计。希望佬们一起交流进步 6个月+几百亿token,终于做出了用起来很舒服的Agent,功能齐全对标Codex! 资源荟萃 本帖使用社区开源推广,符合推广要求。我申明并遵循社区要求的以下内容: 我的帖子已经打上 开源推广 标签: 是 我的开源项目完整开源,无未开源部分: 是 我的开源项目已链接认可 LINUX DO 社区: 是 我帖子内的项目介绍,AI生成、润色内容部分已截图发出: 是 以上选择我承诺是永久有效的,接受社区和佬友监督: 是 以下为项目介绍正文内容,AI生成、润色内容已使用截图方式发出 作为程序员… 一、三个核心架构决策 先给全局结论,后面逐个展开: Agent Loop 与宿主分离 :Rust 只负责「如何思考、调用模型、编排工具、传递事件」,宿主(Electron/Flutter)负责「如何展示、如何接入平台」。AI 永远碰不到宿主本体。 三端同核 :CLI、桌面、移动端共用同一个 Rust Agent Loop,一个协议、一套测试,避免多端行为漂移。 工具契约显式化 :每一层能力(谁执行、谁可见、谁维护)都有 ownership 元数据和契约测试守护,不靠口头约定。 ┌─ Flutter 移动 App ───── FFI 进程内启动 + 鉴权 loopback WebSocket Rust harness ───┼─ CLI(worldbase chat/run/projects)── in-process 直链 core └─ Electron 桌面 ────────── stdio NDJSON JSON-RPC(spawn 二进制) 二、Monorepo 三 workspace + 17 个 crate 仓库按语言和运行时边界拆成三个独立 workspace, 不合并成一个跨语言依赖图 : the-world/ ├── apps/electron/ # Workspace 1: Electron + Vue 3,UI 与桌面宿主能力 ├── harness-rs/ # Workspace 2: 唯一 Rust Cargo workspace(Agent 核心) └── apps/mobile/ # Workspace 3: Flutter,Rust 经 FFI 进程内运行 Rust 侧围绕 Agent Loop 组织成 17 个 crate(分层思路对齐 OpenAI codex-rs): harness-rs/crates/ ├── core/ # Agent 循环 · session/turn · 工具注册 · 权限引擎 · dispatcher ├── protocol/ # JSON-RPC schema、capabilities、事件帧(camelCase 冻结) ├── providers/ # OpenAI / Anthropic / Mock,SSE 流式(reqwest + rustls) ├── tools/ # 原生工具 + Electron 契约快照 + capability 过滤 ├── group/ # 群组协作状态机(5 模式 + 黑板) ├── memory/ # SQLite + FTS5 会话/消息/长期记忆 ├── skills/ # YAML 技能引擎 ├── scheduler/ # 标准 5 段 cron 定时任务(SQLite 持久化) ├── mcp-client/ # MCP stdio / HTTP 客户端 ├── docs/ # 文档解析与基础编辑(calamine/lopdf/OOXML) ├── search/ # Glob/Grep(ignore crate,尊重 gitignore,ripgrep 级检索) ├── app-server/ # stdio NDJSON JSON-RPC(Electron 接入) ├── cli/ # worldbase chat / run / projects ├── exec/ # 命令执行 + macOS Seatbelt 沙箱(桌面域) ├── project-runtime/ # 内置 Node/pnpm 项目运行时(桌面域) ├── im-gateway/ # IM webhook 连接器(飞书/Slack 适配,桌面域) └── mobile-ffi/ # Flutter FFI 导出面(start/get_auth_token/stop) 两条硬规则: harness-rs 不依赖 Electron 或 Flutter ;Electron 不直接链接 Rust crate、Flutter 不复制 Agent 业务逻辑。三个端只通过协议或 FFI 边界交流。 三、为什么选 Rust? 不是信仰,是四个工程理由: 一套 Agent Loop 覆盖三端 。CLI、Electron、Flutter 如果各写一套循环,行为漂移只是时间问题。Rust core 一份实现,三端接入。 provider、权限、取消、事件可以集中测试 ,不依赖某个 UI 宿主。 cargo test --workspace 一条命令验证核心行为。 文档解析跨端复用 。PDF/Word/Excel/PPT 解析用 Rust 生态(calamine、lopdf、OOXML parser),不必把 Node 文档依赖带进移动端。 保留单二进制 / FFI 的分发可能性 。移动端走 dart:ffi 进程内加载,不需要 App 旁边再跑一个服务器。 四、协议设计:一个 dispatcher,三种 transport 核心抽象是「 通用承载 」:同一个 dispatcher,按宿主形态换 transport。 JSON-RPC 2.0 全双工 。宿主 → harness 是命令与流式请求;harness → 宿主是事件通知(带 seq)和 反向请求 (权限弹窗、页面自动化、对话框)。 stdio 上用 NDJSON (换行分隔 JSON),日志走 stderr——和 codex app-server 同款方案。 握手即能力协商 。连接建立时交换 protocolVersion 和 capabilities :宿主声明「我能提供哪些端口、注入哪些工具」,harness 据此动态启用或隐藏对应 Agent 工具。 移动端网络不稳定是 P0 需求,所以事件帧带 seq ,断线重连后可以续传: // 事件帧 {"jsonrpc": "2.0", "method": "ai.stream.event", "params": {"id": 42, "seq": 117, "kind": "delta", "text": "..."}} // 断线重连后 {"jsonrpc": "2.0", "id": 43, "method": "ai.stream.resume", "params": {"id": 42, "afterSeq": 117}} 五、Host Bridge:宿主能力注入与「冻结的 68 项契约」 这是整个迁移里最容易被误解的设计,单独讲。 Rust 负责 Agent Loop,但 Electron 上已经有大量成熟的宿主工具(项目运行时、窗口、页面自动化、图片队列……)。全部重写?不。机制是 能力注入 + host bridge : Electron 既有 68 项公开工具定义 是冻结的 Node 宿主兼容快照,名称、description、JSON Schema 由契约快照测试保持一致,防止漂移。 Rust Agent Loop 执行到这些工具时,通过反向 tool.execute RPC 交回 Electron handler 执行( electron_host_override )。 新通用工具一律在 Rust 实现 ,标记 electron_native() == true 后直接进入 Electron 工具目录——不需要改 68 项快照,也不需要建 Node placeholder。 一条 ownership 规则贯穿始终: 「工具契约对齐」不等于「所有 handler 都已 Rust 化」 。谁执行、谁维护,元数据里写得清清楚楚,契约测试防止边界漂移。 渐进切换的成本也被压到最低——renderer 和 preload 基本不动,只换 main 里的 IPC 代理: // 切换前 ipcMain.handle('conversations:list', (e, args) => conversationStore.list(args)) // 切换后 ipcMain.handle('conversations:list', (e, args) => harness.call('conversations.list', args)) 六、Agent 闭环:生成不是终点,持续管理才是 大部分 AI 工具的流程是:需求 → 生成代码 → 交付,结束。WorldBase 的核心设计目标是让 Agent 对自己生成的东西拥有 持续的管理能力 。 子项目不是「独立运行的小应用」,而是主 AI 管理范围内的 受控服务 。Agent 拿到的工具面: 工具 能力 安全设计 read/write_project_file 读写子项目任意文件 大文件按行分段(默认 200 行,上限 400),写入自动 git commit call_project_api 调用运行中项目的 HTTP API 验证自己的修改真实生效 query_project_database 直接查询子项目 SQLite 仅允许 SELECT ,只读硬约束 analyze_project_data 统计/趋势分析 走宿主数据分析层 safe-write 修改前快照、支持回滚 createSnapshot / rollback 于是「帮我看看那个记账应用最近的数据有什么异常」这句话,Agent 的真实执行路径是:查库(只读 SQL)→ 定位异常 → 读代码找原因 → 改代码 → 调 API 验证 → 必要时回滚。 这一圈闭环是整个项目最核心的架构资产 ——工具不是死文件,是活的能力。 进程层面还有配套设计:项目运行时由内置 Node/pnpm 管理(spawn、健康检查、日志流、端口分配从 :3100 起),LAN Server(:19527)反向代理所有子项目,局域网直接访问。 七、多 Agent 群组:从「协调者传话」到真对话 群组协作经历了两次架构演进,这段踩坑史值得单独说。 第一版是 hub-and-spoke :所有交互必须经 coordinator 中转,成员间无链路;discussion 模式下成员被禁用全部工具,只能「空对空」写笔记;轮次是硬同步屏障;SharedBoard 类型定义了却从未实例化(死代码)。讨论质量可想而知。 第二版重构为点对点 + 共享黑板 : 5 种路由模式 : coordinator_only / targeted / discussion / coordinator_decides / mentioned_agent_decides ,由 @提及 解析决定 共享黑板 :目标 / 假设 / 任务认领 / 决策 / 证据 / 待解问题六字段,显式可查的共享状态( group.board.update ) 讨论中可用工具 :成员不再被剥夺工具,能读文件、能搜索 人在环中(HITL) : group.inject 允许用户中途注入澄清、纠正方向,不用等整轮结束 纯状态机实现 :群组状态机在 Rust group crate,全端复用——桌面和手机跑的是同一套逻辑 子 Agent( spawn_subagents )则保持隔离并行语义:各自独立上下文、互不可见、阻塞到全部完成——这是刻意设计,和群组讨论是两种互补的编排形态。 八、记忆系统:三个模型必须分开 记忆架构里最容易踩的坑:把 Chat Model、Memory Analysis Model、Embedding Model 当成一个东西。WorldBase 显式拆成三层: Chat Model ——回答问题、执行工具、参与对话 Memory Analysis Model ——从对话提取候选记忆、生成摘要、合并冲突、判断重要性(可复用聊天模型,但职责独立) Embedding Model ——文本 → 向量,检索时必须用同一模型生成 query vector,维度/预处理/距离度量必须匹配 存储与索引策略: SQLite 事实数据、来源、状态、任务、FTS5 全文检索 sqlite-vec 可选的向量 KNN 索引(本地派生,非必需) Embedding Model 供应商 API 生成,模型文件不随应用分发 Memory Service 统一的权限、写入、索引、召回、重排入口 Conversation Summary 跨对话回忆的主要检索文档 两个关键决策: 记忆所有者是用户,不是 Agent 。所有 Agent、所有对话通过同一个 Memory Service 访问用户级共享记忆( scopeType=user );项目、群组、Agent 专属内容用更窄的 scope。 没有配置 embedding 模型时,系统只用 SQLite/FTS5 ,不创建、不写入、不查询向量库。不引入 Qdrant/Milvus 等外部服务;未来需要 HNSW 或远程同步时,在不改 Memory Service 接口的前提下换 VectorIndex 实现。 原始聊天记录由 session 日志保存,不直接全部注入新对话——长期层只保存精炼后的记忆和可检索摘要。 九、分层安全边界 Agent 平台的安全不是单点,是一组同心圆。从外到内: 层 机制 宿主隔离 AI 活动范围限定在 Agent 层,宿主本体对 AI 不可写 权限引擎 ask-allow-deny 三态,每个工具调用经权限决策 SQL 边界 query_project_database 仅允许 SELECT 命令执行 exec crate:macOS Seatbelt 沙箱,仅桌面域 移动端能力天花板 握手 capability cei


  • 情报分类:工作与职业机会
  • 分类依据:内容涉及招聘、求职或职业发展
  • 信息来源:服务器 / LINUX DO - 最新话题
  • 发布时间:2026/10/12 16:23:48