2026年了,你的AI Agent还在if-else地狱里翻车?HN热榜126星的Statewright,用状态机让Agent逻辑一目了然——每次对话都是确定性的路径,不再随机跑偏。
为什么AI Agent必备状态机?
先看一个真实场景:你做了一个AI客服Agent,让它处理用户的退款请求。
用传统Prompt驱动的Agent,流程大概是:
用户:"我要退款"
→ Agent收到,开始思考...
→ 有时它直接说"已退款"(跳过了验证)
→ 有时它问了5个问题还没进入退款流程(陷入追问循环)
→ 有时它忘记问订单号就去查库存了(跳过关键步骤)
这不是你的Prompt写得不好——而是大模型的非确定性本质决定了它天然不适合做流程控制。
Statewright的解决方案:把Agent的核心流程建模成可视化状态机,让大模型只负责「在既定状态内做决策」,而不是「决定该走哪条路」。
| 问题 | 无状态机 | 有状态机 |
|---|---|---|
| 跳过关键步骤 | 频繁发生 | 状态转换有前置条件,不可能跳过 |
| 陷入循环 | 常见 | 状态转换是单向的 |
| 上下文丢失 | 依赖Prompt记忆 | 状态本身就是记忆载体 |
| 调试困难 | 只能看对话日志 | 状态图一目了然 |
Statewright 是什么?
Statewright是一个Rust编写的状态机引擎,核心特色:
- 可视化编辑器 — 拖拽节点和边,自动生成状态机代码
- MCP原生集成 — 状态机可以作为MCP工具被任何AI Agent调用
- 确定性执行 — Rust保证状态转换100%可预测
- 可观测性 — 每次状态转换都有日志和时间戳
目前HN评分126,社区反响积极,被拿来与stately.ai做对比。
实战:搭建AI客服退款Agent的状态机
Step 1:设计状态图
退款流程的状态机长这样:
[IDLE] ──用户说"退款"──→ [VERIFY_ORDER]
[VERIFY_ORDER] ──订单验证通过──→ [CHECK_REFUND_POLICY]
[VERIFY_ORDER] ──订单不存在──→ [ASK_ORDER_NUMBER]
[CHECK_REFUND_POLICY] ──符合条件──→ [PROCESS_REFUND]
[CHECK_REFUND_POLICY] ──不符合──→ [REJECT_REFUND]
[PROCESS_REFUND] ──退款成功──→ [SEND_CONFIRMATION]
[PROCESS_REFUND] ──退款失败──→ [HUMAN_ESCALATION]
Step 2:用Statewright定义状态机
# refund_agent.yaml — Statewright 状态机定义
name: refund-agent
initial: IDLE
states:
IDLE:
on:
USER_ASKS_REFUND: VERIFY_ORDER
entry: "等待用户发起退款请求"
VERIFY_ORDER:
on:
ORDER_VERIFIED: CHECK_REFUND_POLICY
ORDER_NOT_FOUND: ASK_ORDER_NUMBER
entry: "验证用户订单号和购买记录"
timeout: 30s → HUMAN_ESCALATION
ASK_ORDER_NUMBER:
on:
ORDER_RECEIVED: VERIFY_ORDER
entry: "向用户索要正确的订单号"
max_retries: 3 → HUMAN_ESCALATION
CHECK_REFUND_POLICY:
on:
ELIGIBLE: PROCESS_REFUND
NOT_ELIGIBLE: REJECT_REFUND
entry: "检查是否在7天无理由退货期内"
PROCESS_REFUND:
on:
REFUND_SUCCESS: SEND_CONFIRMATION
REFUND_FAILED: HUMAN_ESCALATION
entry: "调用支付系统执行退款"
REJECT_REFUND:
on:
USER_ACKNOWLEDGES: IDLE
entry: "告知用户退款被拒的原因"
SEND_CONFIRMATION:
on:
CONFIRMATION_SENT: IDLE
entry: "发送退款成功通知"
HUMAN_ESCALATION:
on:
RESOLVED: IDLE
entry: "转接人工客服,附带完整的状态上下文"
Step 3:通过MCP接入任何AI Agent
Statewright通过MCP暴露状态机,任何支持MCP的Agent都可以直接调用:
{
"mcpServers": {
"statewright": {
"command": "statewright",
"args": ["serve", "--config", "./refund_agent.yaml"],
"env": {
"STATEWRIGHT_PORT": "9090"
}
}
}
}
接入Hermes Agent的配置(在 ~/.hermes/mcp.json 中添加):
{
"statewright-refund": {
"type": "stdio",
"command": "statewright",
"args": ["serve", "--config", "/path/to/refund_agent.yaml"]
}
}
之后Agent对话中就会出现这些MCP工具:
- statewright_get_current_state — 获取当前状态
- statewright_transition — 触发状态转换
- statewright_get_state_history — 查看状态轨迹
- statewright_get_available_transitions — 查看可执行的下一步
Step 4:Agent使用状态机的Prompt模式
你是一个AI客服Agent。退款流程由Statewright状态机管理。
工作方式:
1. 每次收到用户消息,先调用 statewright_get_current_state 确认当前状态
2. 根据当前状态,调用 statewright_get_available_transitions 查看可选路径
3. 在所选路径对应的上下文中与用户对话
4. 条件满足后调用 statewright_transition 进入下一个状态
CRITICAL:你不能跳过状态机定义的状态。如果状态机要求先验证订单,
你就不能说"已退款"——必须先通过 VERIFY_ORDER 状态。
进阶:多Agent协同的状态机
单个客服Agent用状态机已经很清晰,但实际场景往往涉及多个Agent协作。Statewright支持嵌套状态机:
[MAIN_AGENT]──需要查库存──→[INVENTORY_AGENT_状态机]
[MAIN_AGENT]──需要查物流──→[LOGISTICS_AGENT_状态机]
[MAIN_AGENT]──需要人工介入──→[HUMAN_AGENT_状态机]
每个子Agent都有自己的状态机,主Agent只负责编排。这解决了AI Agent开发中最大的痛点之一——子任务间的状态污染。
3个可复制的状态机模板
模板1:文章审核流水线
[DRAFT] → [AI_REVIEW] → [HUMAN_REVIEW] → [PUBLISH]
↘ [REJECT] → [REVISE] → [AI_REVIEW]
模板2:用户引导Onboarding
[WELCOME] → [COLLECT_INFO] → [PAYMENT] → [ACTIVATE]
↘ [TRIAL] → [NUDGE_PAY] → [PAYMENT]
模板3:定时数据采集
[WAIT_SCHEDULE] → [FETCH_DATA] → [PARSE] → [VALIDATE] → [SAVE]
↘ [PARSE_ERROR] → [RETRY] → [FETCH_DATA]
↘ [ALERT_HUMAN]
Statewright vs 竞品速览
| 维度 | Statewright | stately.ai | XState | 纯Prompt |
|---|---|---|---|---|
| 可视化 | ✅ 内置编辑器 | ✅ 专业 | ⚠️ 需插件 | ❌ |
| MCP集成 | ✅ 原生 | ❌ | ❌ | ❌ |
| 确定性 | ✅ Rust保证 | ✅ | ✅ JS | ❌ |
| 学习曲线 | 中等 | 中等 | 中高 | 低 |
| 开源 | ✅ | ❌ SaaS | ✅ | - |
| HN评分 | ⭐126 | - | - | - |
行动清单
今天就可以做的事:
- 10分钟:克隆Statewright仓库
git clone https://github.com/statewright/statewright,跑通Quick Start - 20分钟:把你当前最混乱的Agent流程画成状态图(用纸笔或draw.io都行),看看有几个"鬼状态"(永远达不到的状态)
- 30分钟:用上面的退款Agent模板,改写成你的业务场景,接入Hermes Agent测试一次状态转换
核心认知
AI Agent的可靠性不取决于你的Prompt写得有多好,而取决于你把多少「不确定性」关进了「确定性的笼子」里。状态机就是这个笼子。
