# Magpie 的 Intent Routing 是怎么选模型的

> 每一轮开始时，一个小模型先判断这条消息是难还是易，再决定组里哪个模型先回答。

Author: Shumin Fu  
Published: 2026-11-14  
Updated: 2026-11-14  
Tags: ai-agents, workflow, claude-code  
Canonical: https://funfun.zone/posts/magpie-intent-routing/

<div class="html-embed" lang="zh-CN">
<div class="mir">
<p>Magpie 是 yetone 做的开源工具，跑在你自己的电脑上。它给 Claude Code、Codex、Gemini CLI 这类 coding agent 提供一个统一的模型入口。你可以把多个模型放进同一个路由组，让 agent 选用整个组。Intent Routing 是组里的一种规则：每一轮开始时，一个小的分类模型会先判断这条消息是难还是易，再决定组里哪个模型先回答。</p>
<h2>一轮是怎么选模型的</h2>
<p>一个路由组里通常放一个强模型和一个便宜模型。新的一轮开始时，分类器会读用户的话，并判断这是困难任务还是简单任务。这个答案只决定谁先被问到，另一个模型仍然留在后面做故障转移。选定之后，这个选择会管住整一轮。因此，agent 把工具结果送回来时，请求会回到当初提出工具调用的那个模型，而不会重新分类。</p>
<figure>
  [image: 一轮开始时，分类器先判断难或易，再决定强模型还是便宜模型先回答；失败时另一个模型做故障转移。整一轮包括工具结果都沿用这个选择。]
  <figcaption>图 1　一轮开始时，分类器只决定谁先上场。工具结果也会回到同一个模型。</figcaption>
</figure>
<p>分类器并不是只看到最新这一句。源码说明写明，它拿到的是开启这一轮的用户原文，长消息会保留开头 3000 个字符和结尾 1000 个字符；同时还会拿到上一条用户消息和助手上一次回复，各最多 1000 个字符，并且被告知上一轮属于哪一类。因此，用户只回一句「go on」时，分类器可以按上一轮的类别来判断。官方文档则写分类器只看最新一条消息。就这一点而言，源码说明比文档写得更具体。</p>
<h2>规则按什么顺序检查</h2>
<p>Magpie 自己有一套模板，名字叫 Hard to strong, easy to cheap。示例组用的就是这套模板写出来的四条规则。网关从上往下检查，第一条命中的规则把它指定的成员排到第一。</p>
<p>你可以点选下面的一种情况。你点选其中一种之后，请求原文、规则按顺序检查的结果、分类器是否被问起，以及谁先被问到，都会跟着改变。</p>
<div class="mir-try" id="mir-try">
  <div class="picks" id="mir-picks" role="group" aria-label="Situation"><button type="button" id="mir-pick-quick" data-id="quick" aria-pressed="true">Quick question</button><button type="button" id="mir-pick-hard" data-id="hard" aria-pressed="false">Hard task</button><button type="button" id="mir-pick-goon" data-id="goon" aria-pressed="false">“go on” after a hard turn</button><button type="button" id="mir-pick-tool" data-id="tool" aria-pressed="false">Tool result, mid-turn</button><button type="button" id="mir-pick-compact" data-id="compact" aria-pressed="false">Compaction</button><button type="button" id="mir-pick-image" data-id="image" aria-pressed="false">Message with a screenshot</button><button type="button" id="mir-pick-fail" data-id="fail" aria-pressed="false">Classifier fails, first turn</button><button type="button" id="mir-pick-failprev" data-id="failprev" aria-pressed="false">Classifier fails, after an easy turn</button><button type="button" id="mir-pick-none" data-id="none" aria-pressed="false">Classifier answers 0</button></div>
  <div class="said">
    <span class="mt-label">The request</span>
    <p id="mir-said">what does the -race flag do?</p>
  </div>
  <div class="bench" aria-live="polite">
    <div class="pane">
      <span class="mt-label">1 · Rules, checked in order</span>
      <ol class="rules" id="mir-rules"><li><span class="n">1</span><span class="what">Compaction → cheap model</span><span class="state">No: not a compaction</span></li><li><span class="n">2</span><span class="what">Carries an image → strong model</span><span class="state">No: no image</span></li><li><span class="n">3</span><span class="what">Intent: a hard task → strong model</span><span class="state">No: the turn is easy</span></li><li class="hit"><span class="n">4</span><span class="what">Intent: an easy task → cheap model</span><span class="state">Matches: the turn is easy</span></li></ol>
    </div>
    <div class="pane">
      <span class="mt-label">2 · Classifier</span>
      <div class="answer" id="mir-asked"><span class="pill none">asked once</span><span>It is sent:</span></div>
      <pre id="mir-prompt">Kinds:
1. a hard task: designing, debugging, a change across several files, or planning
2. an easy task: a quick question, a small edit, a lookup, or running a command
<span></span>
The user's message:
&lt;message&gt;
what does the -race flag do?
&lt;/message&gt;
<span></span>
The number of the kind that fits it best (0 only if none does):</pre>
      <div class="answer" id="mir-answer"><span class="pill cheap">answers 2</span><span>Easy.</span></div>
    </div>
    <div class="pane">
      <span class="mt-label">3 · Who is asked</span>
      <ol class="order" id="mir-order"><li class="first cheap"><span class="who">Cheap model</span><span class="role">asked first</span></li><li><span class="who">Strong model</span><span class="role">failover</span></li></ol>
      <p class="why" id="mir-why">Rule 4 decides. The classifier says easy, so rule 4 puts the cheap model first. The strong model stays behind it in case the cheap one fails.</p>
    </div>
  </div>
  <p class="mt-note">这里的消息和分类器答案都是示例。真正的分类器本身是一个模型，因此它给出的回答可能不同。不过，网关对每一种回答的处理，与源码里的做法一致。</p>
</div>

<p>分类器只在「一条带意图的规则有可能成为第一条命中规则」时才会被问起。如果更前面的规则已经命中，比如请求里带了图片，这次调用就不会发生。除了意图、压缩和图片，一条规则还可以加上请求长度、推理强度、来自哪个 agent、开始时间，以及工作目录这些看得见的条件。源码说明强调，这些条件不会被猜测，同一条请求每次都会按同样的方式路由。</p>
<h2>分类器失败时会怎样</h2>
<p>同一道题在 10 分钟内再问一次，会直接用记忆里的答案。分类器失败之后会被搁置 30 秒，这样后面的每一轮都不必再把超时时间等完。</p>
<figure>
  [image: 每条请求按顺序处理：是否在压缩对话、是否仍是同一轮、读取可见事实、必要时才问分类器、分类器变慢或失败时怎么处理、第一条命中的规则说了算，以及把决定记住整一轮。分类器失败或回答 0 时，会沿用上一轮意图，或退回组的默认顺序。]
  <figcaption>图 3　每条请求按这个顺序处理。分类器失败或回答 0 时，会沿用上一轮的意图，或退回组的默认顺序。</figcaption>
</figure>
<h2>它做不到的事</h2>
<p>源码说明也列出了这项机制的短处。这些限制来自对源码的阅读，而不是线上评测。</p>
<figure>
  [image: 六条短处：每轮多一次调用，判断的是消息而不是接下来的工作，难易取决于你写的措辞，没有反馈，换模型会丢掉 prompt cache，一张图片会把对话钉在强模型上。]
  <figcaption>图 4　源码说明里列出的六条短处。</figcaption>
</figure>
<p class="source">根据公开的 Claude Artifact <a href="https://claude.ai/artifact/Guj5eVmEapGk72iy4hgDtk">Magpie Intent Routing</a> 整理，对应开源项目 <a href="https://github.com/yetone/magpie">yetone/magpie</a> 的 commit 873b498。产品介绍参考了 <a href="https://usemagpie.ai/">usemagpie.ai</a>。</p>
</div>
</div>
