Apache Maka WorkHub 深度解读:单协调会话如何构建持久协调层完整指南
【免费下载链接】makaApache Maka (Incubating) is a high-performance agent workspace that keeps a complete record of everything it did.项目地址: https://gitcode.com/GitHub_Trending/mak/maka
Apache Maka 的 WorkHub 需要持久协调入口:不建第二套数据库,给既有 Session 赋予特殊角色实现单协调会话,配合一条原子委派链接与一道确定性 Action Gate,完成崩溃恢复与权威边界。
一、一个值得先问清楚的问题
WorkHub 的定位是一个对话入口:用户在这里提问、澄清意图、延续旧工作、创建新工作。要让它"记住"这一切,工程师的第一反应往往很明确——给 WorkHub 单独建一套数据库、事件存储、转录(transcript,即对话与执行历史的持久记录)基座,再配一个生命周期管理器。
这个诱惑可以理解。协调者需要会话连续性,而连续性通常意味着专门存储。但 Maka 的对话、Turn 准入(root Turn admission,即一次执行回合的正式接收)、模型连接与恢复能力,早已全部落在 Session 基座上。再盖一栋"办公楼",等于同一份事实存两份,从此要同步、要对账、要裁决谁说了算。
架构决策记录(ADR,记录架构决策理由的文档)workhub-coordination-session-adr.md 因此立下铁律:
绝不产生第二个 WorkHub 数据库、事件存储、转录基座,或与 Session 并行的生命周期权威。
由这条约束直接推出三条设计契约:协调对话必须落在既有 Session 基座上;协调层只管对话,不管它所委派的执行;一切写入只认一道确定性关卡,不认模型。
中间的决策随之确定:每个 Runtime Host(运行 Agent 的宿主进程)独立持有一个稳定的 WorkHub 协调会话(Coordination Session)。它不是新实体,而是既有 Session 的一个特殊角色,首次需要时惰性创建,Host 或应用重启后解析回同一个 Session。领域术语的完整定义见 workhub-domain-language.md。
二、设计契约与权威划分:谁为谁负责,谁不为谁负责
这套架构的第一张图纸是权威划分,回答"什么信息由谁持久化":
- 归协调会话的:用户在 WorkHub 发出的消息、普通问答、澄清对话、协调决策、有界委派引用(bounded delegation reference,指向执行侧的受限指针)与协调摘要。它们全部存放在当前 Runtime Host 的协调会话转录里。
- 归普通 Session 的:具体执行、项目与文件系统范围、模型与权限模式、根 Turn 准入、工具调用、工件(artifacts)、恢复、归档与删除,以及权威执行转录。委派一旦成立,这些事实就属于目标普通 Session。
- 无持久权威的:WorkHub 卡片、过滤器、状态摘要、导航辅助。它们是可从 Session 事实随时重建的投影,像数据库视图而非表,重启后重新推导即可。
由此得到两条铁律。其一,协调会话只对协调对话有权威,永远拿不到普通 Session 的执行或生命周期权威。其二,意图(intent)描述用户想要什么,它不选择权威;选择权威的是确定性准入关卡。
实现上,这个角色在 session.ts 中被显式声明:保留角色名workhub_coordination、保留 Session IDmaka_workhub_coordination,以及判定函数isWorkHubCoordinationSessionId。SessionHeader的role?字段注释写明:缺省是普通 Session,特殊角色仍驻留在同一 Session 基座上。Session 的工具配置文件列表包含workhub-coordination-v1与workhub-coordination-v2,说明协调会话复用的就是现有执行通道,只是叠加了专门的工具面。
两处结构性隔离值得注意。按 Host 隔离是有意为之:协调会话只协调同一 Host 的普通 Session,不存在全局协调会话,首阶段不支持跨 Host。协调会话对普通 Session 列表隐藏,并被排除在所有路由候选集之外——关卡层的自我路由拒绝只是纵深防御,替代不了这个结构性约束。
三、从用户输入到安全写入的完整链路
整条链路可以概括为:用户输入 → 意图分析 → 目标解析 → 策略生成提案 → 关卡准入 → 落到归属的 Host 与 Session。下面按"判定、否决、外援"三段拆开。
3.1 怎么判:一条输入只能得出一个处置
普通路由输入最终必须收敛为恰好一个处置提案。判定按编号步骤走:
- 先做意图分析,把请求归类:讨论、执行、新建、延续,还是链接操作。
- 若是链接操作,沿"委派 → Session → Turn"的持久谱系(lineage,指记录间可追溯的生成关系)定位目标;缺失、过期或歧义的链接直接失败关闭(fail closed,宁可拒绝也不猜测),绝不回退到"名字相似"匹配。
- 若是新路由请求,Session Resolver 只返回有界的既有 Session 证据,且被硬性规定不得创建 Session。
- 协调策略(Coordination policy)把证据组合成一个建议性提案(advisory,仅供参考)。
- 提案提交给 Action Gate,准入后才触达归属方。
四种路由处置各占其一:answer_here(在协调会话内直接回答)、delegate_existing(委派给一个有界且有效的普通 Session)、create_new(先建普通 Session 再委派)、clarify(继续澄清,不猜目标、不建 Session)。
纠正、停止、恢复不属于这四种,而是链接操作:它们作用于既有的持久委派。纠正的替换目标仍被限制为delegate_existing或显式create_new准入;停止与恢复只沿持久谱系走,不靠显示名推断。
3.2 谁有否决权:确定性 Action Gate 与幂等重放
模型输出、路由策略、协调策略,在 Maka 里都只有提案权。写入权集中在 workhub-coordination-action-gate.ts 的WorkHubCoordinationActionGate。它在产生任何效果之前校验五类条件:Runtime Host 与目标有效性、归档(archived)与等待(waiting)状态、自我路由排除、create_new必须显式、既有工具与权限上限。替换操作另有三条:可信用户文本中必须存在显式纠正证据;必须按协调转录顺序声明源委派;任何后来的竞争性替换意图一律拒绝。
幂等性靠动作指纹(action fingerprint)实现:每次动作以actionId键控并计算请求指纹。同一actionId携带不同指纹时,关卡以action_conflict拒绝——换皮重试会被识破;指纹一致则返回已缓存的重放结果,副作用只发生一次。"重试同一动作不会执行两次"不是约定,而是关卡的记账规则。
目标选择是另一个关卡场景。协调模型在候选发现后可调用tasks.select_and_delegate,Host 用既有交互权威发布一个持久表单,接受一个确切的不透明选项,再把绑定的 Session/工作区交给同一道关卡。等待期间协调 Turn 已被准入,但只有关卡与目标准入才能启动执行;操作在等待结束后重读活动 Run 权威,永不改写既有路由决策。旧的"回答 → 选择 → 回答"前准入协议与渲染器 Promise 被整体移除,而非保留成第二套选择实现。协议层对应操作workhub.coordination.selectAndDelegate与candidate_set_stale错误定义见 workhub-coordination.ts。
3.3 模型适配器如何"帮忙但不越权"
模型路由适配器是可选安装件,分两个阶段调用无工具模型,边界由 workhub-routing.ts 中的常量钉死(WORKHUB_ROUTING_MAX_CANDIDATES = 32):
- Intent 阶段:使用协调会话保存的连接、模型与思考设置,只看当前请求和至多 8 条有界历史消息,看不到任何候选。系统提示第一句就是"Intent 不得选择 Session"。
- Recall 阶段:仅在
execute与普通continue时第二次调用,看到至多 32 个候选;每个候选只有请求作用域内的不透明引用、有界 Session/工作区名称、状态与新旧分桶。稳定 Session 身份、路径、文件内容、工具与能力一律不传入。
随后由applyWorkHubRoutingPolicy做确定性映射。以下情形全部失败关闭到clarify:模型输出无效、提供方失败、候选不可用、召回为空、结果歧义。没有任何一种隐含create_new——猜不中就问,绝不默默开工。
越权被从结构上堵死:Intent 输出不含目标;Resolver 输出只含不透明候选引用,不能返回创建或处置;链接目标证据同样只是建议,不能证明所有权;模型排序或工具选择单独不能授权任何工作。每个提案仍带着原始可信用户请求,经过 Host 拥有的关卡。生产默认值若要变更,必须走仓库既有的maka eval实验路径,分别报告 Intent 准确率、召回类型准确率、Recall@K、MRR、不安全绑定、隐式创建、不必要澄清、延迟、Token 用量与成本——刻意不另建 WorkHub 专用评估框架。
四、「链接而非复制」的委派模型
一次委派只在两个转录之间持久化一个有界链接,字段结构如下:
delegationId:委派身份,也是后续纠正、停止的键。coordinationTurnId:发起委派的协调 Turn。targetSessionId/targetMessageId/targetTurnId:目标侧的 Session、Message 与 Turn 身份。disposition:处置类型。
原子性是这条链接的灵魂。链接采用协调转录中一条闭合的类型化delegation_assigned记录,在协调会话与目标 Session 的准入权威之下,一次runtime.sqlite事务同时提交该记录与目标待处理消息准入;create_new时目标 Session 元数据也在同一事务中创建。记录携带确切用户文本、已解析目标与目标 Message/Turn 身份、创建上下文与稳定显示名,其指纹拒绝动作身份的冲突复用。
这次事务就是用户可见的分配边界:提交前两个 Session 都看不到工作;提交后 WorkHub 链接与目标输入同时存在。唤醒内存执行器只发生在提交之后;Host 在提交与唤醒之间崩溃,由普通待处理消息恢复接管——WorkHub 不拥有第二个恢复状态机或补偿链。delegation_assigned记录自身就投影出可见的 WorkHub Turn,渲染器不再追加第二条摘要。
执行状态走另一条路:只读投影,而非状态复制。初始分配链接不镜像目标 Turn 的生命周期。WorkHub 向目标 Message 权威查询"哪个 Turn 持久消费或准入了这条 Message",再联合该 Turn 的寿命周期与目标 Session 的确切活跃 Turn 成员关系,投影出running、waiting_for_user、completed、failed、aborted。未消费的转向消息被折叠进后继 Turn、恢复把多个待处理 Message 聚合进一个新 Turn 时,投影依然正确;持久取消墓碑可把撤回的排队 Message 解析为aborted;目标权威暂时不可读时投影为recovering,绝不虚构终结结果。这些状态从不作为可变协调记录追加;Session 变更通知使投影失效,重启后打开 WorkHub 从同一链接与目标事实重建。
这就是混合第一响应契约:delegation_assigned是即时的持久确认,WorkHub 无需等目标执行即可回复"已接受";而目标 Message 是稳定委派身份,targetTurnId只记录准入位置。渲染器在确认前只持久化一个 Host 作用域的动作 id,草稿文本用独立存储键,因此重载既保住幂等性,也不冻结旧文本。消息 schema 定义见 session.ts 的WorkHubCoordinationMessageEnvelope与WorkHubDelegationAssignedMessage。
五、崩溃之后怎么办:破坏性操作的恢复契约
破坏性操作不怕崩溃,怕的是"崩溃后说不清自己做到哪一步"。按崩溃可能发生的时间点,三条线各自有账可查。
纠正(replacement):两段式退役。任何破坏性退役之前,先持久化一条对源委派身份唯一的delegation_replacement_requested记录。随后目标 Session 的 Message 权威二选一:取消仍待处理的委派 Message,或解析该 Message 如何进入执行 Turn——由它创建的根 Turn 可以被停止;既有的用户 Turn 只是把它当转向消息消费了,则属于共享权威,必须保持运行。替换分配与旧链接的delegation_superseded证明原子提交。崩溃若落在"退役之后、替换分配之前",重试同一动作会从声明处恢复这条接缝;替换指纹绑定的是已解析的稳定目标 Session id 而非临时候选引用,元数据刷新不会改变动作身份,重试也不会换到别的 Session。若目标在破坏性边界之后变为归档、消失或等待,协调侧追加delegation_replacement_aborted终结事实,把已退役源移出活动链接,后续重试返回同样的终结结果,而不是展示一个"已停止却未超期"的悬空链接。
直接停止:第一索赔胜出(first-claim-wins)。停止先经共享 Session Resolver 解析目标,然后立即向 Host 询问"该 Session 的哪些委派仍持有可停止的工作",之后才回答用户。WorkHub 投影可重建、窗口打开时可能为空,所以破坏性回答绝不从投影给出。提案只携带解析产物——不透明委派身份与其所属 Session;显示名只是提案侧检索证据,永不进入准入;提案不携带自己的证明,证明由 Host 从持久状态制作。关卡在任何效果前重新验证三件事:分配仍存在、仍属于该 Session、该 Session 上没有其他委派仍持有可停止的工作。执行状态读不到时计为竞争,而非已完成。持久化上,退役前写delegation_stop_requested声明,退役后写delegation_stop_resolved观察;待处理取消墓碑保留破坏性动作身份,两条记录之间崩溃仍保持cancelled_pending(结果枚举另有stop_delivered、already_terminal、not_owned)。根 Turn 的停止在确切目标 Turn 上使用动作派生的中止源,恢复时不会把普通 Session 停止误认成 WorkHub 投递。可见性只为被停的那一个委派证明——因为不存在"退役一个 Session 已删除的委派",对全活动集证明会让一个已删除的 Session 阻塞所有停止;所以过期解析失败关闭,而解析与准入之间的重命名则正确地无关紧要。可信用户文本必须携带直接停止命令,user_stop确认保持在策略输出之外,模型输出与显示名都无法选择停止对象。
背后是全局动作声明:每条持久 WorkHub 记录按"它关于什么"键控(分配按动作,停止/替换按委派),任何单条记录都看不到移动到第二个委派的动作身份。同一协调准入下、在任何效果之前单独取得的持久动作声明就是全局所有者——精确重放收敛于它,其余复用(含被拒或仍在恢复的尝试之后、跨 Host 重启)在效果前失败关闭。声明不携带 Session 外键,因为已提交的破坏性声明必须比目标的移除更长寿:目标 Session 消失时,让停止到达终结解析的是它的移除墓碑,而不是消失的 Message 证明,更不是仅仅不可读的目标。
恢复(resume)。命名恢复直接使用普通 Session 的延续准入,报告resume_started或already_running,不创建第二个协调恢复账本。暂停与基于代词的停止控制列为后续工作。协议层的提案类型与前置条件完整定义于 workhub-coordination.ts。
六、这套方案的代价
收益有三。其一,WorkHub 在不增加第二个持久权威、数据库、事件存储或转录副本的前提下获得持久会话连续性。其二,协调与执行在共享 Session 基座内各自保持独立权威。其三,崩溃恢复全部复用既有机制——待处理消息恢复、墓碑、关卡记账,没有新增状态机。
成本有四。其一,按 Host 边界在用户切换 Runtime Host 时割裂 WorkHub 连续性:每个 Host 有独立协调转录,协调不了另一 Host 的 Session。其二,特殊 Session 角色即使刻意复用基座,也额外带来预置、查找、恢复、保留与 UI 义务。其三,每个被委派的协调 Turn 多一条类型化分配记录(它同时是可见时间线来源)。其四,Work 与 Session 是 1:1、1:N 还是独立持久实体仍未解决,跨 Host 协调被推迟。另需如实说明:ADR 中提到的 Resolver"临时精确名称基线"从未实现,截至 2026-09 的协调是模型驱动的——协调模型发现候选,准入重新验证不透明身份与预期状态,停止/恢复提案携带显式持久目标而非显示名。相关实现见 workhub-coordination-coordinator.ts。
再评估触发条件。若受支持的工作流需要一次 WorkHub 对话协调多个 Host 上的普通 Session,或 Host 切换造成可重建投影无法解决的用户可见连续性损失,应重审按 Host 决策。若实现特殊角色生命周期需要第二个持久权威、或普通基座无法安全强制的例外,应重审特殊角色方案。
四条被否决路线,各一句话收束。第二套 WorkHub 数据库、事件存储或生命周期权威:与铁律正面冲突,出局。跨 Host 的全局协调会话:违反按 Host 隔离,推迟。把普通 Session 完整转录复制进 WorkHub:违反"链接而非复制",只留有界投影。让模型或路由输出在关卡之外直接授权写入:所有写入必须过 Gate,提案权与执行权永久分离。
结语
整个决策浓缩为三个物件:一个特殊角色、一条原子链接、一道确定性关卡。对话持久化在既有基座上,执行状态归还普通 Session,写入收敛到单一否决点。任何要在通用执行子系统之上叠加持久协调层的产品,都可以直接借鉴这套"少即是多"的边界划分。
【免费下载链接】makaApache Maka (Incubating) is a high-performance agent workspace that keeps a complete record of everything it did.项目地址: https://gitcode.com/GitHub_Trending/mak/maka
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考