https://cdn.openai.com/business-guides-and-resources/a-practical-guide-to-building-agents.pdf
什么是 Agents?
传统软件可帮助用户简化和自动化工作流,而 Agent 则能高度自主地代表用户执行相同的工作流。
Agent 是能够代表你独立完成任务的系统。
Agents are systems that independently accomplish tasks on your behalf.
Workflow 是为实现用户目标而必须执行的一系列步骤,这些目标可以是解决客户服务问题、预订餐厅、提交代码更改或生成报告等。
集成了大语言模型但未用其控制工作流执行的应用,如简单的聊天机器人、单轮大语言模型或做情感分类任务,不属于 Agent 。
更具体地说,Agent 具备以下核心特征,使其能够可靠且一致地代表用户执行任务:
第一,它利用大语言模型来管理工作流的执行并做出决策。它能识别工作流何时完成,并在需要时主动纠正自己的行动。若执行失败,它可以停止执行并将控制权交还给用户。
第二,它可以访问各种工具,以便与外部系统进行交互,既可以收集上下文信息,也可以采取行动,并根据工作流的当前状态,动态选择合适的工具,始终在明确界定的约束范围内运行。
何时需要构建 Agent?
构建 Agent 需要重新思考系统如何做出决策,以及如何处理复杂任务。与传统自动化不同, Agent 特别适合那些传统的确定性的和基于规则的方法难以发挥作用的工作流。
以交易风险识别为例。传统系统像是“打勾清单(checklist)”,只要交易满足某些固定条件,就标记为异常。而大语言模型驱动的 Agent,更像一位老练的调查员,它会结合上下文、观察细节,即使没有违反明确规则也能识别可疑活动。这种细致的推理能力正是 Agent 能够有效处理复杂、模糊情况的原因所在。
在评估 Agent 在哪些方面可以创造价值时,应优先考虑那些以往难以实现自动化的工作流,尤其是传统方法遇到阻碍的领域:
1. 复杂决策Complex decision-making: :涉及细节的判断、例外情况或上下文敏感决策的工作流,例如客户服务工作流中的退款审批。
2. 难以维护的规则Difficult-to-maintain rules:由于规则非常广泛且复杂而变得难以管理的系统,更新成本高或容易出错,例如进行供应商安全审查。
3. 严重依赖非结构化数据 Heavy reliance on unstructured data:涉及解释自然语言、从文档中提取含义或与用户进行对话交互的场景,例如处理家庭保险理赔。
在决定构建 Agent 之前,要确保用例能够明确满足这些标准。否则,确定性解决方案可能就足够了。
Agents 设计基础
从最基本的形式来看, Agent 由三个核心组件组成:
1.模型:驱动 Agent 推理和决策的大语言模型。
2.工具:Agent 可以用来采取行动的外部函数或 API。
3.指令Instructions:明确界定 Agent 行为的准则和约束。
以下是使用 OpenAI 的 Agent 软件开发工具包(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,帮智能体调用功能、获取数据。如果一些老系统没有 API,那智能体也可以用“模拟人操作”的方式,比如点网页、填表单,就像人一样去使用系统。
每个工具都应该有标准化的定义,以便在工具和 Agent 之间实现灵活的多对多关系。文档完善、经过充分测试且可复用的工具可以提高可发现性、简化版本管理并避免重复定义。
一般来说,Agent 需要三种类型的工具:
类型 | 功能说明 | 应用举例 |
---|---|---|
数据 | 获取上下文和执行任务所需的信息 | 查询交易数据库、读取PDF文件、访问CRM系统、搜索网页 |
行动 | 主动与系统交互,完成写入、修改、发送等操作 | 发送邮件或短信、更新客户信息、将客服问题转交给人工 |
编排 | 一个智能体指挥多个其他智能体,协同完成复杂任务 | 退款处理智能体、调研助手、写作代理等 |
例如,使用 Agent SDK 时,你可以按以下方式为上述定义的 Agent 配备一系列工具:
from agents import Agent, WebSearchTool, function_tool
@function_tool
def save_results(output):
db.insert({"output": output, "timestamp": datetime.time()})
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.
配置指令
高质量的指令对于任何由大语言模型驱动的应用都至关重要,对于 Agent 来说尤其如此。
清晰的指令可以减少歧义,提高 Agent 的决策能力,从而使工作流执行更加顺畅,减少错误。
Agent 指令的最佳实践:
- 利用现有文档:在整理流程模板时,可以直接参考现有的操作手册、客服话术或公司政策文档,把它们改写成适合大模型理解的版本。
- 用提示词给 Agent 分解任务:从密集的资源中提供更小、更清晰的步骤有助于减少歧义,使模型更好地遵循指令。
- 定义明确的行动:确保流程模板中的每个步骤都对应一个特定的行动或输出。例如,一个步骤可能指示 Agent 向用户询问订单号或调用 API 以检索账户详细信息。明确行动可以减少解释错误的空间。
- 考虑特殊情况(Corner Case):在真实使用中,用户经常会提供不完整的信息,或者问一些意料之外的问题,这时系统就需要做出判断:下一步该怎么走。一个设计良好的流程,应该提前考虑这些“常见偏差”或“异常情况”,并在指令里说明:如果遇到这种情况,可以怎么处理——比如加入条件判断,或者设置一个“备用步骤”,在缺少某项信息时也能继续运行。
可以使用先进的模型,如 o1 或 o3 - mini,从现有文档中自动生成指令。以下是一个说明这种方法的示例 Prompt:
"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 很有吸引力,但客户通常通过渐进式方法取得更大的成功。
一般来说,编排模式分为两类:
1. 单智能体系统:由一个配备了适当工具和指令的模型在循环中执行工作流。
2. 多智能体系统:在多个互相协调的 Agent 之间执行工作流。
继续,详细探讨每种模式。
单智能体系统
单个 Agent 可以通过逐步添加工具来处理许多任务,这样可以控制复杂性,简化评估和维护。每个新工具都能扩展其能力,而不会过早地一定要编排多个 Agents。
每个编排方法都需要“运行”的概念,通常实现为一个循环,让智能体一直运行,直到满足退出条件。常见的退出条件包括工具调用、特定的结构化输出、错误或达到最大轮数。
例如,在 Agents SDK 中,使用 Runner.run()
方法启动 Agent,该方法会循环执行,直到满足以下条件之一:
- 调用了最终输出的工具,由特定的输出类型定义。
- 模型返回了没有任何工具调用的响应(例如,直接的用户消息)。
示例用法:
Agents.run(agent, [UserMessage("What's the capital of the USA?")])
这种循环概念是 Agent 功能的核心。在多智能体系统中,可以有一系列的工具调用和 Agent 之间的交接,但允许模型运行多个步骤,直到满足退出条件。
一种在不使用多 Agent 架构的前提下,管理复杂流程的有效方法,就是使用提示词模板(prompt templates)。与其为每一个具体场景都写一套新的提示,不如使用一套通用的基础模板,然后通过填写不同的“变量”来适配不同需求。
这种做法非常灵活,能够适应多种上下文,而且大大降低了维护成本和测试难度。当有新的使用场景出现时,只需要更新变量,而不必从头重写整个流程。
何时考虑使用多智能体系统?
一般建议是:优先充分发挥单智能体系统的能力。
虽然引入多个 Agents 有助于更清晰地划分任务概念,但也会带来额外的复杂度和系统开销,因此在多数情况下,一个 Agent 配合合适的工具就已足够。
不过,在面对流程复杂度较高的场景时,将提示词和工具合理拆分到多个 Agents 中,可以显著提升系统的性能和可扩展性。
如果发现现有 Agent 无法正确执行复杂指令,或者频繁调用错误的工具,可能就需要将任务进一步细化,创建更加明确分工的 Agent。
以下是常见需要拆分 Agent 的两个参考标准:
- 逻辑复杂:当提示词中包含大量的条件判断(如多个 if-then-else 分支),或模板逻辑变得难以维护时,建议按逻辑片段将任务拆分给不同 Agents 分别处理。
- 工具过载 :问题不在于工具数量本身,而在于它们之间的相似度和重叠度。有些系统能成功管理 15 个以上定义清晰的工具,而另一些则在不到 10 个模糊重叠的工具中就出现混乱。
如果系统中工具名称不清、边界模糊、用途重叠——可以考虑拆分为多个 Agents,各自负责更清晰的子任务,以提升执行效率。
多智能体系统
多智能体系统可以根据不同的业务流程和场景需求,设计出各种结构。
但从实际客户经验来看,总结出两种通用、可落地的设计模式:
- 管理者模式 (Agent 作为工具本身),由一个中心 Agent 担任“管理者”角色,通过工具调用的方式调度多个专职 Agent,每个 Agent 负责一个具体任务或领域。
- 去中心化模式 (Agent 之间相互交接)多个 Agent 平行运行,彼此间根据各自专长进行任务接力和分工协作。
多 Agent 系统可以被抽象为一张图谱,图中的节点代表 Agent:在管理者模式中,连线表示工具调用;在去中心化模式中,连线表示任务的转交和流转。
无论采用哪种编排模式,设计时都应遵循以下通用原则:保持模块灵活、可组合,任务定义清晰,提示词结构明确。
管理者模式
管理者模式的核心是由一个中心 LLM(即“管理者”)通过工具调用,协调一组专业化的 Agent 协同完成任务。
它不会丢失上下文或控制权,而是能在恰当的时间,将任务智能地分派给合适的 Agent,并将各部分结果自然整合为一次流畅的交互。
这种模式带来的好处是:用户体验统一顺畅,每个专业能力都能按需随时调用。
管理者模式非常适合这样的场景:希望由一个 Agent 负责控制整个流程的执行,并且它能直接与用户交互。
例如,可以通过 Agents SDK 如此实现:
from import agents Agent, Runner
manager_agent = Agent(
name= "manager_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."
),
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",
),
],
)
async def main():
msg = input("Translate 'hello' to Spanish, French and Italian for me!")
orchestrator_output = await Runner.run(
manager_agent,msg)
for message in orchestrator_output.new_messages:
print(f" - Translation step: {message.content}")
有些框架采用声明式方式,要求在一开始就明确地定义出流程中的每一个分支、循环和条件判断——通常通过由节点(Agent)和边(代表确定性或动态任务交接)构成的图来描述整个流程。
这种方式虽然可视化效果好,但随着流程变得更动态、更复杂,维护成本会迅速上升。开发者可能还需要额外学习一些专用领域语言(DSL),使用门槛较高。
相比之下,Agents SDK 采用的是更灵活的代码优先(code-first)方式。开发者可以直接用熟悉的编程结构来表达流程逻辑,无需预先定义完整的图结构,从而实现更加动态、可扩展的 Agent 编排能力
去中心化模式
在去中心化的模式中,Agent 之间是“平等协作”的关系,它们可以把手上的任务交接(handoff)给其他 Agent 去继续完成。这个“交接”有点像传接力棒:一个 Agent 跑到某个阶段后,可以把流程和对话状态一起“交给”另一个 Agent,接着往下跑。在 Agents SDK 中,handoff 就是一种特殊的工具或函数,用来实现这种交接机制。
这种模式的特点是:所有 Agent 地位相当,没有谁是总指挥。每个 Agent 都可以根据自己的专长,直接把任务交给另一个更合适的 Agent 来处理,而不需要中间有一个统一协调的“管理者”。
它特别适合那些不需要中央控制、任务分布明确、Agent 各自负责一摊事情的场景。
举个例子:如果用 Agents SDK 来实现一个客服流程,同时要处理 销售 和 售后支持 两个方向的需求,就可以用 去中心化模式 来搭建这个系统。
from agents import Agent, Runner
technical_support_agent = Agent(
name= "Technical Support Agent",
instructions=(
"You provide expert assistance with resolving technical issues, system outages, or product troubleshooting."
),
tools=[search_knowledge_base]
)
sales_assistant_agent = Agent(
name="Sales Assistant Agent",
instructions=(
"You help enterprise clients browse the product catalog, recommend suitable solutions, and facilitate purchase transactions."
),
tools=[initiate_purchase_order]
)
order_management_agent = Agent(
name="Order Management Agent",
instructions=(
"You assist clients with inquiries regarding order tracking, delivery schedules, and processing returns or refunds."),
tools=[track_order_status, initiate_refund_process]
)
triage_agent = Agent(
name="Triage Agent",
instructions="You act as the first point of contact, assessing customer queries and directing them promptly to the correct specialized agent.",
handoffs=[technical_support_agent, sales_assistant_agent, order_management_agent],)
await Runner.run(
triage_agent,
input("Could you please provide an update on the delivery timeline for our recent purchase?")
)
在上面的例子中,用户发来的消息会先进入一个任务分发 Agent(triage_agent),会根据用户的内容来决定要把任务交给谁。
比如发现用户是在咨询订单问题,它就会把对话“转给”专门负责订单处理的 order_management_agent,由它继续接手并处理后续流程。
这种做法特别适合那些希望先判断用户需求,再精准分流到合适 Agent 的场景。还可以让处理订单的 Agent,在处理完后把对话再交还回来,由任务分发 Agent 继续跟进,比如结束语、满意度收集等。