<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Routa Blog</title>
        <link>https://phodal.github.io/routa/blog</link>
        <description>Routa Blog</description>
        <lastBuildDate>Thu, 19 Mar 2026 00:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <item>
            <title><![CDATA[当 AI 进入交付闭环：我们如何设计一套反熵的人机协同治理机制]]></title>
            <link>https://phodal.github.io/routa/blog/routa-fitness-anti-entropy</link>
            <guid>https://phodal.github.io/routa/blog/routa-fitness-anti-entropy</guid>
            <pubDate>Thu, 19 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[这套机制最早来自 Routa 项目内部的 fitness 实践。我们最初把它以 routa-fitness]]></description>
            <content:encoded><![CDATA[<div class="markdown"><p>这套机制最早来自 Routa 项目内部的 fitness 实践。我们最初把它以 <code>routa-fitness</code>
的名字发布到 PyPI，作为 Routa 内部 fitness orchestration 的对外抽象；后来，随着它逐渐从项目内规则执行器演化成一套更独立的
change-lifecycle guardrails，我们把项目改名为 <code>entrix</code>。名字变了，但核心没有变：它仍然围绕 <code>docs/fitness</code>
里的规则定义、基于变更生命周期的质量门槛、风险分流、深度验证，以及在高风险场景下触发人工 review 的机制展开。</p>
<p>真正值得问的问题，不是“这个包能做什么”，而是：</p>
<p><strong>当 AI 开始参与交付，工程系统靠什么判断一项变更到底算不算完成？</strong></p>
<h2>Vibe Coding 的问题，不是更快，而是更容易失控</h2>
<p>Vibe Coding 最迷人的地方，是局部反馈会变得非常顺滑。</p>
<p>你给出一个目标，AI 很快补全代码、修掉报错、加几条测试，终端持续吐出绿色信号：编译通过了，接口通了，页面能点了，测试也过了。整个过程看起来比传统开发更流畅，也更像“事情正在快速推进”。</p>
<p>但问题也恰恰出在这里。</p>
<p>Vibe Coding
提升的是局部推进速度，不会自动提升系统整体可信度。很多时候，熵增就是这样发生的：表面上的“已完成”越来越多，真正决定系统可靠性的约束、不变量和上下文，却没有同步进入自动化流程。代码变多了，绿灯变多了，提交变密了，但工程系统对“这次改动到底安不安全”的判断，并没有一起升级。</p>
<p>过去，这种空白可以靠人来吸收。一个资深评审者会本能地知道：这次改动虽然测试都过了，但仍然值得怀疑；这组 API 虽然都返回成功，但业务规则可能已经在
use case 层失真。可一旦执行者里加入 agent，这些原本依赖经验和默契的判断，如果没有被显式化，就会逐渐变成系统性风险。</p>
<p>所以，Vibe Coding 带来的最大变化，不是单纯的效率提升，而是<strong>完成条件开始漂移</strong>。
代码更快生成了，但“什么叫真的做完了”反而变得更模糊了。</p>
<h2>覆盖率没有错，但旧的完成条件已经不够用了</h2>
<p>几乎所有团队在引入自动化验证时，都会先从测试和覆盖率开始。我们也不例外。覆盖率直观、可量化、容易进入
CI，看起来像一个不错的工程控制面板。它至少能回答一个问题：哪些代码被跑到了。</p>
<p>但 Vibe Coding 里的问题，已经不再只是“有没有跑到”。</p>
<p>功能路径跑通了，负向路径有没有被验证？接口返回 200 了，契约字段有没有漂移？一组 endpoint
看起来都正常，跨层业务不变量是不是已经悄悄被破坏了？改动规模和风险半径已经变大了，系统有没有自动把它升级到需要人工复核的等级？</p>
<p>覆盖率对这些问题的回答能力是有限的。它可以是信号，但不是结论；可以是输入，但不是完成条件。真正重要的，从来不是数字本身，而是*
<em>变更之后，系统最关键的行为到底有没有被证明</em>*。</p>
<p>后来，entrix 的 fitness 规则手册里留下了一句很重要的话：目标不是“覆盖率数字”，而是“变更后核心行为可被验证”。</p>
<p>这句话背后其实是一次方向转折。问题不再是“怎么让 agent 多跑几个测试”，而是：</p>
<p><strong>怎么把完成条件从人脑里的经验，迁移成系统可执行的结构。</strong></p>
<h2>当 AI 进入交付，真正失效的是隐性的判断权</h2>
<p>如果把 AI 看成只是一个更快的代码生成器，那么工程系统面对的似乎只是熟悉的问题：代码更多了，提交更密了，反馈更快了。可真实情况要难得多。</p>
<p>AI 可以很快把局部问题修平，也可以很快制造一种“已经差不多了”的完成感。构建通过了，接口通了，覆盖率也没掉，看起来一切都在朝“完成”推进。问题在于，
<strong>局部信号的增长，并不自动等于系统整体可信度的增长</strong>。</p>
<p>过去很多真正关键的判断，其实从来都不在 CI 里，而在人脑里：</p>
<ul>
<li>这个改动虽然不大，但触到了契约敏感区域</li>
<li>这条测试虽然过了，但没有证明真正关心的业务不变量</li>
<li>这个 diff 看起来绿了，但扩散半径已经超出了普通提交</li>
<li>这类改动不适合再往自动化里压，应该直接拉人进来复核</li>
</ul>
<p>这些判断一直存在，只是过去团队默认靠经验和默契来承担它们。Vibe Coding 的问题，不是凭空制造了新的风险，而是让这些原本隐性的判断权失去了稳定载体。</p>
<p>所以，AI 增加的不是单纯的代码量，而是<strong>系统对判断权显式化的压力</strong>。</p>
<p>真正失效的，不是某一条测试，而是那套默认由人脑兜底的完成标准。</p>
<h2>反熵不是补更多测试，而是重新设计判断结构</h2>
<p>很多团队谈 AI 工程化，第一反应是“把更多事情自动化”。这个方向没有错，但它不够。因为真正棘手的问题常常不是自动化做得太少，而是系统不知道什么时候不该继续自动化下沉。</p>
<p>这也是我们后来越来越清楚的一件事：反熵不是让机器做更多决定，而是重新设计**哪些判断该交给机器，哪些判断只能由机器辅助，哪些判断必须留给人
**。</p>
<p>在 entrix 里，我们最后把这条路径收敛成五个阶段：</p>
<ul>
<li><strong>规则前置（Policy Setup）</strong>：先定义这次变更要如何被证明是安全的。</li>
<li><strong>基础门槛（Quality Gates）</strong>：编译、lint、静态检查、单测、覆盖率这类快速自动化检查。</li>
<li><strong>风险分流（Risk Routing）</strong>：识别高风险目录、diff 扩张，以及通过 graph review context 辅助判断改动扩散。</li>
<li><strong>深度验证（Deep Validation）</strong>：API parity、<code>rust-api-test</code>、security 扫描，以及面向 desktop shell 的
E2E、Accessibility、Visual Regression、performance smoke。</li>
<li><strong>决策闭环（Decision Loop）</strong>：用 hard gates 和 score model 做判断，再把事故、漏检和新经验回写为规则。</li>
</ul>
<p>这个划分最重要的意义，不是看起来更流程化，而是把一个长期含混的问题讲清楚了：</p>
<p><strong>Fitness 不是 SDLC 里的一个步骤，而是嵌在变更生命周期里的多阶段守护层。</strong></p>
<p>越靠左，问题越确定，越便宜，越适合直接自动阻断；越往右，问题越依赖语义、上下文和后果判断，也越需要人的专业介入。真正成熟的人机协同，不是尽量消灭人，而是
<strong>把人的判断放在最值得花成本的位置</strong>。</p>
<p>如果再说得更直白一点：
反熵不是补更多测试，而是把判断结构重新设计清楚。</p>
<h2>Entrix 做的，不是加检查，而是把判断结构写进仓库</h2>
<p>这套东西之所以会慢慢成形，不是因为我们先设计了一套漂亮的方法论，再回头找工具实现；恰恰相反，是因为项目里的真实问题不断逼着我们承认：很多原本依赖
review 经验和团队默契的判断，已经不能继续停留在口头层面了。</p>
<p>所以我们做了三件很朴素、但很关键的事。</p>
<p>第一，把规则写进仓库。
我们把治理规则收进 <code>docs/fitness/*.md</code>，用 frontmatter 去定义 <code>metrics</code>、<code>threshold</code>、<code>tier</code>、<code>hard_gate</code>
，把“应该这样做”变成“系统能读取、能执行、能追责”的结构。</p>
<p>第二，把证据写进仓库。
我们把 <code>unit-test.md</code>、<code>rust-api-test.md</code> 这类文件逐渐做成证据账本，不再只写“应该补测试”，而是明确写出哪些条目是 <code>VERIFIED</code>
，哪些仍然是 <code>TODO</code>，哪些已经 <code>BLOCKED</code>。它还远没有完美，但至少证据开始在仓库里有稳定落点，而不是继续漂浮在口头说明里。</p>
<p>第三，把解释收进执行器。
再往后，我们把规则解释和执行统一收进 <code>routa-fitness</code> 里，让系统不只是“跑几条命令”，而是开始承认哪些信号算 hard gate，哪些该按
tier 分层运行，哪些变化该触发人工 review，哪些检查只应该在 changed-only 场景里执行。</p>
<p>这件事的意义，不在于 Markdown 比 YAML
更优雅，而在于它改变了知识的存在方式。过去，很多判断只存在于人脑里；现在，它们至少开始以仓库内的形式稳定存在。过去，很多“完成”只是口头感觉；现在，它们开始带着证据状态进入系统。</p>
<p>说到底，我们真正固化的，不是检查命令，也不是某几条测试，而是：</p>
<p><strong>在什么地方由机器直接判断，在什么地方由系统辅助标记，在什么地方必须把人拉回来。</strong></p>
<p>这才是代码化固化真正重要的部分。</p>
<h2>我们不是被测试数量逼出来的，而是被验证结构失真逼出来的</h2>
<p>如果要挑一个最能说明这套方法是怎么从项目里逼出来的例子，我会选那个关于 Rust fitness 曾经缺少 <code>application/use-case</code> test
layer 的问题。</p>
<p>这个问题的关键不在于“测试不够多”，而在于测试分层本身出了问题。那时证据主要落在两端：一端是 store / 规则映射层的单元测试，但很多还是
TODO；另一端是 endpoint 级 API 回归和大型 E2E。中间缺掉了一层真正承载业务规则编排的 use case 级验证。</p>
<p>于是结果就变成：很多本来应该建立在业务规则上的信心，被迫建立在 handler 层接口测试数量上。</p>
<p>这和“覆盖率不够”其实是同一个问题的更深版本。问题不再只是数字失真，而是<strong>验证结构本身失真</strong>
。如果验证结构错了，哪怕测试很多，系统仍然可能对关键不变量缺乏直接证据。</p>
<p>后来我们把 <code>tasks</code> 和 <code>sessions</code> 的部分编排逻辑抽进了 application
service，并补上对应测试。这个案例让我们更清楚地看到：反熵不是简单地“加检查”，而是按风险重新分配验证成本。便宜、确定的问题要尽早自动拦下；昂贵、复杂的问题不应该平均铺开，而应该只在高风险时触发；真正高语义密度的判断，则必须承认机器只能辅助，不能代替。</p>
<p>问题不在于测试少，而在于<strong>验证结构可能是错的</strong>。</p>
<h2>从阻断到分流，治理机制开始承担调度职责</h2>
<p>当规则、证据和执行器逐渐稳定下来之后，fitness 的角色也变了。它不再只是回答“通过没”，而开始回答“下一步该交给谁”。</p>
<p>这也是 <code>changed-only</code>、<code>review-trigger</code>、graph review context
这些能力真正有意思的地方。它们表面上看像功能增强，实际上代表了一种治理思路的变化：系统不再满足于对所有改动一视同仁地跑完一遍检查，而开始承认
<strong>变化感知本身就是治理能力的一部分</strong>。</p>
<p>不过就当前实现来说，这套能力还主要落在路径命中、diff 规模和 graph 辅助上下文上，离更完整的风险分流系统还有距离。但方向已经很清楚了：系统开始从“检查器”慢慢长成“调度器”。</p>
<p>尤其是 <code>review-trigger</code>，它背后的判断非常值得保留。不是所有风险都适合继续自动化下沉。有些改动如果触达高风险目录、扩大 diff
半径、碰到契约敏感区域，最合理的动作不是再补几条检查，而是明确要求人工参与。</p>
<p>这件事听起来并不“酷”，但它很真实。成熟的工程治理，不是尽量消灭人，而是知道什么时候必须把人拉回来。自动化的边界被画清楚，反而说明系统开始成熟了。</p>
<h2>我们学到的，是如何给 AI 增加可计算的摩擦</h2>
<p>如果要把这段演进压缩成几条方法论，我会总结成四点。</p>
<p>第一，覆盖率不是完成条件。它是输入，不是结论。真正重要的是关键行为、负向路径、契约一致性和风险升级能不能被联合判断。</p>
<p>第二，治理规则必须进入仓库。一个 agent 在运行时发现不了的规则，在工程上就等于不存在。</p>
<p>第三，证据比口头说明重要。<code>VERIFIED</code>、<code>TODO</code>、<code>BLOCKED</code> 这样的状态看起来很笨，但它们比“应该已经测过了”可靠得多。</p>
<p>第四，自动化系统必须知道何时引入人工。成熟的 Harness Engineering，不是把一切都自动化，而是在高不确定性和高风险场景里增加*
<em>可计算的摩擦</em>*。</p>
<p>如果再把这四点压成一句话，那就是：</p>
<p><strong>AI 参与交付之后，真正重要的不是让生成更快，而是让完成条件、验证证据和审查升级变得可计算。</strong></p>
<p>这也是为什么我们越来越把 fitness function 理解成一种反熵实践。它的目标不是让工程系统看起来更漂亮，而是让它在 AI
参与之后不那么容易失控。</p>
<h2>Vibe Coding 需要的，不是更多绿灯，而是新的治理基础设施</h2>
<p>今天你已经可以直接安装 <code>routa-fitness</code>。它远没有成熟到可以自称平台，也未必天然适合任何仓库；但对于那些已经感受到 AI coding
带来验证压力的团队来说，它至少提供了一个足够具体的起点。</p>
<p>不要再只问“agent 能不能写得更快”，而要开始问：</p>
<p><strong>系统如何判断，它什么时候才算真正完成？</strong></p>
<p>这就是我们最终想表达的事情。Vibe Coding 不是一个 prompt 问题，也不是一个“再补几条测试”的问题。它本质上是一个治理基础设施问题。只要
AI 进入交付闭环，完成条件、验证证据和人工升级路径就不能继续漂浮在口头经验里，它们必须被写进仓库、被执行器读取、被 agent
理解，也被组织持续演化。</p>
<p>未来，我们也许会把 <code>routa-fitness</code> 进一步做成一个 skill，让 agent 在进入项目的第一天，就带着一套可执行的 fitness
结构开始工作。但在那之前，这个项目至少已经证明了一件事：</p>
<p><strong>代码治理不必永远藏在 CI 配置、review 经验和团队默契里。它可以被写进 Markdown，可以被执行器读取，可以被 agent
理解，也可以被组织持续演化。</strong></p></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[AI 编码 3.0：当 Agent 协作开始被系统执行]]></title>
            <link>https://phodal.github.io/routa/blog/when-agents-join-the-board</link>
            <guid>https://phodal.github.io/routa/blog/when-agents-join-the-board</guid>
            <pubDate>Thu, 19 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[过去一年，我们习惯用“AI 编码 2.0”来描述这一波技术跃迁：从代码补全走向 Agent 驱动，从同步交互走向异步执行，从一次性生成走向“生成—验证—回滚”的闭环。在那个阶段，一个共识逐渐清晰：AI 不再只是辅助，而开始参与执行。但如果只停留在这里，我们其实低估了变化的深度，因为真正发生转移的，并不是“谁在写代码”，而是——谁在负责软件交付这件事本身。]]></description>
            <content:encoded><![CDATA[<div class="markdown"><p>过去一年，我们习惯用“AI 编码 2.0”来描述这一波技术跃迁：从代码补全走向 Agent 驱动，从同步交互走向异步执行，从一次性生成走向“生成—验证—回滚”的闭环。在那个阶段，一个共识逐渐清晰：AI 不再只是辅助，而开始参与执行。但如果只停留在这里，我们其实低估了变化的深度，因为真正发生转移的，并不是“谁在写代码”，而是——<strong>谁在负责软件交付这件事本身。</strong></p>
<h2>引子：当看板开始做决策</h2>
<p>最近在实现 Routa 的 Kanban 模块时，我原本以为这不过是一个再熟悉不过的工程任务——定义列、支持拖拽、同步状态、补上自动化触发，这些事情在过去的项目中已经重复过太多次，以至于几乎可以在没有设计的情况下直接实现出来；直到我尝试把 Agent 接入看板，让它们根据列的变化自动执行任务，这个系统才开始表现出完全不同的性质。</p>
<p>问题并不是一开始就显性的，相反，它们往往出现在那些我们过去从不认为需要被建模的“边角”位置：卡片究竟在什么条件下才允许移动，如果当前列中仍然存在未完成的执行步骤，是否还应该允许进入下一列，当 Agent 执行失败时系统应该停留、重试还是回退，这些问题在人类主导的协作体系中通常不会被精确定义，因为团队会通过经验、语境和即时沟通不断修正这些决策，甚至不会意识到这些决策本身的存在。</p>
<p>但一旦执行者变成 Agent，这些原本依赖默契维系的部分就会立刻暴露出来，并且从“可以忽略的细节”转变为“系统必须回答的问题”，因为 Agent 不理解模糊，也不会替系统补全语义，它只能在明确的边界内执行，一旦边界不存在，系统就无法继续运行。</p>
<p>于是你会逐渐意识到，看板正在发生一件微妙但本质的变化：它不再只是一个用于展示工作状态的界面，而开始演化为一个参与决策的控制系统——每一次拖拽不再只是 UI 操作，而是在触发一次状态转移判断；每一个列也不再只是阶段标签，而是在承担执行语义；每一个状态都必须是可判定的，否则整个系统就无法向前推进。</p>
<p>这并不是一个实现层面的复杂度问题，而是一个结构层面的变化。</p>
<p>也正是在这个过程中，我意识到，我们其实已经不再讨论“AI 如何写代码”了，而是在讨论另一件完全不同的事情——<strong>系统如何组织 AI 完成软件交付。</strong></p>
<h2>AI 编码 2.0 是生成系统，AI 编码 3.0 是执行系统</h2>
<p>AI 编码 2.0 解决的是生成问题。我们关注如何让 AI 写出更正确的代码，于是不断强化模型能力，引入更完整的上下文工程与工具链，并通过测试、构建与回滚机制来约束结果。这一切努力，本质上都围绕“输出质量”。但当 Agent 真正进入交付流程，问题的重心开始发生偏移。系统不再只是判断代码是否正确，而是必须回答一组更基础的问题：什么时候执行，是否允许推进，失败后是否重试，何时算完成，以及整个过程是否可信。这些问题不再属于生成，而属于执行系统设计。</p>
<p>这正是 AI 编码 3.0 的起点。**AI Coding 2.0 优化生成，AI Coding 3.0 定义执行。**生成是局部能力，可以通过模型提升；执行是系统行为，必须通过工程体系来约束。一旦我们接受这一点，就会意识到：继续堆叠模型能力，并不能解决系统层面的问题。</p>
<h2>当 Agent 进入流程，协作必须被重新建模</h2>
<p>在传统开发中，流程由人驱动。人决定开始、推进与结束，也在模糊中做出判断。这种机制之所以有效，是因为人类可以处理不确定性，可以在规则不完整时继续前进，并通过沟通不断修正偏差。但 Agent 不具备这种能力。一旦 Agent 成为执行者，系统就不能再依赖“理解”，而必须依赖“判定”。那些原本存在于团队默契中的隐含规则——什么算完成，什么时候可以交接，失败后该怎么办——都必须被显式表达，否则系统将表现为一种熟悉但不可控的状态：看似在运行，但无法预测。</p>
<p>这意味着一个关键转变：**协作必须从经验驱动，转向模型驱动。**协作不再是人与人之间的协调行为，而开始成为系统需要执行的一部分结构。如果这部分结构没有被建模，那么无论引入多少 Agent，本质上都只是把不确定性放大。</p>
<h2>Harness Engineering：让执行从“能做”变为“可证明地做”</h2>
<p>在 AI 编码 2.0 中，我们已经开始引入测试、lint、构建等机制来约束 AI 输出，但这些机制仍然是“辅助验证”。进入 3.0 阶段之后，它们的角色发生了变化：不再只是质量保障工具，而成为执行系统的一部分。这正是 Harness Engineering 的核心。Harness 并不是让 AI 更强，而是让系统更可控。它通过一组可执行约束，将原本依赖经验判断的过程，转化为可验证的工程行为，使系统从“看起来没问题”转向“被证明可以通过”。</p>
<p>这种转变可以理解为一次边界重构：完成不再是主观判断，而是一个可验证状态；验证不再是事后动作，而是驱动流程推进的条件；失败不再是异常，而是系统可处理的分支路径。Harness 在这里承担的，不是增强能力，而是定义边界。它通过验证结果直接影响系统行为——决定是否推进、回退或中断，使“验证”成为执行系统中的控制机制，而不是附属步骤。</p>
<h2>Kanban 作为控制平面：统一状态、流转与验证</h2>
<p>在这个背景下，Kanban 的角色发生了变化。它不再只是展示状态的界面，而开始承担执行控制的职责。系统需要基于看板状态做出决策，而不是仅供人类观察。这意味着，看板中的每一个元素，都必须具备执行语义：列不再是阶段标签，而是状态机节点；卡片不再是描述，而是执行单元；流转不再是操作，而是状态变更；Gate 不再是说明，而是策略入口。</p>
<p>问题在于，在很多团队中，看板、状态模型与验证规则是三套松散系统。人类可以在它们之间建立隐式映射，但 Agent 不行。一旦三者不一致，系统行为就会变得不可预测。因此，执行系统必须收敛为一个统一模型：状态定义边界，流转定义路径，Gate 定义通过条件。这三者不能只是“基本一致”，而必须严格对齐。</p>
<p>这里的关键转变在于：流转不是移动，而是带约束的状态转移；Gate 不是检查项，而是决定是否允许转移的策略。Harness 在此提供验证能力，使 Gate 不再依赖人工判断，而由系统执行。没有验证的流转，本质上是不受控的执行；而一旦验证成为前置条件，看板就不再只是流程的表达，而成为系统可以计算的控制结构。</p>
<h2>编排与约束：多 Agent 系统的真正核心</h2>
<p>引入 Agent 后，一个常见误区是“自动化更多步骤”。但自动化只解决局部执行效率，并不能解决系统行为问题。系统真正需要的是在正确的时间做正确的事，而这依赖两个能力：编排与约束。编排决定执行顺序与推进时机，约束定义边界并防止系统进入非法状态。Harness 提供约束能力，而看板（作为控制平面）提供编排入口，两者结合，构成执行系统的核心。</p>
<p>如果缺乏这两个要素，系统会呈现出一种典型症状：局部自动化能力很强，但整体行为不可预测。多个 Agent 可以同时运行，却无法保证结果的正确性与一致性。换句话说，系统变得更“忙”，却没有变得更“可靠”。</p>
<h2>多 Agent 协作，是一条被验证驱动的执行链路</h2>
<p>当执行模型被统一、验证机制被引入、编排逻辑被明确，多 Agent 协作开始呈现出一种新的结构。它不再是松散的交互网络，而是一条被验证驱动的执行链路。每一个节点对应一个执行上下文，每一次流转对应一次条件满足，每一个推进都经过验证，每一次失败都有明确的恢复路径。</p>
<p>这条链路的关键，不在于有多少 Agent，而在于系统是否能够控制它们的行为。没有 Harness，Agent 只是能力的叠加；有了 Harness，Agent 才成为系统的一部分。系统不再依赖个体能力来维持正确性，而是依赖结构本身。</p>
<h2>从“能完成”到“被证明可以完成”</h2>
<p>回到最初的问题：AI 编码 3.0 究竟改变了什么？它并不是让 AI 写出更多代码，而是让软件交付从“能力问题”，转变为“系统问题”。过去，我们关心的是 AI 能不能完成任务；现在，我们必须关心系统是否可以证明任务已经被正确完成。这意味着每一次执行都需要被约束，每一次结果都需要被验证，每一次推进都需要有依据。</p>
<p>从“能完成”，到“被证明可以完成”，是 AI 编码 3.0 的本质跃迁。它标志着软件工程从依赖经验的实践，走向依赖可计算结构的工程 discipline。</p>
<h2>结语：当协作成为系统行为</h2>
<p>在 AI 编码 2.0，我们让 AI 学会写代码；在 AI 编码 3.0，我们开始让系统学会交付软件。这并不是简单的能力提升，而是工程范式的转变。当 Agent 进入流程，协作不再只是人类行为，而成为系统行为；而一旦协作成为系统行为，它就必须被定义、被约束、被验证。</p>
<p>Kanban 不再只是看板，Harness 不再只是工具，Agent 不再只是助手。它们共同构成了一个新的执行系统，一个将协作转化为可计算结构的系统。软件工程也因此从“组织人如何工作”，转向“定义系统如何工作”。</p>
<p>这是 AI 编码 3.0 真正开始的地方。</p></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[当 Agent 进入看板：从协作界面到可计算系统]]></title>
            <link>https://phodal.github.io/routa/blog/when-agents-join-the-board.zh-CN</link>
            <guid>https://phodal.github.io/routa/blog/when-agents-join-the-board.zh-CN</guid>
            <pubDate>Thu, 19 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[摘要：当执行者从人扩展为 Agent，Kanban 要解决的问题就不再只是“让工作可见”，而是“让流转可判定、让约束可执行、让历史可追踪”。在 Routa 的现有实现里，这种变化已经开始发生：列不再只是标签，流转不再只是拖拽，Gate 也不再只是 checklist。看板正在从协作界面，演化为多 Agent 软件交付的 control plane。]]></description>
            <content:encoded><![CDATA[<div class="markdown"><blockquote>
<p>摘要：当执行者从人扩展为 Agent，Kanban 要解决的问题就不再只是“让工作可见”，而是“让流转可判定、让约束可执行、让历史可追踪”。在 Routa 的现有实现里，这种变化已经开始发生：列不再只是标签，流转不再只是拖拽，Gate 也不再只是 checklist。看板正在从协作界面，演化为多 Agent 软件交付的 control plane。</p>
</blockquote>
<p>导语：过去讨论 Kanban，我们更关心的是如何协作。列怎么分、在制品怎么控、阻塞怎么暴露、节奏怎么稳定。这一套实践在以人为执行者的团队里非常有效，因为人类天然擅长在不完整规则下工作。很多时候，流程之所以成立，并不是因为系统定义得足够严格，而是因为团队成员会在语境里自动补全那些没有被写出来的部分。</p>
<p>但一旦执行者开始变成 Agent，这种默认前提就不成立了。Agent 不会“差不多理解”，也不会“按经验处理一下”。它们依赖的是可判定的状态、明确的边界与稳定的反馈信号。也正因为如此，我越来越觉得，当 Agent 开始真正进入看板之后，Kanban 的本质就已经变了。它不再只是一个帮助团队理解进度的界面，而是在逐步变成一个可以被系统执行的语言。</p>
<h2>看板不是工作流，除非系统真的理解它</h2>
<p>传统 Kanban 的价值，首先在于可视化。Backlog、Doing、Done 这些列，把原本隐性的工作过程拉到台面上，让团队看见工作如何流动、阻塞出现在哪里、交付能力受什么影响。这种设计之所以成立，是因为列的含义很大程度上依赖人来解释。</p>
<p>但对 Agent 来说，问题不在“能不能看见”，而在“能不能判断”。</p>
<p>如果一个系统只能把列显示出来，却不能根据这些列决定接下来该做什么，那么它拥有的只是一个看板界面，而不是一个工作流系统。</p>
<blockquote>
<p><strong>工作流不是你在看板上看到的东西，而是系统能够据此做出判断的东西。</strong></p>
</blockquote>
<p>Routa 的实现已经相当清楚地表明了这一点。卡片移动到新列时，并不是单纯改一个字段，而是会发出 <code>COLUMN_TRANSITION</code> 事件；随后由 <code>KanbanWorkflowOrchestrator</code> 去读取 board 上的列自动化配置，决定这一列是否需要触发 specialist、是否要创建 session、是否要继续同列内的下一步、是否应该在成功后自动推进。换句话说，列已经开始承载运行时语义，而不是只承担视觉分组。</p>
<p>这件事的意义很大。因为一旦列开始被系统解释，看板就不再只是任务墙，而是状态机的外观。</p>
<h2>列必须像状态，而不是像标签</h2>
<p>很多团队其实默认把列当作标签。To Do 和 Backlog 差不多，In Progress 和 Doing 也差不多，只要团队内部能理解，问题似乎就不大。</p>
<p>但在 Agent 系统里，这种“差不多”会迅速变成系统性错误。</p>
<p>如果你的系统里同时存在两套状态模型，一套给 UI 看，一套给业务逻辑用，那么人类当然还能在脑中把它们对齐；Agent 做不到。Agent 只会在边界条件上不断碰撞，然后把这些不一致放大成大量异常路径。</p>
<blockquote>
<p><strong>如果系统里存在两套状态，系统实际上就没有真正的状态。</strong></p>
</blockquote>
<p>Routa 当前的代码很能说明这个问题。Board 明确有 <code>backlog</code>、<code>todo</code>、<code>dev</code>、<code>review</code>、<code>done</code>、<code>blocked</code> 等列，任务也会根据列映射到不同的 <code>TaskStatus</code>。但反过来，状态再映射回列时，却并不是完全对称的一一对应。这并不意味着实现失败，恰恰相反，它把问题暴露得很真实：一旦列开始承担自动化语义，列和状态就不能只是“差不多一致”，而必须是同一个工作流模型的两种投影。</p>
<p>这也是为什么我越来越倾向于把 Agent Kanban 理解为“可计算的工作流外观”，而不是“可以拖拽的任务面板”。只要列还是标签，系统就仍然依赖人类兜底；只有列变成状态，看板才会真正进入软件工程的语境。</p>
<h2>每一次流转，都应该是一个显式契约</h2>
<p>在人类团队里，卡片从一列移动到下一列，很多时候依赖的是软约定。你把卡拖过去，别人自然会理解成“差不多好了”；你在评论里留一句话，后面的人大概知道该接手什么。</p>
<p>这种方式在人类协作中完全合理，因为协作本身就建立在共识和补位能力之上。</p>
<p>但 Agent 不能靠共识工作。对它来说，流转必须是显式的契约。</p>
<p>一次状态转移，从来不只是“从 A 移动到 B”。它背后至少包含几件事情：是否允许进入目标列、进入之后是否需要自动触发某个 specialist、如果失败了如何补偿、如果同一泳道还有下一步，当前卡片是否根本不该离开这一列。</p>
<blockquote>
<p><strong>流转不是移动，而是一次决策。</strong></p>
</blockquote>
<p>Routa 在这里做了一个很正确的选择。任务手动移动列时，系统会先检查当前泳道是否还有未完成的自动化 step。如果当前 specialist 结束后，同一列里还有下一个 specialist 要接着跑，那么这张卡会被直接阻止离开当前列。这个设计看起来严格，实际上非常重要。因为它把“列内多步协作”从隐含约定提升成了运行时契约。</p>
<p>一旦流转变成契约，工作流才具备可预测性；而没有可预测性，多 Agent 协作就很容易退化成一串互相打断的会话。</p>
<h2>Gate 不是 checklist，而是策略</h2>
<p>很多团队都说自己有质量门，但真正落到系统里，常常只是 checklist。是否有测试结果，是否上传了截图，是否留了说明，满足这些形式要求后，任务就被视为“可以进入下一阶段”。</p>
<p>在人类团队里，这样的门禁勉强还能工作，因为人会继续解释上下文，也会在不合理时主动拦下来。</p>
<p>但在 Agent 系统里，Gate 不能只是“有东西”，而必须是“允许通过”。</p>
<blockquote>
<p><strong>证据的存在，不等于验证已经成立。</strong></p>
</blockquote>
<p>Routa 现在已经有了 Gate 的雏形。列自动化配置允许声明 <code>requiredArtifacts</code>，例如截图、测试结果、代码差异；任务进入目标列之前，系统会检查这些 artifact 是否存在。与此同时，dev lane 的监督模式还可以要求某个 session 不只是结束，还必须留下 <code>completionSummary</code> 或 <code>verificationReport</code>，否则即便 session 看起来成功，也不会被认定为真正完成。</p>
<p>这已经比“靠备注说明做完了”严肃得多。但它也非常清楚地提示出下一步方向：Gate 不应该停留在存在性检查上，而应该继续向策略判定演进。系统里已经有 <code>verificationVerdict</code> 这样的字段，这说明领域模型其实已经在为“通过”与“不通过”预留位置。真正需要补齐的，是让流转逻辑开始消费这些判定结果，而不是只消费“是否填了报告”。</p>
<p>一旦 Gate 被提升为策略，Kanban 才会从管理界面变成交付系统。</p>
<h2>比自动化更重要的，是编排</h2>
<p>引入 Agent 之后，一个非常常见的误区是：把每一列都变成自动化节点。Backlog 进一个 Agent，Dev 进一个 Agent，Review 再进一个 Agent，看起来整条链路已经全部自动了。</p>
<p>但问题也恰恰出在这里。系统开始做很多事，却没有谁真正负责决定什么时候该做、什么时候不该做、什么时候失败、什么时候需要恢复。</p>
<p>Kanban 的核心从来不是“自动化每一步”，而是“管理工作的流动”。当执行者变成 Agent，这个原则只会变得更重要。</p>
<blockquote>
<p><strong>自动化负责执行，编排负责决策。</strong></p>
</blockquote>
<p>Routa 当前真正有价值的，不是 specialist prompt 本身，而是 <code>KanbanWorkflowOrchestrator</code> 这种编排层的存在。它会监听 <code>AGENT_COMPLETED</code>、<code>AGENT_FAILED</code>、<code>AGENT_TIMEOUT</code> 和 <code>REPORT_SUBMITTED</code> 这些事件，维护 active automations，决定当前列是否需要恢复、是否应启动同列内下一步、是否应该自动推进到下一列。在 dev 阶段，它甚至还会配合 watchdog 和 <code>ralph_loop</code> supervision mode，对长时间没有活动的 session 进行恢复或重试。</p>
<p>这说明一个很重要的工程判断：在 Agent 系统里，提升效率的不是“有多少自动化步骤”，而是“谁在监督整条链路”。没有编排层，自动化很快就会失控；有了编排层，自动化才可能成为可治理的能力。</p>
<h2>历史不能是副产品，而必须是一等公民</h2>
<p>人在协作时，历史通常是副产品。评论是历史，提交记录是历史，即时通信也是历史。只有真的出问题时，团队才会回头去翻这些信息。</p>
<p>但对 Agent 系统来说，这样的历史形态太松散了。</p>
<p>每一次交接、每一个失败原因、每一次恢复尝试、每一条 lane 间请求，都必须变成结构化事实。否则系统根本无法解释自己为什么这么做，也无法告诉你它是在哪一步偏离了预期。</p>
<blockquote>
<p><strong>如果一项工作无法回放，系统其实并不理解它。</strong></p>
</blockquote>
<p>Routa 在这方面的设计是很值得肯定的。任务不是只保存一个当前运行中的 <code>triggerSessionId</code>，而是保存 <code>laneSessions</code> 与 <code>laneHandoffs</code>。前者记录某个 session 属于哪个列、哪个步骤、哪个 specialist、何时开始、何时结束、是否处于 recovery 模式；后者记录相邻泳道之间的请求与响应，例如环境准备、运行时上下文、澄清说明或命令重跑。</p>
<p>这会带来一个很重要的变化：多 Agent 协作不再只是聊天记录，而开始变成可重放的执行历史。再加上 Agent 通过 MCP 工具回写 <code>completionSummary</code>、<code>verificationReport</code> 等结构化字段，系统终于可以把“发生了什么”与“为什么这样判断”一起保留下来。</p>
<p>没有这层历史，Kanban 最多只是一个当前态界面；有了这层历史，它才真正具备 trace、治理与改进的基础。</p>
<h2>在软件交付里，卡片永远离不开执行上下文</h2>
<p>传统任务管理系统有一个容易被默认接受的前提：卡片描述的是工作本身，至于工作在哪里做、如何做、依赖什么环境，那是执行层的事情。</p>
<p>但软件交付从来不是这样。一个任务是否真的可执行，往往不只取决于描述是否清晰，还取决于它绑定了哪个仓库、哪个分支、哪个 worktree、哪个 session、哪个运行环境。</p>
<blockquote>
<p><strong>在软件工程里，工作永远不会脱离它的执行上下文。</strong></p>
</blockquote>
<p>Routa Kanban 之所以值得继续写，就是因为它已经开始把这些上下文从背景信息提升成显式对象。任务可以绑定 codebase，进入 <code>dev</code> 列时会尝试自动创建 worktree，任务还会关联 session、lane 历史与 artifact。更进一步，系统给 Agent 的 task prompt 里，还会明确规定当前列可以使用哪些 Kanban MCP 工具、什么时候允许 <code>move_card</code>、什么时候必须先补齐 artifact。</p>
<p>这件事的价值，不在于“提示更详细”，而在于它把执行上下文从聊天记忆里抽离出来，放回到了系统模型里。卡片因此不再只是描述单元，而开始接近一个真正的执行单元。</p>
<h2>从可视化走向可计算</h2>
<p>把这些变化放在一起，其实能看到一个非常清晰的演进方向。</p>
<p>Kanban 一开始解决的是可视化问题，让团队理解工作在哪里；随后，它通过 WIP 限制、流动管理和阻塞暴露来优化效率。而当 Agent 开始成为执行者之后，系统面对的核心要求变成了另一件事：所有关键环节都必须可判定、可执行、可验证。</p>
<blockquote>
<p><strong>协作可以容忍模糊，计算不能。</strong></p>
</blockquote>
<p>这会推动看板发生一系列根本性的变化：</p>
<ul>
<li>列从标签变成状态</li>
<li>流转从操作变成契约</li>
<li>Gate 从检查变成策略</li>
<li>历史从副产品变成系统资产</li>
<li>上下文从背景信息变成显式执行边界</li>
</ul>
<p>软件工程的关注点也因此发生偏移。过去，我们更关心的是如何帮助人类团队沟通与协作；现在，我们必须同时定义系统自身的行为边界。</p>
<blockquote>
<p><strong>当 Agent 开始执行工作，软件工程就越来越变成一门关于可计算性的学科。</strong></p>
</blockquote>
<p>所以，如果今天让我概括这件事，我不会说“Kanban 正在拥抱 Agent”。我更愿意说，Kanban 正在被迫进入软件工程更深的层次。它不再只是帮助人理解工作的界面，而是在逐步变成一种让系统理解工作、约束工作、验证工作、追踪工作的语言。</p>
<p>这也是为什么我会觉得，Agent 时代真正值得投入的，不只是更强的模型能力，也不是更顺滑的聊天体验，而是这些能把能力收敛成系统行为的工程结构。因为只有当看板真的从协作界面演化为可计算系统，多 Agent 软件交付才有机会从演示走向日常生产。</p></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Harness Engineering 的下一步：用 Fitness Function 定义 AI Agent 的完成条件]]></title>
            <link>https://phodal.github.io/routa/blog/harness-fitness-function</link>
            <guid>https://phodal.github.io/routa/blog/harness-fitness-function</guid>
            <pubDate>Mon, 16 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[当 Harness Engineering 开始落地，问题就不再只是"怎么生成代码"]]></description>
            <content:encoded><![CDATA[<div class="markdown"><h2>当 Harness Engineering 开始落地，问题就不再只是"怎么生成代码"</h2>
<p>Harness Engineering 之所以成为热门话题，是因为大家意识到 AI Coding 的问题不只是模型能力问题。上下文工程、提示词策略、多 Agent 协作都很重要，但这些讨论大多停留在生成侧。一旦 AI Agent 真正进入软件交付流程，另一个更棘手的问题就会浮现：<strong>系统究竟如何判断，这个 Agent 已经完成了任务？</strong></p>
<p>过去"完成"被包裹在人类经验里——开发者写完代码、跑过测试、提交 PR、经过 review，团队形成共识。但在 Agent Loop 中，这种默认前提不再成立。Agent 可以很快生成代码、修掉报错，但它同样会制造另一类结果：代码看起来已经完成，实际上只是完成了一半。</p>
<p>这类问题并不抽象：功能路径跑通，不代表负向路径被覆盖；接口修改了，不代表契约同步了；测试数量增加，不代表关键不变量得到验证。<strong>Harness Engineering 的下一步，是把"完成"从经验判断转化为可执行、可审计、可阻断的工程信号。</strong></p>
<h2>Fitness Function 在 AI 时代，不再只是架构概念</h2>
<p>Fitness Function 来自演进式架构，用来持续验证系统是否满足架构特征。但在 AI Agent 参与开发后，它的角色发生了重要变化：<strong>不再只是"架构质量检查"，而是成为一种完成条件机制。</strong></p>
<p>AI Agent 并不天然理解"什么叫真正做完"。它会把局部信号当成完成依据——命令执行成功了、测试绿了、报错消失了。但这些局部成功从来不等价于整体完成。Fitness Function 的新角色，就是把工程条件编码成 Agent 能消费的形式，明确告诉系统"哪些信号一旦没有出现，任务就不能被视为完成"。</p>
<p>Fitness Function 真正重要的地方，在于它能帮助系统重新建立可信的完成判断。它不再只是演进式架构术语，而是 Harness Engineering 的核心部件：<strong>决定 Agent 在什么条件下才被允许退出循环。</strong></p>
<h2>Routa 的 Fitness 架构：一个工程回答</h2>
<p>我们在 Routa 里直接在代码库中构建了一套完整的 Fitness 架构。Fitness 必须是仓库的一部分，能被 Agent 读取、被脚本执行、被 CI 消费，并在失败时阻断流程。</p>
<h3>目录结构</h3>
<pre><code>docs/fitness/
├── README.md              # 规则手册：防御理念、维度定义、门禁规则
├── unit-test.md           # 测试证据：frontmatter + 验证状态
├── api-contract.md        # 契约证据：OpenAPI 一致性检查
├── rust-api-test.md       # API 测试矩阵
├── security.md            # 安全扫描规则
├── code-quality.md        # 代码质量规则
└── scripts/
    └── fitness.py         # 统一执行器：解析 frontmatter，执行检查
</code></pre>
<h3>架构流程</h3>
<pre><code>┌─────────────┐     ┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│  AGENTS.md  │────▶│  README.md  │────▶│ 证据文件    │────▶│ fitness.py  │
│  (入口导航)  │     │  (规则手册)  │     │ (frontmatter)│     │ (统一执行器) │
└─────────────┘     └─────────────┘     └─────────────┘     └──────┬──────┘
                                                                    │
                    ┌───────────────────────────────────────────────┘
                    ▼
            ┌───────────────┐     ┌───────────────┐     ┌───────────────┐
            │   Hard Gate   │     │   评分汇总    │     │   CI 集成     │
            │  (阻断/通过)   │     │  (≥90 通过)   │     │  (门禁机制)   │
            └───────────────┘     └───────────────┘     └───────────────┘
</code></pre>
<p>入口从 <code>AGENTS.md</code> 开始，它只定义最小执行边界：代码变更后必须运行 Fitness 检查；提交必须保持 baby-step。对于 Agent 来说，<strong>入口比说明更重要</strong>——它需要先被带到正确的位置，而不是一上来理解整个世界。</p>
<h2>规则必须可读，也必须可执行</h2>
<p>我们把规则写进 Markdown 的 frontmatter 里，而不是写死在 CI 配置或外部 DSL 中。这样做的理由：如果规则只对机器友好，团队无法自然维护；如果规则只对人友好，系统无法统一执行。</p>
<h3>Frontmatter 示例</h3>
<pre><code class="language-yaml">---
dimension: testability
weight: 14
threshold:
  pass: 80
  warn: 70

metrics:
  - name: ts_test_pass
    command: npm run test:run 2&gt;&amp;1
    pattern: "Tests\\s+(\\d+)\\s+passed"
    hard_gate: true

  - name: rust_test_pass
    command: cargo test --workspace 2&gt;&amp;1
    pattern: "test result: ok"
    hard_gate: true
---
</code></pre>
<p>规则既是可阅读知识，也是可执行声明。新增一个 Fitness 维度，只需在 <code>docs/fitness</code> 目录下新增一个带 frontmatter 的 Markdown 文件。</p>
<h2>证据文件：工程账本</h2>
<p>规则声明只是第一层。一个可靠的 Fitness 系统还需要记录验证状态：哪些场景已经 <code>VERIFIED</code>，哪些仍然 <code>TODO</code>，哪些被标记为 <code>BLOCKED</code>。</p>
<pre><code class="language-markdown">### 集成测试（与 API 行为强绑定）
- [x] notes 流程
  - status: `VERIFIED`
  - required: create/list/get/delete 的成功/失败闭环
  - evidence: `docs/fitness/rust-api-test.md`
- [ ] store: workspace
  - status: `TODO`
  - required: CRUD、查询过滤、归档状态一致性
</code></pre>
<p>证据文件不是普通的测试说明书，而是<strong>工程账本</strong>。它让代码库中的历史经验以稳定的方式被保存下来，成为 Agent 和执行器都能理解的验证上下文。</p>
<h2>执行器：收回规则解释权</h2>
<p>规则和证据都存在后，关键问题是：谁来解释它们？最危险的恰恰是这一步——规则虽然写下来了，但执行时总会出现模糊空间。</p>
<h3>fitness.py 核心逻辑</h3>
<pre><code class="language-python">def run_metric(metric: dict, dry_run: bool = False) -&gt; tuple[str, bool, str]:
    """Run a single metric command and check result."""
    name = metric.get('name', 'unknown')
    command = metric.get('command', '')
    pattern = metric.get('pattern', '')

    result = subprocess.run(
        ["/bin/bash", "-lc", command],
        capture_output=True, text=True, timeout=300
    )
    output = result.stdout + result.stderr

    if pattern:
        passed = bool(re.search(pattern, output, re.IGNORECASE))
    else:
        passed = result.returncode == 0

    return name, passed, output
</code></pre>
<p>执行器扫描 <code>docs/fitness/*.md</code>，解析 YAML frontmatter，逐项执行命令，根据输出模式或退出码判定通过与否。它做了一件关键的事：<strong>把规则解释权从人的经验中收回来，交给统一执行器。</strong></p>
<p>系统不再接受"这次应该问题不大"这种模糊表述，而只接受规则中声明过的命令、可观察的输出和门禁结果。</p>
<h2>契约一致性：防止语义漂移</h2>
<p>Routa 是双后端系统（Next.js + Rust/Axum），AI Agent 最容易制造的问题是<strong>语义漂移</strong>：某个局部修改本身是对的，但多个实现之间开始悄悄失去同构关系。</p>
<pre><code class="language-yaml"># api-contract.md frontmatter
metrics:
  - name: openapi_schema_valid
    command: npm run api:schema:validate 2&gt;&amp;1
    pattern: "schema is valid|validation passed"
    hard_gate: true

  - name: api_parity_check
    command: npm run api:check 2&gt;&amp;1 &amp;&amp; echo "api parity passed"
    pattern: "api parity passed"
    hard_gate: true
</code></pre>
<p>OpenAPI 文件被当作单一事实来源，要求契约优先于实现变更，要求 Next.js 与 Rust 两侧围绕同一组 endpoint 收敛。<strong>契约优先，是在给 Agent 提供一个不容易漂移的重心。</strong></p>
<h2>Hard Gate：真正定义"完成"的地方</h2>
<p>在 AI Agent 场景下，单纯的评分体系是不够的。Agent 天然会把"还不错"误解成"可以结束"。所以 Fitness 最终不是评分系统，而是<strong>阻断系统</strong>。</p>
<table><thead><tr><th>Gate</th><th>命令</th><th>阈值</th></tr></thead><tbody><tr><td>ts_test_pass</td><td><code>npm run test:run</code></td><td>100%</td></tr><tr><td>rust_test_pass</td><td><code>cargo test --workspace</code></td><td>100%</td></tr><tr><td>api_contract_parity</td><td><code>npm run api:check</code></td><td>pass</td></tr><tr><td>lint_pass</td><td><code>npm run lint</code></td><td>0 errors</td></tr></tbody></table>
<p>Hard Gate 失败直接阻断，不计入评分。它把"质量折损"和"流程终止"明确区分开来。<strong>Hard Gate 就是 Agent 时代的 Definition of Done</strong>——在什么条件下，这个自动化参与者被允许退出循环。</p>
<h2>结语：AI 时代的软件工程，需要重新发明"完成"</h2>
<p>当越来越多的代码由 AI Agent 生成、修改与修复时，软件工程真正面临的变化，不只是"写代码的人变了"，而是"完成这件事的判定方式变了"。</p>
<p>Routa 的实践给我们的启发：用 <code>AGENTS.md</code> 提供入口导航，用 Markdown frontmatter 声明规则，用证据文件记录验证状态，用统一执行器收敛规则解释，用契约检查约束多实现一致性，再用 hooks 与 CI 把这一切接进完整的交付链路。</p>
<p><strong>Harness Engineering 最终要解决的，是软件工程里那个最根本的问题之一：当自动化参与者越来越多时，系统究竟如何重新定义"完成"。而 Fitness Function，正在成为这个问题最直接、也最工程化的答案。</strong></p></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[当 Kanban 不再管理人：Routa Kanban 如何管理 Agent Team]]></title>
            <link>https://phodal.github.io/routa/blog/routa-kanban-agent-team-management</link>
            <guid>https://phodal.github.io/routa/blog/routa-kanban-agent-team-management</guid>
            <pubDate>Sun, 15 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[摘要：当 Agent 开始结队工作时，真正的挑战就不再是“它们能不能写代码”，而是“我们能不能管理它们”。Routa Kanban]]></description>
            <content:encoded><![CDATA[<div class="markdown"><blockquote>
<p>摘要：当 Agent 开始结队工作时，真正的挑战就不再是“它们能不能写代码”，而是“我们能不能管理它们”。Routa Kanban
的意义，不在于把传统看板套上一层 AI 外壳，而在于把任务流、执行上下文、运行历史、验证证据和队列压力，收敛成一个可观察、可调整、可约束的
control plane。而要让这样的界面真正成立，关键不在 UI，而在它背后的 Harness Engineering。</p>
</blockquote>
<p>导语：前两篇文章里，我分别讨论了 Routa 作为开放多 Agent 编排平面的设计，以及 Agent Team 在约束下的构建方式。到了 Routa
Kanban 这里，问题已经从“如何组织 Agent”继续往前推进了一步，变成了“如何管理 Agent Team”。这篇文章想讨论的，不只是一个看板页面，而是一种新的工程判断：在
AI4SE 时代，如果我们希望多 Agent 协作真正进入日常软件交付，就必须同时建设管理界面与工程护栏，而不是只建设聊天能力。</p>
<p>在不少 AI Agent 产品里，协作仍然主要以会话的形式存在。我们看到的是聊天窗口、Prompt 历史、Session
列表，以及一些零散的日志输出。这种形态当然能工作，在演示里甚至常常显得很聪明，但它很难运营。你看不清系统当前有多少任务正在运行，看不清哪些任务因为资源受限而排队，看不清某张卡到底绑定了哪个仓库和哪次运行，也看不清失败发生在规划、实现还是验证阶段。对于真正的软件交付来说，这样的系统仍然过于“会话化”，而不够“工程化”。</p>
<p>这也是我开始认真思考 Routa Kanban 的原因。在我看来，它并不是把一个传统任务看板加上一层 AI 皮肤，而是尝试把多 Agent
协作从“消息驱动”推进到“流动驱动”，再进一步推进到“管理驱动”。一旦把问题放在这个尺度上，Kanban 的意义就变了。它不再只是展示任务状态的界面，而开始接近
Agent Team 的 control plane。</p>
<h2>看板为什么在 AI 时代重新变得重要</h2>
<p>传统敏捷实践中，看板的价值首先在于可视化工作流。Backlog、Doing、Done 这些列帮助团队理解任务如何流动、阻塞出现在哪里、在制品是否过多。但在
Agent Team 的语境里，这种理解已经不够了。因为当执行主体从人扩展为 Agent
之后，一张卡不再只是“有人要处理的工作项”，一列也不再只是“任务当前所在的位置”。它们开始承载更重的运行时语义。</p>
<p>在 Routa Kanban 的现有实现里，一张卡片已经逐渐接近一个可运行的工作单元。它不仅有标题和目标，还绑定了
board、column、provider、role、specialist、codebase、session、worktree 与验证状态。列本身也不再只是视觉分组，而是在演化为一个带策略的
stage。进入某一列，意味着谁应该接手；停留在这一列，意味着任务应当运行在什么上下文里；离开这一列，则意味着是否已经满足某种验证条件。</p>
<p>从这个角度看，Routa Kanban 的价值，不是“把 Jira 做成 AI 版”，而是把多 Agent 协作里原本散落在
Prompt、约定和日志中的隐性约束，逐步显性化。它把“谁来做”“在什么地方做”“做完以后如何证明”这些事情，从聊天上下文里拉回到一个可以被持续观察和调整的管理界面里。对于一个真正想进入团队日常工作的
AI 系统来说，这个变化比单纯提升交互体验要重要得多。</p>
<h2>管理界面真正要管理的，是运行时事实</h2>
<p>一个多 Agent 系统最容易制造的幻觉，就是让人误以为只要消息足够多、对话足够长，协作就已经发生了。事实恰恰相反。真正决定系统是否可管理的，从来不是消息本身，而是运行时事实。</p>
<p>首先是队列与并发。一旦 Agent 不再串行处理工作，而开始并发接手多张卡片，系统就立刻进入了新的复杂度层级。此时，最关键的信息不是某个
Agent 刚刚说了什么，而是哪几张卡正在运行，哪几张卡还在等待，当前并发上限是多少，哪些工作因为资源压力被延后。这也是为什么我认为
Routa Kanban 里对 running、queued 与 session concurrency limit 的呈现非常关键。它让看板第一次开始承担“系统压力可视化”的职责，而不是只承担“业务状态展示”的职责。</p>
<p>其次是仓库上下文。软件任务从来不是一个脱离代码现实的纯文本问题。一个任务是否真的可执行，往往取决于它在哪个代码库里执行、绑定了哪个分支、是否已经创建对应的
worktree，以及当前 Session 是否仍然处于正确的目录中。没有这些上下文，所谓多 Agent 协作很容易退化成一组脱离代码现实的对话。Routa
Kanban 当前已经开始把 codebase、repo health、worktree 与任务卡绑定在一起，这一点尤其重要，因为它让卡片从“描述单元”开始转向“执行单元”。</p>
<p>再次是运行历史。没有 run history 的多 Agent 系统，是无法真正调试的。你可以看到一张卡现在位于 Review，但你看不到它之前经历了什么、被哪个
specialist 接手过几次、为什么 rerun，以及某次失败之后系统是否进入了预期的补偿路径。对于 Agent Team 来说，run history
的意义和传统分布式系统里的 tracing、audit trail 并没有本质差异。它不是锦上添花，而是系统可运营性的基础。</p>
<p>也正因为如此，我越来越倾向于把 Routa Kanban 理解为 Agent Team 的运行时视图，而不是任务清单。它管理的不是消息，而是事实；不是聊天，而是流动；不是单次交互，而是持续交付。</p>
<h2>Kanban 能不能成立，取决于它背后的 Harness</h2>
<p>但如果我们只盯着界面，很容易错过更关键的一层。Routa Kanban 能否真正成立，根本不取决于看板本身，而取决于它背后的 Harness
是否足够扎实。</p>
<p>我越来越认同一个判断：在 Agent-first 的软件系统里，真正的核心竞争力不是谁能生成更多代码，而是谁能为 Agent
提供更稳定的执行约束、验证回路和反馈机制。换句话说，管理界面只是表层，Harness Engineering
才是底座。没有这个底座，看板只是一层漂亮的皮肤；有了这个底座，看板才有机会成为 control plane。</p>
<p>对 Routa 来说，这个底座至少包含几类能力。第一类是结构化任务与明确边界。任务必须是对象，而不是一段聊天记忆。Objective、Scope、Acceptance
Criteria、Verification Commands 这些字段存在的意义，不是为了让表单更完整，而是为了给 Agent
提供稳定的工作边界。第二类是事件驱动与状态持久化。系统必须知道任务何时进入某个阶段、何时触发某个
specialist、何时完成、何时失败，以及这些状态如何被保存和恢复。第三类是执行上下文隔离。代码库、分支、worktree、session
和权限模型必须在运行时保持一致，否则所谓自动化只会制造更多隐蔽错误。</p>
<p>而最关键的一类能力，是验证与硬门禁。一个多 Agent 管理界面如果只负责“发起任务”和“显示状态”，它最终仍然只是一个调度面板。只有当它背后连接着
fitness function、契约优先、lint、测试、API parity、可执行验证证据这些机制时，Kanban 才真正从“任务面板”升级为“交付面板”。在
Routa 现有实践里，这种倾向已经相当明确了。双后端语义一致性、fitness hard gates、可执行证据优先，这些东西都在传达同一个信息：AI
系统不能只靠能力堆叠，还必须靠约束收敛。</p>
<p>这也是为什么我更愿意把 Routa Kanban 放在 Harness Engineering 的语境里讨论。它不是为了给 Agent Team
增加一个更直观的入口，而是为了把原本分散在架构、测试、事件流与执行环境中的工程事实，汇聚成一个可以被人持续管理的界面。</p>
<h2>这件事为什么仍然是软件工程</h2>
<p>如果从 Thoughtworks 长期强调的软件工程传统来看，这件事其实并不陌生。DevOps 早就告诉我们，自动化一旦扩大，最重要的不是脚本数量，而是反馈回路是否完整。TDD
和 Refactoring 也早就告诉我们，验证不能是事后附加的善意动作，而必须成为系统结构的一部分。DDD
则提醒我们，真正能长期演化的系统，必须先把领域语义建清楚，再去谈界面和实现。</p>
<p>Routa Kanban 的有趣之处，就在于它让这些原则在 AI4SE 语境下重新变得具体。Board、Column、Task、Session、Artifact、Worktree
这些对象，不再只是工程实现里的数据结构，而是在共同定义一个新的交付域模型。在这个模型里，看板不是 PM
的装饰品，而是操作面；卡片不是沟通媒介，而是可运行契约；列也不是状态标签，而是流程策略的承载体。</p>
<p>如果把这个趋势再往前推一步，我们甚至可以看到它与 Legacy Modernization
之间的某种相似性。很多遗留系统的根本问题，不是功能不能跑，而是边界模糊、状态不可追踪、失败路径无人负责。今天不少 AI Agent
产品其实也面临类似问题。它们常常展示出惊人的局部能力，却缺少稳定的运行模型。Routa Kanban 如果继续沿着现在这条路演进，它真正现代化的，不只是开发界面，而是
Agent Team 本身的操作系统。</p>
<h2>真正的难点，是把界面语言兑现为运行时语义</h2>
<p>也正因为我把它看作 control plane，而不是普通功能页，所以我更在意它现在还没有完全闭环的地方。这次 review
代码时，我最强烈的感受并不是“这个页面做得很好”，而是“这个方向是对的，但必须继续把语义往运行时压实”。</p>
<p>例如，列级自动化已经允许配置 entry、exit、both 这样的触发语义，但运行时并没有完全兑现这套语言。又例如，当 Dev 阶段自动创建
worktree 失败时，任务虽然会被打入 blocked，但 blocked lane 的自动化补偿链路并没有在所有异常路径上完整接上。再例如，既然
Routa 明确是一套双后端系统，那么 board 配置语义就不应该长期停留在单一前端实现里，而应该尽快沉淀为真正共享的领域模型。</p>
<p>这些问题并不会削弱这篇文章的判断，恰恰相反，它们让这个判断变得更真实。因为一个管理界面如果只在成功路径上成立，就还称不上管理界面。只有当失败路径、补偿路径、重试语义、验证证据和跨实现一致性都被同等严肃地处理时，它才真正具备了工程上的可信度。</p>
<p>这也是我想保留的一点 Fowler 式诚实。好的架构文章，不是把系统写成已经完成的胜利，而是把系统正在逼近的问题说清楚，把真正值得继续投资的方向说明白。</p>
<h2>结语：Kanban 是表层，Harness 才是护城河</h2>
<p>所以，如果今天让我用一句话总结 Routa Kanban，我不会说它是“一个支持 Agent Team 的看板能力”。我更愿意说，它是在尝试回答一个更大的问题：当
Agent 不再只是个人副驾，而开始成为团队成员之后，我们该用什么样的工程方式来管理它们？</p>
<p>我的答案是，首先需要一个管理界面，但更重要的是，这个界面必须建立在 Harness Engineering
之上。它必须连接结构化任务、事件驱动状态、执行上下文隔离、验证证据、fitness hard gates 与契约一致性。只有这样，Kanban
才不是一张漂亮的任务墙，而是 Agent Team 的 control plane。</p>
<p>这也是我认为 Routa Kanban 值得继续写、继续做、继续打磨的原因。因为在 AI4SE
的下一阶段，真正决定系统能否进入日常生产的，往往不会是某次惊艳的代码生成，而是这套系统是否已经具备了被团队管理、被组织信任、被工程约束长期守护的能力。</p></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Agent Team 实践与架构设计：在约束下构建可演进的一个人开发团队]]></title>
            <link>https://phodal.github.io/routa/blog/agent-team-design-practice</link>
            <guid>https://phodal.github.io/routa/blog/agent-team-design-practice</guid>
            <pubDate>Mon, 02 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[尽管我们可以用最好的模型完成所有的事情，但是约束才是我决定写这篇文章的一个出发点：约束越多，问题就越好玩。]]></description>
            <content:encoded><![CDATA[<div class="markdown"><p>尽管我们可以用最好的模型完成所有的事情，但是约束才是我决定写这篇文章的一个出发点：约束越多，问题就越好玩。</p>
<p>构建多 Agent 系统时，我们面临三大核心约束：</p>
<ol>
<li><strong>Token 是硬约束</strong> — 上下文窗口有限，每个 Agent 必须精确控制输入。</li>
<li><strong>流程需可复用</strong> — 临时 Prompt 不够，需要升级为结构化的 Specialist。</li>
<li><strong>工具选择需灵活</strong> — Claude Code、OpenCode、Codex 各有优势，需要根据任务动态选择。</li>
</ol>
<p>结合最近正在构建的 Routa（ <a href="https://github.com/phodal/routa">https://github.com/phodal/routa</a> ），分享我的一些新想法，以及现有一些实践，诸如于如何通过 <strong>Specialist 角色化</strong>、<strong>状态外置</strong> 和 <strong>MCP
跨 Agent 通信</strong>，将 “多 Agent 协作” 打造成可演进的工程系统，而非一次性 Prompt 的堆叠。</p>
<h2>引子 1：Token 与成本约束下的 Agent Team</h2>
<p>在设计 Routa 多 Agent 系统作为软件开发平台的时候，我一直想解决一个成本的问题 + 协同的问题：</p>
<blockquote>
<p>事实上，我并不想为任何的 token 付钱 —— 作为一个开发者，用自己的钱去支持一个淘汰自己工具的公司，是愚蠢的。如果是用于工作的工具，
公司应该为我付钱；如果是用于生活的话，我只想休息。</p>
</blockquote>
<p>在这种场景下，我的 Coding Agent 工具就比较杂乱了：</p>
<ul>
<li>已经无了的 Thoughtworks global（前司）购买的 message-base + 额外付费的 的 Cursor</li>
<li>自己写的 AutoDev Agent，需要自己接入模型（好在，好几家模型厂商会付钱给我评测，可以用好几年）</li>
<li>现在的公司（Inspire，原 Thoughtworks 中国业务）购买的、难用的、带有非常便宜的 Opus 4.6 的 AWS Kiro</li>
<li>GitHub 赞助开源作者的 Copilot Pro 版本（message-base 非常划算，特别适合个人买单）</li>
<li>Augment Code 赞助开源作者的 Augment Enterprise 版本</li>
<li>其它国产模型：GLM、Minimax、有人赞助的 DeepSeek、没有赞助我的 Kimi</li>
</ul>
<p>在没有公司完全买单的 Cursor 之后，我需要一种更好的方式，能在一个月非常好地利用、编排工具，这样的话 Kiro + Copilot 提供的 Opus/Sonnet，就能发挥最大价值
—— 当然要我说最好用的还是 Augment Code，但是只是 backup，Claude Code 虽然强，但是上下文的<strong>时间成本太高了</strong>。怀念 Cursor 的前端能力。</p>
<p>但是我觉得这个问题对于大部分人来说是相似的，诸如于：</p>
<blockquote>
<p>在节省最好的编码模型 token 的同时，利用好高性价比的国产模型作为 background agent 来做更多的事情。</p>
</blockquote>
<h2>引子 2：Agent Team 的技术基石与原则</h2>
<p>基于此作为出发点 Routa 与其它多 Agent 系统有着非常大的区别。整个 Routa 的架构有点类似于现在的人类团队的构成。Routa
本身是没有 Coding Agent，它有：</p>
<ul>
<li>一个“伟大”的团队领袖。用于编排 Agent 的 Workspace Agent。</li>
<li>不同出身的团队成员。<!-- -->
<ul>
<li>工具：Claude Code、OpenCode、Codex 等工具的 AI Agent</li>
<li>模型：高价值产出的 Opus 模型、又快又好的 Sonnet 模型，高性价比的 GLM 等模型</li>
</ul>
</li>
</ul>
<p>在这种模式下，我们要解决一个问题：</p>
<blockquote>
<p>即使单个组件不可靠，也能搭建出高度可靠的系统 —— Leslie Lamport</p>
</blockquote>
<p>通俗也来说：</p>
<blockquote>
<p>如何把不同能力的 Agent 组合起来，让强模型做规划，弱模型做执行，在节省成本的同时保证质量？</p>
</blockquote>
<p>因此，Routa 的核心原则可以总结为：</p>
<ul>
<li>跨 Agent 协议 ACP 与 Routa EventBridge，实现标准化通信。</li>
<li>跨 Agent 上下文工程：一个 Agent 的分析可被另一 Agent 高效利用。</li>
<li>角色化 Agent 与角色驱动的 Prompt 工程落地。</li>
<li>AI Agent 的协作与通讯体系化。</li>
<li>流程 Skill 化，规范以 Spec 为核心。</li>
</ul>
<h2>演进优先：可替换原则 — ACP Provider 可插拔</h2>
<p>作为一个 AI 时代身处在没落的<strong>咨询行业</strong>的技术专家，我一直相信，可演进性才是我的竞争力，也是构建系统的核心 —— 尽管，供应商绑定（Vendor Lock-in）
也是一个非常“不错”的商业模式，但是那可是屎山。</p>
<p>既然，我们不想被某个商业、闭源的工具绑定，诸如于 Claude Code，那么我们就需要设计成可演进的系统，ACP 协议是我们根据业内的趋势发现最好的一种
方式（没有之一），通过 ACP 我们可以灵活地替换 AI 编程工具。按能力与场景灵活选择：</p>
<ul>
<li><strong>Claude Code</strong>：复杂推理、架构设计</li>
<li><strong>OpenCode</strong>：快速实现、代码生成</li>
<li><strong>Codex</strong>：简单修复、重复任务</li>
<li><strong>Gemini</strong>：多模态任务</li>
</ul>
<p>基于此模式，只需要设计一个更好的协作方式协同就行了。诸如 Routa 采用的 MCP 方式：</p>
<blockquote>
<p>所有 Provider 都通过统一 MCP 配置接入 Routa 协调服务器，无需修改 Agent 逻辑即可切换。</p>
</blockquote>
<pre><code class="language-json">{
  "name": "routa-coordination",
  "type": "http",
  "url": "http://localhost:3000/api/mcp",
  "env": {
    "ROUTA_WORKSPACE_ID": "ws-123"
  }
}
</code></pre>
<p>其核心设计要点：</p>
<ol>
<li>Agent 只关注角色，不感知底层 Provider</li>
<li>Provider 可在运行时切换</li>
<li>动态 Registry + 内置 Presets 双层机制确保兼容性与可演进性</li>
</ol>
<p>动态发现与内置 Presets：</p>
<p>Routa 支持 <strong>动态发现 Agent</strong>，通过 ACP Registry 获取最新版本和配置，实现无缝扩展。同时，Routa 提供 <strong>内置 Presets</strong> 定义标准
Agent 的启动方式：</p>
<ul>
<li><strong>Preset 来源优先级</strong>：Registry（动态） &gt; Bundled（内置） &gt; User（自定义）</li>
<li>动态发现保证系统始终支持最新 Agent</li>
<li>内置 Presets 保证基础兼容性</li>
<li>用户可按需扩展 Presets</li>
</ul>
<p>核心设计要点：</p>
<ol>
<li>Agent 只关注角色，不感知底层 Provider</li>
<li>Provider 可在运行时切换</li>
<li>动态 Registry + 内置 Presets 双层机制确保兼容性与可演进性</li>
</ol>
<h2>可组合原则 — Specialist 按需组合</h2>
<blockquote>
<p>职责清晰，角色独立；组合灵活，系统可扩展。</p>
</blockquote>
<p>在复杂系统中，单一角色无法覆盖所有场景。Routa 将 Specialist 设计为可组合、可扩展的核心单元，每个 Specialist 专注职责，按需组合。如下是
在上个阶段（上周）中，Routa 参考 Augment Code 的 Intent 内置的 Specialist：</p>
<table><thead><tr><th>角色</th><th>核心职责</th><th>Model Tier</th><th>工具权限</th></tr></thead><tbody><tr><td><strong>ROUTA (Coordinator)</strong></td><td>规划任务、委派子 Agent</td><td>SMART</td><td>无文件编辑，仅委派</td></tr><tr><td><strong>CRAFTER (Implementor)</strong></td><td>编写实现、落地代码</td><td>FAST</td><td>完整文件编辑权限</td></tr><tr><td><strong>GATE (Verifier)</strong></td><td>审核、标准检查</td><td>SMART</td><td>只读 + 消息通信</td></tr><tr><td><strong>DEVELOPER (Solo)</strong></td><td>独立规划与实现</td><td>SMART</td><td>完整权限，不委派</td></tr></tbody></table>
<p>随着，我们添加了 Event/Hook driven 的功能，我们添加了自定义 Specialist，如：issue-enricher，当新创建了 issue 之后，可以自动调用 Agent
来分析代码：</p>
<pre><code class="language-bash">GitHub Webhook (issues.opened)
    ↓
handleGitHubWebhook() — 匹配 trigger rules
    ↓
WorkflowExecutor.trigger() — 创建 WorkflowRun
    ↓
BackgroundTask (每个 workflow step 一个)
    ↓
ACP Process — 使用 specialist 配置
</code></pre>
<p>而在我们的实现里，当你使用了 Claude Code 之后，Specialist 也是一个 Skill。在我们的设计里，Specialist 和 Skill 使用相同的
Markdown + YAML frontmatter，可以互相转换。</p>
<h2>状态外置与上下文隔离</h2>
<p>基于 ACP 协议与我们的事件驱动架构，以及未来 trace 方案，我们参考 Agent Trace 标准，遵循 <strong>可重放、可回滚、可审计</strong> 的原则，
将关键状态外置到持久化介质，而非完全依赖内存。</p>
<h3>File-Based 状态管理</h3>
<p>因此，在存储上分为：</p>
<ol>
<li><strong>Database Stores</strong> — 存储结构化数据：Agent、Task、Note、Workspace 等</li>
<li><strong>File-Based Traces</strong> — 持久化追踪记录，按日期分文件：<code>.routa/traces/{day}/traces-{datetime}.jsonl</code></li>
</ol>
<p>这里的 Trace 是协作事实来源，而非调试日志：</p>
<ul>
<li>谁（provider/model/contributor）</li>
<li>什么时候（timestamp）</li>
<li>哪个会话/工作区（sessionId/workspaceId）</li>
<li>做了什么（eventType + tool）</li>
<li>影响哪些文件</li>
<li>VCS 上下文（branch/revision）</li>
</ul>
<p>由于我们是 Tauri + Next.js 双架构，所以还需要：</p>
<blockquote>
<p>状态外置保证跨环境一致性，可在本地文件或 Serverless 数据库之间无缝切换。</p>
</blockquote>
<p>对于 issue 等其它方式也是相似的，基于 Agents.md 与代码库中的 issues/ 目录，记录 Agent 遇到的问题，方便未来排查。 而在 Agent 协同上，
我们需要的东西更多，诸如 explore agent 生成的 context 可以先存储在临时目录，或者当前项目中等。</p>
<h3>上下文隔离原则 — 按角色裁剪</h3>
<p>每个 Agent 只接收必要上下文：</p>
<ul>
<li><strong>ROUTA</strong>：完整 Spec、任务列表、Agent 状态。</li>
<li><strong>CRAFTER</strong>：任务 Note、Acceptance Criteria、验证指令、相关文件。</li>
<li><strong>GATE</strong>：只读 Spec、任务 Note、Agent 对话、验证计划。</li>
</ul>
<p><strong>要点：</strong> 避免浪费 Token，精确控制信息。</p>
<h2>流程代码化 — Prompt → Skill → Specialist 绑定</h2>
<blockquote>
<p>流程不是一次性指令，而是可复用能力的组合与角色化绑定。</p>
</blockquote>
<p>大部分 Specialist 本质上类似于 SKILL.md，是一个可复用的能力单元。但是，Specialist 是一个角色，它是一个有状态的、可交互的、有权限的
Agent。它可以调用不同的 Skill，也可以不调用 Skill。也因此，Routa 的流程复用遵循三层绑定关系：</p>
<table><thead><tr><th>层级</th><th>定义</th><th>载体</th><th>生命周期</th></tr></thead><tbody><tr><td><strong>Prompt</strong></td><td>一次性指令文本</td><td>用户输入或代码字符串</td><td>单次使用</td></tr><tr><td><strong>Skill</strong></td><td>可复用的能力单元</td><td><code>SKILL.md</code> 或 <code>~/.claude/skills/</code></td><td>跨项目复用</td></tr><tr><td><strong>Specialist</strong></td><td>角色 + 权限 + 工具</td><td>Database / YAML / 硬编码</td><td>系统级绑定</td></tr></tbody></table>
<p>其核心绑定流程如下：</p>
<ol>
<li><strong>定义 Skill</strong>：Skill 是独立的能力单元，可跨项目复用。</li>
<li><strong>绑定 Specialist</strong>：将 Skill 赋予角色，并配置权限、模型与执行边界。</li>
<li><strong>运行时注入</strong>：系统根据 Specialist 配置，将 Skill 注入到 Agent 执行流程中。</li>
</ol>
<h4>Specialist 的特性</h4>
<ul>
<li><strong>角色边界</strong> — 通过 <code>roleReminder</code> 强制行为约束</li>
<li><strong>工具权限控制</strong> — 不同 Specialist 有不同操作权限（如 ROUTA 仅委派，GATE 只读）</li>
<li><strong>标准化流程</strong> — 每个 Specialist 有明确执行步骤，保证流程可靠</li>
<li><strong>Skill 可复用</strong> — 多个 Specialist 可以共享同一 Skill，降低维护成本</li>
</ul>
<h2>事件驱动：把流程变成可组合的故事</h2>
<blockquote>
<p>我们过去习惯写线性脚本，一条条指令顺序执行。但现实里，流程总是充满不确定——任务会延迟、结果会变化、不同角色需要协作。于是，我开始思考：
如果把流程当作事件流，会怎样？</p>
</blockquote>
<p>在日常开发中：我们推送代码到 GitHub，触发了 CI/CD 流程、代码扫描、自动部署，甚至还有通知机器人。每一次推送都是一个事件，
每个服务响应事件的方式都不同，但整体流程依然可靠。事件驱动，就是在软件开发中把这种自然触发机制抽象出来，让每一步可组合、可观察。</p>
<p>所以，让每个步骤都有独立的 Agent 去实现，问题就变得非常简单了。</p>
<h3>EventBus — 流程的神经网络</h3>
<p>在这个架构里，EventBus 就像系统的神经网络，每个 Agent 都是独立的节点。事件在网络里流动，有的只触发一次，有的需要优先响应，
有的要等一组任务完成——它们的订阅方式灵活多样：</p>
<ul>
<li><strong>One-shot</strong>：一次触发，任务完成即注销</li>
<li><strong>Priority</strong>：重要事件优先响应</li>
<li><strong>Wait-group</strong>：等待一组 Agent 都完成</li>
<li><strong>Pre-subscribe</strong>：先订阅再触发，避免竞态</li>
</ul>
<blockquote>
<p>想法很简单：<strong>让事件推动流程，而不是让人盯着轮询。</strong></p>
</blockquote>
<h3>EventBridge — 不同系统的桥梁</h3>
<p>不同系统、不同 Provider 事件格式不一样。EventBridge 就像一座桥，把各种事件统一成标准格式，让我们可以用同一套逻辑去处理：</p>
<ul>
<li>调用工具、更新计划、发送消息都变得统一</li>
<li>跨系统可观测，任何事件都能追踪</li>
<li>流程透明，出问题也容易回溯</li>
</ul>
<h3>Workflow — 事件背后的秩序</h3>
<p>事件本身是无序的，但任务依赖必须被尊重。Workflow 就是把事件背后的秩序梳理清楚：</p>
<ul>
<li>每个步骤是一个 <code>BackgroundTask</code></li>
<li>用 <code>dependsOnTaskIds</code> 明确依赖</li>
<li>BackgroundWorker 自动调度，依赖满足就执行</li>
<li>支持 <code>parallel_group</code> 并行，提高效率</li>
</ul>
<blockquote>
<p>小技巧：<strong>顺序和并行可以共存，事件流让协作不再堵塞。</strong></p>
</blockquote>
<h3>控制复杂度 — 自由与边界</h3>
<p>即便是事件驱动，也不能完全放开。无限嵌套的任务会把系统拖垮，太多并行会让调度爆炸。于是我们加了几个边界：</p>
<pre><code class="language-typescript">export const MAX_DELEGATION_DEPTH = 2;    // 防止无限递归
export const MAX_PARALLEL_TASKS = 10;     // 控制任务图规模
export const DEFAULT_TASK_TIMEOUT = 300;  // 超时保护
</code></pre>
<blockquote>
<p>核心思想：<strong>事件驱动让系统灵活，但边界保证长期可控。</strong></p>
</blockquote>
<h2>分层资源管理原则 — 任务驱动的 Specialist</h2>
<blockquote>
<p>Token 并不是免费的算力，而是一种稀缺资源。</p>
</blockquote>
<p>因此，核心问题是：<strong>如何在节省成本的同时保证系统可靠？</strong> 答案是——<strong>为不同任务配置专门的 Specialist，并通过模型可配置实现资源精细调度</strong>。</p>
<h3>1. 任务驱动 Specialist — 合适的模型做合适的事</h3>
<p>每个任务场景对应一个专门的 Specialist：简单任务用性价比高的模型，复杂任务用强模型，重复任务交给自动化 Specialist。</p>
<blockquote>
<p>核心思想：<strong>不要用万能模型解决所有问题，而是根据任务需求动态选择最合适的模型和工具。</strong></p>
</blockquote>
<h3>2. 模型可配置 — 动态分配与调度</h3>
<p>Routa 的设计允许每个 Specialist 在运行时选择和切换模型：</p>
<ul>
<li><strong>Provider 可插拔</strong> — Claude、DeepSeek、GLM、OpenCode 等可按需接入</li>
<li><strong>动态模型分层</strong> — 根据任务复杂度和预算自动选择高/中/低能力模型</li>
<li><strong>事件驱动调度</strong> — 每次模型调用都是一个事件，系统按优先级分配资源</li>
<li><strong>降级与兜底</strong> — 高价值模型不可用时自动触发备用模型</li>
</ul>
<p>问题就变成了：</p>
<blockquote>
<p><strong>把简单任务交给便宜模型，把复杂任务交给强模型，把重复任务交给自动化 Specialist。</strong>
<strong>模型可配置 + 任务驱动 Specialist + 事件调度，让有限资源发挥最大价值。</strong></p>
</blockquote>
<h2>通信分离原则 — 能力与权限的边界</h2>
<p>在多 Agent 协作中，工具不仅仅是一个个函数，而是 Agent 与外部世界交互的接口。每个 Specialist 需要不同的能力，也需要不同的权限边界
—— ROUTA 不应该能直接修改文件，GATE 不应该能执行命令，CRAFTER 需要完整的编辑权限。</p>
<p>但工具本身是中立的，它不关心谁在调用它。真正关心的是：<strong>谁来调用、能做什么、应该被限制什么。</strong></p>
<blockquote>
<p>协作是逻辑，执行是能力，两者不应该混在一起。</p>
</blockquote>
<p>在 Routa 的架构中，我们将通信层与执行层明确分离：</p>
<ul>
<li><strong>Service 层</strong>：处理任务调度、Agent 协作、状态管理、Trace 记录。</li>
<li><strong>Tool 层</strong>：提供可执行能力，可以被任意 Provider 调用。</li>
</ul>
<p>这种分离带来的好处是：</p>
<ol>
<li><strong>协作逻辑独立</strong>：Service 可以独立演化，不需要关心底层实现。</li>
<li><strong>工具可复用</strong>：同一个 Tool 可以被不同的 Provider 调用。</li>
<li><strong>职责清晰</strong>：Service 关注"谁做什么"，Tool 关注"怎么做"。</li>
</ol>
<p><strong>要点：</strong> 协作是逻辑，执行是能力，两者不应该混在一起。</p>
<p>核心 MCP 工具示例：</p>
<table><thead><tr><th>工具</th><th>用途</th><th>调用者</th></tr></thead><tbody><tr><td>delegate_task_to_agent</td><td>委派任务给子 Agent</td><td>ROUTA</td></tr><tr><td>send_message_to_agent</td><td>跨 Agent 消息通信</td><td>所有</td></tr><tr><td>report_to_parent</td><td>向父 Agent 报告执行结果</td><td>CRAFTER, GATE</td></tr><tr><td>list_agents</td><td>查看当前 Agent 状态</td><td>ROUTA</td></tr><tr><td>read_agent_conversation</td><td>读取 Agent 对话历史</td><td>ROUTA, GATE</td></tr><tr><td>set_note_content</td><td>创建/更新任务 Note</td><td>ROUTA, DEVELOPER</td></tr><tr><td>subscribe_to_events</td><td>订阅系统事件</td><td>ROUTA</td></tr></tbody></table>
<h2>示例：Issue Enricher</h2>
<p>我不想做一个“自动回复机器人”。 当一个 GitHub Issue 出现时，我希望它真的被理解，而不是被总结。</p>
<p>于是我把它接入 Routa 的事件系统：GitHub Webhook 进入 BackgroundTask，启动 ACP Process，由一个 DEVELOPER Specialist 执行完整流程。</p>
<p>这个 Specialist 不只是调用模型，而是按固定步骤工作：</p>
<blockquote>
<p><strong>Understand → Analyze（检索代码库）→ Explore（推导多种方案）→ Output（结构化写回）。</strong></p>
</blockquote>
<p>它可以是单 Agent，也可以拆成多个 Specialist 组成 Workflow。分析用 smart 模型即可，复杂推导再升级——资源是可调度的，而不是固定的。</p>
<p>这个例子对我来说验证了一件事：</p>
<blockquote>
<p>多 Agent 协作不是堆模型，而是把“触发、角色、流程、资源”工程化。</p>
</blockquote>
<p>当 Issue 被创建时，它不是被丢给一个模型，而是进入一个可以演进的团队系统。</p>
<h2>总结</h2>
<p>写这篇文章，其实是因为我在一个很现实的环境里做选择：模型有成本，工具会变化，供应商会绑定，而个人开发者不可能无限制地为 token
买单。在这种约束下，我更关心的不是“哪个模型最强”，而是系统能不能演进。</p>
<p>Routa 的这些设计——事件驱动、Specialist
角色化、状态外置、模型分层、协议解耦——本质上都在回答同一个问题：如何把不稳定的模型能力，组织成一个稳定的工程系统。与其依赖某一个强模型，不如把规划、执行、验证拆分成不同角色；与其写一次性
Prompt，不如把流程固化为可复用的能力；与其把状态塞进上下文，不如让它成为可以回放和审计的事实记录。</p>
<p>多 Agent 协作如果只是堆模型，那它只是成本放大器。但如果它是可组合、可替换、可调度的结构，它就变成了一种新的开发组织方式。对我来说，这件事的意义不在于“更智能”，而在于“更可控、更可持续”。</p>
<p>在约束之下构建系统，反而更有确定性。这也是我做 Routa 的真正动机。</p></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[从 AutoDev 到 Routa：开放生态下的新一代多 Agent 编排实践]]></title>
            <link>https://phodal.github.io/routa/blog/from-autodev-to-routa</link>
            <guid>https://phodal.github.io/routa/blog/from-autodev-to-routa</guid>
            <pubDate>Mon, 02 Mar 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Routa 是一个 “工程化的多 Agent 协作框架”：它把任务、状态、事件和执行拆成可控模块，让开放生态下的多 Agent 系统可以真正落地，而不是靠]]></description>
            <content:encoded><![CDATA[<div class="markdown"><blockquote>
<p>Routa 是一个 <strong>“工程化的多 Agent 协作框架”</strong>：它把任务、状态、事件和执行拆成可控模块，让开放生态下的多 Agent 系统可以真正落地，而不是靠
Prompt 默契拼接。</p>
</blockquote>
<p>年前，在为某客户设计基于 OpenCode / Claude Code 的 AI Coding 解决方案时，围绕 ACP（Agent Client Protocol）这一通用化、
标准化的 Coding Agent 协议，我开始重新思考一个问题：</p>
<blockquote>
<p>在开放生态下，多 Agent 系统应该如何构建？</p>
</blockquote>
<p>这一次的探索，与我们在 AutoDev 中所设计的多 Agent 体系有着本质差异。</p>
<p>AutoDev 更强调“自研一体化”的多 Agent 架构：自研 Agent、自研调度、自研协作机制等。而在 Routa 中，我们尝试构建一个更加开放的编排系统。
它不再依赖单一实现，而是面向生态进行协作与整合。在新的 Routa 架构中：</p>
<ul>
<li>可以接入不同实现的 Coding Agent（如 Codex、OpenCode、Qwen Code 等），而不局限于 AutoDev Agent</li>
<li>基于 Tool 的 Agent 协同体系，通过 MCP Server 提供 Agent 创建、调度与工具能力</li>
<li>通过统一的结构化 Spec/Tasks 进行意图编排，而非依赖 Prompt 级别的隐式协作</li>
</ul>
<p>在这篇文章里，我们将讲述<strong>Routa 的多 Agent 体系是如何组织起来的，以及为什么这样设计。</strong></p>
<p>PS：在设计 Routa，我们参考了 Augment Code 的 Intent、JetBrains 的 ACP 管理等。</p>
<h2>从经验到方法：Routa 的三个取舍</h2>
<p>与其说是“原则”，不如说是三种工程取舍。</p>
<h3>取舍一：优先开放协作，而不是绑定单一实现</h3>
<p>在 Routa 里，Agent 是可替换的能力单元，不是系统的中心。系统中心是“协作协议与任务流”。这意味着：</p>
<ul>
<li>你可以按场景接入不同的 Coding Agent：Claude Code、OpenCode、Codex 等</li>
<li>你可以在不重写业务逻辑的前提下切换 Provider</li>
<li>你可以随着生态变化持续替换底层能力</li>
</ul>
<p>一句话总结：<strong>Routa 关注的是“如何把人和 Agent 组织成有效协作”，而不是“押注某个固定 Agent 实现”。</strong></p>
<p><strong>从 FinOps 视角看</strong>，角色分工不仅是工程整洁，更意味着 <strong>"算力成本的分层优化"</strong>：ROUTA 规划者需要全局视野，可以使用昂贵且强大的模型（如
GPT-4o / Claude 3.5 Sonnet），而部分 CRAFTER 执行者或独立验证动作可以路由给本地运行的、成本更低的专有模型（如 Qwen Code /
DeepSeek Coder）。这展现了 Routa 在企业级部署时对 <strong>"Token 经济学"</strong> 的考量。</p>
<h3>取舍二：优先角色分工，而不是全能 Agent</h3>
<p>多 Agent 失败的常见原因是角色塌缩：同一个 Agent 既负责规划又负责实现还负责验收，最后责任边界消失。Routa 与其它 MAS
系统一样，把角色拆开，
并强调边界：</p>
<table><thead><tr><th>角色</th><th>主要职责</th><th>边界</th></tr></thead><tbody><tr><td>ROUTA（Coordinator）</td><td>规划、拆解、委派、汇总</td><td>不直接写实现代码</td></tr><tr><td>CRAFTER（Implementor）</td><td>按任务完成实现</td><td>不扩大任务范围</td></tr><tr><td>GATE（Verifier）</td><td>按验收标准验证结果</td><td>不替代实现职责</td></tr><tr><td>DEVELOPER（Solo）</td><td>单 Agent 交付完整任务</td><td>适用于轻量场景</td></tr></tbody></table>
<p>这种分工的价值很直接：出问题时知道该看哪里，做复盘时知道谁对什么负责。在创建 Agent 时，只需要关注它应该完成的任务，而不需要关注它
如何完成任务。</p>
<h3>取舍三：优先可验证交付，而不是“提示词默契”</h3>
<p>在多 Agent 协作里，真正昂贵的是“对齐成本”：目标是否一致、范围是否一致、完成标准是否一致。Routa 的做法是把参考 Intent 任务描述结构化，
而不是只靠自然语言约定。每个任务至少要回答四件事：</p>
<ol>
<li>目标是什么（Objective）</li>
<li>范围是什么（Scope）</li>
<li>完成标准是什么（Definition of Done）</li>
<li>怎么验证（Verification）</li>
</ol>
<p>当这些信息被结构化后，协作就从“靠经验”变成“可检查、可追踪、可复用”。</p>
<h2>Routa 的多 Agent 体系</h2>
<p>简单说，Routa 是一个 <strong>多 Agent 协作的“协调平面”</strong>。它不替代任何外部 Agent，而是让不同的 Agent 在工程上可以**可控、可追踪、可验证地协作
**。</p>
<p>换句话说：</p>
<ul>
<li>它知道“任务是什么、谁执行、结果如何回报”</li>
<li>它提供稳定的“动作接口”，上层不需要关心内部实现</li>
<li>它让异步的多 Agent 协作变成一种可观察、可管理的工程能力</li>
</ul>
<p>你可以把它想象成：</p>
<blockquote>
<p>Routa = 结构化大脑 + 事件驱动协调器 + 状态管理器</p>
</blockquote>
<h3>Routa 的核心特性</h3>
<ol>
<li><strong>协议融合架构</strong>。Routa 内部通过 <strong>ACP</strong> 管理 Agent 进程生命周期，通过 <strong>MCP</strong> 暴露协作工具，并支持 <strong>A2A Bridge</strong>
以实现跨平台联邦扩展。三者分工明确：MCP 管工具、ACP 管客户端进程、A2A 管联邦协作——这种"用垂直协议做水平协同"的设计，让
Routa 能够无缝接入异构 Agent 生态。</li>
<li><strong>结构化任务</strong>。任务不是随意的文本，而是包含目标、范围、验收标准等字段的结构化对象；这样每个 Agent 执行的任务都是可追踪的，协作结果可以直接验证。</li>
<li><strong>事件驱动协作</strong>。系统用事件流来推动任务状态，从"等待执行"到"任务完成"，每一步都可观测；这不仅让多 Agent
并发协作不会变成混乱的轮询或黑箱，更为企业提供了每一级 Agent 决策的 <strong>"白盒化"审计日志（Audit Trails）</strong>。</li>
<li><strong>工具化能力暴露</strong>。协作动作被封装成"可调用工具"，比如 <code>create_task</code>、<code>delegate_task_to_agent</code>、<code>subscribe_to_events</code>、
<code>report_to_parent</code> 等；上层 Agent 或前端可以直接调用，而不需要关心内部执行细节。</li>
<li><strong>状态持久化与容错恢复</strong>。同一套协作语义，可以在 Web、桌面或其他部署环境复用；通过结构化的 Task 和
Stores，系统能从断点快速恢复执行（Resilience），而不是从头开始消耗 Token。</li>
</ol>
<p>在<strong>工具化能力暴露</strong>这一点上，我们主要参考的是 Intent 的设计和实现。</p>
<h2>HOW：Routa 如何把开放编排落成工程能力</h2>
<p>这一节会刻意把描述落在“代码里的抽象”，而不是停留在口号：你看得到它们在哪一层、负责什么，以及为什么这些边界能支撑开放生态下的多 Agent 协作。</p>
<h3>0）先统一系统边界：<code>RoutaSystem</code> 是“协调平面的组合件”</h3>
<p>Routa 在代码里把“协调平面”收敛成一个中心对象：<code>RoutaSystem</code>。它不等于某个 Agent，而是把协作所需的基础设施组合起来：</p>
<ul>
<li><strong>Stores（状态持久化与容错恢复）</strong>：<code>AgentStore</code> / <code>TaskStore</code> / <code>ConversationStore</code> / <code>WorkspaceStore</code>。这些 Store 提供了
<strong>状态持久化</strong>能力——如果某个 CRAFTER 陷入死循环（类似 AutoGen 常被诟病的对话混乱），或者发生网络中断，Routa 的架构能够依靠结构化的
Task 和 Stores <strong>从断点恢复执行</strong>，而不是从头开始消耗 Token。</li>
<li><strong>EventBus（可观测性与审计追踪）</strong>：不仅把协作推进从"轮询脚本"变成"可订阅事件流"，更为企业提供了每一级 Agent 决策的<strong>白盒化审计日志</strong>。
基于事件驱动架构，系统的每一次状态变更、任务委派、结果汇报都被完整记录，满足企业级的 Governance 和 Auditability 需求。</li>
<li><strong>Tools（动作入口）</strong>：<code>AgentTools</code> / <code>NoteTools</code> / <code>WorkspaceTools</code>，把“要做什么”固定成可调用的动作</li>
</ul>
<p>同时，<code>RoutaSystem</code> 支持多种存储形态（InMemory / Postgres / SQLite）但保持同一套接口：这让"运行形态变化"
不需要重写协作语义。这种设计也为"时间旅行（Time Travel）"调试能力奠定了基础——在复杂企业级场景下，能够追溯和回放任何一次协作过程。</p>
<h3>1）把协作动作变成协议工具：Tools → MCP 工具面</h3>
<p>在 Routa 里，“创建任务、委派、订阅事件、汇报结果”不是散落在各处的私有调用，而是统一走 <code>Tools</code> 的门面，然后再被注册成 MCP 工具。</p>
<p>关键点是：<code>RoutaMcpToolManager</code> 会把这些动作注册到 MCP Server 上（例如 <code>create_task</code>、<code>delegate_task_to_agent</code>、<code>subscribe_to_events</code>、<code>report_to_parent</code> 等）。这样上层接入任意支持 MCP 的外部 Agent 时，拿到的是一组<strong>稳定的工具集合</strong>，而不是一堆“需要记住的提示词约定”。</p>
<p>对应的工程收益：</p>
<ul>
<li>协作能力是“接口契约”，可以版本化、可测试</li>
<li>Provider 侧只要能连上 MCP，就能调用同一套协调动作（配置差异交给适配层处理）</li>
</ul>
<h3>2）把“任务”当作数据结构：<code>Task</code> 字段贯穿创建→执行→验收</h3>
<p>Routa 不是把任务当成一段聊天上下文，而是把它当成一等数据对象：</p>
<ul>
<li><strong>意图字段</strong>：title / objective / scope</li>
<li><strong>交付字段</strong>：acceptanceCriteria（Definition of Done）</li>
<li><strong>验证字段</strong>：verificationCommands（可执行的验证入口）</li>
<li><strong>编排字段</strong>：dependencies / parallelGroup / status / assignedTo</li>
</ul>
<p>这也是为什么 Routa 可以把“对齐成本”从人脑记忆，迁移到结构化字段：同一个任务在不同 Agent 之间流转时，口径不会随着对话漂移。</p>
<p><strong>从混合记忆（Hybrid Memory）架构的视角看</strong>，Task 的结构化字段实际上是极佳的 <strong>工作记忆（Working Memory）隔离</strong> 实践。Routa
通过结构化字段切断了不必要的聊天上下文（Chat History），这不仅降低了 Prompt 对齐成本，更避免了无关信息在 Agent 之间传递导致的
<strong>注意力偏移（Distraction）</strong>，相当于在架构层面实现了优秀的<strong>上下文管理（Context Management）</strong>，有效防止长周期任务中的"
上下文腐化（Context Rot）"。</p>
<h3>3）用事件驱动解决异步协作：<code>EventBus</code> 提供订阅语义，而不是靠轮询</h3>
<p>多 Agent 协作一旦并发起来，最先失控的是“状态同步”：谁完成了？谁卡住了？该不该汇总？</p>
<p>Routa 在工程上把它收敛到 <code>EventBus</code>：</p>
<ul>
<li>统一事件类型（例如任务状态变化、汇报提交、Agent 完成等）</li>
<li>支持一次性订阅（one-shot）、优先级投递（priority）、以及 <code>after_all</code> 这类“等一组都完成再通知”的 wait-group 语义</li>
<li>支持 pre-subscribe（先订阅再触发动作），避免竞态条件把事件丢掉</li>
</ul>
<p>对应的工程收益：并发规模变大时，协作推进仍然是可观察、可解释、可回放的。</p>
<p><strong>从企业级治理（Governance）视角看</strong>，EventBus 的价值远不止解决异步协作的状态同步问题。它实际上构建了系统的 *
<em>可观测性（Observability）</em>* 基础设施：每一次 Agent 决策、每一次任务状态变更、每一次汇报提交都被完整记录，形成可审计的事件链。
这让企业在面对合规审查或事故复盘时，能够精确追溯" 谁在什么时候做了什么决策"。</p>
<p>在指标上，可以结合 Agent Trace 等工具，来构建 AI 的可度量性（Metrics）：例如，可以度量 Coding Agent 带来的效率提升。</p>
<h3>4）委派不止是“分配”，而是“生成可运行的子执行单元”：<code>RoutaOrchestrator</code></h3>
<p>很多 MAS 的“委派”停留在“把任务文本转发给另一个 Agent”。Routa 更进一步：当 Coordinator 使用委派工具时，<code>RoutaOrchestrator</code> 会把一次委派落成完整的执行链路：</p>
<ol>
<li>创建子 Agent 记录（带 role、parentId、modelTier 等边界）</li>
<li>生成面向角色的 delegation prompt（由 specialist 配置驱动，例如 CRAFTER/GATE）</li>
<li>通过 ACP process manager <strong>拉起一个真实的外部 Agent 进程/会话</strong>，把任务作为初始输入</li>
<li>订阅 <code>REPORT_SUBMITTED</code> 等事件，在子 Agent 回报后唤醒父 Agent，形成闭环</li>
</ol>
<p>这个设计把“角色化协同”从概念落实为运行时机制：你能追踪每个子 Agent 的会话、状态、回报，并让汇总动作有明确触发条件。</p>
<h3>5）多后端不是重复实现，而是语义对齐：同一套 API / 同一套协作模型</h3>
<p>Routa 同时支持 Web 与桌面形态，本质不是“做两套系统”，而是把协作语义抽象清楚后，在不同运行时提供相同的 API：</p>
<ul>
<li>Web 侧可以用 Next.js/TypeScript 提供 REST/MCP 接入</li>
<li>桌面侧可以用 Rust（axum）实现同样的 HTTP 层（并复用核心领域概念），本地用 SQLite 保证稳定与可移植</li>
</ul>
<p>对使用者来说，差异被压缩到“部署与存储选择”，而不是“协作流程要重写”。</p>
<h2>总结</h2>
<p>从 AutoDev 到 Routa，变化的不是“换了哪个模型”，而是方法论：</p>
<ul>
<li>从“自研一体化”走向“开放协作”</li>
<li>从“全能 Agent”走向“角色化协同”</li>
<li>从“Prompt 默契”走向“可验证交付”</li>
</ul>
<p>Routa 不是要替代所有 Agent，而是要成为一个稳定的多 Agent 协调平面：让外部能力可以接入，让协作过程可控，让交付结果可验证。</p></div>]]></content:encoded>
        </item>
    </channel>
</rss>