跳到正文

AgentLoom 总体技术设计 ​

更新:2026-10-09。代码核对基线:9941e31(master)。本文描述该基线的实际架构,并单独列出尚未落地的设计。产品处于开发测试阶段。

AgentLoom 是面向团队的低代码 Agent 平台。用户集中管理模型连接、Skill、MCP 工具和知识资料,通过配置并发布 Agent,让团队成员从网页或 API 发起任务。Agent Runtime 是核心,管理端负责把可运行配置交给 Runtime。

配套文档:产品需求、Runtime 详细设计、平台、API 与数据设计、部署运维、源码目录。

1. 需求与实现对照 ​

“已实现”表示代码路径和本地测试已存在,不等于真实供应商、Docker、NFS 或生产集群均已完成联调。

用户需求当前实现边界与后续工作
多人使用,Agent 属于空间账号、邀请码、owner/member、空间资源、API Key没有完整 RBAC、多空间切换和企业组织体系;个人运行记录不向全空间开放
配置后发布才能调试草稿与发布版本分离;网页/API 仅运行已发布配置同一会话固定版本;配置快照不等于所有外部资产永久可用
DeepSeek 与 OpenAI,Key 后发现模型模型发现、目录元信息、测试连接、Chat Completions 工具调用供应商列表未必给窗口大小;使用返回元信息、已知目录或保守回退,不能保证自动知道所有限制
Codex 类自主 Loop模型决策、工具执行、结果反馈、完成检查、继续/等待补充模型完成检查是判断机制,无法代替真实测试证据
ReAct / 自动 Plan共用 Loop,Plan 通过 update_plan 生成和调整计划后执行没有人工批准每一步的 Plan 模式
运行时按需创建子 Agent内嵌模板、独立 Prompt/资源/上下文,继承主模型不单选模型或模式;不递归;当前顺序执行;每 Run 最多 8 次委派
Skill 文件夹与 Git 导入SKILL.md、附件、按需读取、容器命令公开 HTTPS Git;不能据此宣称完整兼容所有 Codex/Claude Code 宿主能力
外部或自建工具快速接入外部 MCP HTTP/SSE、托管 Python MCP、ToolServer SDK托管构建与调用需要 Docker;私有 Git、独立执行集群尚未实现
Loop 与实际执行解耦工具请求总线、工具注册表、Handler、统一结果总线在进程内;一次执行请求只交一个处理器,通知才支持多订阅者
各执行边界可扩展 Hook模型、工具、上下文、压缩、主/子任务、Embedding Hooks可信 Python 注册;未开放上传/Git Hook、隔离 Worker 和管理页面
连续会话与主动压缩原始消息记录、模型视图、压缩快照、默认 80% 阈值及轮数条件Token 是估算值;不是精确供应商 tokenizer;长期 MemoryService 尚未实现
失败或中断后恢复加密检查点、阶段恢复、已保存结果复用、未知结果保护恢复原 Run;不保证外部系统 exactly-once;不等于自动跨节点接管
list/grep/read/write 等系统工具10 个文件/命令工具、共享 POSIX 适配、隔离工作区没有多文件 patch、交互 PTY、后台进程会话等能力
上传业务知识文本MD/TXT/SQL 入库、混合检索、文档引用、Embedding Hooks当前是数据库中的 RAG 文档;文件式 Wiki、目录阅读及在线 Wiki 编辑不在本轮新增范围

2. 总体架构 ​

AgentLoom 当前实现架构

采用模块化单体:一个 FastAPI 进程承载管理接口、运行服务、Runtime 与进程内事件总线。模块边界已经部分通过 Protocol、注册表、回调和组装参数表达;不通过“先拆成多个服务”实现模块化。

层负责什么不负责什么当前入口
网页与 HTTP 接入表单、鉴权上下文、请求校验、事件展示、文件下载模型密钥解析、工具实际执行Vue、routes
平台应用服务资源管理、发布、会话准入、运行生命周期、历史与索引在路由中编写模型决策循环services
Runtime 组装将冻结配置、策略、存储和能力装配为实例登录、草稿管理、文档上传runtime.py
Runtime 核心Loop、上下文、模型请求、计划、完成判断、预算、Hooks根据工具名实现文件/MCP 等功能engine.py、模块契约
能力执行工具契约、授权/校验、工作区、Skill、MCP、知识检索、委派向模型开放任意宿主路径或平台凭据tool_runtime.py、handlers
基础设施SQL、文件存储、供应商 HTTP、Docker、持久化回调产品配置与模型决策database.py、workspace_store.py、sandbox.py

Runtime 不反向依赖 apps/api。API 负责提供资源快照、检索等执行服务,以及保存状态和观察事件的回调。当前部分 SQL 仍在路由内,数据访问还没有全部收口到 Repository;“逻辑分层”不能理解为所有目标类都已创建。

3. 可插拔边界 ​

模块替换在可信宿主的 Python 组装阶段进行;这与普通用户从页面上传任意插件是两个不同的能力范围。

边界当前契约/对象替换时必须保持的约束
模型网关ModelGateway.invoke(ModelRequest)统一消息/工具调用结构;通过公共调用计数、Hooks 和响应校验
上下文管理ContextManager连续追加、恢复、原记录与可见视图区分、合法消息组
压缩CompactionPolicy.compact(...)只处理完整组;保留任务;失败不推进压缩水位
完成检查CompletionPolicy.review(...)返回 complete / continue / blocked
执行策略ExecutionStrategy注入指令、授权行动、候选结果检查;复用 Loop
预算ExecutionLimits正整数模型调用与迭代限额;其他平台限额尚未全部统一成策略对象
HookHookPointRegistry / HookRegistry / HookManager挂点白名单、输出校验、版本与代码指纹、恢复语义
工具ToolDefinition / ToolRegistry / ToolRuntime服务端绑定权限、JSON Schema、超时/取消、恢复策略
文件与命令WorkspaceProvider、POSIX Store、Sandbox由宿主限定空间/Agent/会话/实例;模型不指定存储根目录
执行服务build_tool_context 与 PlanEditor / ChildRunner / CitationRecorder / InvocationState将执行状态适配为受限接口;检索、MCP、技能由各 Handler/适配器处理,避免依赖 Engine 内部状态
状态与观测persist、事件回调、Observer持久化成功后才推进事实;观察失败不能伪造工具结果

RuntimeModules.bindings() 把实现的 module_id 与 JSON 配置写入检查点;恢复校验模块身份。它不是从检查点动态导入代码的加载器。更换实现由宿主通过 create_engine 显式注入对象并校验绑定,同时处理旧检查点兼容;当前没有通用 ModuleRegistry,工具与 Hook 则各有注册表。生命周期关闭只关闭归属自己的资源,同一对象不重复关闭。

仍缺少的独立边界:统一 CheckpointStore 端口、分布式 Scheduler/LeaseStore、独立子任务调度器、MemoryService、完整资源引用追踪与撤销过滤。persist 回调已经隔离了保存动作,但 Engine 仍持有执行状态并知道哪些边界必须保存;这部分不能由观察者异步替代。

4. 从配置到运行 ​

4.1 配置和发布 ​

  1. 空间成员配置主 Agent 的模型、Prompt、模式、资源、子模板和上下文策略。
  2. 发布服务校验资源,并保存发布快照;Hooks 绑定、模块相关配置和知识文档集合随快照固定。
  3. 网页/API 指定版本或选择最新发布版本。未发布草稿不能启动。
  4. 创建会话时固定 Agent 版本;后续新提问沿用该会话版本。已有 Run 的恢复使用其原发布与检查点。API 省略 version 时仍取 Agent 最新版,因此继续旧会话须显式传原会话版本;若已发布新版却省略版本,会因 Session 版本不匹配被拒绝。

主模型运行时按原资源 ID 读取当前 Key,模型 ID/provider/base URL 仍取发布快照。目前凭据轮换只能安全用于同一连接身份;更换供应商或端点应创建新的模型连接并重新发布。代码尚未对聊天连接的身份迁移建立完整约束,详见平台设计中的发布边界。外部 MCP 凭据和文件资源另有快照/存储规则,不能把“发布不可变”理解为所有凭据都自动轮换。

4.2 一次任务 ​

text
网页 / API
  → 认证 + 空间/版本校验 + 会话/并发准入
  → 创建 Run、工作区绑定、事件和运行句柄
  → 读取连续历史,create_engine 装配模块
  → ContextManager 准备当前模型视图
  → 模型 Hook → 预算/协议校验 → ModelGateway → 保存结果 → 后置 Hook
  → 模型有 tool_calls:逐个通过 EventBus 请求 ToolRuntime
  → 工具 Hook → 核心授权/参数校验 → Handler → 保存真实结果 → 后置 Hook
  → 将有效观察追加到上下文,继续 Loop
  → 候选回答 → 完成检查 → 继续 / needs_input / succeeded
  → 事务提交终态和事件,清理归属资源

Plan 通过 update_plan 工具维护结构化步骤。Loop 不充当固定 DAG 调度器。子任务由主模型委派,子实例使用自己的 Prompt 和资源集合,继承主模型;内部对话保持隔离,结果通过委派工具回到父实例。

4.3 三种通道必须区分 ​

通道目的失败和消费方式
tool.execute 请求/响应执行一次能力并等待结果关联 ID;单处理器;超时/取消传递到执行方
通知/Observer记录调用开始、完成与诊断等观测可以有多个订阅者;观察异常不能替代实际结果
SQL 事件 → SSE将已记录的运行变化交给前端/API 客户端按序号续接和去重;断开浏览器不等于取消 Run

因此写共享存储仍先经过总线,但不会把一个写请求广播给所有节点。未来若接入消息队列,必须保留“单执行权、关联结果、持久化和重复投递控制”的语义。

5. 会话、上下文、压缩与记忆 ​

标识/记录生命周期内容
Session多次提问绑定空间、用户、Agent 版本;组织已提交主实例历史
Run一次新提问及其恢复任务状态、模型预算、事件、检查点、主/子实例
Instance主实例或单个子任务独立 Prompt、对话、计划和调用进度;逻辑线程为 (run_id, instance_id)
session_messages连续来源记录用户输入、补充、模型与工具记录;保留失败/取消中已提交的有效事实
session_views可复用的上下文视图已压缩的模型视图、覆盖水位与计数基线;不是原文替代品
Checkpoint原 Run 的恢复点实例状态、pending 调用、模块绑定、Hook 阶段、压缩与预算相关状态

同会话的新提问建立新 Run,继承兼容历史视图并接上后续记录;不会复制旧 pending 调用和取消标记。恢复旧 Run 则沿用旧执行线程,不自动吸收其后新建的 Run。子任务内部对话不会全部摊入主会话;父实例只看到显式返回的结果。

默认压缩在有效输入预算的 80% 触发,压缩后目标为 60%,也可按新提问轮数或当前实例 action 模型步骤触发;子实例不增加父实例计数。有效预算扣除输出预留与安全余量,并受模型输入上限约束。新发布使用的 BudgetCompactionPolicy 无论软阈值是否启用,仍执行硬预算校验,消息、工具 schema 与 Hook 增补都纳入检查。旧字符策略及未实现可选 validate_request 的自定义压缩器不自动获得窗口硬校验;替换模块时必须显式保持这项约束。

原始记录不因压缩删除。当前按完整消息组和保守 Token 估算压缩,covered_seq 是视图覆盖水位,尚不是每句摘要对应的精细来源范围。工具结果进入模型视图时有 24,000 字符上限,完整事实的保留不代表每轮模型都读取完整内容。

长期记忆尚未实现。会话历史和压缩摘要解决“本会话能继续处理什么”,未来 MemoryService 才负责跨会话提取、整理、版本、撤销及按需回查。目标设计见上下文管理设计,当前算法和恢复细节见Runtime 设计。

6. Hooks 与可恢复操作 ​

HookManager 是 Runtime 的正式模块。挂点决定允许读写的字段、返回 schema、异常策略与超时;Hook 不能获取任意 Engine 引用后直接修改执行状态。修改请求后仍进行核心授权、协议和预算校验。

一次 durable operation 的要点是:保存有效输入 → 调用底层能力 → 保存真实结果 → 执行 after Hook → 保存有效输出。没有绑定 Hook 时仍使用同一路径,因为这些记录也服务调用级恢复。后置处理失败后恢复会复用真实结果,不重新调用已经完成的外部能力。

当前挂点契约为 v2,严格校验必需字段和额外字段;旧检查点使用宿主已知的 v1 契约兼容。绑定保存 Hook 版本、代码指纹与配置,恢复校验后再执行。文件源码指纹与动态字节码指纹都有明确范围;闭包、全局状态和外部依赖不能仅靠函数指纹覆盖,需要部署者提供完整工件 code_hash。

Hook 使用单调时钟预算;墙上时钟 deadline 只用于展示。可信异步 Handler 在进程内执行,超时不是对任意阻塞代码的强制隔离。上传执行、独立 Worker、按用户安装 Hook 和可视化调试仍待建设。Embedding 使用独立的持久化操作记录和冻结索引处理链,见Embedding 专题。

7. 持久化、文件与恢复 ​

业务数据、发布、Run、事件、加密检查点、会话消息和知识索引保存在 SQL。默认测试使用 SQLite;用户部署可以使用 PostgreSQL。二者都有 001–005 编号迁移。供应商 Key、检查点及会话敏感记录按各表处理加密,不是整个数据库加密;知识正文、部分配置和运行事件仍需数据库访问保护。

文件分为三类:导入包 data/assets;新工作区 data/workspaces 或配置的共享卷;旧 Run 兼容目录 data/runs。加密根密钥 data/encryption.key 需要单独保护和备份。共享工作区不自动同步技能包、托管镜像或平台密钥。

主文件域按空间、Agent、Session 隔离,同会话多次 Run 共用。子文件域再按 Run/实例隔离。数据库 run_workspaces 固定存储 backend、volume ID 和逻辑 scope,节点的绝对挂载路径可以不同。shared_posix 必须验证已有 .agentloom-volume,不匹配时失败,不悄悄回退到本地目录。

POSIX 文件适配执行路径校验、描述符相对访问、拒绝符号链接/硬链接等、原子替换、内容哈希条件写和锁。命令容器仅挂载当前工作区与只读技能;若执行或清理结果未知,保留隔离标记,阻止进一步写入和命令执行,避免在状态未明时继续修改文件。

中断位置当前处理
调用前恢复校验配置与检查点,继续合法阶段
真实结果已保存,after Hook 未完成继续后处理,复用保存的结果
外部工具已经发出但结果未知根据工具恢复策略处理;不可安全重放的操作要求先核实实际状态
模型请求已发出但响应未知需要显式 retry_unknown_models 授权,防止无意重复计费/请求
容器清理不确定保留隔离标记;由运维确认容器及文件状态后处理
完成后持久化失败单进程内保留待收尾记录并重试提交;不能替代跨进程持久队列

当前不支持安全的多 Worker/集群运行。 Run 句柄仍在内存,启动数据库初始化会处理中断任务,没有 Worker 租约或 fencing token。把数据库和文件都共享后直接启动第二个应用进程,会破坏任务归属判断。未来集群还需要持久调度、执行权租约、单调隔离令牌、幂等与状态接管协议。

8. 安全与权限边界 ​

  • 管理资源与发布 Agent 在空间内共享;Run 详情、事件、恢复/取消、会话历史和产物由发起用户访问。API Key 也通过所属用户/空间进入同一检查路径。
  • 模型只看到已绑定工具及服务端限定的资源。空间 ID、真实文件根目录、模型 Key 和数据库凭据不由模型提供。
  • 用户文档、工具返回和 Skill 文件是执行输入,不能提升平台权限。Prompt 约束不能替代 Handler 的授权和路径边界。
  • Docker 系统命令要求宿主非 root、匹配 UID/GID、预加载镜像、本地 socket;默认无网络、只读根文件系统、限制 CPU/内存/进程。Docker 或普通子进程本身不等于完整多租户恶意代码隔离。
  • 远程模型和 MCP 是网络信任边界;应由部署环境限制可访问端点。当前没有完整统一的出口代理和目的地址策略。
  • 历史正文按资源撤销做精细过滤、跨节点执行权、完整审计/限流、聊天模型连接身份迁移约束仍有待补齐。不要把当前 owner/member 和文件隔离视为完整企业安全体系。

9. 验证依据与交付边界 ​

本次为文档整理,代码基线不变。基线最近一次隔离回归记录为 540 项 Python 测试、12 项前端测试通过,静态/格式检查、TypeScript 与 Vue 构建通过;使用临时 SQLite、替身模型/Embedding 和测试 MCP。该记录不代表本次重新跑过,也不证明真实供应商、远程 PostgreSQL、Docker/NFS/gVisor 已完成本轮联调。

复验命令、安全范围、环境限制见部署运维文档。常见能力的真实验收证据应分开记录:协议替身测试、真实供应商调用、容器执行、共享卷多机探测、故障恢复测试不能互相替代。

10. 后续演进顺序 ​

顺序工作完成判据
1固化契约与数据边界发布连接身份保护、API/类型契约检查、Repository/CheckpointStore 收口,兼容旧数据
2执行环境真实验证非 root Docker、技能/托管 MCP、NFS/NAS 锁与断连恢复的独立环境验收
3补齐运行模块统一限额、可替换子任务调度器、资源来源与撤销过滤、工具大结果按需回查
4可持久调度与集群Run 归属、租约/fencing、消息重复投递、取消/接管与清理协议;再允许多 Worker
5用户扩展与长期记忆隔离 Hook Worker、版本化扩展管理;独立 MemoryService 的提取/授权/撤销

业务 Wiki 的新增形态暂缓;现有 RAG 作为能力适配器继续独立于 Loop。是否新增文件型知识阅读,应在后续需求明确后设计,不借本次整理扩大实现范围。