<!-- title: 人在回路中断税：六栈审批闸门横评 -->

生产级智能体落地的头号死法，在 2026 年已经收敛成一句话：**智能体执行了一个没有人批准过的副作用。** 模型把草稿写得很漂亮、推理链很完整，然后在最后一步调用了 `issue_refund`、`drop_table`、`send_email`、`transfer_funds`——而这一步恰恰是唯一不可逆、也最该有人盯着的环节。于是"人在回路"（Human-in-the-Loop，HITL）从可选项变成了 2026 年所有主流框架的**一等公民原语**。问题是：每家框架实现审批闸门的方式天差地别，而**加一道闸门从来不是免费的**。本文把 LangGraph、OpenAI Agents SDK、CrewAI、AutoGen、LlamaIndex Workflows、裸 SDK 自研这六条路线放在一起，从"中断粒度—状态持久化—恢复机制—阻塞模型"四个轴实测，算清那笔被普遍低估的**中断税账**。

## 一、先看清"中断税"的四张账单

在比框架之前，必须先承认一个事实：审批闸门不是"加个 `if ask_user`"那么轻量。它会从四个方向同时向你收税。

**第一张账单是延迟税。** 智能体一旦在某个节点挂起等待人类，整个 run 的尾延迟就从"模型推理的十几秒"被拉长到"人响应的几分钟甚至几小时"。一个本来 12 秒跑完的退款流程，加上人工复核，端到端可能变成 4 分钟起步。**吞吐和延迟在这里是同一个旋钮**：闸门越严，单位时间能完成的 run 越少。

**第二张账单是状态持久化税。** 想在几小时后恢复执行，框架必须在挂起点把**完整状态**序列化落盘——LangGraph 的 checkpointer、OpenAI 的 RunState、CrewAI 的 Memory，本质都是干这件事。每一次中断都意味着一次 DB 写入、一次状态 schema 绑定，以及"恢复时环境已变"的时序漂移风险。

**第三张账单是粒度税。** 审批可以挂在 run 级（最粗，要么全程没人管、要么全程堵死）、节点级、工具级、事件级（最细）。粒度太粗，闸门沦为橡皮图章；粒度太细，操作员被淹没在"批准/批准/批准"的疲劳里，照样橡皮图章。**正确的粒度，应当对齐"副作用的可逆性边界"**——只有真正不可逆、不可补偿的操作才需要拦。

**第四张账单是恢复正确性税。** 从序列化快照恢复时，工具签名可能已经变了、外部系统状态可能已经漂移、被批准的草稿参数可能已经过期。能优雅恢复，是 2026 年区分"玩具 demo"和"生产 agent"的分水岭。下面六条路线，差的正是这四张账单上的得分。

## 二、六栈审批闸门多维度对比

| 框架 | 中断粒度 | 状态持久化 | 恢复机制 | 阻塞模型 | 审批面范围 | 到首个闸门成本 |
|------|----------|------------|----------|----------|------------|----------------|
| **LangGraph** | 节点级 / 任意 `interrupt()` 点 | 内置 checkpointer（Postgres/SQLite/Memory） | `Command(resume=)` 沿 `thread_id` | 异步，可在任意节点挂起 | 节点级，细到单次 interrupt 调用点 | 中（须懂 graph + state schema） |
| **OpenAI Agents SDK** | 工具级 `needs_approval` | `RunState` 可序列化（run-wide） | `Runner.resume_from_state` | 流式 `run_streamed`，事件驱动 | **run-wide**，覆盖子 agent 工具调用 | 低（装饰器一行声明） |
| **CrewAI** | 任务级 `human_input=True` | 依赖 Memory / Flow state | `kickoff` + Flows 重入 | 同步阻塞，等标准输入 | 单任务级，粒度粗 | 低（一个布尔位） |
| **AutoGen** | 回合级 `human_input_mode` | 对话历史（GroupChat） | UserProxy 重发接续 | 同步阻塞，常驻 user proxy | 回合级，proxy 拦截 | 中（须配 proxy + 终止条件） |
| **LlamaIndex Workflows** | 事件级 `wait_for_event` | `Context.data` + 检查点 | 事件重投递 | 异步事件循环 | 事件级，挂在任意 step | 中高（须自定义 Event 类型） |
| **裸 SDK 自研** | 任意点（写哪停哪） | 自建（Redis / DB） | 自建 webhook 回调 | 完全自控 | 完全自定义 | 高（全手写） |

## 三、LangGraph：`interrupt()` + `Command(resume=)`——最可审计的一等公民

LangGraph 在 2026 年把 `interrupt()` 升级为一等公民原语，取代了早期只能用 `interrupt_before` / `interrupt_after` 在节点边界挂起的笨重写法。它的核心机制是：当图执行到 `interrupt(payload)` 这一行时，**立即暂停，用 checkpointer 把当前完整状态按 `thread_id` 落盘**，把 payload 抛给调用方；人类决策回来后，用 `Command(resume=decision)` 沿同一个 `thread_id` 把图从精确挂起点接续跑下去。

```python
from langgraph.graph import StateGraph
from langgraph.types import interrupt, Command
from langgraph.checkpoint.postgres import PostgresSaver

def review_node(state):
    decision = interrupt({"pending_action": state["draft_action"]})  # 在此挂起
    return {"action": state["draft_action"]} if decision["approved"] else {"action": None}

graph = builder.compile(checkpointer=PostgresSaver(...))
cfg = {"configurable": {"thread_id": "run-42"}}
graph.invoke(user_input, cfg)                                  # 暂停在 interrupt
graph.invoke(Command(resume={"approved": True}), cfg)          # 人工决策后恢复
```

优点在于**审计性极强**：每一次挂起/恢复都是一条带 `thread_id` 的可回放轨迹，配合 time-travel 调试能精确复现"当时为什么要做这个操作"。缺点是延迟税和状态税都不低——Postgres checkpointer 每次中断都要写一行状态，state schema 一旦演进，老 `thread` 的恢复就会踩兼容坑。变现上，LangGraph 的 HITL 模式最适合**金融风控、运维变更审批**这类强合规场景，是"训练营卖合规故事"的最佳素材，但教学门槛偏高，学员得先吃透 graph 与 channel。

## 四、OpenAI Agents SDK：`needs_approval` + `RunState`——声明式、最轻量的闸门

OpenAI Agents SDK 在 2026 年 2 月 5 日发布的 v0.8 里，把 HITL 做成了整个 SDK 最重要的更新之一。官方文档的原话点明了它的设计哲学：*"Use the HITL flow to pause agent execution until a person approves or rejects sensitive tool calls. Tools declare when they need approval, run results surface pending approvals as interruptions, and RunState lets you serialize and resume runs."*——**工具自己声明何时需要审批**，run 结果把待审批项作为中断抛出，`RunState` 负责序列化与恢复。最关键的一句是审批面 **"run-wide, not limited to the current top-level agent"**：即使是 handoff 到子 agent 后触发的工具调用，同一个 run 内的审批状态依然统一管控。

```python
from agents import Agent, Runner, function_tool

@function_tool(needs_approval=True)        # 一行声明：此工具需人工放行
def issue_refund(order_id: str, amount: float) -> str:
    return f"refunded {amount} for {order_id}"

agent = Agent(name="Billing", tools=[issue_refund])
result = Runner.run_streamed(agent, input="refund order 8821")
async for ev in result.stream_events():
    if ev.type == "approval_request":
        snapshot = result.to_state()        # 序列化 run-wide 状态
        result = Runner.resume_from_state(snapshot, approved=True)
```

它的杀手锏是**声明式与低门槛**：在工具上加 `needs_approval=True` 就完成了审批接入，不必手写状态机。工具级粒度天然对齐"副作用可逆性"——只有真正会改世界的工具才声明需要审批，普通只读工具一路放行，延迟税压到最低。缺点是粒度被钉死在"工具级"，想要"同一工具、看参数决定要不要审"就得在 `needs_approval` 里塞一个返回布尔值的判断函数，灵活性不如 LangGraph 的任意点中断。变现上它是**独立开发者做 SaaS 包装最快**的一条路：上手成本最低，配 MCP 工具能快速搭出带审批的垂直 agent，适合做"48 小时复刻一个客服/退款 bot"的快闪训练营。

## 五、CrewAI：`human_input=True`——简单粗暴，但粒度是硬伤

CrewAI 的 HITL 是六栈里最直白的：给 `Task` 传一个 `human_input=True`，该任务跑完就停下来、把结果丢给操作员，由人在终端敲 yes/no 或补一段反馈。配合 2026 年成熟的 Flows（用 `@start` / `@listen` 编排的事件流），可以在 Flow 层做更结构化的等待与重入。

```python
from crewai import Agent, Task, Crew
refund_agent = Agent(role="Billing specialist", ...)
approve_task = Task(
    description="Draft the refund action for {order}",
    expected_output="refund draft",
    human_input=True,          # 阻塞，等待操作员输入
    agent=refund_agent,
)
Crew(agents=[refund_agent], tasks=[approve_task]).kickoff()
```

优点是**门槛极低、心智负担最小**，一个布尔位就接入了 HITL，非常适合做"角色化团队 + 人工质检"的内部工具。但它的粒度是任务级——粗到要么整段任务没人管、要么整段任务都阻塞，**正好踩在"粒度税"最痛的区间**。而且它默认走标准输入阻塞，天生不适合跨进程、跨机器的分布式审批场景（比如人不在终端、审批要等到明天）。恢复机制也较弱，CrewAI 的状态持久化依赖 Memory 和 Flow，没有 LangGraph 那种"精确 thread_id 复活"的强保证。变现上，CrewAI 的 HITL 适合**面向小团队、非技术运营人员**的内容审核、文案发布类训练课，卖点是好懂；但凡客户要强审计、要恢复轨迹，CrewAI 就得让位给 LangGraph。

## 六、AutoGen：`UserProxyAgent`——回合级拦截，常驻代理成本高

AutoGen 走的是"对话即控制"的路子。它用一个常驻的 `UserProxyAgent` 充当人类代理，靠 `human_input_mode`（`NEVER` / `TERMINATE` / `ALWAYS`）决定每个回合是否打断，再用 `is_termination_msg` 判定结束。2026 年的 AutoGen 0.5+ 还补上了异步的 `interrupt` 与用户响应回调，能更细地控制"何时回弹给人"。

```python
import autogen
proxy = autogen.UserProxyAgent(
    "approver",
    human_input_mode="ALWAYS",      # 每次回复都回弹给人
    is_termination_msg=lambda x: "APPROVED" in (x.get("content", "")),
    max_consecutive_auto_reply=0,
)
# GroupChat(proxy, assistant) —— proxy 在副作用回合前拦截
```

优点是**与多智能体对话模型天然契合**：任何 agent 想动作，都得先过 proxy 这一关，等于把审批焊进了对话协议。缺点同样明显——**常驻代理是资源黑洞**：proxy 要在线等着，`ALWAYS` 模式下每个回合都阻塞，对话一长，延迟税和连接维护成本都直线上升。回合级粒度也比工具级粗：模型可能在一个回合里既查询又退款，proxy 只能在回合边界拦，想只拦退款那一动作就力不从心。变现上，AutoGen 的 HITL 最适合**研究型、探索型多智能体**场景（科研、数据分析需人指点方向），但做成面向企业的产品化审批，体验和成本都不如 OpenAI SDK / LangGraph。

## 七、LlamaIndex Workflows：事件级闸门——最灵活，代价是自己造轮子

LlamaIndex 的 Workflows 把一切抽象成事件（Event），HITL 在这里自然落成"在某一步 `wait_for_event` 等一个人类决策事件"。它的粒度是事件级——比节点级、工具级都更细，能精确到"在 step A 和 step B 之间插入一段等待"。

```python
from llama_index.core.workflow import Workflow, step, Event, Context

class ApprovalEvent(Event): action: dict

class BillingFlow(Workflow):
    @step
    async def draft(self, ctx: Context, ev: StartEvent) -> ApprovalEvent:
        ctx.data["draft"] = make_draft(ev.input)
        return ApprovalEvent(action=ctx.data["draft"])

    @step
    async def gate(self, ctx: Context, ev: ApprovalEvent) -> StopEvent:
        decision = await ctx.wait_for_event(HumanDecisionEvent, timeout=3600)
        return StopEvent(result=execute(ev.action) if decision.ok else None)
```

优点是**表达力最强**：异步事件循环让它天生适合跨服务、长时延的分布式审批（人几小时后通过 webhook 推回一个 `HumanDecisionEvent`）。缺点是**所有结构都要自己造**——`ApprovalEvent`、`HumanDecisionEvent` 都得自定义，状态靠 `Context.data` 手工管理，持久化和恢复没有开箱即用的强保证，本质是把中断税的大头转嫁给了开发者。上手门槛在六栈里偏高，**适合愿意为灵活性付工程税的团队**。变现上，它适合做成"工作流即代码"的高级训练营，但门槛劝退大多数初学者，更适合面向有经验工程师的进阶课。

## 八、裸 SDK 自研：把控制权 100% 拿在自己手里

最后一栈不是某个框架，而是"不要框架"——直接拿 Anthropic Claude / OpenAI 原生 SDK，在 agent loop 里手写挂起与恢复。模型每抛出一个 `tool_use`，执行前你先判断这个工具是不是副作用型；是，就把当前对话 + 工具调用塞进 Redis，返回一个 `approve:<id>` 的 key，外部系统（IM、工单、审批平台）拿 key 去找人，人批了走 webhook 把 key 标记放行，循环接续。

```python
import anthropic, json, redis
cl = anthropic.Anthropic(); r = redis.Redis()

def checkpoint_pending(conv, tool_use):
    key = f"approve:{r.incr('aid')}"
    r.setex(key, 3600, json.dumps({"conv": conv, "tool": tool_use.model_dump()}))
    return key        # 外部系统展示 key 给审批人；webhook 回调后恢复
```

它的全部价值就是**零抽象税、零锁定**：中断粒度、审批面、持久化后端、超时与重试策略，完全由你定义，最适合已经有一套工单/审批基建的企业把 agent"嵌"进既有治理流程。代价是工程税最高——你要自己处理状态序列化、幂等恢复、并发 run 的隔离、token 上下文在恢复时的重建。**六栈里延迟税和状态税可控性最强，但代码量也最大。** 变现上它不是训练营产品，而是**咨询/外包项目**的最佳形态：帮企业把 agent 审批焊进既有 SOX/合规流程，客单价远高于卖课。

## 九、审批闸门：挂起—恢复的生命周期

```mermaid
flowchart TD
    A[智能体 run 启动] --> B{执行下一步}
    B -->|只读工具| B
    B -->|副作用工具需审批| C[框架触发 interrupt]
    C --> D[Checkpointer/RunState 序列化完整状态]
    D --> E[挂起 run, 抛出 approval_request]
    E --> F{人类决策}
    F -->|批准| G[沿 thread_id/RunState 恢复]
    F -->|拒绝| H[短路退出 / 改写草稿]
    F -->|超时未决| I[补偿事务或告警]
    G --> J[执行真实副作用]
    H --> J
    J --> K[run 结束]
    I --> K
```

这张图藏着中断税的全部成本点：C→D 是状态持久化税（一次写盘），E→F 是延迟税（挂起时长不可控），C/D 的恢复点是恢复正确性税（环境漂移），而 F 的"批准/拒绝/超时"三分支，决定了闸门是真治理还是橡皮图章——**没有超时补偿分支的 HITL，在 2026 年等于没做。**

## 十、按场景的推荐方案

- **强合规、强审计（金融风控、运维变更、医疗处方）**：首选 **LangGraph**。`interrupt()` + `Command(resume)` + Postgres checkpointer 给你最完整、最可回放的审批轨迹，`thread_id` 让每一次挂起都能精确复现。
- **快速做垂直 SaaS、独立开发者**：首选 **OpenAI Agents SDK v0.8**。`needs_approval=True` 一行接入，run-wide 审批面覆盖子 agent，工具级粒度天然对齐副作用边界，上手最快。
- **非技术运营团队的内容质检**：选 **CrewAI** `human_input=True`。门槛最低，缺点是粒度粗，只适合内部工具别上生产强审计。
- **研究型/探索型多智能体**：选 **AutoGen** UserProxy。对话协议级审批自然，但接受常驻代理的连接与延迟成本。
- **跨服务、长时延、分布式审批**：选 **LlamaIndex Workflows** 事件级闸门，或干脆**裸 SDK 自研**。前者要你造事件轮子，后者要你造全部轮子，但都把延迟税和恢复策略的控制权牢牢攥在自己手里。
- **企业已有工单/审批基建**：直接 **裸 SDK 自研**，把 agent 审批挂进既有 SOX 流程，别让框架的 checkpointer 与企业治理系统割裂成两套真相。

一句话收束：**2026 年选 HITL 框架，本质是在"上手成本、审计强度、粒度精度、恢复保证"四个轴上做取舍。** 真正决定闸门价值的，从来不是用了哪个框架，而是你把审批挂在**副作用的可逆性边界**上、并为"人类永远会拖到最后一刻才点批准"这件事预留了超时与补偿分支。

## 参考来源

1. [Interrupts — LangGraph Docs](https://docs.langchain.com/oss/python/langgraph/interrupts) — 官方 `interrupt()` / `Command(resume=)` / checkpointer 持久化机制说明。
2. [Human-in-the-loop — OpenAI Agents SDK](https://openai.github.io/openai-agents-python/human_in_the_loop/) — `needs_approval` 声明、approval_request 中断与 run-wide `RunState` 序列化/恢复。
3. [OpenAI Agents SDK v0.8 Deep Dive: HITL & Codex Tool](https://www.paperclipped.de/en/blog/openai-agents-sdk-hitl-codex-tool/) — 2026-02-05 v0.8 发布，`needs_approval` + `RunState` 序列化解析。
4. [Adding Human Approval Gates to AI Agents Without Killing Throughput](https://www.bestaiweb.ai/how-to-add-human-approval-gates-to-agents-with-langgraph-autogen-and-crewai-in-2026/) — LangGraph/AutoGen/CrewAI 三栈审批闸门与吞吐权衡。
5. [LangGraph vs CrewAI vs AutoGen in 2026: Pick the Right AI Agent Framework](https://dev.to/cristian_iridon_286794874/langgraph-vs-crewai-vs-autogen-in-2026-pick-the-right-ai-agent-framework-or-skip-frameworks-4m2c) — HITL 粒度对比与"何时该跳过框架"的判断。
6. [Guardrails and human review | OpenAI API](https://developers.openai.com/api/docs/guides/agents/guardrails-approvals) — guardrails 自动校验与 human review 双机制的官方指引。

> [!tip] 51学通信知识星球
> **星主：爱卫生**（微信：gprshome201101）——公众号「51学通信」创办者，19 年通信行业运维与讲师经验，著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书（各大电商平台有售）。
> **星球定位**：深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域，主打运维岗位与信令分析。
> **当前规模**：5200 篇主题 / 990 个回答，198 元/年。
> **加入福利**：加入星球后请加爱卫生微信，拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题，另有群内分享。
> **AI 加持**：51学通信知识星球已作为 skill 接入 WorkBuddy，使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例，做总结、找文档和 PPT 等场景全覆盖。

![51学通信知识星球海报-扫码加入](https://wiki.500nian.com/images/zhixingqiu_qrcode.png)
