Agent 工作流可控 Agent 范式

从 Workflow Bot 到可控 Autonomous Agent

这是一篇通用 AI Agent 架构笔记。法律材料处理只是贯穿全文的案例,用来说明高风险业务里如何设计自主性、工具调用、人工审批和审计边界。

原典与参考

本文的主要论证基于以下公开原典和厂商文档:

其中最关键的一句话来自 Anthropic 对 workflow 和 agent 的区分:

Workflows are systems where LLMs and tools are orchestrated through predefined code paths. Agents, on the other hand, are systems where LLMs dynamically direct their own processes and tool usage.

这句话可以作为本文的核心判断标准:

如果控制流主要由代码预定义,它是 workflow。
如果控制流主要由模型根据目标、上下文和工具结果动态决定,它才接近 agent。

一句话结论

大多数团队以为自己在做 autonomous agent,实际上是在做 command bot 或 workflow bot。

这不是坏事。Command bot 和 workflow bot 都是有价值的阶段。真正的问题是:

不要把 workflow bot 包装成 autonomous agent,
也不要把高风险业务直接交给无边界的 prompt loop。

更稳妥的演进路径是:

Command Bot

Workflow Bot

Human-in-the-loop Workflow

Bounded Autonomous Agent

Audited Agentic System

真正成熟的 Agent 系统,不是“模型更聪明”,而是“自主性被设计成可度量、可中断、可审批、可追踪的系统能力”。


1. 先定义:什么不是 Agent

很多产品界面里有一个聊天框,用户可以输入自然语言,于是团队就称它为 Agent。

但聊天框不是 Agent。

下面这些系统都可能长得像 Agent,但本质不是 autonomous agent。

1.1 Command Bot

典型形态:

/summarize
/search
/run_review
/create_ticket

架构是:

User Command

Command Router

Handler

Tool / LLM / Database

Result

优点:

  • 可预测
  • 易测试
  • 权限边界清楚
  • 出错容易定位

缺点:

  • 用户必须知道有哪些命令
  • 系统不会主动规划
  • 很难处理开放目标

Command bot 是很好的工具孵化阶段,但不是 autonomous agent。

1.2 Workflow Bot

典型形态:

if user says "start intake":
  load questionnaire
elif user says "run review":
  run review tool
elif active_question:
  save message as answer
else:
  show next action

这类系统有状态、有步骤、有工具,但控制流主要还是代码写死。

它符合 Anthropic 所说的 workflow:

LLM 和工具被预定义代码路径编排。

Workflow bot 很适合生产系统,因为它可靠。但如果用户期待的是“自由跟随指令、自主规划、多步执行”,workflow bot 会显得很笨。

1.3 Prompt Loop

另一种极端是把所有控制权交给一个巨大 prompt:

你是一个专业助手。你需要理解用户目标、选择工具、完成任务、必要时请求人工确认……

然后让模型循环调用工具。

这看起来最像 agent,但在生产里最危险:

  • 权限边界模糊
  • 状态难恢复
  • 工具调用难审计
  • 失败路径不可控
  • 高风险写入可能越权

所以成熟系统不是在 workflow bot 和 prompt loop 之间二选一,而是要设计一个有边界的 agentic system。


2. Agent 的最小能力模型

结合 ReAct、Toolformer、OpenAI Agents SDK、LangGraph 和 AutoGen 的实践,一个可称为 Agent 的系统至少要有这几个能力:

Observe → Think / Plan → Act with Tools → Inspect Result → Continue / Stop / Ask Human

更工程化地说:

1. 读取上下文
2. 理解用户目标
3. 制定计划
4. 选择工具
5. 执行工具
6. 观察工具结果
7. 更新状态
8. 决定继续、停止、澄清或请求人工审批

这和 ReAct 的核心思想一致:语言模型不只是回答,还要交替进行 reasoning 和 acting。

但生产系统要比论文 demo 多几层:

policy
permission
budget
checkpoint
human approval
audit log
evaluation

没有这些控制面,Agent 很容易变成不可控的自动化黑盒。


3. 通用架构:把 Agent 拆成六层

一个更稳的通用 Agent 架构可以拆成六层:

User Interface

Conversation Layer

Intent / Goal Layer

Planner / Control Plane

Tool Execution Layer

State / Audit / Evaluation Layer

3.1 Conversation Layer

聊天记录只负责交互,不应该成为业务状态的唯一来源。

错误做法:

把用户说过什么、任务执行到哪一步、业务事实是什么,全部塞进 chat history。

更好的做法是分开:

Conversation State:用户和系统说过什么
Task State:当前 run 执行到哪里
Domain State:业务对象的真实结构化状态
Audit State:谁在什么时候做了什么

法律材料处理案例里,这对应:

Conversation:律师和 Agent 的对话
Task:当前是否在 intake、review、evidence request
Domain:申请人信息、文件、事实、缺口、审阅结论
Audit:字段来源、模型建议、人工修改、审批记录

3.2 Intent / Goal Layer

不要直接把用户消息送进工具。

用户说:

继续

可能表示:

  • 回答当前问题
  • 继续上一个 workflow
  • 运行下一步 review
  • 解释当前状态
  • 同意 pending action

所以 Agent 需要先识别 intent:

answer_question
ask_clarification
start_workflow
run_review
correct_state
approve_action
reject_action
ask_knowledge
unknown

法律材料处理案例里,最容易犯的错误是:

只要 active intake 存在,就把所有用户输入都当成当前字段答案。

这会导致用户说“这个问题是什么意思?”也被保存成业务字段。

3.3 Planner / Control Plane

Planner 不是简单地把 intent 映射成一个工具。

真正的 plan 应该包含:

objective
steps
required_tools
risk_level
approval_required
stop_condition
fallback

例如用户说:

帮我看看这个申请还缺什么。

一个合理 plan 是:

1. read current case state
2. inspect known profile facts
3. inspect uploaded documents
4. compare against checklist
5. identify gaps
6. explain which gaps are facts vs assumptions
7. propose next actions

如果 plan 中包含写入、外部发送、状态覆盖,就应该进入 HITL。

3.4 Tool Execution Layer

工具层是 Agent 的能力边界。

不要给 Agent 一个万能工具:

execute_sql(query)
write_database(table, payload)
call_internal_api(url, body)

更好的工具是业务语义化:

list_documents(case_id)
extract_profile_fields(document_id)
compare_against_checklist(case_id, checklist_id)
propose_profile_patch(case_id, fields)
create_review_note(case_id, issue_ids)
request_human_approval(run_id, proposed_changes)

每个工具都应该声明:

input schema
output schema
permission
side effect
idempotency key
approval policy
audit behavior
error type

Toolformer 证明了模型可以学会使用工具;生产系统则必须定义模型能用什么工具、什么时候能用、用错了如何恢复。

3.5 Human-in-the-loop Layer

OpenAI Agents SDK、LangGraph、AutoGen 都把 human-in-the-loop 作为 Agent 系统的重要能力。

HITL 不是“输出后给人看一眼”,而是:

pause → persist state → ask human → apply decision / patch → resume

LangGraph 的 interrupt 模式尤其适合作为心智模型:

Graph execution reaches interrupt
state is checkpointed
human reviews or edits
execution resumes from that point

OpenAI Agents SDK 的 tool approval 也强调:敏感工具调用可以暂停,等待 approve / reject,再 resume。

这对所有高风险业务都重要,不只是法律。

3.6 State / Audit / Evaluation Layer

Agent 不能只靠“看起来回答得不错”上线。

必须能回答:

它看过哪些输入?
调用了哪些工具?
每个工具返回了什么?
哪些内容是模型推断?
哪些内容被人工确认?
哪些动作真正写入了系统?
如果重跑,结果是否可复现?

这就是 audit layer 的价值。


4. 法律材料处理案例:为什么 workflow bot 会卡住

假设我们在做一个 immigration legal agent。它的任务包括:

  • 收集 applicant profile
  • 读取上传材料
  • 抽取关键事实
  • 判断证据缺口
  • 生成给客户的补件请求
  • 准备律师 review pack

最早版本可能是这样:

/new
/intake
/review
/evidence

这很好测试,但用户体验会有问题。

用户会自然地说:

这个申请现在还缺什么?
先别保存,解释一下为什么要问这个字段。
申请人叫张三,工资 42k,SOC code 是 2136,CoS 已经下来了。
帮我生成一封给客户的补件邮件。

如果系统只是 command router,它就无法真正理解这些开放指令。

如果系统处于 active intake,然后把所有输入都当成当前问题答案,就会出现严重错误:

用户:这个问题是什么意思?
系统:把“这个问题是什么意思?”保存为 applicant.fullName 的候选值。

这说明问题不在 UI,而在架构:

chat input 被同时当成命令、答案、问题、审批、工具参数。

解决办法不是加更多按钮,而是拆层:

先识别 intent
再决定是否需要工具
再决定是否会写入
写入前生成 proposed action
人工确认后再 commit

5. 从写入角度区分 Agent 行为

Agent 的行为可以按风险分层:

read-only reasoning
read-only retrieval
draft generation
proposed state change
durable write
external action

不同层级对应不同控制策略。

行为例子策略
read-only reasoning解释当前状态允许自由执行
retrieval搜索知识库、读取文件权限校验 + 引用来源
draft generation草拟邮件、生成摘要标记为草稿
proposed state change建议更新字段生成 diff,不落库
durable write写入 profile / case state人工审批
external action发邮件、提交表单强制审批 + 审计

法律案例中,Profile 字段写入应该走:

Model extracts value

Proposed Profile Patch

Human review / edit / reject

Commit confirmed value

Audit event

这比“模型直接写数据库”安全得多。


6. Bounded Agent:自主性不是开关

很多讨论把 Agent 分成“自主”和“不自主”。这个二分不够工程化。

更好的问题是:

它在哪些边界内自主?

边界可以包括:

可调用工具集合
最大工具调用次数
最大 token / time budget
可读数据范围
可写数据范围
是否允许外部副作用
是否需要人工审批
失败后是否可重试
是否必须引用来源

一个 bounded agent 可以这样配置:

{
  "mode": "case_review",
  "allowed_tools": [
    "read_case_state",
    "list_documents",
    "search_knowledge_base",
    "propose_profile_patch",
    "draft_client_request"
  ],
  "forbidden_tools": [
    "commit_profile_patch",
    "send_email"
  ],
  "max_steps": 8,
  "requires_approval_for": [
    "profile_patch",
    "client_facing_message",
    "external_submission"
  ]
}

这才是生产可用的自主性。


7. Prompt 应该局部化,而不是统治系统

早期 Agent 常见反模式:一个超级 system prompt 管一切。

你是一个专业助手。你需要理解用户、使用工具、遵守合规、避免错误、必要时询问人类……

这种 prompt demo 很快,但生产不可维护。

更好的方式是把 prompt 拆成局部契约:

intent classifier prompt
planner prompt
fact extraction prompt
gap analysis prompt
client message drafting prompt
review summary prompt

每个 prompt 都绑定:

明确输入
明确输出 schema
明确禁止事项
明确引用来源
明确置信度规则
明确失败格式

例如字段抽取不要返回散文,而应返回结构化结果:

{
  "field": "employment.annualSalary",
  "value": "42000",
  "source": {
    "document_id": "doc_123",
    "quote": "Annual salary: £42,000"
  },
  "confidence": 0.87,
  "needs_human_review": true
}

结构化输出不是形式主义,而是后续验证、审批、审计、评估的基础。


8. 评估不能只看“像不像人”

Agent 系统的评估至少分四层。

8.1 Intent 层

  • 是否正确区分问题、命令、答案、审批、纠错
  • active workflow 下是否误吞用户输入
  • 模糊输入是否会澄清,而不是乱写

8.2 Tool 层

  • 工具选择是否正确
  • 参数是否正确
  • 是否遵守权限
  • 失败是否可恢复
  • 是否避免重复副作用

8.3 State 层

  • 是否正确更新 structured state
  • proposed change 是否可审阅
  • 是否保留来源和置信度
  • 是否避免覆盖人工确认值

8.4 Outcome 层

  • 用户任务是否完成
  • 输出是否有引用来源
  • 是否区分事实和推断
  • 是否在高风险点中断
  • 人工修改率是否下降

对于法律材料处理案例,还可以看:

字段抽取准确率
缺失材料误报率
缺失材料漏报率
人工审阅节省时间
客户补件问题清晰度
review pack 可用率

没有 eval 的 Agent,只是一个看起来聪明的 demo。


9. 常见反模式

9.1 把 workflow bot 叫 autonomous agent

如果系统只能识别几个固定命令,就不要承诺“自主跟随指令”。

正确做法是明确显示模式:

Limited workflow mode
Read-only knowledge mode
Autonomous review mode
Approval required mode

9.2 用 pending approval 锁死整个 chat

如果有一个待审批写入,系统不应该禁止用户继续问问题。

应该禁止的是新的高风险写入,而不是 read-only conversation。

允许解释、讨论、澄清。
阻止叠加新的 durable write。

9.3 让模型直接写最终业务数据

危险写法:

LLM output → database

更安全:

LLM output → proposed diff → validation → human approval → commit

9.4 一个超级 Agent 包办所有任务

超级 Agent 难以测试、难以审计、难以定位错误。

更稳的是:

多个 bounded agentic steps
+ deterministic workflow glue
+ shared audit layer

9.5 把状态藏在聊天记录里

Chat history 不是数据库。

业务系统应该维护结构化状态,而不是从一长串自然语言对话里反推出事实。


10. 推荐目标架构

可以把成熟 Agent 系统理解成:

                 ┌────────────────────┐
                 │ User / Reviewer UI  │
                 └─────────┬──────────┘

                 ┌────────────────────┐
                 │ Conversation Layer │
                 └─────────┬──────────┘

                 ┌────────────────────┐
                 │ Intent / Goal      │
                 └─────────┬──────────┘

                 ┌────────────────────┐
                 │ Planner / Policy   │
                 │ budget / approval  │
                 └─────────┬──────────┘

        ┌────────────────────────────────────┐
        │ Tool Execution Layer               │
        │ schema / permission / idempotency  │
        └─────────┬──────────────────────────┘

        ┌────────────────────────────────────┐
        │ Structured State                   │
        │ facts / tasks / proposed changes   │
        └─────────┬──────────────────────────┘

        ┌────────────────────────────────────┐
        │ Audit / Eval / Observability       │
        └────────────────────────────────────┘

法律材料处理只是这个范式的一个高风险案例。其他场景也类似:

  • 企业知识库 Agent
  • DevOps Agent
  • 财务对账 Agent
  • 客服升级 Agent
  • 数据分析 Agent
  • 代码修改 Agent

共同点是:

读可以自由一些。
写必须受控。
外部副作用必须审批。
状态必须结构化。
行为必须可审计。

11. 最终总结

从 command bot 到 workflow bot,再到 autonomous agent,本质不是“越来越像人聊天”,而是“越来越能处理不确定目标”。

可以用三句话总结:

Command Bot 解决入口问题。
Workflow Bot 解决流程问题。
Bounded Autonomous Agent 解决开放目标下的动态决策问题。

但 Agent 的自主性不能脱离控制面:

没有 tool schema,自主性就是越权。
没有 HITL,自主性就是风险。
没有 audit,自主性就是黑盒。
没有 eval,自主性就是幻觉指标。

因此,真正值得建设的不是一个无所不能的 Agent,而是一套可控的 agentic system:

用 workflow 固化边界,
用 planner 处理不确定目标,
用 tool schema 限制能力,
用 HITL 管理风险,
用 audit 保留证据,
用 eval 驱动迭代。

这也是 Anthropic、OpenAI、LangGraph、AutoGen 这些原典实践共同指向的方向:

Autonomy is not a switch. It is an engineered capability.