跳到主要内容

附录 B:术语、状态机与不变量速查

本附录不是新的功能介绍,而是前 21 章的“压缩索引”。当界面、API、数据库、Daemon 和 Agent CLI 对同一件事使用不同名字时,先回到这里确认对象、状态和责任边界,再沿源码链接下钻。


1. 为什么 Multica 特别需要一份术语表

Multica 同时横跨协作产品、任务调度、机器运行时、Agent 协议、代码仓库和外部集成。许多词在日常交流中可以互换,但在实现中不能互换:

  • “Agent 在线”可能是协作者对象存在、Runtime 在线,或某台 Daemon 正在连接;
  • “任务开始”可能指记录已创建、已被调度、已被 Runtime 接收,或 Agent 子进程真的开始执行;
  • “会话”可能指 Multica Chat Session,也可能指上游 Provider Session;
  • “完成”只说明某个状态机抵达终态,不自动代表代码已经提交、推送、合并或部署。

这类歧义会直接造成错误的查询、错误的告警和错误的恢复动作。下面先给出最重要的对象关系。


2. 核心领域对象

术语精确定义不是什么主要落点
Workspace多租户、权限、数据查询和事件订阅的第一边界不是单纯的 UI 分组服务查询、认证中间件、所有 workspace-scoped 资源
User全局账号身份不等于某个 Workspace 中的权限认证与个人资料
MemberUser 在某个 Workspace 中的成员关系与角色不是独立登录账号Workspace 授权
Agent可被分配工作、带 Provider 配置与协作身份的持久对象不是进程,也不保证在线Agent service、数据库 agent 记录
Daemon运行在某台机器、连接服务器并执行任务的长生命周期进程不是 Agent,也不是单个 Taskcmd/daemon、Daemon WebSocket
Runtime某 Workspace 内 Agent、Provider、Profile 与执行位置的注册关系不是操作系统进程本身Runtime service、调度约束
Task一次不可变历史意义上的执行尝试;重试通常创建子 Task不是 Issue,也不是 Provider Sessiontasks、Task service
Provider SessionClaude、Codex、ACP 等上游执行器用于续接上下文的会话标识不是 Multica Chat SessionAgent backend、task session 字段
Chat SessionMultica 产品中的一段用户与 Agent 对话不等于上游模型会话Chat service、前端 Chat 状态
Issue可被分配、评论、追踪状态的协作工作项不等于执行尝试Issue service
Comment ThreadIssue 中触发、补充和追问任务的协作上下文不是 Task message 流Comment / Issue trigger
Task MessageAgent 执行期间产生的规范化增量消息不是普通 Issue 评论Task event/message persistence
ProjectWorkspace 内组织 Issue、资源与视图的产品对象不是 Git 仓库的同义词Project service
RepositoryVCS 仓库元数据和远端协作对象不必然等于本地工作目录GitHub/VCS service
Workdir某次执行实际读写代码的位置不等于仓库裸缓存Daemon environment
Env RootMultica 管理执行环境时的根目录不是用户任意指定目录Environment manager
Bare Cache为减少重复 clone 而保存的裸仓库缓存不是 Agent 的可编辑工作树Repo cache
Worktree从缓存或仓库为任务准备的可编辑检出不是永久业务记录Repo checkout / GC
SkillWorkspace 中可分发、启停、版本化的能力包不等于 MCP ServerSkill service
Runtime Local SkillDaemon 在本机发现、可上报的 Skill不保证已安装到 WorkspaceDaemon skill discovery
MCP Server向 Agent 暴露工具的 Model Context Protocol 服务不等于 Connected AppPrompt/runtime capability assembly
Connected AppOAuth 或第三方平台连接,为 Skill/MCP 提供外部能力不等于 MCP 协议本身Connected App service
SquadLeader 与 Worker Agent 的协作拓扑不是一个共享进程Squad service
Autopilot定时或 webhook 驱动的自动化定义不是一次执行Autopilot service
Autopilot Trigger触发条件和入口配置不是调度后的 RunTrigger persistence
Rule VersionAutopilot 规则的不可变版本快照不是可直接执行的 TaskRule version persistence
Autopilot Run一次自动化编排实例,可能创建 Issue 或直接建 Task不等于其下游 TaskAutopilot run service
Webhook Delivery一次外部 webhook 的接收、验签、去重与处理记录不代表业务已成功完成Webhook delivery queries
Event Bus提交后向实时客户端传播变化的通知通道不是权威数据存储In-process/Redis bus
Browser WebSocket面向 UI 的 workspace 事件订阅不是 Daemon 控制通道WebSocket handler
Daemon WebSocketServer 与执行节点之间的调度、心跳和 RPC 通道不是浏览器事件流Daemon protocol

2.1 三个最容易混淆的对象

判断问题时可用四个问题拆开:

  1. Agent 记录是否存在且可被当前 Workspace 使用?
  2. 是否有满足 Provider/Profile/执行模式的 Runtime?
  3. 承载 Runtime 的 Daemon 是否在线并有并发容量?
  4. 当前 Task 到底处于排队、已派发还是已运行?

3. Task 状态机

Task 是整个系统最重要的持久状态机。状态定义分散在 SQL 查询、Task service、Daemon 协议和前端展示中,因此不能只看一个枚举。

状态含义谁推进可否视为正在执行
deferred因重试退避等原因延后,尚未进入可领取队列Task service / 延迟调度
queued已具备调度资格,等待合适 Runtime 领取Server claim loop
dispatchedServer 已把领取权交给某 Runtime,并建立 claim fencingServer + Daemon 握手尚不能保证
waiting_local_directory需要用户本地目录,Daemon 正等待目录准备或授权Daemon / 本地目录流程
runningDaemon 已确认开始执行Daemon
completed本次执行成功终止Daemon / Task finalization终态
failed本次执行失败终止,并记录结构化失败原因Daemon、Server recovery终态
cancelled被用户或系统取消API、Daemon、reconcile终态

3.1 状态机必须记住的约束

  • queued 只表示可被领取,不表示某台机器已经收到任务。
  • dispatched 是所有权转移的中间态,不等于 Agent 子进程已运行。
  • 只有 Daemon 确认实际启动后才进入 running
  • completedfailedcancelled 是终态。
  • 重试不应把原 Task 从终态改回 queued;它创建带父子关系的新 Task,从而保留审计历史和尝试预算。
  • claim 最终化失败时,dispatched 可以通过严格的比较并交换条件回退到 queued;这不是普通业务状态迁移。
  • stale dispatch 的回收依赖 claim generation、派发时间和当前状态,不能只用“最后更新时间过旧”粗暴重派。
  • 终态写入必须带状态条件,避免完成、失败与取消互相覆盖。

3.2 “成功”到底成功了什么

Task completed 只表示 Agent backend 返回了平台认可的成功结果,并完成 Task 收尾。它不自动保证:

  • 修改已形成 Git commit;
  • commit 已 push 到远端;
  • Pull Request 已创建;
  • CI 已通过;
  • PR 已合并;
  • 生产环境已部署;
  • Issue 已进入 done

这些结果应由 VCS、Issue、CI 或部署系统各自的状态与证据确认。

3.3 Task 事件名称

实时层围绕 Task 常见的事件/阶段包括:

事件或阶段用途
task:queued新任务进入队列
task:dispatch向 Daemon 下发任务
task:waiting_local_directory等待用户本地目录
task:running已确认开始执行
task:progress进度或心跳类变化
task:message规范化 Agent 消息增量
task:completed成功终态
task:failed失败终态
task:cancelled取消终态

事件名是通知契约;数据库 Task 行仍是权威状态。


4. Runtime、Daemon 与连接状态

4.1 Runtime 在线状态

Runtime 面向产品通常呈现为:

  • online:存在有效 Daemon 连接和心跳,可参与调度;
  • offline:无有效承载连接,不应继续分配新工作。

4.2 Daemon 本地健康状态

CLI/本地控制面还可能展示:

  • starting:进程已启动,尚未完成连接或就绪;
  • running:本地进程健康;
  • stopped:本地进程未运行。

这套本地生命周期与 Server 视角的 Runtime online/offline 不等价。网络分区时可能出现“本地进程 running,但 Server 已判定 Runtime offline”。

4.3 心跳与失联恢复

失联恢复必须同时处理两类事实:

  1. Runtime 是否还能承接新任务;
  2. 已处于 dispatched/running 的 Task 是否需要失败、回收或重试。

5. Agent backend 与消息协议速查

5.1 支持的 Provider 标识

当前 Agent 注册层可见的 Provider 标识包括:

ProviderProviderProviderProvider
claudecodebuddycodexcopilot
opencodedevecoopenclawhermes
picursorkimikiro
antigravityqodertraecligrok
qwen

注册入口见 server/pkg/agent/agent.go

5.2 协议族而非单一协议

协议族代表 Provider适配难点
Stream JSONClaude、CodeBuddy、Qwen、Cursor增量事件、工具调用配对、最终结果判定
App Server JSON-RPCCodex初始化、线程/turn 生命周期、JSON-RPC 相关性
ACPHermes、Kimi、Kiro、Qoder、Trae CLI、Grokcapability 协商、session load、MCP transport
Run JSONOpenCode、DevEco不同事件 schema 和 provider-executed tool
独立 JSON 协议Copilot、OpenClaw、Pi各自的消息与会话语义
transcript / 非交互执行Antigravity日志解析、终态错误提升

Provider 的共同点不是命令行参数,而是最终都被归一化为平台消息和结果。

5.3 统一消息类型

类型含义
text面向用户的自然语言输出
thinking推理或计划型内容;展示与持久化需服从产品策略
tool-useAgent 发起工具调用
tool-result工具执行结果
status生命周期或进度状态
error明确错误消息
log诊断日志,不一定面向最终用户

归一化层要维持序列顺序、工具调用关联、时间戳单调性和终态唯一性。

5.4 backend 结果状态

Provider 适配器常见最终结果包括:

  • completed
  • failed
  • aborted
  • timeout
  • cancelled

它们是 Agent backend 结果,不应未经转换就直接当作 Task 数据库状态。Task service 负责映射、分类、重试和最终化。


6. 结构化失败原因

失败原因定义和分类入口见 server/pkg/taskfailure/failure.goserver/pkg/taskfailure/classify.go

6.1 平台侧失败

原因码典型含义优先检查
queued_expired长时间没有可用 Runtime 或容量Runtime 在线、Provider/Profile 匹配、并发上限
runtime_offline承载 Runtime 离线Daemon 连接、心跳、网络
runtime_recovery失联后的平台恢复收尾reconcile 日志、claim generation
timeout平台任务超时Task deadline、Agent 是否仍有输出
iteration_limit超过允许迭代次数prompt 复杂度、工具循环
agent_blockedAgent 明确阻塞阻塞原因、缺少用户输入或权限
api_invalid_requestAPI 请求本身不合法handler validation、请求参数

6.2 Agent / Provider 侧失败

原因码典型含义是否常适合自动重试
agent_error.provider_auth_or_access登录、API key、组织或模型访问权限否,先修复凭据/权限
agent_error.provider_quota_limit余额、额度或用量上限通常否
agent_error.provider_capacity_or_rate_limit429/529、上游拥塞是,带退避
agent_error.provider_server_errorProvider 5xx 或内部错误通常是,带上限
agent_error.provider_network断流、DNS、连接拒绝、网络超时是,按预算退避
agent_error.process_failureCLI 非零退出或进程异常视 stderr 与可执行文件而定
agent_error.empty_or_unparseable_output输出为空或协议解析失败先检查版本和适配器
agent_error.agent_timeoutAgent backend 自身超时视任务幂等性重试
agent_error.context_overflow上下文窗口溢出否;应缩减上下文或新建会话
agent_error.missing_config缺少 Provider 必需配置
agent_error.model_not_found_or_unavailable模型名无效或不可用否,修正模型配置
agent_error.runtime_version_unsupportedCLI/Runtime 版本不兼容否,升级或降级
agent_error.runtime_missing_executable找不到 Provider CLI否,安装并修复 PATH
agent_error.unknown无法可靠归类人工检查原始错误

“可自动重试”仍需满足 Task 的最大尝试次数、父子尝试预算和幂等性要求。


7. Autopilot 与 Webhook 状态机

7.1 Autopilot Run

当前 service 创建 Run 时通常会根据执行模式直接进入 issue_createdrunning。逻辑上可把触发到落库前看作 pending,但排障时应以数据库实际状态为准。

状态含义
issue_created已创建 Issue,后续通过 Issue 触发链执行
runningRun-only 模式已创建/关联下游 Task
completed下游结果满足成功条件
failed调度、Issue/Task 或下游执行失败
skipped规则、幂等或业务条件决定不执行

实现入口见 server/internal/service/autopilot.go

7.2 Webhook Delivery

状态含义
queued已通过入口校验并等待处理
dispatched某个处理者已持有 claim
rejected验签或入口策略拒绝
ignored合法但不匹配触发条件
failed处理过程失败

Webhook HTTP 响应还可能表达 duplicateskipped;它们不一定是 delivery 表中的持久状态,不能混用。

7.3 签名校验结果

签名状态含义
not_required当前入口未要求签名
valid签名存在且验证通过
invalid签名存在但验证失败
missing要求签名但请求未提供

Webhook 被 HTTP 层接收,只能证明入口处理成功;它不证明 Run 已创建,更不证明下游 Task 成功。


8. 认证凭据与前缀

凭据前缀/形态使用者作用域
用户 PATmul_CLI / API 用户用户身份与其可访问 Workspace
Cloud Node PATmcn_云执行节点节点注册和受限控制面
Daemon Tokenmdt_Daemon机器/Runtime 连接
Task Tokenmat_单次任务环境强约束到 Task 能访问的 API
JWT无固定前缀Web 会话用户浏览器认证

关键不变量:

  • 凭据只用于它被设计的信任边界,不能用 Daemon token 代替用户 token;
  • Task token 的 workspace、task、agent 等约束必须在服务端重新校验;
  • Token 原文不得进入日志、Task message、Agent prompt 或分析事件;
  • CLI profile 负责选择凭据,不改变服务端授权判断;
  • 本地任务环境缺少 Task token 或任务标记时,应 fail closed,而不是回退使用用户全权凭据。

9. 实时事件与一致性

协议中的资源事件命名空间包括:

类别资源
工作项issueissue_metadatacommentreactionissue_reaction
执行agenttaskdaemonchatautopilotsquad
工作区workspacemembersubscriberactivityinvitation
组织projectproject_resourcelabelissue_labelspropertyissue_propertiespin
能力skill
集成github_installationpull_requestvcs_connectionlark_installationslack_installation

完整常量见 server/pkg/protocol/events.go

9.1 Event Bus 的四条不变量

  1. 业务变更先持久化,事件用于传播已经成立的事实。
  2. 浏览器收到事件后可以增量更新,也可以失效并重取;HTTP/DB 是最终真相。
  3. 多实例部署必须使用跨实例 Bus,否则连接在 A 实例、写入发生在 B 实例时会漏通知。
  4. 事件可能重复、延迟或在断线期间丢失,消费者必须幂等并具备重同步路径。

9.2 消息顺序

Task message 需要可比较的序号或单调时间戳。Provider 原始时间不可靠时,适配层应保证平台写入顺序。前端不能仅用到达顺序推断业务因果。


10. Capability 协商

Capability 是兼容性门禁,不是装饰字段。

10.1 Daemon capability

Capability含义
skill-bundles-v1支持服务端下发/同步 Skill bundle
coalesced-comments-v1支持合并后的评论上下文协议
rpc-v1支持 Daemon RPC 控制消息

10.2 App capability

Capability含义
chat-draft-restore-v1客户端能安全恢复 Chat 草稿,不需要服务端回显 prompt

常量与注释见 server/pkg/protocol/messages.go

兼容原则:

  • Server 只有在对端声明 capability 后才发送新语义;
  • 未声明时走旧协议或降级路径;
  • capability 表示“理解并能正确处理”,不能仅因为字段可解析就声明;
  • 新 capability 应有双向兼容测试和旧版本回退测试。

11. 并发控制与 fencing 速查

场景主要原语防止的问题
批量领取 queued Task事务、FOR UPDATE SKIP LOCKED多调度者领取同一任务
Task 派发最终化状态条件、claim generation、dispatched_at旧 Daemon 或旧派发覆盖新所有者
执行环境准备prepare lease两个执行者同时创建/清理同一 workdir
Autopilot schedulerlease token + heartbeat多实例重复触发
Webhook workerclaim token同一 delivery 被并行处理
外部渠道消息dedup/claim token重复投递创建重复任务
Task 终态conditional updatecomplete/fail/cancel 竞态覆盖
消息持久化sequence / 单调时间流消息乱序
Skill/配置同步content hash / version无变化重复下发、旧版本覆盖新版本
API 创建idempotency key / unique index客户端重试造成重复业务对象

11.1 fencing 的核心判断

“我曾经拥有过这个任务”不足以写入。每一次副作用都要证明:

  • 当前 Task 仍处于允许该写入的状态;
  • 当前 claim generation/token 仍是最新;
  • 当前 Daemon/Run/Delivery 仍是所有者;
  • 终态尚未被另一条路径写入。

12. 数据与多租户不变量

12.1 Workspace 边界

  • 每个 workspace-scoped API 都要从认证上下文解析 Workspace,并验证 Member 关系;
  • SQL 查询应显式带 workspace_id,不能只靠上层“已经查过”;
  • 从 Task、Issue、Agent、Project 等对象跳转时,要确认关联对象属于同一 Workspace;
  • 事件订阅和 publish topic 必须带 Workspace 隔离;
  • 缓存键、React Query key、幂等键也必须纳入 Workspace。

12.2 数据库约束策略

当前仓库约定倾向于在新设计中避免用外键级联承载业务语义,删除与归档由 service 显式处理。历史 migration 可能保留旧式外键,阅读时应区分“现存遗产”和“新增规则”。

12.3 审计历史

  • Task 重试创建新尝试,不重写旧终态;
  • Autopilot Rule 用版本快照保留当时规则;
  • Webhook Delivery 保存入口、验签与处理证据;
  • 需要追责的对象优先归档或追加记录,不以 hard delete 抹掉历史;
  • 用户可见评论与机器执行消息分别建模,避免将诊断流污染协作历史。

13. 执行环境不变量

模式工作目录来源平台能否安全 GC典型风险
托管仓库环境bare cache + task worktree能,受租约和状态保护并发 checkout、陈旧 worktree
已有本地仓库用户指定目录只能做受限操作覆盖用户未提交变更
等待本地目录用户/桌面端后续提供尚不能执行误把 dispatched 当 running
无仓库任务临时环境或服务配置缺少预期源码上下文

必须保持:

  • GC 不删除 active lease、running Task 或用户自有目录;
  • worktree 路径经过根目录约束和规范化,不能目录穿越;
  • checkout、prepare、cleanup 都是可恢复步骤;
  • 对用户仓库默认保留未提交更改,不执行破坏性 reset;
  • 仓库认证材料只在必要进程环境中短暂存在;
  • “目录存在”不等于“仓库处于正确 revision 且可安全执行”。

14. Prompt 与上下文不变量

Prompt 是多个受信程度不同的上下文层组装结果:

关键原则:

  • 用户评论、Issue 文本、仓库文件和外部 webhook 都是不可信内容,不得覆盖系统授权边界;
  • Workspace Context 不是单段 prompt,而是一组可追踪来源;
  • Secret 不应写进 prompt;需要凭据的能力通过受控环境或工具调用提供;
  • coalesced comments 要保留作者、顺序和触发点,不能拼接成无法区分来源的一段文本;
  • Provider Session 可续接对话,但权限与工作区上下文每次任务都应重新验证;
  • 上下文溢出应缩减、总结或新建会话,而不是盲目重试同一 payload。

15. 前端分层不变量

责任不应承担
packages/core类型、API client、query keys、跨端状态与业务 hooks浏览器或移动端专属 UI
packages/ui纯 UI 组件与设计系统服务请求和业务 store
packages/views可复用业务视图宿主路由、宿主 store、平台 API
Web/Desktop host路由、Browser 能力、桌面桥接复制 core 业务逻辑
Mobile app移动导航、原生适配、独立宿主假设 DOM 或桌面 IPC 存在

状态约定:

  • React Query 管理服务端状态;
  • Zustand 管理客户端偏好、局部交互或跨组件 UI 状态;
  • query key 必须带 Workspace;
  • WebSocket 用于更新/失效缓存,不能成为唯一数据源;
  • API 边界通过 schema 解析;parseWithFallback 只用于有明确兼容策略的降级;
  • views 通过 props/callback 接收宿主能力,避免反向依赖应用层。

16. 一条状态该找谁负责

现象首要责任层第一证据下一跳
Task 一直 queuedServer 调度Task 行、候选 Runtime 查询Runtime 在线、并发和 Provider/Profile
Task 卡在 dispatchedServer ↔ Daemon 握手claim generation、Daemon WS 日志reconcile 与派发确认
卡在 waiting_local_directoryDesktop/CLI/Daemon 本地目录流程local-directory 请求与响应路径权限和目录标记
running 但无消息Agent backend子进程、stdout/stderr、协议 parserProvider CLI 版本与认证
显示成功但没看到代码执行环境/VCSworkdir、git status、commit/push 证据Task output 与 VCS integration
UI 不刷新实时层/前端缓存WS 事件、query key、HTTP 重取Redis Bus 与 workspace topic
Autopilot 重复运行scheduler 幂等lease token、trigger key、Run 记录多实例租约与唯一约束
Webhook 收到但没运行webhook worker/规则Delivery 状态、签名、匹配结果Autopilot Run / Task
Agent 显示离线Runtime/DaemonServer 心跳与连接记录本地 daemon status、网络
重试次数异常Task retry policy父子 Task、attempt/max_attemptsfailure reason 分类
跨 Workspace 数据异常授权/查询workspace_id 和 Member 校验SQL 条件、cache/query key

17. 常见错误等式

下面这些等式全部是错的:

错误等式正确理解
Agent = DaemonAgent 是协作者配置;Daemon 是机器进程
Agent = Runtime一个 Agent 可有不同 Provider/Profile 的 Runtime
Runtime online = 本地进程存在Server 需要有效连接和心跳证据
Task = IssueIssue 是协作工作项;Task 是一次执行尝试
Task = Provider SessionTask 属于平台;Session 属于上游执行器
Chat Session = Provider Session一个是产品对话,一个是执行器续接标识
Comment = Task Message评论属于协作历史;Task message 属于执行流
queued = 正在运行queued 仅表示等待领取
dispatched = Agent 已启动仍需 Daemon 确认 running
completed = 已提交/推送/部署需分别查询 Git、VCS、CI、部署状态
Event = 数据真相Event 是通知;DB/HTTP 是权威
Webhook 2xx = 自动化成功只证明入口已处理
本地目录存在 = 环境就绪还需 revision、权限、租约与安全检查
MCP = Connected AppMCP 是工具协议;Connected App 是外部连接
Skill 已发现 = Skill 已安装启用本地发现、Workspace 安装和 Runtime 下发是不同阶段

18. 阅读状态机的源码入口

主题入口
Task 创建、领取、运行、终态、重试server/internal/service/task.go
Task SQL 原子迁移server/pkg/db/queries/agent.sql
失败原因与重试属性server/pkg/taskfailure/failure.go
Provider 错误分类server/pkg/taskfailure/classify.go
Daemon 协议与 capabilityserver/pkg/protocol/messages.go
实时资源事件server/pkg/protocol/events.go
Agent backend 注册server/pkg/agent/agent.go
Autopilot Runserver/internal/service/autopilot.go
Webhook Delivery SQLserver/pkg/db/queries/webhook_delivery.sql
Runtime/Daemon 协调server/internal/daemon
前端 query key 与 APIpackages/core

19. 排障最短路径

遇到任何“Agent 没有工作”的问题,可按这条顺序查:

不要从 UI spinner 直接推断后端状态,也不要先从 Provider 日志开始。Task 行和 claim 是跨层关联所有证据的主键。


20. 版本阅读声明

本附录对应 multica-0.4.10 源码快照。它刻意区分:

  • 代码中真实持久化的状态;
  • service 内部的逻辑阶段;
  • HTTP 响应或 UI 展示用的状态;
  • Provider backend 的原始结果。

后续版本若新增 Provider、Task 状态或 capability,应同时更新:

  1. 状态机及合法迁移;
  2. SQL 条件与并发 fencing;
  3. Server/Daemon 协议兼容;
  4. 前端 schema、query key 和展示;
  5. metrics label allowlist;
  6. 失败恢复与端到端测试;
  7. 本附录和相应章节。

至此,主文 21 章中的对象、状态和边界可以通过本附录快速交叉定位;若要顺序阅读源码,请配合附录 A:源码导航与阅读路线