HEXIS:把 Agent Skills 编译成状态机
Skill 文档今天多半还是 markdown:领域知识、步骤说明、脚本与模板打包在一起,需要时塞进上下文。SkillsBench 一类评测已经说明「有 curated skill」能抬通过率;但另一半问题几乎同样刺眼——写清楚了,也不等于执行时会按顺序、按依赖、按分支做完。[1]
常见路径是 Skill + ReAct:整份 skill 当上下文,模型在「读懂任务」和「下一步该调哪个工具」之间反复推断。检查失败了却只报失败、不按 skill 要求去改;条件分支写在文档里,却被模型跳过;长轨迹里历史变厚,相关条款更难被用上。论文把这类现象说成:任务推理与控制决策绑在同一次解码里,偏差会按步累积。[1]
HEXIS(HEXIS: Compiling Agent Skills into Extended Finite State Machines,arXiv:2609.30123v2)的动作不是再改一版更好读的 skill 文案,而是把已有 skill 编译成扩展有限状态机(extended FSM):知识留在各状态的局部指令里,控制流变成守卫(guard)与转移;增量编译器用 skill 条款与工具接口起草机器,再用开发轨迹对齐、补状态;任何更新都要先过静态检查,并回放当前与全部已接受轨迹才入库。四基准 × 四执行器上,相对 Skill + ReAct 成功率平均高 16.2 个百分点;用 Qwen3.8-27B 执行时,执行 token 相对 Skill + ReAct 少 38.4–88.9%(各基准不同)。[1]
站内已经写过「技能库一大,先加载什么」和「相关技能该不该注入」——Progressive Disclosure、SkillDelta。HEXIS 回答的是下一层:skill 一旦被选中,怎么可靠地执行它,而不是再猜控制流。
和站内叙事怎么对齐
可以把「skill 生命周期」拆成三段,避免三篇文章抢同一句话:
| 阶段 | 站内入口 | 管什么 |
|---|---|---|
| 披露 / 加载 | Progressive Disclosure | 技能库变大时,先 frontmatter、按需 load_skill,别 eager 全塞 |
| 激活 / 注入 | SkillDelta | 相关 ≠ 一定有增益;有/无技能配对历史预测任务条件收益 |
| 执行 / 兑现 | 本文 HEXIS | 选中之后,把条款里的顺序、依赖、分支编成可执行控制,而不是每步再推断 |
再叠一层 harness 视角:扩张 harness,而不是堆上下文 讲的是「反复出现的控制决策长成程序」;HEXIS 更具体——输入对象就是现成的 skill 文档,输出是带变量绑定与守卫的 FSM,模型只在状态内做推理与生成。规格侧若你习惯 SpecHarness 那种「提案 vs 权威收尾」,可以把 HEXIS 的 runtime 转移想成对控制义务的机械兑现:judge 状态可以写出 verdict,失败路径由边走到修订,而不是再赌模型记不记得「失败后必须改」。[1]
新手向的 skill / 工具拼装仍可看 Agent Skills 入门;本文默认你已经有一份在用的 skill,关心的是执行合规与成本。
问题为什么难:偏差会乘起来
论文把 skill 文档拆成两块(自然语言里往往缠在一起):
- 知识 (\mathcal{K}_D):怎么做某类操作、判据是什么、例子与说明;
- 控制要求 (\mathcal{R}_D):顺序、数据依赖、分支、重复、终止与禁止项。[1]
Native 执行大致是:把整份 (D)、任务输入 (x)、历史 (h_t) 一起交给策略,每步采样动作。要求写在上下文里只是「影响选择」,并不强制。于是每一步都有一个局部偏离概率 (\epsilon_t):在仍合规的历史条件下,下一步是否落到 skill 允许的操作集合之外。固定步长 (K) 下,至少出现一次偏离的累积概率会按 ((1-\bar\epsilon_t)) 连乘展开——步数一长,哪怕单步偏一点点,整体「全程合规」也会塌。[1]
HEXIS 的切割是:相关知识进状态局部指令(以及资源引用);控制要求编成状态、带守卫的边、终止规则。状态做完操作后,runtime 按变量取值取第一条守卫为真的出边;例如模型可以按 skill 的检查标准写「未通过」,路由却由机器走到「修订」状态,而不是再问模型「接下来你想干嘛」。在编码忠实、条件能正确建立时,边界上的控制决策就不再依赖又一次模型推断——直接对准上面那条累积风险。[1]
编译的形式目标被写成:在满足结构与接口约束的机器族里,尽量减小「给定机器配置后,对 skill 允许的后续延续还剩多少不确定性」(条件熵意义下的表示损失)。实践里并不去估熵,而是用静态检查 + 轨迹回放决定是否接受一次更新;附录把接受规则与该目标联系起来。[1]
机器长什么样
扩展 FSM 记为 (M=(Q,q_0,V,\mathrm{op},E,F,\tau)):有限状态集、初态、类型化变量、操作、有序出边、终止态(含 fallback (q_{\mathrm{fb}}))及结果类别。[1]
非终止态分三类:model、judge、tool。每个状态有读集 (R_q)、写集 (W_q),以及局部指令 (p_q) 或工具调用。执行时 model/judge 只看见 (p_q) 与 (\nu_{R_q}),编译器没声明的依赖进不了该状态——这是相对「整份 skill + 全历史」的硬收缩。Judge 从固定标签集写出一个标签;出边守卫是变量上的布尔测试;操作失败或输出解析失败则进 fallback。每个非终止态都必须有一条守卫恒真的默认边;循环计数器有上限与出口,保证环有界。[1]
直觉上:状态机在记账「做到哪一步、中间结果在哪些变量里」;模型在状态内做推理与生成;下一步操作由守卫决定,而不是由模型再读一遍 skill 猜。[1]
增量编译:先起草,再靠轨迹补洞
流程两段(论文 Figure 3):初始化与轨迹更新。[1]
初始化。 构造模型从 skill 抽出带引文的规则(必做操作、顺序、禁止、终止、事件标签等),引文必须在文档中出现,工具与标签必须在接口表 (\mathcal{T}) 里,否则丢掉。再据此起草机器,并用检查器错误列表在有限轮内重写;文档每个条款应落到某个状态或写进某条局部指令。Check(M) 要过五类条件,包括:语法与图(字段与守卫良构、从初态可达、能到终止、非终止态有默认边);变量(每个状态的读集 ⊆ 沿所有入路径都已定义的变量——分支两侧都要赋值);终止态证据变量已定义;以及规则在图上的可达性刻画(例如「必做 (o)」意味着去掉做 (o) 的状态后验证型终止不可达;「(o_1) 先于 (o_2)」意味着去掉 (o_1) 后 (o_2) 不可达)。过不了则初始化失败。[1]
轨迹更新。 从一条开发轨迹抽出事件序列(工具调用或模型输出及其输入输出与推理文本)与记录结果。构造模型把事件与现有状态对齐:同类型且判定「该状态能完成该操作」则复用;对不上就新建;与 skill 操作无关则忽略。工具事件还要求同工具;优先可达状态;若新边会绕过必经状态则拒绝。在机器副本上加状态、加边、从结果读守卫、把传递值变成变量绑定;同一守卫通向两个不同后继时,插入新的 judge 状态用标签分流;新环加计数器。[1]
候选是否接受,取决于:副本通过 Check,且对当前轨迹与档案里每条已接受轨迹回放都成功。回放时状态返回轨迹里记录的输出(不再真调模型/工具),要求对齐状态按序出现、不进 fallback、终止类别与记录一致。因为回放用的是记录输出,以前接受过的轨迹失败,只可能是改守卫或改了路径上的转移。失败的候选允许在可达状态上再对齐一次;再失败则丢弃该轨迹。[1]
这一点对工程很重要:HEXIS 不是「搜一个在某一模型上碰巧好用的工作流」,而是以 skill 为编译对象,用轨迹补洞,但用静态检查 + 全量已接受回放卡住回归——和「记忆里多塞几段成功经验、下次再让模型自己想」不是一类东西。[1]
实验:四基准、四执行器
评测四个基准,各配一份 skill;任务二分成功/失败,报 hold-out 成功率。后三个基准约按 80/20 划分(随机种子 2026)。[1]
| 基准 | 任务与 skill(论文设定) |
|---|---|
| SpreadsheetBench | 107 个已验证单元格操作任务;SigLeak spreadsheet skill;开发/测试 50/57 |
| LiveMathematicianBench | 数学家级选择题(选项固定种子打乱);SigLeak skill;开发 487 / 测试 121(按月分层) |
| InfiAgent-DABench | 257 题写代码分析数据;Pandas Pro skill;206/51(按难度分层) |
| LongSeal(SealQA) | 证据散落在长网页集合;离线只用给定网页;SigLeak skill;203/51 |
基线与 HEXIS 共用执行器与工具,差别在 skill 怎么供给:Skill + ReAct(原生)、AWM(成功轨迹归纳工作流进上下文)、ReasoningBank(成败轨迹蒸馏策略再检索)、SkillOpt(执行反馈改 skill 文再原生执行)、AFlow(搜模型调用工作流)。执行模型:托管 qwen3.6-flash、GLM-4.7-FlashX,以及本地 vLLM FP8 的 Qwen3.5-9B、Qwen3.8-27B。编译、SkillOpt、记忆归纳由 Claude Fable 5.1 完成。机器只用 skill 文档与全部 qwen3.6-flash 开发轨迹(成败都要,含中间结果)编译与 refinement;然后同一台机器直接转到另外三个执行器,不改状态/提示/绑定/转移,也不对目标模型重编译。[1]
另报 request-level full compliance(RFC):对请求与接口适用的、可机械核验的要求是否全部满足(文件交付、输出格式、工具使用等),与答案对错分开算。[1]
主结果怎么读
论文 Table 1:HEXIS 在 16 个设定里有 15 个高于 Skill + ReAct,并在 11 个设定拿到最佳或并列最佳。相对 Skill + ReAct 的平均增益 16.2pp。增益最大在 LiveMath(约 31.4–38.0pp);最小在 DABench(约 1.9–4.0pp),那里原生成功率已经 78.4–86.3%。经验注入或改文案并不稳定:AWM、ReasoningBank、SkillOpt 在 LiveMath 上,对至少两个执行器会掉到 Skill + ReAct 之下。AFlow 在 LiveMath 有竞争力,但在本地执行器的 DABench 上落到 51.0% 与 15.7%;而只从 qwen3.6-flash 轨迹编出的机器,在转交的另外 12 个设定里有 11 个仍改进——说明「跨模型复用控制结构」成立,而不等于搜来的工作流天然可迁移。[1]
举几个便于核对的格子(均为成功率 %,Skill + ReAct → HEXIS):
- Spreadsheet × qwen3.6-flash:45.6 → 75.4
- LiveMath × qwen3.6-flash:44.6 → 76.9;× Qwen3.8-27B:33.9 → 71.9
- DABench × Qwen3.8-27B:86.3 → 88.2(原生已高,空间小)
- LongSeal × qwen3.6-flash:7.8 → 21.6;× Qwen3.5-9B:23.5 → 23.5(并列,即未抬升的那一格)[1]
RFC 与成功率同向:LiveMath 上原生全合规只有约 23.1–79.3%,HEXIS 抬到 91.7–100%;DABench 原生合规已 88.2–98.0%,成功率增益也小。论文还做了对照:把同一台编译好的机器渲成 prompt 让模型自己跟(Prompt-only),相对真正 runtime 执行,平均成功率低 16.8pp、合规低 28.0pp——说明收益主要来自程序化控制,不是「把 FSM 描写得更清楚」这一条文本优化。[1]
合规必要但不充分:SpreadsheetBench × qwen3.6-flash 上,SkillOpt 与 HEXIS 都能到 100% 合规,成功率却是 59.6% vs 75.4%——状态里怎么用 skill 知识仍然重要。[1]
Token:不是每个执行器都省
Figure 5:相对 Skill + ReAct,HEXIS 在长上下文 LongSeal 上省得最多(qwen3.6-flash 约 90.0%,Qwen3.5-9B 约 80.8%),与「每状态只读声明输入、不啃累积历史」一致。在 Spreadsheet 与 LiveMath 上,对 qwen3.6-flash 成本反而略升(约 +4.9%、+8.9%),因为机器显式加了校验步。其余取决于执行器:Qwen3.8-27B 上 HEXIS 在每个基准都最省,相对 Skill + ReAct 少 38.4–88.9%;GLM-4.7-FlashX 少 28.4–94.5%;Qwen3.5-9B 在另外三个基准上反而更费 token。[1]
写进自家成本账时建议记住:HEXIS 卖的是控制外置;token 曲线随执行器与是否多验一步而变,不要把摘要里的区间当成「任意模型一律暴降」。
和 SkillOpt 叠在一起
Table 2(SpreadsheetBench):原 skill 上 Skill + ReAct 45.6% / 213k token;原 skill + HEXIS 75.4% / 223k;SkillOpt 文案 + 原生 59.6% / 257k;SkillOpt + HEXIS 84.2% / 69k——相对「优化后的 skill 仍原生执行」再高 24.6pp,token 少约 73.2%。相对「原 skill + HEXIS」还再高 8.8pp。论文结论很干脆:内容优化与执行结构互补——SkillOpt 改指导质量,HEXIS 管怎么兑现。[1]
这和站内「改 agents.md / 改 skill 文案」经验一致:文案变好能抬天花板,但若每步控制仍靠推断,合规与成本仍会抖。
相关工作三路,HEXIS 卡在哪
论文把邻近工作收成三条线,便于和站内 harness 叙事对照(Figure 2):[1]
-
Skill 优化(改文档):SkillOpt 用执行反馈改 skill,留下验证集上更好的版本。文案更好,但每一步控制仍交给执行器推断——第 3.1 节分析的累积偏离可以照样发生。Formal Skill 则把 skill 做成带 executor / hooks / 本地运行时状态的程序;HEXIS 也做显式控制,但从现有 skill 文档出发,再用轨迹 refinement,因此优化后的 skill 可以直接当编译输入(Table 2)。[1]
-
记忆增强(加经验):Reflexion、Agent Workflow Memory、ReasoningBank 把成败经验变成可检索文本或工作流描述。它们扩大「模型知道什么」,不改变「执行如何被控制」:何时套用经验仍靠推断,且新上下文还和变长的交互历史抢窗口。[1]
-
工作流搜索(显式程序):StateFlow 用状态机组织任务阶段;AFlow 用 MCTS 搜模型调用工作流;TraceCompiler、Compile Then Page 从轨迹或 SOP 约束编译。这些方法通常不以「现有 skill 文档」为编译对象;搜出来的工作流也可能在执行器之间抖得很厉害——论文在 §5.3 用 AFlow 的跨模型落差作反例。HEXIS 编译的是 skill 本身:知识留在状态提示里给模型推理,runtime 执行控制流。[1]
一句话:改文案、加记忆、搜工作流都能抬分,但 HEXIS 赌的是把控制从解码里抠出来,并且输入接口对齐你已经在维护的 skill 文件。
开发时轨迹怎么进机器(工程直觉)
初始化失败很常见的原因,不是「模型不够聪明」,而是 skill 条款与工具接口对不齐:规则引文对不上原文、工具名不在 (\mathcal{T})、分支一侧没给后面状态要用的变量赋值。论文的变量条件用最大不动点式的 (\mathrm{Def}(q)):只有所有入路径都定义过的变量,才能出现在读集里——这比「某条快乐路径上碰巧有值」严得多,也更接近你在静态分析里对 SSA / definite assignment 的直觉。[1]
轨迹对齐时,构造模型扮演的是「这个事件算不算某个已有状态能做的操作」。对不上就新建状态,并把推理文本与相关条款写进局部指令。若两条边同一守卫通向不同后继,就插 judge——这等于承认:自然语言 skill 里「看起来一样的条件」在执行时其实需要显式标签分流。回放失败则拒收更新,避免「为了修这一条轨迹,弄坏昨天已经验收的十条」。[1]
对维护者来说,档案 (\mathcal{P}_k) 类似一组可回放的回归夹具:不是单元测试代码,但是同一类约束——改图必须还能复现历史对齐路径。
附录里还有什么值得抄进 harness
机器规模(qwen3.6-flash 诊断): 约 12–17 个状态、19–35 条边。图不大也可以有大量状态重访:Spreadsheet 平均约 10.60 次 revisit、最长可到数十步机器步;这些重访含再分析、跑工具、验输出,不等于 hub 上的错误重试。LiveMath / LongSeal 的 runtime retry 很少;真正进入「整份 skill 解释型 fallback」的任务更少。[1]
LiveMath 实例机(附录 B.4): 12 状态、19 显式转移、18 类型变量;含 model / judge / tool / 终止 / fallback。路径典型是:分析 → 选题 →(可选)完整性 judge 回修 → 写文件命令 → bash 写 → read 回读 → 内容一致性 judge → 已验证报告或未验证报告。「verified」在这里指交付文件与机器选题一致,不证明数学答案正确——读指标时别把控制闭环的 verified 和任务对错混为一谈。[1]
换编译器: 用 Claude Sonnet 5(low effort)编译、仍用 qwen3.6-flash 执行,四基准仍全面高于 Skill + ReAct,相对 Fable 编译机只低约 2.0–4.2pp。收益不绑死在某一个编译模型上。[1]
局限与可落地清单
作者自己写明:机器覆盖受 skill 文档与开发轨迹质量限制——文档与轨迹从未表达的要求或分支,机器里也可能没有。静态检查与回放验证的是已记录路径,不保证状态内推理正确,也不保证覆盖未见情形。未来方向包括有针对性的轨迹采集与更强的状态内校验。[1]
若你在自家 agent / harness 里试「skill → 可执行控制」,可以按论文机制列一张最小清单(不是复现实验脚本):
- 先分清披露、激活、执行:库大用 progressive disclosure;注入用增益预测;执行才考虑编译控制流。
- 把 (\mathcal{R}_D) 从上下文里抠出来:顺序、依赖、禁止、终止尽量变成状态与守卫,而不是只靠加粗提醒。
- 状态输入白名单:读集 / 写集显式化,避免「全历史 + 全 skill」再次耦合。
- 更新要可回归:新轨迹改图前,静态检查 + 回放全部已接受轨迹;失败就拒收,而不是静默漂移。
- 跨模型先迁控制结构:一台源模型轨迹编好的机器,能否在别的执行器上保持增益,比「每个模型重搜一个工作流」更接近可维护产物。
- 合规与正确分开记账:RFC 类机械检查与答案正确率并列;Prompt-only 对照能告诉你收益是不是来自 runtime。
- 和 skill 文案优化叠用:先 SkillOpt(或人工修订)再编译,往往比只做其中一件更稳——论文 Table 2 是直接证据。[1]
匿名代码与实验产物计划放在论文给出的 anonymous.4open.science 链接;正式发布前以作者仓库为准。[1]
读 Table 1 时别踩的坑
主表是「四基准 × 四执行器」的成功率网格,摘要里的 16.2pp 是相对 Skill + ReAct 的十六格平均增益,不是某一个明星格子。读表时建议同时看三件事:[1]
- 谁第二:Spreadsheet × Qwen3.8-27B 上 AFlow 73.7% 略高于 HEXIS 71.9%——HEXIS 不是每个格子都第一,论文自己的表述是「15/16 高于 Skill + ReAct,11/16 最佳或并列最佳」。
- 原生已经很高时增益变小:DABench 四格只抬 1.9–4.0pp;这时更该看 RFC 与 token,而不是只追成功率标题。
- 转交不等于重搜:机器只在 qwen3.6-flash 轨迹上编,却能在 GLM / 本地 Qwen 上多数设定仍赢——这是「控制结构可迁移」证据,不要和「每个执行器单独调参」混为一谈。[1]
另:SkillsBench 里 curated skill 把平均通过率从 33.9% 提到 50.5%(87 任务、八领域)是另一篇工作的数字,说明 skill 有价值;HEXIS 回答的是 skill 执行层,不要把两篇的百分点直接相加讲故事。[1]
数字之外:什么时候不该上 HEXIS
不是每条 skill 都值得立刻编译成 FSM。结合论文局限与站内经验,下面几类更适合先停在「好文档 + ReAct / 轻量 checklist」:
- 探索性极强、分支几乎不可枚举的研究型任务:轨迹覆盖不到的分支,机器里也不会 magically 出现;强行编译容易得到「假完整」的图。[1]
- skill 本身还在周更、条款互相打架:先做 SkillOpt / 人工修订,再编译;否则静态检查会反复红,或者编出互相矛盾的守卫。
- 执行器极弱、状态内推理已经是瓶颈:HEXIS 不保证状态内生成正确;LiveMath 上 verified 只保证文件与选题一致,不保证数学对。[1]
- 你其实缺的是加载与激活策略:库很大时,先做 progressive disclosure / SkillDelta,再谈执行编译——否则你会在错误的 skill 上做出很漂亮的状态机。
反过来,下面几类更像 HEXIS 的甜点:SOP 感强、工具接口稳定、失败后必须修订、交付物要机械验收(写文件、回读、格式、禁止跳步)。Spreadsheet / 数据分析 /「必须写盘再校验」类流程,和论文主结果的分布是对齐的。[1]
与 扩张 harness 合读时:Growing Harness 强调从反馈里长出程序;HEXIS 强调从已有 skill 文档编译。两者可以衔接——skill 稳定后编译一次,再用轨迹更新补洞,而不是每次任务都从零搜工作流。
结语
Skill 解决的是「专门知识如何打包复用」;ReAct 解决的是「如何交错推理与行动」。二者叠在一起之后,缺口往往在中间:条款里的控制流,仍然每一步靠模型重推断。HEXIS 把这条线拉成编译问题——知识留在状态内,流程交给扩展 FSM;增量编译用检查与全轨迹回放守住可回归性;实验上相对 Skill + ReAct 平均 +16.2pp,并在 Qwen3.8-27B 上给出 38.4–88.9% 的执行 token 降幅区间。[1]
对站内读者:若你刚读完 progressive disclosure / SkillDelta,可以把 HEXIS 标成同一条 skill 链上的执行层;若你在长 harness(grow the harness、SpecHarness),它提供的是「从现有 skill 文档出发」的一条具体编译路径,而不是再堆一段记忆或再搜一个易碎工作流。
参考
[1] WorldBuilder013, Minghao Li. HEXIS: Compiling Agent Skills into Extended Finite State Machines. arXiv:2609.30123v2, 2026. https://arxiv.org/abs/2609.30123 · HTML