企业在构建智能体系统时,第一个直觉通常是“设计几个专家 Agent,让它们互相交接”。Intuit 的团队正是这样起步的:先建了一批专家 Agent,再加一个中央编排层来路由任务。这个架构存活了大约三个月。失败原因很具体:Agent 之间用自然语言传递结果,每一次交接都丢失上下文,十个 Agent 的链条不是偶尔出错,而是按设计在累积错误。重建后的系统放弃了“Agent 传递结果”的模式,转向共享的技能与工具层,每个 Agent 调用同一套经过验证的能力,而不是通过语言互相“告知”自己做了什么。
这个教训指向企业级智能体系统的一条核心原则:Agent 的拓扑结构不是设计的重点,Agent 所依托的确定性底座才是。规模本身就会惩罚脆弱的编排——SAP 对 208 个生产场景的评估显示,当 Agent 数量从“部门级”(20–80)扩展到“企业级”(200),Agent 发现噪声成为主要瓶颈,编排性能的下降主要由规模驱动,而非任务复杂度。以下三个设计点,是让系统在规模下仍然可运行的最低要求。
长时运行的 Agent 必须被当作有状态的服务进程。LangGraph 的 interrupt 机制提供了可复用的模式:调用 interrupt() 时,checkpointer 将图状态写入持久化存储,执行暂停;恢复时用同一个 thread_id 和 Command(resume=...) 从精确断点继续,而不是重新推理。生产环境必须使用数据库支撑的 checkpointer,而非内存存储。
from langgraph.types import interrupt, Command
from langgraph.checkpoint.postgres import PostgresSaver
def approval_node(state: RunState):
decision = interrupt({"order_id": state["order_id"],
"risk": state["risk_score"],
"reasoning_trace": state["trace"]}) # 完整上下文随暂停保留
return {"approved": decision["approved"]}
with PostgresSaver.from_conn_string(DB_URL) as saver:
graph = builder.compile(checkpointer=saver)
config = {"configurable": {"thread_id": f"order-{order_id}"}}
graph.invoke({"order_id": order_id}, config) # 执行至审批节点暂停
graph.invoke(Command(resume={"approved": True}), config) # 审批后精确续跑interrupt 暂停时保留的不只是消息历史,而是完整的图状态、工具调用结果和中间决策。审批人离开八小时后回来,系统从暂停点继续,消耗零计算资源等待期间。Checkpoint 的语义是执行契约:一次运行要么到达终态,要么停留在可恢复的断点上,没有“丢失进度”的中间态。
Intuit 的失败直接对应一个设计决策:Agent 之间传递什么。自然语言交接要求下游 Agent 推断上游的推理过程,推断本身引入噪声,而噪声在链条中逐跳放大。企业级系统必须把交接定义为结构化数据包,包含任务、约束、已验证的事实和明确的验收条件,而不是一段描述性的文字。Microsoft Agent Framework 的 handoff 模式提供了一个可借鉴的约束:每次交接遵循强制 schema,接收方验证后才能接管。更严格的实现还要求同一时刻只有一个 Owner,Owner 转移是原子的,每次交接有唯一 handoff_id,失败可回滚。
from pydantic import BaseModel
from typing import Literal
class HandoffPacket(BaseModel):
task_id: str
handoff_id: str
from_agent: str
to_agent: str
goal: str
constraints: list[str] # 必须遵守的业务/合规约束
verified_facts: dict[str, Any] # 上游已验证的事实,下游不得重新推断
acceptance_criteria: list[str] # 下游完成后必须满足的条件
trace_ref: str # 指向完整推理 trace 的引用,而非全文
def handoff(packet: HandoffPacket, owner_lock: OwnerLock):
owner_lock.assert_current(packet.from_agent) # 原子性校验
owner_lock.transfer(packet.from_agent, packet.to_agent)
return agent_registry[packet.to_agent].accept(packet) # schema 验证后接管关键不在 BaseModel 本身,而在于 verified_facts 和 acceptance_criteria 是下游 Agent 必须接受的事实,而非需要重新解释的输入。推理 trace 通过 trace_ref 引用而非嵌入,避免上下文膨胀。自然语言仍然可以出现在 Agent 与用户的交互层,但 Agent 之间的控制流必须走结构化契约。
提示词和 System Message 不是权限边界。企业级架构必须在每一次模型/工具调用之前放置一个策略执行点(PEP),由独立的策略决策点(PDP)做出 ALLOW / REQUIRE_APPROVAL / DENY 的确定性裁决。策略以数据形式存在,封禁一类操作是修改策略表并下发,秒级生效,不走代码发布。
def authorize_tool(tool: str, args: dict, ctx: dict) -> str:
decision = pdp.evaluate(
principal=ctx["agent_identity"], # Agent 实例身份,非终端用户身份
action=tool,
resource=args.get("target"),
session_taint=ctx["taint"], # 会话级污点:是否接触过敏感数据
context=ctx,
)
if decision.effect == "DENY":
raise PermissionDenied(decision.rule_id, decision.reason)
if decision.effect == "REQUIRE_APPROVAL":
return "pending" # 进入人工闸门,不是模型自行决定
return "allowed"session_taint 是容易被忽略但关键的一层:红队已经证明“读文件(只读,放行)→ 注入内容诱导 HTTP 外发(常规工具,放行)”的组合链,每一步单独合规,串起来是数据外渗。会话级污点标记让 PEP 在组合层面阻断,而不是逐工具审查。同时,principal 必须是 Agent 实例的身份,而非终端用户的身份——Agent 以谁的名义行动、权限如何下沉到下游资源,是身份链设计的核心问题。
成本熔断和循环检测必须在调用发生之前拒绝,而非事后告警。开源的 budget-guard-agents 提供了 per-task 预算、循环检测和 kill-switch 的中间件模式:重复的相同调用触发 LoopDetected,预算耗尽触发 BudgetExceeded,均以异常形式阻断执行流。评估闭环则要求把生产失败转化为 CI 门禁:Golden Dataset 回归,通过率低于阈值或出现回归时阻止发布,安全类用例一票否决。Schneider Electric 以 350 人的 AI Hub 支撑 60 多个 Agent,其 LLMOps 纪律正是围绕可观测性、评估和部署建立起来的。
Intuit 两次重建架构的经历说明了一个容易被低估的事实:企业级智能体系统的核心设计对象不是 Agent,而是 Agent 之间、Agent 与资源之间的确定性边界。持久化执行保证任务不会因中断而丢失,结构化交接契约保证规模不放大错误,策略执行点保证模型无法绕过权限。三者叠加,Agent 的“智能”才有机会被可靠地交付到生产环境中。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。