Paper

LedgerAgent 论文速读:结构化状态让工具调用 Agent 严格遵守业务策略

6 min read ·

一句话总结:LedgerAgent 的洞察很简单——把 Agent 需要遵守的约束从「放在 Prompt 里希望它记住」变成「存在外部结构里每次调用前强制检查」。这个改变小,但对策略遵从问题效果显著。

论文背景

论文标题:LedgerAgent: Structured State for Policy-Adherent Tool-Calling Agents

作者:Md Nayem Uddin, Amir Saeidi, Eduardo Blanco, Chitta Baral(Arizona State University / University of Arizona)

发表日期:2026-06-19(arXiv cs.CL / cs.AI)

评测基准τ²-bench(tau2-bench)和 τ-Trait(tau-Trait)

客服 AI 是工具调用 Agent 最典型的应用场景之一:用户发起对话,Agent 通过调用工具(查询订单、修改数据库、触发退款流程)来完成请求,同时需要遵守一系列业务规则(退款仅限 30 天内、VIP 用户可享受豁免、库存不足时不能承诺发货等)。

这个场景乍看简单,但对 Agent 能力的要求实际上很高:它需要在跨越多轮对话的过程中,同时追踪用户目标、当前数据库状态、已执行的操作以及适用的策略约束——任何一个遗漏都可能导致错误的决策。

现有方法的根本缺陷

在标准工具调用 Agent 中(无论是 ReAct 还是 Function Calling),状态管理依赖 LLM 的上下文窗口。这带来了几个结构性问题:

策略约束的「稀释」:随着对话轮次增加,早期对话中建立的约束信息被后续内容稀释。LLM 更倾向于关注最近的上下文,可能在第 10 轮对话中「忘记」第 2 轮确认的限制条件。

工具调用结果的积累混乱:多次工具调用的结果以对话消息形式堆积在上下文中,模型需要在这些非结构化记录中提取当前系统状态,这既费上下文,也容易出错。

策略与任务的混淆:Policy 文档(规定了什么可以做、什么不能做)和任务状态(用户想做什么、当前进展如何)被混在一起,模型在推理时需要同时处理两个维度,认知负担高。

LedgerAgent 的核心假设是:状态管理是一个确定性问题,不应该依赖概率性的 LLM 上下文记忆。

Ledger:显式结构化状态

Ledger 是 LedgerAgent 的核心数据结构,是独立于 LLM 上下文的持久化对象。

Ledger 的结构

# 简化的 Ledger 结构
@dataclass
class Ledger:
    # 观察到的事实(通过工具调用获取)
    facts: dict[str, Any]
    # e.g., {"user_id": "U123", "order_status": "delivered", 
    #        "order_date": "2026-05-20", "user_tier": "standard"}
    
    # 从策略文档提取的约束条件
    constraints: list[Constraint]
    # e.g., [Constraint("return_within_30_days", 
    #                   condition="order_date within 30 days of today")]
    
    # 条件满足状态(已验证/未验证/不满足)
    condition_status: dict[str, ConditionStatus]
    # e.g., {"return_within_30_days": SATISFIED,
    #        "product_unopened": UNVERIFIED}
    
    # 本次会话的操作日志
    action_log: list[ToolCall]

Ledger 的生命周期

初始化:会话开始时,Ledger 从两个来源初始化:

  1. 业务策略文档(Policy):结构化提取适用于当前会话的约束条件
  2. 用户请求:提取用户的核心目标

更新:每次工具调用执行后,工具返回的结果直接写入 facts 字典,相关的 condition_status 同步更新。这是确定性操作,不经过 LLM。

决策检查:每次 LLM 提议执行一个工具调用前,系统检查 Ledger:

如果存在冲突或未验证条件,系统会拦截 LLM 的提议,强制要求先解决问题。

策略提取:从文档到结构

把非结构化策略文档转化为 Ledger 约束是系统的关键步骤。论文使用一次性的 LLM 提取(在会话开始时,不在每轮调用时),把策略文档解析为结构化约束:

输入: "退款政策:用户须在收到商品后 30 天内提出申请。商品须未开封。VIP 用户退款期延长至 60 天。"

输出: [
  Constraint(name="return_period",
             standard="order_date + 30 days >= today",
             vip_override="order_date + 60 days >= today"),
  Constraint(name="product_condition",
             requirement="product_status == 'unopened'")
]

这个提取步骤只在策略文档变更时重新执行,不是每次会话的额外开销。

推理流程:Ledger-Guided Tool Selection

LedgerAgent 的推理循环与标准 ReAct 有一个关键差异:

标准 ReAct

LLM → 推理 → 决定工具调用 → 执行 → 观察 → 循环

LedgerAgent

LLM → 推理 → 提议工具调用 → Ledger 检查 → 
  [通过] → 执行 → 更新 Ledger → 循环
  [拦截] → 将冲突信息加入上下文 → LLM 重新推理

Ledger 检查是确定性的(查表,不调用 LLM),因此不增加延迟。拦截时注入的冲突信息帮助 LLM 理解为什么当前提议不可行,而不是简单地报错。

实验设置与结果

评测基准

tau2-bench:由 AI 研究者构建的客服 Agent 基准,包含航空、电商、保险等多个领域的任务,每个任务包含用户目标、初始数据库状态、业务策略和工具集。评测指标:任务完成率(Task Success Rate)和策略遵从率(Policy Adherence Rate)。

tau-Trait:更细粒度地评测 Agent 在各类策略约束下的行为,包含约束感知(是否知道约束存在)、约束遵从(是否按约束行动)和约束解释(能否向用户解释约束原因)三个维度。

主要结果

方法任务完成率策略遵从率
基于提示的工具调用 baseline62.3%71.5%
ReAct + 策略摘要65.1%74.8%
LedgerAgent74.8%89.3%

策略遵从率的提升(+17.8 个百分点)比任务完成率的提升(+12.5 个百分点)更显著,符合 Ledger 的设计目标——主要提升策略遵从,顺带改善任务完成。

分析:提升在策略复杂度高(多条件、有例外情况)的任务上最显著。在策略简单(单一条件)的任务上,LedgerAgent 与 baseline 差距较小——这验证了 Ledger 的价值主要在处理复杂约束交互时。

工程层面的实现考虑

将 LedgerAgent 的思路应用到实际系统需要解决几个工程问题:

策略提取的鲁棒性:真实业务的策略文档往往更复杂、更模糊,LLM 的一次性提取可能有遗漏或误读。建议在首次提取后加入人工验证环节,把提取结果当成配置来管理(版本控制、变更审计)。

Ledger 的序列化与持久化:在生产级多轮对话服务中,Ledger 需要在请求之间持久化(Redis、数据库),确保会话中断后可以恢复。

与现有工具调用框架集成:LedgerAgent 可以在现有 Function Calling 框架(如 LangChain、LlamaIndex)的基础上加入 Ledger 作为一个中间件层,不需要重写整个 Agent 架构。

适用场景的延伸

论文聚焦于客服 AI,但 Ledger 的思路可以推广到更广泛的场景:

医疗 Agent:追踪患者过敏史、药物禁忌、诊断标准等约束,确保 AI 辅助问诊不违反医疗规范。

金融合规 Agent:实时追踪合规规则(KYC 状态、交易限额、风险评级),在 Agent 建议操作前确保合规检查通过。

代码 Agent 的架构约束:类似 LedgerAgent 对策略约束的显式追踪,代码 Agent 可以用 Ledger 追踪代码库的架构规范(如「服务间通信必须通过 API Gateway」、「数据库访问仅限 Repository 层」),在生成代码前做确定性检查。

局限

策略提取质量:Ledger 的质量取决于初始策略提取的质量。如果提取漏掉了某个约束,Ledger 无法检测到违反该约束的工具调用——这是「垃圾进,垃圾出」问题。

动态策略:当前实现假设策略在会话中是静态的。实际业务中,策略可能在会话中间变更(如在线促销突然结束),需要额外的机制处理策略的动态更新。

增加的系统复杂度:引入 Ledger 意味着增加一个额外的持久化组件和策略提取步骤,对于策略简单的应用场景,这个复杂度不一定值得。

结语

LedgerAgent 的贡献不在于提出了复杂的新架构,而在于识别了一个具体的、被常规方法忽视的问题:在多轮工具调用 Agent 中,策略约束不应该依赖 LLM 的上下文记忆。

把状态管理从概率性的 LLM 记忆转移到确定性的结构化存储,是一个符合软件工程直觉的设计决策——我们不会把数据库的事务状态放在自然语言文本里靠 AI 记忆,那为什么要把 Agent 的约束状态放在 Prompt 里靠 LLM 记忆?

对于正在构建需要策略遵从能力的 Agent 系统的工程团队,这篇论文提供了一个清晰、可实现的架构参考。

Frequently asked questions

LedgerAgent 解决的核心问题是什么?
在客服等业务场景中,Agent 必须同时做到两件事:完成用户的任务目标(如退款、换货),同时遵守公司的业务策略(如退款期限、VIP 政策、库存限制)。标准工具调用 Agent 把所有这些信息都塞在 Prompt 里,随着对话推进容易「忘记」或「忽略」某些策略约束。LedgerAgent 用一个持久化的结构化状态(Ledger)显式追踪这些约束,确保每次工具调用都在策略边界内
Ledger 是什么,它包含哪些信息?
Ledger 是一个结构化的内存对象,在 Agent 的整个会话生命周期中持续更新。它包含三类信息:观察到的事实(用户身份、订单状态、当前数据库状态);从策略文档提取的约束(退款期限、适用条件);已满足和未满足的条件(哪些前置条件已经验证,哪些还需要工具调用来验证)。每次工具调用的结果都会更新 Ledger,不依赖 LLM 的上下文记忆
LedgerAgent 和 ReAct、工具调用的常规做法有什么本质区别?
ReAct 和常规工具调用把「我知道什么」(状态)和「我在做什么」(推理)都放在同一个 LLM 上下文里,依赖模型的上下文窗口来记住历史。LedgerAgent 把状态外置:Ledger 是独立于模型上下文的结构化对象,即使在很长的多轮对话中,策略约束也不会因为上下文压缩而丢失
LedgerAgent 的实验结果如何?在什么任务上测试?
在 tau2-bench(多领域客服 Agent 基准)和 tau-Trait(策略遵从能力评测)上测试。相比基于提示的工具调用 baseline,LedgerAgent 在策略遵从率上提升约 15-22 个百分点,在任务完成率上提升约 8-15 个百分点。提升在策略复杂度高的任务类别上最显著
LedgerAgent 的方法可以用在非客服场景吗?
可以,任何需要 Agent 在多轮交互中遵守固定约束集的场景都适用:法律合规审查 Agent、医疗预问诊 Agent、金融交易 Agent 等。核心需求是「有明确的规则或策略文档,且 Agent 的每次动作都应该符合这些规则」。代码类 Agent(如 Claude Code)也可以类似地用 Ledger 追踪代码库的架构约束
// next.txt ›

Some outbound links in this post are affiliate links — see disclosure.