你以为的 AI Agent 开发:写好 Prompt,坐等结果。
实际的 AI Agent 开发:加了 500 字规则,Agent 还是跳步骤;加到 1000 字,它开始忘记发邮件;加到 2000 字,token 费用让你怀疑人生。


一、引子:我也曾是 Prompt 加长党

我记得第一次认真搭 AI Agent 的时候,充满信心地写下了一段 System Prompt:

你是一个图书馆管理助手。在续借书籍之前,必须先检查书的状态。续借完成后,必须发送确认邮件给用户……

跑了十次,七次正常,三次翻车——有时跳过了状态检查,有时忘了发邮件。

于是我加更多规则。规则越加越长,Agent 的表现时好时坏,像一个靠心情上班的实习生。

这不是我一个人的故事。这是 2026 年大多数 AI Agent 开发者的日常。


二、Prompting 跑步机:越跑越累,原地踏步

我把这个现象叫做 “Prompting 跑步机”——你在不断地跑,消耗大量精力,但实际上没有前进。

为什么 Prompt 工程有天花板?

大语言模型的本质是概率采样。无论你的 Prompt 写得多精确,它都是在"建议"模型去做某件事,而不是"命令"。

这里有几个根本性问题:

1. 注意力衰减:Prompt 越长,模型对后半段规则的遵守率越低。你加了 20 条规则,模型到第 18 条可能已经"走神"了。

2. 规则冲突:随着规则增多,它们之间开始相互矛盾。模型会按照自己的"理解"来取舍,而不是按你的意图。

3. 上下文污染:在多轮对话中,用户的输入会逐渐"覆盖"你的 Prompt 效果。用户说"快点,不用确认了",Agent 可能真的就跳过确认步骤了。

4. 无法测试:你怎么单元测试一段自然语言 Prompt?几乎不可能写出确定性的测试用例。

结论:Prompt 工程能把你带到 80%,但那最后的 20% 是它够不到的地方。

根本原因在于:你用自然语言写的规则,在模型眼里和用户说的话是同等地位的"文本"。可靠的 Agent 行为,需要代码级别的保障,而不仅仅是语言级别的祈祷。

下面这组实验数据,会让你对这句话有具体感受。


三、四种方案横向对比:数据说话

AWS 在开源 Strands Agents SDK 时,做了一个非常扎实的评估实验:设计了一个图书馆续借场景,用 600 次自动化测试对比了五种行为控制方案。
在这里插入图片描述

实验场景包含多种混合请求(查询 + 续借、单纯续借、无效操作等),每次测试都验证 Agent 是否完整执行了正确的步骤序列。

结果如下:

方案 通过率 平均输入Token 平均输出Token 特点
无指令(基线) 15.7% 1,870 401 什么都不说,AI 自由发挥
简单 Prompt 指令 82.5% 2,329 430 最常见方案,有明显上限
SOP 文档 99.8% 9,879 459 准确率高但 token 成本爆炸
Steering Hooks 100.0% 3,346 598 最优平衡点
Graph 工作流 80.8% 3,116 1,125 固定流程好用,混合场景崩溃

几个值得关注的数字:

  • SOP 文档能达到 99.8%,但平均输入 Token 高达 9,879——是 Steering Hooks(3,346)的近 3 倍。在高并发场景下,这个差距会直接体现在账单上。

  • Graph 工作流看起来不错(3,116 Token),但通过率只有 80.8%,比简单 Prompt 还低一点点。原因在于它太"死板"——遇到混合请求就不知道怎么办了。

  • Steering Hooks 以适中的 Token 消耗,实现了 100% 的通过率。这个数字不是统计意义上的"约等于100%",是字面意义上的 600/600。
    在这里插入图片描述


四、Steering 机制深度解析:它到底是什么魔法?

Steering Hooks 的核心思想其实非常朴素:不在事前把所有规则塞进 Prompt,而是在运行时"即时介入"。

就像一个有经验的老师傅带徒弟——不是在出发前把所有情况都预讲一遍,而是在关键节点上实时提醒:“等等,你得先检查书的状态。”
在这里插入图片描述

4.1 两个拦截点

Strands Agents SDK 提供了两个核心钩子:

  • steer_before_tool:在 Agent 调用工具之前触发。此时你可以检查"即将发生什么",如果条件不满足,可以拦截并给出指导(Guide),或者放行(Proceed)。

  • steer_after_model:在 模型生成响应之后触发。此时可以检查模型的输出是否符合预期,比如语气是否合适、内容是否完整。

这两个钩子覆盖了 Agent 推理循环中最关键的两个时机。

4.2 初始化:把 Handler 装进 Plugins

# 创建 Agent 时,将多个 handler 作为 plugins 传入
# 每个 handler 负责一个关注点,像插件一样可拔插
agent = Agent(
    tools=tools,
    system_prompt=system_prompt,  # system_prompt 保持简洁
    plugins=[
        renewal_workflow_handler,       # 控制续借流程顺序
        confirmation_workflow_handler,  # 控制确认邮件流程
        confirmation_tone_handler,      # 控制确认消息的语气
        model_tone_handler,             # 控制模型整体回复风格
    ],
)

注意:每个 handler 只负责一件事。这是单一职责原则在 Agent 设计中的具体体现。你可以自由组合、单独测试每一个 handler。

4.3 核心 Handler:工作流验证(原文完整版)

下面是原文中 steer_before_tool 的完整实现,用于确保续借流程的步骤顺序正确、数据来源可信:

async def steer_before_tool(
    self, *, agent, tool_use, **kwargs
):
    # Only validate renewal attempts
    if tool_use.get("name") != "renew_book":
        return Proceed(reason="Not a renewal tool call")

    # Get the history of tool calls from the ledger
    ctx = self.steering_context.data.get()
    ledger = ctx.get("ledger", {})
    tool_calls = ledger.get("tool_calls", [])

    # Was book status verified first?
    status_checked = any(
        c["tool_name"] == "get_book_status"
        and c["status"] == "success"
        for c in tool_calls
    )

    if not status_checked:
        return Guide(
            reason="Check book status before renewing."
            " Use get_book_status first, then retry."
        )

    # Is the book recalled?
    for c in tool_calls:
        if (
            c["tool_name"] == "get_book_status"
            and c["status"] == "success"
        ):
            result = json.loads(c["result"][0]["text"])
            if result.get("status") == "RECALLED":
                return Guide(
                    reason="Cannot renew a RECALLED book."
                )

    # Does the library card match the user's actual card?
    renewal_card = tool_use.get("input", {}).get(
        "library_card_number"
    )
    for c in tool_calls:
        if (
            c["tool_name"] == "get_user_info"
            and c["status"] == "success"
        ):
            result = json.loads(c["result"][0]["text"])
            user_card = result["library_card_number"]
            if renewal_card != user_card:
                return Guide(
                    reason=f"Wrong library card."
                    f" Use {user_card} instead."
                )

    return Proceed(reason="Workflow validation passed")

这段代码是纯 Python,完全确定性,零 LLM 调用。它做了三重验证:

  1. 步骤顺序:续借前必须先调用 get_book_status
  2. 业务规则:被召回(RECALLED)的书不能续借
  3. 数据真实性:图书馆卡号必须来自 get_user_info,不能用用户自报的值(防幻觉、防注入)

4.4 Handler:用 LLM 检查语气

对于"语气是否积极"这类难以用代码规则表达的需求,Steering 支持用另一个 LLM 作为裁判:

async def steer_after_model(
    self, *, agent, message, stop_reason, **kwargs
):
    if stop_reason != "end_turn":
        return Proceed(reason="Not a final response")

    text = " ".join(
        block.get("text", "")
        for block in message.get("content", [])
    )

    # Run an LLM judge agent to evaluate tone
    steering_agent = Agent(
        system_prompt=TONE_PROMPT,
        model=steering_model,
    )

    result = steering_agent(
        f"Evaluate this message:\n\n{text}",
        structured_output_model=ToneDecision,
    )

    if result.structured_output.decision == "guide":
        return Guide(reason=result.structured_output.reason)

    return Proceed(reason="Tone check passed")

这个 handler 在模型生成响应之后触发,用一个独立的小 LLM 来评估语气。如果语气不符合要求,返回 Guide 让主模型重新生成。确定性规则 + LLM 裁判,两种策略组合使用

几个关键设计亮点:

  1. Ledger 机制:SDK 自动记录每次工具调用的名称、输入、输出和状态,你不需要手动维护状态机。完整的调用历史就在 ledger["tool_calls"] 里。

  2. 三种返回值Proceed(放行)、Guide(软纠偏,模型重新规划)、还有 Interrupt(硬中断)。Guide 是最常用的——它不报错,只是给模型一个方向。

  3. 可组合性:多个 handler 作为 plugins 串联执行,各司其职,可以独立单元测试。


五、失败案例解剖:简单 Prompt 为什么不够用?

回到那个图书馆实验,让我们看看简单 Prompt 指令(82.5% 通过率)是如何失败的:

失败原因分布:

  • 43% 的失败:Agent 跳过了状态检查,直接尝试续借。原因是用户的请求很直接(“帮我续借《深入理解计算机系统》”),模型判断"任务明确,无需额外检查"。
  • 40% 的失败:Agent 完成续借后忘记发确认邮件。原因是模型认为"主要任务完成了",后续步骤在紧凑的推理中被省略。

这两个失败模式揭示了 Prompt 控制的本质局限:模型是在用"理解"来执行规则,而不是在"强制执行"规则。

当用户的表达与规则之间存在隐性冲突时,模型往往选择满足用户的显性需求,而忽略规则中的隐性要求。

更深层的原因是:Prompt 中的规则在模型看来,和用户说的话是同等地位的"文本"。当用户强烈表达了某个意图,模型会在"遵守规则"和"满足用户"之间做权衡——而这个权衡的结果是概率性的,不可预测的。

你可能今天跑出 90%,明天换个用户措辞就跌到 70%。这种不稳定性,在生产环境中是致命的。

Graph 工作流的失败则更有意思:在定义好的单一流程中,它表现不错(96.6%);但当用户发出"查询 + 续借"的混合请求时,Graph 直接崩了——因为它没有处理这种组合的节点路径。固定图结构的代价,是对多样性的零容忍。

这个场景很典型:用户说"帮我查一下《深入理解计算机系统》还能借多久,顺便帮我续一下"。这是一个完全合理的自然语言请求,但预定义的工作流图里没有"先查后续"这条路径,Agent 就懵了。

Steering Hooks 因为是"运行时介入"而非"预定义流程",可以优雅地处理各种混合场景。无论用户的请求多么随机,只要满足了业务规则,就放行;不满足,就纠偏。这才是真正的灵活与可靠并存。


六、决策指南:什么时候用什么方案?

不是所有项目都需要 Steering Hooks。这里给一个清晰的选择框架:

用简单 Prompt 指令,当:

  • ✅ 场景简单,步骤少(1-3步)
  • ✅ 对准确率要求不高(85% 以上够用)
  • ✅ 快速原型,还在验证方向
  • ❌ 不适合:生产环境、有法务/合规要求、步骤有严格顺序依赖

用 SOP 文档,当:

  • ✅ 流程非常复杂,需要详细的上下文说明
  • ✅ Token 成本不敏感(内部工具、低频场景)
  • ✅ 团队有大量现成的 SOP 文档可复用
  • ❌ 不适合:高并发场景、成本敏感型应用

用 Graph 工作流,当:

  • ✅ 流程完全固定,没有分支和意外情况
  • ✅ 需要可视化流程图(给非技术人员展示)
  • ✅ 每个节点都有明确的输入输出定义
  • ❌ 不适合:需要处理多种混合请求、流程动态变化的场景

用 Steering Hooks,当:

  • ✅ 准确率要求高(95%+),生产环境
  • ✅ 流程有步骤依赖(A 必须在 B 之前)
  • ✅ 需要可测试、可维护的控制逻辑
  • ✅ 场景多样,包含混合请求
  • ✅ Token 成本需要控制(优于 SOP)
  • ❌ 不适合:超简单场景(杀鸡用牛刀)

一句话原则:如果你的 Agent 要上生产,并且有任何步骤顺序要求,请认真考虑 Steering Hooks。


七、总结:Steering 不是银弹,但它是目前的最优解

让我们最后做一次清醒的评估。

Steering Hooks 确实解决了 Prompt 工程的核心痛点:它将行为控制从"语言层"移到了"代码层",从"概率性建议"变成了"确定性拦截"。600 次测试全部通过,不是运气,是机制。

但它也不是万能的

  • 需要开发者理解 Agent 的推理循环(学习曲线存在)
  • Handler 需要维护,随业务变化需要更新
  • 对于简单场景,反而是过度设计

我的建议

  1. 新项目先用简单 Prompt,快速验证方向。不要一上来就过度设计,简单 Prompt 能带你走到 80%,这个阶段够用了。

  2. 出现"规律性出错"就引入 Steering。当你发现"每次在某个步骤 Agent 都会犯同样的错误",这就是 Steering Hooks 的用武之地。把那个规律,从 Prompt 文字变成确定性的 Python 判断。

  3. 每个 Handler 必须有单元测试。这是 Steering Hooks 相比 Prompt 最大的工程优势。你可以 mock 一个 tool_use,验证 handler 的返回值,完全不需要跑真实的 LLM。

  4. 保持 Handler 细粒度。不要把所有逻辑塞进一个 handler,就像你不会把所有业务逻辑塞进 main() 函数一样。一个 handler,一个关注点。

  5. 监控 Ledger 数据。Strands SDK 的 Ledger 机制记录了每次工具调用的详细信息,这是排查 Agent 行为问题的金矿。生产环境一定要把 Ledger 数据持久化。

AI Agent 开发正在从"Prompt 魔法"走向"工程化"。但这条路的难点不是技术——技术已经有了——而是承认"写更多 Prompt"已经不是正确答案这件事

很多团队还在 Prompting 跑步机上跑着,只是因为没人愿意停下来说:我们在用错误的工具解决问题。

有意思的是,AWS 选择把这个机制做成开源 SDK,而不是封装成黑盒服务。这背后的信号是:Agent 可靠性不是一个"托管就能解决"的问题,它需要开发者深度介入。这既是挑战,也是护城河。

你现在的 Agent,是在第几步出错的?

把那个规律性的"坑",从 Prompt 文字变成一个 steer_before_tool。可能只需要 10 行代码,你就能从 82% 跳到 100%。

欢迎在评论区说说你 Agent 最常翻车的步骤——说不定你的案例可以写成下一篇。


参考资源


本文基于 AWS Strands Agents SDK 官方评估数据撰写,实验数据来自 600 次自动化测试。


Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐