Multica Squad 源码级排障指南解码 leader 路由、leader briefing 与全部触发链路【免费下载链接】multicaMake humans and AI agents work as one team — open-source and self-hostable.项目地址: https://gitcode.com/GitHub_Trending/mu/multica在 MulticaMake humans and AI agents work as one team 的自托管开源项目中Squad 是「路由与协作对象」层面的核心概念它本身不是 Agent不会自己干活而是把工作统一路由到其leader_id指向的那个 Agent 身上。server/internal/service/builtin_skills/multica-squads/references/squad-source-map.md是一份为内置技能multica-squads服务的「源码地图」用于在任务需要精确源码路径、边界行为、测试或契约核验时给出证据链。本文以此文档为骨架结合 SKILL.md 的使用语义与仓库中的迁移文件、handler、CLI 实现与测试用例系统拆解 Squad 的对象模型、CLI 命令、leader 路由契约、leader briefing 注入机制以及 assignment / comment / autopilot / child-done / private leader 五条触发链路最终给出可直接执行的测试验证命令让你既能排查「Squad 为什么没跑」也能放心地在源码层面求证「Squad 到底该怎么跑」。这份源码地图的定位与适用场景squad-source-map.md并不是给普通用户看的操作手册而是给 AI Agent尤其是运行multica-squads内置技能的 Agent准备的源代码证据文件。它记录的每一条结论都锚定到具体文件路径、函数名乃至行号区间要求在使用时满足三条纪律任务需要精确的 source path、边界行为、测试或契约核验时优先查阅它它被设计为SKILL.md技能声明文档的配套参考——当 Agent 需要把「行为断言」上升到「源码证据」时从此文件取经排查思路默认是「先查行为契约再下结论」而不是想当然地认为代码有 bug。实际排障时的第一动作是一组只读命令按序执行multica issue get issue-id --output json multica squad get squad-id --output json multica squad member list squad-id --output json multica issue comment list issue-id --roots-only --summary --output json multica issue comment list issue-id --thread thread-id --tail 30 --output json其中两次评论读取是有顺序的扫描—展开序列先扫 root 评论拿到梗概再按需展开相关的 thread——mention 触发原因、失败原因和用户指令通常藏在回复里单纯的 root 扫描永远拿不到它们。命令形态不清楚时一律查 help 而不是猜multica squad --help multica squad member --help multica issue update --help multica issue comment add --help同时该技能有明确的副作用红线不要为了测试而执行 assign、comment、mention、update、delete 或记录 squad activity——这些操作会改动工作区状态或触发 Agent 运行。对象模型三张表与前后端类型DB 结构Squad 的核心数据全部落在三类迁移与查询文件中server/migrations/084_squad.up.sql # base table: name, description, leader_id, creator_id server/migrations/085_squad_archive.up.sql # archived_at, archived_by columns server/migrations/088_squad_instructions.up.sql # instructions column server/pkg/db/queries/squad.sql packages/core/types/squad.ts关键事实均可在迁移文件中逐一印证squad表存储name、description、leader_id、creator_id084_squad.up.sql并通过UNIQUE(workspace_id, name)保证名称在工作区内唯一、通过leader_id REFERENCES agent(id) ON DELETE RESTRICT强约束 leader 必须是 workspace agentsquad_member表存储member_type、member_id与role且member_type被 CHECK 约束限定为agent或memberCHECK (member_type IN (agent, member))以UNIQUE(squad_id, member_type, member_id)防止重复成员issue 的assignee_type在 084 迁移中被扩展为支持squad新约束为CHECK (assignee_type IN (member, agent, squad))085 迁移为squad增加archived_at TIMESTAMPTZ、archived_by UUID两列归档元数据088 迁移为squad增加instructions TEXT NOT NULL DEFAULT 列。前端类型契约packages/core/types/squad.ts 与后端保持一一对应Squad接口包含id、workspace_id、name、description、instructions、avatar_url、leader_id、creator_id、archived_at/archived_by以及列表响应专用的member_count与member_previewSquadMemberType是字符串联合类型agent | memberSquadActivityOutcome是action | no_action | failedSquadMemberStatus中 human member 的status恒为nullv1 没有人形成员的存在性信号UI 借此把真人成员渲染进同一列表而不显示状态胶囊。CLIsquad、member 与 activity 命令全景CLI 命令的权威实现位于 server/cmd/multica/cmd_squad.go覆盖三类操作。所有写操作前先用--help确认精确 flag。Squad 本体命令multica squad list --output json multica squad get squad-id --output json multica squad create --name name --leader agent-name-or-id --output json multica squad update squad-id --instructions leader coordination policy --output json multica squad delete squad-id结合源码中init()注册的 flagcmd_squad.go 的 create/update 区块create必填--name与--leaderleader 可按 agent 名或 ID 解析可选--description默认输出 jsonupdate支持--name、--description、--instructions、--leader、--avatar-url增量更新默认输出 jsonlist/get/delete默认 table 输出可用--output json切换。Member 子命令multica squad member list squad-id --output json multica squad member add squad-id --member-id id --type agent|member --role role --output json multica squad member remove squad-id --member-id id --type agent|member multica squad member set-role squad-id --member-id id --member-type agent|member --role role --output json源码默认值注意member add的--type默认agent、--role默认memberset-role的--role是必填的「新角色标签」。Squad leader evaluation 命令写操作multica squad activity issue-id action|no_action|failed --reason why --output jsonactivity是写操作把 leader 对某个 issue 的评估结论写入时间线。runSquadActivity在 cmd_squad.go 中的实现细节outcome 严格限定为actionleader 委派或行动了、no_action评估后认为无需动作、failedleader 遇到错误三者之一其余值直接报错附带--reason短说明最终 POST 到/api/issues/issue-id/squad-evaluated。它接受哪个 issue是你当前这一轮 turn 正在跑的那个 issue。目标 issue不必assign 给你的 squad——squadmention 到个人 Agent 拥有的 issue、或 leader task 绑定在子 issue 上都能正常记录。服务端校验的是你的 task 行is_leader_task加盖章的squad_id不是 issue 的 assignee。被 stage barrier 唤醒的 leader 跑在父 issue上所以要对着父 issue 记录而不是你刚读的那个子 issue传无关 issue id 会被拒绝且报错信息会点名你应该用的 issue。如果调用失败不要静默退出——no_action的评论禁令只在记录成功后生效。此时应该补发一条简短评论说明 outcome且仅当这一轮尚未评论过在action路径上你的委派评论本身就是那条记录。Squad 字段语义哪些进 prompt、哪些只是展示文档对字段逐一划定了「运行时影响边界」这是排障时最容易踩坑的地方id/workspace_id— 标识与归属name— 显示名工作区内唯一description— 人读的元数据/展示文本不要假定它对运行时 prompt 有影响除非源码证明了消费方instructions— 工作区级指令追加进 leader briefing不会被直接注入每个成员avatar_url— 可选的 squad 头像leader_id— leader 的 agent ID是 squad 路由工作的运行时目标creator_id— 创建者archived_at/archived_by— 归档元数据已归档 squad 会被 assignment / autopilot 路由路径拒绝member_count/member_preview— 仅出现在 list 响应中。instructions的正确用法是写「面向 leader 的协调策略」squad 职责、委派预期、何时请示人类、评审/交接规则。不要把它写成假设每个成员都会自动收到的内容——事实恰恰相反见下文的 briefing 注入范围。成员侧字段同理role只是 roster 里的角色标签不要假定它创造调度、权限或路由行为非空role才会出现在 leader briefing 的 roster 里。Create / Update 契约leader 必须是 workspace agent创建/更新的后端实现在 server/internal/handler/squad.goCreateSquad 约 L200-272UpdateSquad 约 L287-364校验逻辑使用 server/pkg/db/queries/agent.sql 的GetAgentInWorkspace。契约如下创建必须提供leader_idsquad.go L215-218leader 必须是 workspace agent——createL230-237与 updateL333-338都通过GetAgentInWorkspace校验已归档的 leader 不会被 create/update 拒绝GetAgentInWorkspace的 SQL 是WHERE id $1 AND workspace_id $2agent.sql L15-17没有 archived 过滤。也就是说这里可以把已归档 agent 设为 leader它会在路由/dispatch 阶段才 fail-closed例如 readiness gatesquad.go L945 的isSquadLeaderReady→ L1017 的service.AgentReadiness、assignment 校验issue.go L2625-2627、autopilot 准入autopilot.go L885-891leader 会被自动添加为 roleleader 的成员squad.go L258-263update 修改leader_id时若新 leader 尚不是成员也会自动补加为 roleleadersquad.go L340-347。Leader Briefing注入内容与「越权注入」的边界结构leader task 的 briefing 由 server/internal/handler/squad_briefing.go 构建buildSquadLeaderBriefingL180、buildSquadRosterL197、renderMemberRowL279、agentSkillsRosterSegmentL315、formatRosterRowL326在 server/internal/handler/daemon.go约 L1187、L1530完成注入。briefing 追加到 leader agent 的 instructions内容包含Squad Operating Protocol固定常量的系统级规则文件头为## Squad Operating ProtocolSquad Roster成员名、成员类型、mention markdown、非空 roleagent 成员额外列出其已分配工作区技能skills: a, b无技能则显示no skills assigned已归档的 agent 成员被跳过内置multica-*技能被排除human 成员不携带技能段Squad Instructions仅在instructions非空时出现squad_briefing.go L110-112。Agent 成员列出技能的机制是loadSquadMemberSkillNames底层走ListAgentSkillNamesByAgentIDs目的是让 leader按能力委派而不是靠 role 标签猜。关键边界注入比权限更宽briefing 的注入以is_leader_task为开关而这个 flag也会因别人拥有的 issue 上出现squadmention 而触发MUL-3724。也就是说一个被进他人 issue 的 leader 会拿到完整 roster 与委派规则但 protocol 里携带的是显式禁令「不要改这个 issue 的状态」buildSquadLeaderBriefing接收一个ownsIssueStatus参数通过squadOperatingProtocolFor选择职责 6仅当issue.assignee_type squad且issue.assignee_id squad.id时授予状态管理权squadParentStatusOwned否则给出显式禁令squadParentStatusNotOwned。quick-create 路径传false——issue 还不存在当 claim 的防御性 gate 扣下 briefing 时squad_id为 NULL、squad 被硬删除、enqueue 后 leader 被换掉handler 同时会在 claim 响应里清掉is_leader_task使 run 降级为普通 agent turn。daemon 从这个 flagquick-create 还加上squad_id推导 leader 角色绝不从 briefing 文本推断MUL-5811每个 claim 响应携带leader_role_resolved: true告诉 daemon 这些字段是权威的。早于该能力的服务端不会带它daemon 看到缺席时会回退到旧式推断——「## Squad Operating Protocol出现在 instructions 里」。这是解读旧版本唯一正确的方式#4951 之前根本不发is_leader_task#4951 之后虽然发 flag 却不保证附带 briefing。该字段仅存在于 claim 阶段永不被渲染进 prompt没有追踪到任何行为会把instructions注入给每个squad 成员。Leader Evaluation Recordingactivity的授权与降级语义记录路径涉及 server/internal/handler/squad.goRecordSquadLeaderEvaluation 约 L949、server/cmd/multica/cmd_squad.gorunSquadActivity 约 L459、server/internal/service/squad_no_action.go 的HasSquadLeaderNoActionEvaluationForTask、以及 server/internal/handler/comment.go约 L1851的 no_action 评论拒绝逻辑。契约极其讲究权威来源是X-Task-ID指出的 TASK 行不是 issue 的 assignee校验task.issue_id issue.id、task.is_leader_task、task.squad_id有效。squad 从task.squad_id加载目标 issue 可以 assign 给任何人MUL-6622 / GH #7487。修复前基于issue.assignee_type squad的 gate 与 claim 侧的is_leader_taskgate 不一致导致squad-on-agent-issue 与 leader-task-on-child 两条路径上该调用不可满足task 用GetAgentTaskInWorkspace而非GetAgentTask加载——后者是全局按 id 查找而拒绝路径会引用 task 的 issue id。检查顺序是 load-bearing 的先租户范围再「caller 拥有此 task」最后才谈任何引用 task 派生 id 的消息两道授权门task.agent_id caller然后是squad.leader_id caller。第二道必须存在因为行上的is_leader_task只是 enqueue 时的意图INTENTleader 在 claim 前被换掉时daemon.go 会清掉resp.IsLeaderTask并把 task 当普通 agent turn 跑而行上仍保留is_leader_task true。没有这道实时校验被降级的 run 就可能写下 leader 裁决并压掉自己的评论。要移除这道 gate必须先把 claim 实际交付的角色持久化activity_log.actor_id记的是task.agent_id不是squad.leader_idno_action评论抑制查找按task.agent_id匹配此处若记成实时 leader id 会静默破坏抑制机制leader agent 跑一个非 leader task会被拒绝——它此刻不是以 leader 身份运行runtime 也只对is_leader_task强制该调用no_action评论禁令以该写入成功为前提comment.go L1851 检查 activity 是否存在所以注入的 instructions 告诉 leader调用报错时就回退成一条评论——上限一条且仅当本轮尚未评论过。Issue Assignment 行为squad 赋值与状态权威赋值实现涉及 server/internal/handler/issue.go约 L2614-2632 的 assignee 校验、server/internal/handler/squad.goshouldEnqueueSquadLeaderOnAssign 约 L990、enqueueSquadLeaderTask 约 L1027与 server/internal/service/task.go。将 issue 赋给 squad 的形式是assignee_type squad assignee_id squad-id契约要点assignee_typesquad路由到squad.leader_idsquad.go L1028-1050status 为backlog的赋值不会立刻 enqueuesquad.go L991-993把 issue 移出 backlog 可能触发 leadersquad.go L990-994 →isSquadLeaderReadyassignee 变更会先取消该 issue 上已有的 task再走新 assignee 路径private leader 的访问权限在assign 时issue.go L2629-2632与enqueue 时canEnqueueSquadLeadersquad.go L1037双重检查已归档 squad / 已归档 leader 在 assign 时即被拒绝issue.go L2622-2627对 pending task 应用去重squad.go L1042-1048父 issue 状态由 agent 管理自 MUL-6417 起 brief 的状态规则是「工作真正改变状态时writeWorkflowIssue才落笔」的事实判断leader 变体追加一条要点——委派成员不等于交付完成所以 dispatch turn 让父 issue 保持in_progressin_review要等确认整体目标达成的再触发。Squad Operating Protocolsquad_briefing.go仍为拥有型 leader 写明持续性的in_progress→ 稍后in_review职责。StartTask/CompleteTask不写 issue 状态不再有 assignee gateguest leader 什么都不写不是因为缺少授权而是「没有推动 issue 状态变化的 turn 本就没有可记录的内容」状态名是分类规则自定义状态完整继承所属分类的行为MUL-6243server/internal/issuestatus/issuestatus.go 的Effective/Resolve只要工作区存在自定义状态brief 就会列出工作区状态目录MUL-6460writeIssueStatusCommand位于 server/internal/daemon/execenv/runtime_config_sections.go。赋值的校验会拒绝缺失的 type/id 配对、不存在的 squad、已归档 squad、已归档 leader以及 actor 无权访问的 private leader。Comment / Mention 行为唤醒的是 leader不是全员触发计算位于 server/internal/handler/comment.gocomment triggers 约 L1057-1199squad mention 分支约 L1352enqueue 侧在 squad.goenqueueSquadLeaderTask 约 L986lastTaskWasLeader 约 L915与 server/internal/service/task.go 的EnqueueTaskForSquadLeader。契约在 squad-assigned 的 issue 上评论可以唤醒 leader——评论路径经computeCommentAgentTriggerscomment.go L1124计算触发器其 assigned-squad 分支是computeAssignedSquadLeaderCommentTriggercomment.go L1162-1199同一计算也支撑 trigger-preview 端点显式 squad mention 格式为Squad Name该格式在 comment.go L1352-1391 被解析解析 squad、读leader_id、enqueue leader task并以当前评论作为 trigger commentsquad mention 不会 fan out 到成员——enqueue 只针对squad.LeaderIDcomment.go L1104-1112squad.go L1007 走 assign/backlog 路径leader task 使用is_leader_tasktrue经EnqueueTaskForSquadLeaderleader 自触发环路被防护same-leader / last-task-was-leader 守卫comment.go L1173-1176、squad.go L915 的 lastTaskWasLeader与成员显式 mention 跳过comment.go L1177-1179。Autopilot 行为squad 赋值的解析与准入实现位于 server/internal/service/autopilot.goresolveAutopilotLeader 约 L617-655dispatch 约 L88-111与 server/internal/handler/autopilot.go保存期校验 validateAutopilotAssignee 约 L845-893。对assignee_type squad的 autopilot可执行 agent 从squad.leader_id解析——resolveAutopilotLeader的 squad 分支autopilot.go L639-651readiness/admission 检查针对 leader保存期校验拒绝已归档 squad/leaderhandler/autopilot.go L881-891dispatch 时重跑resolveAutopilotLeaderAgentReadiness已归档 squad fail-closed / 跳过 dispatch——errSquadArchivedautopilot.go L644-645create_issueautopilot创建出的 issue 保持assignee_type squad与assignee_id squad-id实际执行的 agent 是解析出的 leaderautopilot.go L88-97run_onlyautopilot不创建 issuetask 直接为解析出的 leader 创建autopilot.go L99-106经 resolveAutopilotLeader 于 autopilot.go L284 dispatch。Child-done Parent Triggerstage barrier 的串行交接当子 issue 关闭某个 stage barrier、且父 issue 赋给 squad 时父 squad leader 会被触发。实现在 server/internal/handler/issue_child_done.godispatchParentAssigneeTrigger 约 L246triggerChildDoneSquad 约 L304。几条容易误判的边界路由只到 leader——一次EnqueueTaskForSquadLeader落在 leader 上没有成员 fan-out没有自触发守卫同 squad 或共享 leader 的子 issue 依然会唤醒父 squad leader——这次唤醒是打到父 issue上的串行交接也是 stage barrier「推进/收尾」指令的唯一载体MUL-3969镜像自 agent 路径的 MUL-2808。再触发仅受HasPendingTaskForIssueAndAgent限制对每个父 issue agent 幂等没有 leader-invocation gatechild-done 不会重新检查子 issue 的完成者能否调用 leader。父 issue 在 squad-assign 时已做过权限检查validateAssigneePair唤醒它自己的 leader 属于协调交接而非一次全新调用。若在这里重查对DEFAULT private leader会 fail-closed——子 issue 的完成者是 agent/system actor没有可解析的人类发起者于是所有 process-squad 流水线在第一阶段之后就被卡死而直连 leader-agent 的父 issue 却一路正常MUL-4063 / GH #4928。Agent 与 squad 的 child-done 现在共享同一条无 gate 的路径任何未来的 invocation gate 必须同时加到两者上父状态不会被 barrier 自动推进系统评论只是请 leader 继续或在整体目标达成时运行multica issue status parent-id in_review。Squad Operating Protocol 中常驻的「Own the parent issue status」职责仅在 issue 属于本 squad 时出现表达同一预期系统评论标记收尾时刻。自 MUL-6417 起该写入本身不需要授权——brief 的事实判断已覆盖——但done仍归人类/集成方所有。Private Leader Access触发门与视图门是两回事调用门invocation gate实现在 server/internal/handler/agent_access.gocanInvokeAgent 约 L48-108canEnqueueSquadLeader 约 L261-267与 server/internal/handler/squad.goenqueueSquadLeaderTask gate 约 L955-974。注意这是MUL-3963 的触发门与视图门canAccessPrivateAgent截然不同canEnqueueSquadLeader加载 leader 后委托给canInvokeAgentagent_access.go L261-267canInvokeAgent按有效的发起用户判定member actor 就是其本人agent/system actor 是链路顶端的人类发起者originatorUserID解析不到时为agent_access.go L48-54agent 的所有者随时可以调用自己的 agentagent_access.go L57-59permission_mode ! public_to即 private时是 deny-by-default——没有 admin 旁路、没有 A2A 旁路只有 owner 分支能过agent_access.go L61-65public_to模式查 invocation 目标 allow-listworkspace目标放行任何 workspace 成员以及工作区内部的 agent/system 主体即使解析不到人类workspaceBroadmember目标要求解析出的人类匹配team目标在 V1 中不生效agent_access.go L82-106接入点enqueueSquadLeaderTasksquad.go L955-974squad 的 assign/promote 路径在 actor 无法调用 leader 时拒绝 enqueuemember 作者即本人 originatoragent 署名的触发器传注意child-done 唤醒不再走这道门——见上文MUL-4063。测试组与一键验证源码地图给出了完整的测试矩阵全部位于 server/internal/handler 下server/internal/handler/squad_assign_trigger_test.go server/internal/handler/squad_comment_trigger_test.go server/internal/handler/squad_briefing_test.go server/internal/handler/squad_private_leader_test.go server/internal/handler/autopilot_private_leader_test.go server/internal/handler/squad_no_action_test.go同一目录下还可看到更多相关用例如squad_evaluation_provenance_test.go、squad_id_enqueue_test.go、squad_creator_scope_test.go、squad_parent_status_contract_test.go、squad_worker_comment_wakes_leader_test.go、issue_child_done_test.go等。回到仓库根后运行下面的验证命令即可一次跑完与 squad 相关的全部测试go test ./internal/handler -run Test.*Squad|Test.*squad|Test.*Autopilot.*Squad|Test.*ChildDone.*Squad常见错误假设结论速查最后把源码地图与 SKILL.md 反复强调的边界浓缩为一份速查表适合在排查与文档引用时直接对照Squad 不是 Agent它本身不执行工作squad 工作路由到leader_id不是每个成员squad mention、squad assignment、squad autopilot 同理都解析到 leader 一人instructions是 leader briefing 内容不是自动的成员 promptdescription未被证明是运行时 prompt 内容role是 roster 上下文不是自动调度backlog 上的赋值不会立刻开工把 squad-assigned issue移出 backlog才可能触发 leader第一次 leader dispatch 不等于父 issue 完成——父 issue 保持in_progress直到 leader 稍后确认整体目标并推进到in_review服务端也不会在子 issue 完成时自动翻转父状态只会唤醒 leader 并给出显式请求含收尾时的in_review指令拿到 leader briefing 不代表有状态权威被进他人 issue 的 squad 是 guest——roster 与委派规则照拿multica issue status不行activity记录的是「当前 turn 正在跑的 issue」授权来自 task 行而非 issue assignee已归档 squad/leader 在各路由阶段统一 fail-closed但 create/update 阶段不拦截。需要更深一步时完整源码路径、行号锚点、边界行为与测试文件清单都可回到 references/squad-source-map.md 与 SKILL.md 本身继续追证。【免费下载链接】multicaMake humans and AI agents work as one team — open-source and self-hostable.项目地址: https://gitcode.com/GitHub_Trending/mu/multica创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
