关于 multica-mentioning
面向 Multica 协作的 Agent 技能,说明评论中的提及链接如何解析、哪些提及会触发 Agent,以及预览和结果的处理规则。
主要功能
- 01基于 UUID 的提及语法
- 02Agent 与小队的任务触发规则
- 03成员和议题链接行为
- 04触发预览与抑制规则
- 05广播和待处理任务规则
适用场景
- 01在评论中指派 Agent 或小队
- 02链接成员或议题而不触发任务
- 03预览评论将触发的 Agent
- 04排查被阻止或合并的提及
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ multica-ai/ multica --skill multica-mentioning安装后在 Claude Code 中输入/multica-mentioning确认已加载。
附带文件references/mentioning-source-map.md
详细介绍
提及与委派
本技能说明提及链接在 Multica 后端中的行为(WHAT),并追溯到源码。是否要提及——避免循环、对确认保持沉默——在你的运行时简报的 Mentions 部分;遵循它,不要在此重复。
以下每一条断言都固定到源码,位于
references/mentioning-source-map.md。如果行为与本文档有任何差异,源码映射表是重新核对它的地方。
提及链接由真实 UUID 构建
后端只通过这种 Markdown 形式识别提及:
[@Label](mention://<type>/<id>)
解析器(server/internal/util/mention.go 中的 util.MentionRe)接受
恰好四个 <type> 值加上 all 哨兵值,而 <id> 组只接受十六进制字符和短横线,或者字面字符串 all:
(member|agent|squad|issue|all)/([0-9a-fA-F-]+|all)
所以链接目标是真实实体 UUID(或 all),绝不是显示名称。方括号之间的标签是自由文本——那是人类可读名称所在的位置。
有一种 mention:// 形式故意位于此解析器之外:
[Label](mention://project/<uuid>)。project 不在上面的类型组中,
所以后端永远不会解析它,它也无法入队任何东西——它是一个仅用于渲染的链接,每个客户端都会使其可导航(Web 和桌面端上的 chip,移动端上点击即可打开项目的普通链接)。这正是重点:
项目引用绝不应该能够启动一次运行。可自由使用它来指向
一个项目(参见 multica-projects-and-resources 技能);本文档中的其他一切
都是关于解析器确实识别的四种类型(加上 all)。
步骤 1 —— 用 --output json 查找 UUID
名称不是 UUID。先从匹配的列表命令查找 UUID:
- 一个人 →
multica workspace member list --output json→ 使用user_id - 一个 agent →
multica agent list --output json→ 使用id - 一个 squad →
multica squad list --output json→ 使用id
对于一个人,提及 id 是 user_id,而不是成员关系行的 id——后端自己的名册格式化器使用 user_id 来表示成员提及。按显示名称匹配。如果名称有歧义或不存在,不要猜测——在你的评论中说明这一点,而不是发出一个损坏的链接。
第 2 步 — 四种类型以及每种类型究竟会入队什么
格式:[@Name](mention://<type>/<uuid>)。<type> 与 id 来源必须匹配,否则链接会解析到错误的实体(或什么都解析不到)。
| 要…… | type | uuid 来自 | 后端会做什么 |
|---|---|---|---|
| 触发一个 agent | agent | agent.id | 为该 agent 入队一次运行(EnqueueTaskForMention) |
| 把工作交给一个 squad | squad | squad.id | 解析该 squad 的 leader_id,并为 LEADER agent 入队一次运行 |
| 链接一个人 | member | member.user_id | 渲染一个链接;不会入队任何东西 — 不会运行 agent |
| 引用一个 issue | issue | issue.id | 渲染一个链接;不会入队任何东西 — 始终安全 |
mention 触发集合由 computeMentionedAgentCommentTriggers(server/internal/handler/comment.go)计算;评论路径会把该结果合并进 computeCommentAgentTriggers,并通过 enqueueCommentAgentTriggers 将其入队。它只作用于两种类型:squad 分支解析该 squad 并把它的 leader 加入触发集合;此后所有不是 agent 的都会被跳过(if m.Type != "agent" { continue }),然后 agent 分支加入该 agent。member 或 issue mention 两个分支都进不去,因此不会入队任何任务。
因此,member mention 并不会让某个人“运行”,并且本技能并不声称它会通过 Go 评论处理器投递通知 — 该处理器中并不存在这样的代码路径(见源码映射)。已得到验证的是上述契约:只有 agent 和 squad mention 会入队工作。
预览与按评论抑制
较新的客户端可以在创建或编辑评论之前调用 POST /api/issues/{id}/comments/trigger-preview。预览端点使用与创建和编辑重新触发相同的 computeCommentAgentTriggers 函数,因此显示的 agent 标签来自后端规则,而不是客户端的重新实现。
在预览编辑时,客户端可以发送 editing_comment_id。服务端会验证该评论属于同一工作区和 issue,推导或检查该编辑的父评论上下文,并且只排除 trigger_comment_id 为同一评论的待处理任务。该 issue 上任何其他评论产生的待处理任务仍会对预览去重。
在创建或编辑评论时,客户端可以发送一个可选的 suppress_agent_ids 数组。服务端仍会先计算完整的触发集合,然后作为后置过滤移除那些 agent ID。字段缺失或为空会保留旧行为。一个有效但不在计算出的触发集合中的 UUID 是无操作;格式错误的 UUID 会在请求边界被拒绝。
@all 是广播类型
@all 使用字面量 all,从不使用 UUID:
[@all](mention://all/all)
它面向该 issue 上的所有人。它不会让任何特定 agent 运行。而且它在触发时很特殊:带有 @all mention 的评论会被视为广播,从而抑制 issue 负责人的评论自动触发(以及其他隐式路由回退 — 线程父级 / 会话所有者)。用 @all 来通知,而不是向负责人请求工作。
@all 只会抑制那些隐式路由。同一条评论中显式的 @agent / @squad mention 仍会正常触发(MUL-5411):一条内容为 [@all](mention://all/all) heads up — [@Preflight](mention://agent/<uuid>) please take this 的评论会入队 Preflight,且不会入队其他人。显式 mention 优先于广播;参见 server/internal/handler/comment.go 中的 computeCommentAgentTriggers,其中显式 mention 分支会在 @all 短路之前被求值。
不会发生什么(这样结果就不会让你意外)
这些情况都不会启动一次新的运行,也都不会产生错误响应——但它们是三件不同的事,而响应会告诉你究竟是哪一种。一个从未解析成功的提及是真正静默的空操作。一个解析成功但被拒绝的提及会出现在 trigger_outcomes 中,状态为 status: "blocked",并带有 reason_code。一个目标已经繁忙的提及会返回 coalesced 或 deferred:不会启动第二次运行,但你的评论确实会被并入已经在运行的任务,因此它仍会被读取。发送后请读取那个数组——这是所有这些情况唯一会显现的地方。
- 在应填 UUID 的位置填了名称。
mention://member/Alice是无效的。id 分组只接受十六进制字符+连字符或all;典型名称中的非十六进制字母会使整个模式匹配失败,因此解析器什么也不返回。 - 一个像十六进制但错误的 UUID。 一个格式看起来正确、但不属于任何实体的 UUID 确实会解析成功,然后在查找时空操作:工作区范围的查询找不到任何 Agent,该提及被报告为受阻,原因为
invocation_not_allowed。该代码是故意含糊的——打错字的 UUID 和真正的权限拒绝被有意设计得看起来完全相同,因为你输入的 id 可能指向另一个工作区中的私有 Agent,而原因绝不能确认它存在。因此,当你看到invocation_not_allowed时,请先拿该 UUID 与实时名册核对,再去改动任何可见性或调用设置(MUL-5548);multica squad member list <squad-id> --output json会返回用于构建该提及的member_id。一个匹配该模式但根本不是有效 UUID 的 id(mention://agent/-)会被 id 解析器拒绝,并以target_unavailable受阻——非 UUID 在任何地方都指代不了任何实体,因此它不隐藏任何东西。这两种情况都绝不会是错误响应。 - 一个已经待处理的任务。 即使
@agent/@squad正确,当目标在此 issue 上已有待处理任务时,也不会启动第二次运行(HasPendingTaskForIssueAndAgent)。这是合并,不是丢弃:该评论会合并进那个任务,结果是coalesced(相同的已审阅 head)或deferred(不同的 head)——不要把它当作“提及没生效”而重新发送。编辑预览是唯一的例外:editing_comment_id会忽略正在被编辑的同一条评论产生的待处理任务,因为保存会在重新计算触发器之前取消那些旧任务。它仍然以评论为范围,而不是整个 Agent 范围的绕过。 - 一个已归档的 Agent,或一个未绑定运行时的 Agent(同样地,一个其 leader 如此的 squad):分别以
target_unavailable和runtime_offline受阻。两者都只在 invoke 门禁之后才检查,因此一个无权调用该目标的调用者永远不会得知其状态。 - 一个你无法调用的私有 Agent: 受阻——提及路径对
@agent和@squad都依据canInvokeAgent进行门禁。那是运行门禁,不是可见门禁:自 MUL-3963 起,一个能在 UI 中打开私有 Agent 的工作区管理员仍然可能无法触发它,因此能够查看该目标并不意味着能够提及它。(canEnqueueSquadLeader包装器是 squad 分配/提升路径,而非此路径;子任务完成唤醒没有门禁——参见 multica-squads 技能。)
一条跨 issue 的链会保留其人类(MUL-6490)。A2A 门禁评判你链顶端的人类,而该人类会随你写的评论一起传递:评论会记录撰写它的那次运行,因此它所唤醒的运行会继承你的发起者。当你评论的 issue 与你正在其上运行的 issue 不同时,这一点同样成立——即常见的“创建 issue Y,然后在那里协调”流程——因此,在你自己的 issue 上有效的委派,在你刚创建的 issue 上依然有效。它不会反过来成立:任何情况下都不会替换成另一个人类(你的 Agent 的所有者,或目标 issue 的发起者),所以如果你的链顶端没有人类,那么无论你移到哪个 issue,成员范围的允许列表都会保持关闭。
关于自动化(MUL-4857)的一个细节:当一次未归属的 autopilot 运行(schedule/webhook 派发没有人类发起者,因此 A2A 门控没有可依据的人类)在处理该 autopilot 创建的 issue 期间通过 @mention 进行委派时,调用门控会回退到 autopilot 创建者 作为实际调用用户——也就是最初允许首次派发的同一主体。因此,运行中途的 @agent / @squad 委派,只有在 autopilot 创建者能够调用该目标时(owner / public_to 匹配)才会触发,否则保持跳过。这仅涉及授权——入队运行的发起者/归属不变。
该回退绑定到已验证的任务谱系:仅当发起委派的运行自身的任务正是处理该 autopilot issue 的任务时(author == task agent,task.issue_id == 此 issue),它才适用,因此一个在其他地方工作的运行绝不能通过在其 issue 上评论来借用另一个 autopilot 创建者的权限。
同一权限也承载普通的已分配小队队长唤醒(worker 在 autopilot issue 上的结果评论仍可唤醒队长),并且它能在目标繁忙时保留:如果被提及的 agent 已在运行,则该委派会在该运行完成时以同一权限重放,因此绝不会丢失。
编辑被视为一次全新操作——它会从编辑操作重新推导该评论的谱系。只有 agent 作者编辑自己的评论时,才会将该谱系重新标记为编辑任务;任何其他编辑者——包括 workspace owner/admin 编辑 agent 的评论——都会清除它。因此,从无关 issue 编辑一条旧的 autopilot 评论,或 admin 编辑 agent 的评论(管理权限,而非调用权限),会在延迟的 completion-reconcile 阶段失败关闭,而不是复用原始运行的权限。
错误 → 正确
错误:@alice please review
→ 纯文本,无链接,解析为空,无人被触达。
错误:[@Alice](mention://member/Alice) please review
→ "Alice" 不是 UUID;id 分组会拒绝非十六进制字母,模式不匹配,链接静默失效。
正确:
multica workspace member list --output json→ Alice 的user_id= 7f3a…[@Alice](mention://member/7f3a…) please review→ 真实user_id解析成功;链接会渲染并解析到 Alice。
@all 广播:[@all](mention://all/all) heads up — 会触达所有人,不运行任何特定 agent,并抑制 assignee 自动触发。
这些确切形态由一个 Go 行为测试(TestMentioningSkillTeachesTheParserContract)固定,该测试将它们送入 util.ParseMentions:名称形式解析为空,真实 UUID 形式解析成功,@all 解析为 {all, all},而带有真实 UUID 的错误 type 仍会解析(这就是为什么 type 必须与 id 来源匹配)。
参考资料
references/mentioning-source-map.md — 针对正则、入队分支、@all 抑制以及 CLI id 来源映射的 file:line 证据,并明确注明 Go 评论处理器中不存在成员通知投递路径。