Skip to content

routing: try a group's rules on a message before saving them #2829

Open

Description

@ggbdpq

A real case: a user routes with a group, intent rules and a small classifier (Clef on Cloudflare Workers AI, say). The intents are written in English, as the templates suggest: a hard task: designing, debugging, a change across several files, or planning. Then they are stuck: their own message — 帮我把这个函数改成并发安全的 ("make this function concurrency-safe") — will the classifier call it hard or easy? The rule doesn't say: its behavior is whatever the small model answers for that message. Today the only way to learn it is to save the draft, run a real agent conversation, and read classWhy on the Routing page. Every wording change walks the loop again.

Proposal

A try box under the rules in the group editor. Paste a message and see, in under a second in the GUI, which intent the classifier picked, which rule matched, and which member goes first — for an unsaved draft.

Implementation

  • One decision function for try and live traffic: the part of ruleFor that keeps nothing is split out as turnDecide. A live turn calls it and keeps what it decided under turnRules, as before; TryRule only calls it. No dry-run flag crosses the hot path.
  • A try asks the classifier by itself (directAnswer): no shared cache read or write, no rest for a classifier that failed, no failure note on the group's card, and no request to any member.
  • Three entries: the editor's try box, POST /api/groups/try, and magpie group try <id> <message…> — the CLI decides beside any running magpie, asking the classifier itself from the same files, for a saved group.
  • The answer is the trace's own RuleHit, rendered by the Routing page's existing ruleWhy/classWhy.

Verified

  • 14 cases on real machines, macOS and Windows, all passing. On Windows the GUI's real classifier calls took 548–791 ms and the CLI 0.79–1.08 s (process start included); on macOS the CLI decided in 654 ms. No member model took a request the whole time. A try's classifier call is recorded like any classifier call (agent: magpie, kind: routing) and shows on the Routing page with the classifier badge.
  • Branch ggbdpq-try-rule: 22952132 is the feature, b96469dc fixes the single-intent wording. Both commit bodies carry the full record: guard tests shown red when broken and green restored; go vet and go build on darwin, linux and windows; the GUI in Chromium and WebKit — routing-rule-try.test.cjs 16/16, and the 17 group-editor regression files it runs with, 194 tests across both engines.

Savings (an estimate)

Tuning a group of 2–3 intent rules usually takes 5–20 tries. Each try today is a real agent conversation (about 10k–50k tokens) plus 0.5–2 minutes of hands-on time; a try is about 150 tokens and under a second.

Boundaries

  • Purely additive: remove it and no existing path changes.
  • It serves users who write intent rules and iterate on their wording. A group with no deciding rules says so at once and asks the classifier nothing.
  • A try is a preview: a conversation's first turn, no reasoning, images or folder, and it knows nothing of affinity or rests.
  • One observation: with a single intent in the group, small models occasionally lean toward 1 (one "hey, what's up?" came back as a hard task). A try shows this; it doesn't fix it.

Open question

On the Routing page, a try's classifier call looks the same as a live one. Whether to tell them apart (a field of its own) is the maintainer's call; the branch doesn't do it.


Attribution: If these commits are applied, please keep their author (ggbdpq) or add Co-authored-by: ggbdpq <ggbdpq@gmail.com>.

AI: written with AI assistance — Generated-by: GLM-5.3-Flash (ZCode).

Activity

  1. ggbdpq commented on Oct 23, 2026

    @ggbdpq
    ContributorAuthor

    Refresh of the branch for #2829, the Routing group editor's "Try these rules" box shared earlier on ggbdpq-try-rule at b96469dc: what a draft's rules would decide for a conversation's first turn saying the words given — the classifier asked for real, the matching rule named, nothing routed and nothing kept — through POST /api/groups/try and magpie group try, beside any running magpie; and a group with a single intent asks whether the turn is it, not which of the kinds it is.

    Rebased onto fa22bc64 (new head 26eb3fbe). The only conflict was internal/gui/assets/plugins/routing/i18n.js, where upstream and this branch added entries at the top of the same four language blocks; both sides are kept, no wording changed. internal/gateway/rules.go, where ruleFor and turnDecide live, has no upstream change since the old base, so the gateway side carries over as it was.

    Tests, all on the new head:

    • go test ./internal/gateway/ green (whole package); go test -tags nogui ./internal/cli/ green; the internal/gui package's TestGroup*/TestTry*/TestTurn* green. (TestProxyCheckSaysAProxyPassedBy is red, and is red on a clean fa22bc64 too — pre-existing, not this change's.)
    • routing-rule-try.test.cjs 16/16 in Chromium and WebKit across the five languages; i18n-keys, routing-intent-fallback and five group-editor regressions (group-editor-align, group-editor-fits, group-fold, routing-groups-jump, routing-save-blank) 93/93.

    Refreshed with AI assistance (GLM-5.3-Flash via ZCode).

  2. yetone commented on Oct 27, 2026

    @yetone
    Owner

    谢谢 @ggbdpq,需求说得很清楚,分支和测试记录也很完整。这次先不合,原因如下:

    • 它在 Routing 的分组编辑器里加了一块新的界面。10-14 gui: make the Routing context lazy and align wide cards #1354 回滚之后定下的规矩是:社区提出的界面新增和布局改动默认不做,除非 owner 要求。写意图规则的用户不多,而这块界面所有人打开分组编辑器都会看到。
    • 合进来需要把 ruleFor 拆成 turnDecide,这会动到每个路由轮次都要走的热路径。分支基于 fa22bc64,之后 main 上的 rules.go 又改过(规则可以列多个模型,见 hit.More),没法原样落上去。
    • 第二个提交改的是单意图分组在 classWhy 里的措辞,live 流量也会受影响,跟 try 不是一件事。真要做的话应该单独提。

    现在想验证规则写法,可以不跑完整的 agent 对话:保存分组后,直接对网关发一条只有你那句话的请求,model 写分组 id,max_tokens 设成 1;规则里限定了 agent 的话,用 Authorization: Bearer magpie-<agent>。这一条就是新对话的第一轮,Routing 页会显示 classWhy、命中的规则和先走的成员。代价是成员会收到一次极短的请求。

    这条先开着,留给 owner 决定要不要做界面版。如果只要 CLI/API(magpie group try,不加界面),建议单独开一个 issue 讨论。

  3. ggbdpq commented on Oct 27, 2026

    @ggbdpq
    ContributorAuthor

    Thanks for the detailed reply, and I accept the decision — the UI-addition rule settled after the #1354 rollback is a fair line, and the turnDecide hot-path concern stands on its own. The branch stays on the fork for reference. If a non-UI variant (rule-side verification only, via the gateway request you described or a CLI/API form) is ever wanted, I'm happy to discuss it in a separate issue. The no-UI recipe you gave is already useful as is.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions