openai-agents-python 智能体(Agent)开发指南:核心配置、工具编排与生命周期管理
【免费下载链接】openai-agents-pythonA lightweight, powerful framework for multi-agent workflows项目地址: https://gitcode.com/GitHub_Trending/op/openai-agents-python
Agent是 openai-agents-python 框架中应用的核心构建块:一个配置了指令(instructions)、工具(tools)、任务转移(handoffs)、安全防护措施(guardrails)与结构化输出(structured outputs)的大语言模型(LLM)封装。本指南以 docs/zh/agents.md 为骨架,结合 Agent 源码 展开,覆盖Agent的全部核心配置项、提示词模板、上下文注入、输出类型、多智能体编排模式、生命周期钩子以及工具使用行为控制。读完本文,你将能够独立定义、克隆、配置并运行一个生产可用的智能体,并理解其底层运行机制。
智能体:应用中的核心构建块
在 openai-agents-python 中,Agent代表一个被配置好的 LLM 实例。它本身不负责运行循环——真正的编排由Runner完成:SDK 通过Agent+Runner的组合,替你管理模型轮次、工具调用、安全防护、任务转移与会话状态。
对于 OpenAI 模型,SDK 默认使用 Responses API。如果你希望自行控制模型调用循环,可以直接使用 Responses API;而
Agent+Runner的差异在于编排:SDK 为你管理轮次、工具、安全防护措施、任务转移和会话。
在动手之前,请先确定你的使用场景,以选择合适的指南入口:
| 如果你想要…… | 接下来阅读 |
|---|---|
| 选择模型或提供商设置 | 模型 |
| 为智能体添加能力 | 工具 |
| 让智能体针对真实代码仓库、文档包或隔离工作区运行 | 沙箱智能体快速入门 |
| 在管理器式编排与任务转移之间进行选择 | 智能体编排 |
| 配置任务转移行为 | 任务转移 |
| 运行轮次、流式传输事件或管理对话状态 | 运行智能体 |
| 检查最终输出、运行项或可恢复状态 | 结果 |
| 共享本地依赖项和运行时状态 | 上下文管理 |
如果你要定义或自定义单个基础Agent(而非SandboxAgent),请继续阅读本页。
基本配置
Agent最常用的属性如下表所示(来源于 Agent 数据类定义):
| 属性 | 必需 | 说明 |
|---|---|---|
name | 是 | 便于人类阅读的智能体名称。源码在__post_init__中校验其必须为字符串(见 agent.py)。 |
instructions | 否 | 系统提示词或动态指令回调。强烈建议设置。请参阅动态指令。 |
prompt | 否 | OpenAI Responses API 提示词配置。接受静态提示词对象或函数。请参阅提示词模板。 |
handoff_description | 否 | 当此智能体作为任务转移目标提供时显示的简短说明。 |
handoffs | 否 | 将对话委派给专业智能体。请参阅任务转移。 |
model | 否 | 要使用的 LLM。未设置时使用agents.models.get_default_model()返回的默认模型(见 agent.py)。请参阅模型。 |
model_settings | 否 | 模型调优参数,例如temperature、top_p和tool_choice,对应 ModelSettings。 |
tools | 否 | 智能体可以调用的工具。请参阅工具。 |
mcp_servers | 否 | 为智能体提供基于 MCP 的工具的 MCP 服务器。请参阅 MCP 指南。 |
mcp_config | 否 | 微调 MCP 工具的准备方式,例如将其 schema 转换为严格模式,以及设置 MCP 失败信息的格式。请参阅 MCP 指南。 |
input_guardrails | 否 | 针对此智能体链的第一个用户输入运行的安全防护措施。请参阅安全防护措施。 |
output_guardrails | 否 | 针对此智能体的最终输出运行的安全防护措施。请参阅安全防护措施。 |
output_type | 否 | 用于替代纯文本的 structured outputs 类型。请参阅输出类型。 |
hooks | 否 | 智能体作用域内的生命周期回调。请参阅生命周期事件(钩子)。 |
tool_use_behavior | 否 | 控制是将工具结果送回模型继续循环,还是结束运行。请参阅工具使用行为。 |
reset_tool_choice | 否 | 在工具调用后重置tool_choice(默认值:True),以避免工具使用循环。请参阅强制使用工具。 |
一个最小可运行的示例(来自 docs/zh/agents.md):
from agents import Agent from agents.decorators import tool @tool def get_weather(city: str) -> str: """returns weather info for the specified city.""" return f"The weather in {city} is sunny" agent = Agent( name="Haiku agent", instructions="Always respond in haiku form", model="gpt-5-nano", tools=[get_weather], )从源码角度看,Agent继承自AgentBase(见 agent.py),后者承载了name、handoff_description、tools、mcp_servers、mcp_config等被RealtimeAgent等共享的基础参数。__post_init__(agent.py)会对所有关键字段做类型校验,例如instructions必须是字符串或可调用对象、tool_use_behavior必须是"run_llm_again"、"stop_on_first_tool"、StopAtTools字典或可调用函数。
本节中的所有内容均适用于
Agent。SandboxAgent基于相同理念构建,并额外添加了default_manifest、base_instructions、capabilities和run_as,用于工作区作用域内的运行。请参阅沙箱智能体概念。
提示词模板
通过设置prompt,你可以引用在 OpenAI 平台中创建的提示词模板。当通过 Responses API 访问 OpenAI 模型时,此功能可用。
使用步骤:
前往 https://platform.openai.com/playground/prompts
创建一个新的提示词变量
poem_style。创建包含以下内容的系统提示词:
Write a poem in {{poem_style}}使用
--prompt-id标志运行代码示例。
from agents import Agent agent = Agent( name="Prompted assistant", prompt={ "id": "pmpt_123", "version": "1", "variables": {"poem_style": "haiku"}, }, )从源码看,Prompt是一个 TypedDict,包含id(必填)、version(可选)和variables(可选),见 prompts.py。PromptUtil.to_model_input()(prompts.py)负责将 Prompt 对象或动态函数解析为 Responses API 的ResponsePromptParam,最终下发id、version与variables。
你也可以在运行时动态生成提示词——传入一个接收GenerateDynamicPromptData(内含context与agent)并返回Prompt的函数,普通函数与async函数均可:
from dataclasses import dataclass from agents import Agent, GenerateDynamicPromptData, Runner @dataclass class PromptContext: prompt_id: str poem_style: str async def build_prompt(data: GenerateDynamicPromptData): ctx: PromptContext = data.context.context return { "id": ctx.prompt_id, "version": "1", "variables": {"poem_style": ctx.poem_style}, } agent = Agent(name="Prompted assistant", prompt=build_prompt) result = await Runner.run( agent, "Say hello", context=PromptContext(prompt_id="pmpt_123", poem_style="limerick"), )动态函数必须返回Prompt字典,否则会抛出UserError(prompts.py)。
上下文
智能体以其context类型作为泛型参数。上下文是一种依赖注入工具:它是由你创建并传递给Runner.run()的对象,随后会传递给每个智能体、工具、任务转移等,并作为智能体运行所需依赖项和状态的集合。你可以提供任何 Python 对象作为上下文。
from dataclasses import dataclass @dataclass class Purchase: id: str @dataclass class UserContext: name: str uid: str is_pro_user: bool async def fetch_purchases(self) -> list[Purchase]: # implement your logic here return [] agent = AgentUserContext有关完整的RunContextWrapper接口、共享用量追踪、嵌套的tool_input以及序列化注意事项,请阅读上下文指南。在运行期间,工具函数、动态指令、钩子、任务转移和防护措施都会收到包装后的RunContextWrapper,通过context.context访问你的原始对象。
输出类型
默认情况下,智能体生成纯文本(即str)输出。如果你希望智能体生成特定类型的输出,可以使用output_type参数。常见选择是使用 Pydantic 对象,但框架支持任何可以封装在 Pydantic TypeAdapter 中的类型,例如 dataclass、列表、TypedDict 等。
from pydantic import BaseModel from agents import Agent class CalendarEvent(BaseModel): name: str date: str participants: list[str] agent = Agent( name="Calendar extractor", instructions="Extract calendar events from text", output_type=CalendarEvent, )注意:传入
output_type后,即表示要求模型使用 structured outputs,而不是常规纯文本响应。
从源码看,output_type接受普通类型或AgentOutputSchemaBase实例;如果你希望使用非严格 JSON schema,可传入AgentOutputSchema(MyClass, strict_json_schema=False),或通过继承AgentOutputSchemaBase提供自定义 JSON schema(见 agent.py)。在__post_init__中,output_type会被校验为类型、AgentOutputSchemaBase或泛型起源(agent.py)。
多智能体系统设计模式
多智能体系统有多种设计方式,但通常有两种具有广泛适用性的模式:
- 管理器(agents as tools):中央管理器/编排器将专业子智能体作为工具调用,并保留对对话的控制权。
- 任务转移(handoffs):对等智能体将控制权转移给接管对话的专业智能体。这是一种去中心化模式。
两者的关键区别在于控制权归属:agents as tools 中,原始智能体始终掌控对话;handoffs 中,被委派的智能体会接收对话历史记录并接管对话。
管理器(agents as tools)
customer_facing_agent负责处理所有用户交互,并调用作为工具公开的专业子智能体。请在工具文档中了解更多信息。
from agents import Agent booking_agent = Agent(...) refund_agent = Agent(...) customer_facing_agent = Agent( name="Customer-facing agent", instructions=( "Handle all direct user communication. " "Call the relevant tools when specialized expertise is needed." ), tools=[ booking_agent.as_tool( tool_name="booking_expert", tool_description="Handles booking questions and requests.", ), refund_agent.as_tool( tool_name="refund_expert", tool_description="Handles refund questions and requests.", ) ], )源码层面的as_tool()(agent.py)将智能体转换为一个FunctionTool:与 handoffs 不同,被调用时子智能体接收的是生成的输入而非对话历史;且调用结束后对话仍由原智能体继续。它还支持custom_output_extractor、is_enabled、on_stream、needs_approval、结构化parameters等高级参数。仓库中的 agents_as_tools.py 与 agents_as_tools_streaming.py 提供了可直接运行的完整示例。
任务转移
配置的任务转移目标是智能体可以委派任务的子智能体。发生任务转移时,被委派的智能体会接收对话历史记录并接管对话。此模式支持模块化的专业智能体,使其能够出色完成单一任务。请在任务转移文档中了解更多信息。
from agents import Agent booking_agent = Agent(...) refund_agent = Agent(...) triage_agent = Agent( name="Triage agent", instructions=( "Help the user with their questions. " "If they ask about booking, hand off to the booking agent. " "If they ask about refunds, hand off to the refund agent." ), handoffs=[booking_agent, refund_agent], )在源码中,handoffs接受Agent实例或Handoff对象列表(agent.py),并支持条件启用的is_enabled回调;handoff_description会作为 LLM 判断何时转移的依据。
动态指令
在大多数情况下,你可以在创建智能体时提供指令。不过,你也可以通过函数提供动态指令。该函数将接收智能体和上下文,并且必须返回提示词。普通函数和async函数均可接受。
from agents import Agent, RunContextWrapper def dynamic_instructions( context: RunContextWrapper[UserContext], agent: Agent[UserContext] ) -> str: return f"The user's name is {context.context.name}. Help them with their questions." agent = AgentUserContext源码中instructions字段的类型即str | Callable[[RunContextWrapper[TContext], Agent[TContext]], MaybeAwaitable[str]] | None(agent.py),印证了它既可以是静态字符串,也可以是接收上下文与智能体实例、返回字符串(支持同步与异步)的指令生成函数。仓库中的 dynamic_system_prompt.py 是一个可运行的动态指令示例。
生命周期事件(钩子)
有时,你可能希望观察智能体的生命周期。例如,你可能希望在特定事件发生时记录事件日志、预取数据或记录用量。
钩子分为两个作用域:
RunHooks:观察整个Runner.run(...)调用,包括向其他智能体进行的任务转移。AgentHooks:通过agent.hooks附加到特定智能体实例。
回调上下文也会随事件而变化:
- 智能体开始/结束钩子接收
AgentHookContext,它会封装你的原始上下文,并携带共享的运行用量状态。 - LLM、工具和任务转移钩子接收
RunContextWrapper。
典型的钩子触发时机如下:
on_agent_start:特定智能体开始运行时;on_agent_end:该智能体完成最终输出时。on_llm_start/on_llm_end:紧邻每次模型调用的前后触发。on_tool_start/on_tool_end:在每次本地工具调用前后触发。对于函数工具,钩子context通常是ToolContext,因此你可以检查工具调用元数据,例如tool_call_id。on_handoff:控制权从一个智能体转移到另一个智能体时。
如果希望为整个工作流设置一个统一观察器,请使用RunHooks;如果希望将生命周期回调限定到特定智能体,请使用AgentHooks。
from agents import Agent, RunHooks, Runner class LoggingHooks(RunHooks): async def on_agent_start(self, context, agent): print(f"Starting {agent.name}") async def on_llm_end(self, context, agent, response): print(f"{agent.name} produced {len(response.output)} output items") async def on_agent_end(self, context, agent, output): print(f"{agent.name} finished with usage: {context.usage}") agent = Agent(name="Assistant", instructions="Be concise.") result = await Runner.run(agent, "Explain quines", hooks=LoggingHooks()) print(result.final_output)从源码看,RunHooksBase定义了on_llm_start、on_llm_end、on_agent_start、on_agent_end、on_handoff、on_tool_start、on_tool_end等回调接口,AgentHooksBase则额外提供on_start/on_end(见 lifecycle.py)。两套接口均为基类,你只需覆写需要的方法。仓库中的 lifecycle_example.py 与 agent_lifecycle_example.py 展示了完整用法。有关完整的回调接口,请参阅生命周期 API 参考。
安全防护措施
安全防护措施允许你在智能体运行的同时并行检查/验证用户输入,并在智能体生成输出后对其进行检查/验证。例如,你可以筛查用户输入和智能体输出是否与任务相关。请在安全防护措施文档中了解更多信息。
在源码中,input_guardrails仅在该智能体是链中的第一个智能体时运行(针对首个用户输入),output_guardrails仅在智能体产生最终输出时运行(见 agent.py)。仓库中的 input_guardrails.py 与 output_guardrails.py 提供了可直接参考的示例。
智能体克隆与复制
通过在智能体上使用clone()方法,你可以复制一个智能体,并可选择更改任意属性。
pirate_agent = Agent( name="Pirate", instructions="Write like a pirate", model="gpt-5.6-sol", ) robot_agent = pirate_agent.clone( name="Robot", instructions="Write like a robot", )源码中的clone()基于dataclasses.replace实现,执行的是浅拷贝(agent.py)。需要注意:tools、handoffs、mcp_servers、input_guardrails、output_guardrails等列表属性不会被复制——未传入的属性会共享原智能体的同一个列表,例如cloned.tools.append(extra_tool)也会改变原智能体。若想让克隆体拥有独立的列表,请显式传入新列表,例如agent.clone(tools=[*agent.tools, extra_tool])。另外,clone()还会在仅替换model时自动继承对应的默认model_settings。相关行为测试见 test_agent_clone_shallow_copy.py。
强制使用工具
提供工具列表并不总是意味着 LLM 会使用工具。你可以通过设置ModelSettings.tool_choice强制使用工具。有效值包括:
auto,允许 LLM 决定是否使用工具。required,要求 LLM 使用工具(但它可以智能决定使用哪个工具)。none,要求 LLM不使用工具。- 设置特定字符串,例如
my_tool,要求 LLM 使用该特定工具。
使用 OpenAI Responses 工具搜索时,具名工具选项受到更多限制:不能通过tool_choice指定纯命名空间名称或仅延迟加载的工具,且tool_choice="tool_search"不会指定ToolSearchTool。在这些情况下,建议使用auto或required。有关 Responses 特有的限制,请参阅托管工具搜索。
from agents import Agent, ModelSettings from agents.decorators import tool @tool def get_weather(city: str) -> str: """Returns weather info for the specified city.""" return f"The weather in {city} is sunny" agent = Agent( name="Weather Agent", instructions="Retrieve weather details.", tools=[get_weather], model_settings=ModelSettings(tool_choice="get_weather") )源码中ToolChoice的类型别名即为Literal["auto", "required", "none"] | str | MCPToolChoice | None(model_settings.py),与文档描述的四种取值一一对应。仓库中的 forcing_tool_use.py 提供了完整示例。
防止工具使用循环:reset_tool_choice
为防止无限循环,框架会在工具调用后自动将tool_choice重置为auto。此行为可通过agent.reset_tool_choice(默认True)配置。产生无限循环的原因是:工具结果会发送给 LLM,而 LLM 随后会由于tool_choice再次生成工具调用,如此无限重复。
底层实现位于 tool_execution.py 的maybe_reset_tool_choice():
def maybe_reset_tool_choice( agent: Agent[Any], tool_use_tracker: AgentToolUseTracker, model_settings: ModelSettings, ) -> ModelSettings: """Reset tool_choice if the agent was forced to pick a tool previously and should be reset.""" if agent.reset_tool_choice is True and tool_use_tracker.has_used_tools(agent): return dataclasses.replace(model_settings, tool_choice=None) return model_settings该函数在运行循环的每一轮模型调用前被调用(见 run_loop.py 与 run_loop.py):只要智能体已使用过工具且reset_tool_choice为True,就会把tool_choice重置为None(即auto),避免模型被强制反复调用同一工具。
工具使用行为
Agent配置中的tool_use_behavior参数控制工具输出的处理方式(agent.py):
"run_llm_again":默认行为。运行工具后,由 LLM 处理结果并生成最终响应。"stop_on_first_tool":将第一次工具调用的输出用作最终响应,不再由 LLM 进行后续处理。
from agents import Agent from agents.decorators import tool @tool def get_weather(city: str) -> str: """Returns weather info for the specified city.""" return f"The weather in {city} is sunny" agent = Agent( name="Weather Agent", instructions="Retrieve weather details.", tools=[get_weather], tool_use_behavior="stop_on_first_tool" )StopAtTools(stop_at_tool_names=[...]):如果调用了任一指定工具,则停止运行,并将其输出用作最终响应。
from agents import Agent from agents.agent import StopAtTools from agents.decorators import tool @tool def get_weather(city: str) -> str: """Returns weather info for the specified city.""" return f"The weather in {city} is sunny" @tool def sum_numbers(a: int, b: int) -> int: """Adds two numbers.""" return a + b agent = Agent( name="Stop At Stock Agent", instructions="Get weather or sum numbers.", tools=[get_weather, sum_numbers], tool_use_behavior=StopAtTools(stop_at_tool_names=["get_weather"]) )StopAtTools在源码中是一个 TypedDict,包含stop_at_tool_names: list[str](agent.py)。需要注意:该配置仅对函数工具(FunctionTool)生效,托管工具(如 file search、web search)始终由 LLM 处理结果(agent.py)。
ToolsToFinalOutputFunction:自定义函数,用于处理工具结果,并决定是以最终输出结束运行,还是让 LLM 继续处理。
from agents import Agent, FunctionToolResult, RunContextWrapper from agents.agent import ToolsToFinalOutputResult from agents.decorators import tool from typing import List, Any @tool def get_weather(city: str) -> str: """Returns weather info for the specified city.""" return f"The weather in {city} is sunny" def custom_tool_handler( context: RunContextWrapper[Any], tool_results: List[FunctionToolResult] ) -> ToolsToFinalOutputResult: """Processes tool results to decide final output.""" for result in tool_results: if result.output and "sunny" in result.output: return ToolsToFinalOutputResult( is_final_output=True, final_output=f"Final weather: {result.output}" ) return ToolsToFinalOutputResult( is_final_output=False, final_output=None ) agent = Agent( name="Weather Agent", instructions="Retrieve weather details.", tools=[get_weather], tool_use_behavior=custom_tool_handler )从源码看,ToolsToFinalOutputResult包含is_final_output: bool(是否为最终输出;若为False,LLM 会再次运行并接收工具调用输出)与可选的final_output: Any(必须匹配智能体的output_type)(agent.py)。ToolsToFinalOutputFunction的类型签名是接收RunContextWrapper与工具结果列表、返回(可等待的)ToolsToFinalOutputResult的函数(agent.py),因此同步与异步处理函数均可使用。
小结
本文以 docs/zh/agents.md 为主体,完整覆盖了Agent的定义与全部核心配置:从基本属性(name、instructions、tools、model等)到提示词模板与动态指令,从泛型上下文注入到结构化输出类型,从管理器/任务转移两种多智能体模式到生命周期钩子,再到tool_choice强制工具、tool_use_behavior工具使用行为与reset_tool_choice防循环机制,并逐一给出了对应的源码位置(agent.py、model_settings.py、prompts.py、lifecycle.py、tool_execution.py)与可运行示例(examples/basic、examples/agent_patterns)。
下一步,你可以依据后续指南选择中的决策表,继续深入模型选择、工具、任务转移、运行智能体、结果处理与上下文管理,或在需要隔离工作区与沙箱原生能力时转向沙箱智能体概念。
【免费下载链接】openai-agents-pythonA lightweight, powerful framework for multi-agent workflows项目地址: https://gitcode.com/GitHub_Trending/op/openai-agents-python
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考