Agent

精读 12 条构建生产级 AI Agent 的实战指南(下)

发布于 2025年7月22日

引言

我在过去一年里构建了十几个不同类型的 Agent 应用。期间踩了无数坑:Agent "失忆"、工具调用失败、提示词效果不稳定等等问题

直到我看到了 HumanLayer 团队总结的"12 条构建可靠 AI 应用的实践原则",很多困扰我的问题终于有了系统性的解决方案。它们可能会让你的 Agent 能力提升 10 倍。

这是实战指南的下半部分。如果你想看前 6 条原则,请移步 精读 12 条构建生产级 AI Agent 的实战指南(上)

12 条实践原则

7. 通过工具调用(Tool Call)连接人类的交互

Agent 与人类的交互也应该视为一种标准的工具调用(Tool Call)

这种方法能构建出更可靠、可持久化、支持异步交互的复杂智能体工作流,尤其适用于需要人类审批或干预的自动化任务。

如下 request_human_input 是一个用来与人类交互的 tool。你的 Agent 可以"暂停"等待人类响应,然后无缝恢复工作。

<request_human_input>
  intent: "request_human_input"
  question: "你想将 v1.2.3 版本部署到生产环境吗?"
  context: "这将会影响真实的用户."
  options: {
    urgency: "high"
    format: "yes_no"
  }
</request_human_input>

<human_response>
  response: "是的,请继续"
  approved: true
  timestamp: "2024-03-15T10:30:00Z"
  user: "alex@company.com"
</human_response>

另外应该让 LLMs 始终输出包含意图(intent)的结构化数据。比如你问“今天杭州天气怎么样?”,LLMs 可能回答“杭州今天....”,也可能调用 fetch_weather 工具,这使得系统难以预测。

让 LLMs 的每个输出都带上明确的意图标识。这样你的代码就能轻松处理各种情况:

<final_answer>
  intent: "final_answer"
  message: "杭州今天...."
</final_answer>
<fetch_weather>
  intent: "fetch_weather"
  city: "杭州"
</fetch_weather>

这是一种意图-执行分离的设计模式,LLMs 负责决策,代码负责执行。干净利落。

8、自主控制工作流

根据具体使用场景,构建适合需求的自定义工作流。特别是需要跳出循环、等待人工响应或其他长时间运行的任务。你还能实现:

  • 工具调用结果的汇总、缓存
  • 使用其他 LLMs 评估输出的质量
  • 实现更精细的上下文管理、内存管理
  • 日志记录、追踪与指标
  • 在 Agent 端实现对 API 调用的速率限制
  • 实现 Agent 的可靠暂停

我们可以在一个 while 循环中控制工作流,其中有三个关键的分支逻辑:

  • 请求澄清(异步中断) request_clarification: 当 Agent 需要人类提供更多信息,向人类发送消息,保存状态,跳出循环。(后续会再触发继续的流程)
  • 执行工具 (同步循环) fetch_open_issues: 需要调用工具时执行,continue 进入下一个循环
  • 请求审批 (异步中断) create_issue: 当 Agent 想要执行高风险操作时,像人类发起审批,保存状态,跳出循环
while True:
  if intent = 'request_clarification':
    // Do something
    send_message_to_human;
    save_thread;
    break;
  if intent = 'fetch_open_issues':
    // Do something
    continue;
  if intent = 'create_issue':
    // Do something
    request_human_approval
    save_thread;
    break;

这种高度自定义的工作流可以避免等待长时间的 sleep 时进程中断状态丢失、不可控的 YOLO 等问题。

9、压缩错误信息到上下文

通过将工具执行失败的错误信息压缩后放到上下文中,赋予 Agent “自我修复”的能力。

示例代码如下,考虑将错误信息在 format_error 进行处理压缩。

  # ...
  except Exception as e:
    thread["events"].append({
      "type": 'error',
      "data": format_error(e),
    })

你还可以实现错误重制,添加一个错误次数计数器,比如处理错误超过 3 次之后交给人类解决。

优点:

  • 自我修复:LLMs 可以读取错误消息,并根据错误调整重试
  • 持久性:即使工具调用失败了,Agent 可以继续运行

10、构建小型、专注的 Agent

LLMs 有局限性,在大型的复杂的任务中更容易出错,超长的上下文容易迷失准确的目标。应该让 Agent 专注于特定的领域,常见的实践在 3-10(最多20) 个步骤,让它更加可控。

主要优势:

  • 可控的上下文:LLMs 表现会更好
  • 明确的职责:每个 Agent 都有明确的目标
  • 高可靠性:在复杂的工作流中不易“迷失”
  • 简化测试:更容易对特定功能进行测试和验证
  • 更好调试:出现问题时,更容易定位和修复

即使未来 AI 能处理更长的上下文,我依然推荐这个做法。因为小型 Agent 更容易组合成多 Agent 系统。

11、预取上下文

有些信息需要模型通过调用工具来获取,但是你可以通过代码预取后放入上下文。一次来减少 token 消耗(省钱)。

下面举一个例子:

你是一个xxx

{{ 历史对话 }}


{
  intent: '获取系统信息'
},
{
  intent: '其他工具'
},

获取系统信息是你提供的一个 tools,但是我们可以预先就提供系统信息。改成这样:

你是一个xxx。

用户的系统为 MacOS,xxxx

{{ 历史对话 }}

{
  intent: '其他工具'
}

省掉一次工具调用,就是省掉一笔费用。前提是你已经知道希望模型调用哪些工具,并且确定会调用。让 LLMs 去做复杂的事情。

12、从任何地方触发 Agent

让你的 Agent 可以从任何地方被触发。

邮件、网页、社交工具、定时任务、监听事件...你能想到的渠道,都应该能启动你的 Agent。这样做的好处显而易见:

  • 随时随地接入:用户在哪里,Agent 就在哪里
  • 自动化程度更高:不只是人工触发,系统事件也能启动
  • 集成能力更强:可以连接各种工具和平台

总结

这 12 条原则不是教条,而是无数次踩坑后的血泪总结。希望这些内容能让你少走一些弯路。 如果你觉得这篇文章对你有帮助,欢迎点赞、分享,你的支持是我持续创作的最大动力!

相关资源: