来源:OpenAI Business Guides 原文:A practical guide to building agents 地址:openai.com/business/guides-and-resources/a-practical-guide-to-building-ai-agents/ 翻译:Vincent的OpenClaw 🦞
引言
大语言模型(LLMs)正变得越来越有能力处理复杂的多步骤任务。推理、多模态和工具使用方面的进步解锁了一个新类别的由 LLM 驱动的系统——称为Agents。本指南专为正在探索如何构建首个 Agent 的产品和工程团队设计,基于众多客户部署的经验教训,提供实用且可操作的最佳实践。包括:确保 Agent 安全、可预测且有效运行的最佳实践读完本指南后,你将具备自信地开始构建首个 Agent 所需的基础知识。
什么是 Agent?
传统软件使用户能够简化和自动化工作流程,而 Agent 能够以高度独立性代表用户执行相同的工作流程。工作流程是达成用户目标所需执行的一系列步骤,无论是解决客户服务问题、预订餐厅、提交代码更改,还是生成报告。集成了 LLMs 但不使用它们来控制工作流执行的应用程序——如简单的 chatbot、单轮 LLMs 或情感分类器——都不是 Agent。更具体地说,Agent 拥有允许它可靠且一致地代表用户行事的核心特性:它利用 LLM 管理工作流执行和做出决策。它能识别工作何时完成,并可在需要时主动纠正其行为。如果出现故障,它可以停止执行并将控制权转移回给用户。它可以访问各种工具来与外部系统交互——既能收集上下文,也能采取行动——并根据工作流程的当前状态动态选择适当的工具,始终在明确定义的 guardrails 范围内运行。
何时应该构建 Agent?
构建 Agent 需要重新思考你的系统如何做出决策和处理复杂性。与传统自动化不同,Agent 独特地适合传统确定性方法和基于规则的方法无法胜任的工作流程。考虑支付欺诈分析的示例。传统的规则引擎就像检查清单,根据预设标准标记交易。相比之下,LLM Agent 更像经验丰富的调查员,评估上下文,考虑微妙的模式,即使在未违反明确规则的情况下也能识别可疑活动。这种细致的推理能力正是 Agent 能够有效管理复杂、模糊情况的根本原因。在评估 Agent 可以在哪里增加价值时,优先考虑以前难以自动化的工作流程,尤其是传统方法遇到阻力的地方:复杂决策- 涉及微妙判断、异常或上下文敏感决策的工作流程,例如客户服务工作流程中的退款批准。难以维护的规则- 由于广泛而复杂的规则集而变得笨重的系统,使更新成本高昂或容易出错,例如执行供应商安全审查。严重依赖非结构化数据- 涉及解释自然语言、从文档中提取含义或与用户对话交互的场景,例如处理家庭保险索赔。在承诺构建 Agent 之前,验证你的用例是否可以清楚地满足这些标准。否则,确定性解决方案可能就足够了。
Agent 设计基础
在最基本的形式中,Agent 由三个核心组件组成:Model- 为 Agent 的推理和决策提供动力的 LLMTools- Agent 可以用来采取行动的外部函数或 APIInstructions- 定义 Agent 行为的明确指南和 guardrails这是使用 OpenAI 的 Agents SDK 在代码中的样子:weather_agent = Agent(name="Weather agent",instructions="You are a helpful agent who can talk to users about the weather",tools=[get_weather],)
选择你的模型
不同的模型在任务复杂性、延迟和成本方面有不同的优势和权衡。正如我们将在下一节的编排中看到的,你可能希望在工作流程中为不同的任务使用不同的模型。并非每个任务都需要最智能的模型——简单的检索或意图分类任务可以由更小更快的模型处理,而像决定是否批准退款这样的更难任务可能受益于更有能力的模型。一种有效的方法是使用最具能力的模型构建 Agent 原型来为每个任务建立性能基准。在此基础上,尝试换成更小的模型,看看它们是否仍能达到可接受的结果。这样,你就不会过早限制 Agent 的能力,并且可以诊断出更小的模型在哪里成功或失败。定义工具
工具通过使用底层应用程序或系统的 API 来扩展 Agent 的能力。对于没有 API 的遗留系统,Agent 可以依靠 computer-use 模型通过 Web 和应用程序 UI 直接与这些系统和应用程序交互——就像人类一样。每个工具都应该有标准化的定义,使工具和 Agent 之间能够灵活地建立多对多关系。良好的文档化、经过全面测试和可重用的工具提高了可发现性,简化了版本管理,并防止了冗余定义。类型 | 说明 | 示例 |
|---|
数据工具 | 使 Agent 能够检索执行工作流所需的上下文和信息 | 查询事务数据库或 CRM 系统、读取 PDF 文档或搜索网页 |
Action 工具 | 使 Agent 能够与系统交互以采取行动,如向数据库添加新信息、更新记录或发送消息 | 发送电子邮件和短信、更新 CRM 记录、将客户服务工单转交给人工 |
编排工具 | Agent 本身可以作为其他 Agent 的工具——见编排部分的 Manager Pattern | 退款 Agent、研究 Agent、写作 Agent |
例如,以下是使用 Agents SDK 为上面定义的 Agent 配备一系列工具的方式:from agents import Agent, WebSearchTool, function_toolimport datetime@function_tooldef save_results(output):db.insert({"output": output,"timestamp": datetime.datetime.now(),})return "File saved"search_agent = Agent(name="Search agent",instructions="Help the user search the internet and save results if asked.",tools=[WebSearchTool(), save_results],)
随着所需工具数量的增加,考虑将任务拆分到多个 Agent(见编排)。配置指令
高质量的指令对任何 LLM 驱动的应用程序都至关重要,但对 Agent 尤其重要。清晰的指令减少歧义并改善 Agent 的决策,从而实现更顺畅的工作流执行和更少的错误。使用现有文档- 创建例程时,使用现有的操作程序、支持脚本或策略文档来创建 LLM 友好的例程。例如,在客户服务中,例程大致可以映射到知识库中的各个文章。提示 Agent 分解任务- 从密集的资源中提供更小、更清晰的步骤,有助于最大程度地减少歧义,并帮助模型更好地遵循指令。定义明确的动作- 确保例程中的每个步骤对应于特定的动作或输出。例如,步骤可能指示 Agent 询问用户的订单号或调用 API 来检索账户明细。对动作(甚至面向用户的消息的措辞)保持明确,留给解释的错误空间就更少。捕获边缘情况- 现实世界的交互经常会产生决策点,例如当用户提供不完整的信息或提出意外问题时如何继续。健壮的例程会预见常见的变体,并包含如何用条件步骤或分支来处理它们的说明,例如如果缺少所需的信息片段则使用替代步骤。你可以使用 o1 或 o3-mini 等高级模型从现有文档自动生成指令。"You are an expert in writing instructions for an LLM agent.Convert the following help center document into a clear set of instructions,written in a numbered list.The document will be a policy followed by an LLM.Ensure that there is no ambiguity, and that the instructions are written as directions for an agent.The help center document to convert is the following {{help_center_doc}}"
编排
在基础组件到位后,你可以考虑编排模式来使你的 Agent 能够有效地执行工作流程。虽然立即构建具有复杂架构的完全自主 Agent 很有诱惑力,但客户通常通过增量方式取得更大的成功。单 Agent 系统- 配备适当工具和指令的单模型在循环中执行工作流程多 Agent 系统- 工作流执行分布在多个协调的 Agent 中单 Agent 系统
单个 Agent 可以通过逐渐添加工具来处理许多任务,使复杂性保持可管理,并简化评估和维护。每个新工具扩展其能力,而不会过早地迫使你编排多个 Agent。每种编排方法都需要 "run" 的概念,通常实现为一个循环,让 Agent 运行直到达到退出条件。常见的退出条件包括工具调用、某种结构化输出、错误或达到最大轮数。例如,在 Agents SDK 中,Agent 使用 Runner.run 方法启动,该方法在 LLM 上循环,直到:调用了final-output tool,由特定的输出类型定义。模型返回没有任何工具调用的响应(例如,直接的用户消息)。Agents.run(agent,[UserMessage("What's the capital of the USA")])
这种 while 循环的概念是 Agent 运行的核心。在多 Agent 系统中,正如你接下来将看到的,你可以有一系列工具调用和 Agent 之间的交接,但允许模型运行多个步骤直到满足退出条件。管理复杂性而不切换到多 Agent 框架的有效策略是使用 prompt 模板。与其为不同的用例维护众多单独的提示,不如使用接受策略变量的单一灵活基础提示。这种模板方法易于适应各种上下文,大大简化了维护和评估。随着新用例的出现,你可以更新变量而不是重写整个工作流程。""" You are a call center agent. You are interacting with{{user_first_name}} who has been a member for {{user_tenure}}. The user'smost common complains are about {{user_complaint_categories}}. Greet theuser, thank them for being a loyal customer, and answer any questions theuser may have!"""
何时考虑创建多个 Agent
我们的一般建议是首先最大化单个 Agent 的能力。更多的 Agent 可以提供直观的概念分离,但会引入额外的复杂性和开销,因此通常带有工具的单个 Agent 就足够了。对于许多复杂的工作流程,将提示和工具拆分成多个 Agent 可以提高性能和可扩展性。当你的 Agent 无法遵循复杂指令或始终选择错误的工具时,你可能需要进一步划分你的系统并引入更多不同的 Agent。复杂逻辑- 当提示包含许多条件语句(多个 if-then-else 分支),且提示模板难以扩展时,考虑将每个逻辑段拆分到单独的 Agent 中。工具过载- 问题不仅是工具的数量,而是它们的相似性或重叠。一些实现成功地管理了 15 个以上明确定义的独特工具,而其他实现则在少于 10 个重叠工具时挣扎。如果通过提供描述性名称、清晰参数和详细描述来提高工具清晰度并不能改善性能,请使用多个 Agent。多 Agent 系统
虽然多 Agent 系统可以为特定的工作流程和要求设计无数种方式,但我们的客户经验突出了两种广泛适用的类别:Manager(Agent 作为工具)- 中央 "manager" Agent 通过工具调用协调多个专业 Agent,每个 Agent 处理特定任务或领域。去中心化(Agent 交接给 Agent)- 多个 Agent 作为对等方运行,根据其专业领域相互交接任务。多 Agent 系统可以建模为图,Agent 表示为节点。在manager pattern中,边表示工具调用;而在去中心化 pattern中,边表示在 Agent 之间转移执行的交接。无论采用哪种编排模式,相同的原则都适用:保持组件灵活、可组合,并由清晰、结构良好的提示驱动。Manager Pattern
Manager Pattern 使一个中央 LLM——"manager"——能够通过工具调用无缝协调专业 Agent 网络。Manager 不会失去上下文或控制,而是在正确的时刻将任务委托给正确的 Agent,轻松地将结果综合成连贯的交互。这确保了流畅、统一用户体验,专业能力始终按需可用。这种模式非常适合只希望一个 Agent 控制工作流执行并与用户直接交互的工作流程。例如,以下是使用 Agents SDK 实现此模式的方式:from agents import Agent, Runnerspanish_agent = Agent(name="Spanish agent",instructions="You translate the user's message to Spanish.",)french_agent = Agent(name="French agent",instructions="You translate the user's message to French.",)italian_agent = Agent(name="Italian agent",instructions="You translate the user's message to Italian.",)orchestrator_agent = Agent(name="orchestrator_agent",instructions=("You are a translation agent. You use the tools given to you to translate.""If asked for multiple translations, you call the relevant tools in order.""You never translate on your own; you always use the provided tools."),tools=[spanish_agent.as_tool(tool_name="translate_to_spanish",tool_description="Translate the user's message to Spanish.",),french_agent.as_tool(tool_name="translate_to_french",tool_description="Translate the user's message to French.",),italian_agent.as_tool(tool_name="translate_to_italian",tool_description="Translate the user's message to Italian.",),],)
去中心化 Pattern
在去中心化模式中,多个 Agent 作为对等方运行,根据其专业领域相互交接任务。每个 Agent 都有自己的专长,当一个 Agent 完成任务或遇到需要另一种专业知识的场景时,它会将控制权交接给另一个 Agent。例如,以下是使用 Agents SDK 实现去中心化模式的方式:from agents import Agent, Runnerspanish_agent = Agent(name="Spanish agent",instructions="You only speak Spanish.",)french_agent = Agent(name="French agent",instructions="You only speak French.",)italian_agent = Agent(name="Italian agent",instructions="You only speak Italian.",)spanish_agent.handoffs = [french_agent, italian_agent]french_agent.handoffs = [spanish_agent, italian_agent]italian_agent.handoffs = [spanish_agent, french_agent]triage_agent = Agent(name="Triage agent",instructions="Determine which language the user needs and hand off to the appropriate specialist agent.",handoffs=[spanish_agent, french_agent, italian_agent],)
Guardrails
护栏是确保 Agent 行为安全、可预测的关键保障。护栏分为两类:输入护栏和输出护栏。输入护栏
输入护栏在用户输入传递给 Agent 之前进行检查,用于过滤不适当的请求或防止越狱攻击。from agents import Agent, GuardrailFunctionOutput, InputGuardrail, Runnercheck_agent = Agent(name="Check agent",instructions=("Determine whether the user's input is a request to do math. ""If it is, output 'math'. If it is not, output 'not_math'."),)async def math_guardrail(ctx, agent, input_data):result = await Runner.run(check_agent, input_data, context=ctx.context)return GuardrailFunctionOutput(output_info=result.final_output,tripwire_triggered=result.final_output == "math",)main_agent = Agent(name="Main agent",instructions="You are a helpful assistant.",input_guardrails=[InputGuardrail(guardrail_function=math_guardrail),],)
输出护栏
输出护栏在 Agent 生成输出之后进行检查,用于确保输出符合预期格式和内容要求。护栏的关键概念
Tripwire(触发线):当护栏检测到违规内容时,tripwire_triggered 设为 True,系统会抛出异常并停止执行输入护栏在 Agent 处理之前运行,输出护栏在 Agent 生成输出之后运行护栏本身也可以是 Agent,利用 LLM 的理解能力进行更智能的判断护栏的最佳实践
分层设置护栏:在系统不同层面设置护栏,形成纵深防御不要过度依赖护栏:护栏是安全网,不是替代良好的 Agent 指令
总结
注重安全- 实施 Guardrails 和人工监督
原文包含大量代码示例和架构图,详细请访问:https://openai.com/business/guides-and-resources/a-practical-guide-to-building-ai-agents/