运行智能体
你可以通过 Runner 类运行智能体。你有 3 种选择:
Runner.run():以异步方式运行并返回RunResult。Runner.run_sync():同步方法,内部只是调用.run()。Runner.run_streamed():以异步方式运行并返回RunResultStreaming。它以流式模式调用 LLM,并在收到事件时将其流式传递给你。
from agents import Agent, Runner
async def main():
agent = Agent(name="Assistant", instructions="You are a helpful assistant")
result = await Runner.run(agent, "Write a haiku about recursion in programming.")
print(result.final_output)
# Code within the code,
# Functions calling themselves,
# Infinite loop's dance
在结果指南中了解更多。
智能体循环
当你在 Runner 中使用 run 方法时,你会传入一个起始智能体和输入。输入可以是字符串(会被视为一条用户消息),也可以是输入项列表,这些输入项是 OpenAI Responses API 中的 items。
然后 Runner 会运行一个循环:
- 我们用当前输入为当前智能体调用 LLM。
- LLM 生成输出。
- 如果 LLM 返回
final_output,循环结束并返回结果。 - 如果 LLM 执行了 handoffs,我们更新当前智能体和输入,并重新运行循环。
- 如果 LLM 生成了工具调用,我们执行这些工具调用,追加结果,并重新运行循环。
- 如果 LLM 返回
- 如果超过传入的
max_turns,我们会抛出MaxTurnsExceeded异常。
Note
判断 LLM 输出是否被视为“最终输出”的规则是:它产生了所需类型的文本输出,并且没有工具调用。
流式传输
流式传输让你在 LLM 运行时额外接收流式事件。流结束后,RunResultStreaming 将包含本次运行的完整信息,包括生成的所有新输出。你可以调用 .stream_events() 获取流式事件。在流式传输指南中了解更多。
运行配置
run_config 参数让你为智能体运行配置一些全局设置:
model:允许设置一个全局 LLM 模型,不受每个 Agent 自身model设置的影响。model_provider:用于查找模型名称的模型提供方,默认为 OpenAI。model_settings:覆盖智能体级设置。例如,你可以设置全局temperature或top_p。session_settings:在运行期间检索历史记录时,覆盖会话级默认值(例如SessionSettings(limit=...))。input_guardrails、output_guardrails:要在所有运行中包含的输入或输出安全防护措施列表。handoff_input_filter:应用于所有任务转移的全局输入过滤器(如果任务转移本身未设置)。输入过滤器允许你编辑发送给新智能体的输入。更多细节见Handoff.input_filter的文档。nest_handoff_history:可选启用的 beta 功能,会在调用下一个智能体之前,将之前的对话记录折叠为单条 assistant 消息。由于我们仍在稳定嵌套任务转移,该功能默认禁用;设置为True启用,或保持False以透传原始对话记录。当你未传入RunConfig时,所有 Runner methods 会自动创建一个RunConfig,因此快速入门和示例会保持默认关闭;任何显式的Handoff.input_filter回调也会继续覆盖该设置。单个任务转移可通过Handoff.nest_handoff_history覆盖该设置。handoff_history_mapper:当你选择启用nest_handoff_history时,一个可选的可调用对象会在每次接收到规范化后的对话记录(history + handoff items)时被调用。它必须返回要转发给下一个智能体的完全一致的输入项列表,从而让你无需编写完整的任务转移过滤器,也能替换内置摘要。tracing_disabled:允许你为整个运行禁用追踪。tracing:传入TracingConfig以覆盖本次运行的导出器、进程或追踪元数据。trace_include_sensitive_data:配置追踪是否包含潜在敏感数据,例如 LLM 与工具调用的输入/输出。workflow_name、trace_id、group_id:设置本次运行的追踪工作流名称、trace ID 和 trace group ID。我们建议至少设置workflow_name。group ID 是可选字段,可让你跨多次运行关联追踪。trace_metadata:要包含在所有追踪中的元数据。session_input_callback:在使用 Sessions 时,自定义在每个回合前如何将新的用户输入与会话历史合并。call_model_input_filter:在模型调用前立即编辑已完全准备好的模型输入(instructions 和输入项)的钩子,例如裁剪历史或注入系统提示词。tool_error_formatter:在审批流程中工具调用被拒绝时,自定义模型可见的消息内容。
嵌套任务转移以可选启用的 beta 形式提供。通过传入 RunConfig(nest_handoff_history=True) 来启用折叠对话记录行为,或对特定任务转移设置 handoff(..., nest_handoff_history=True) 来开启。如果你更希望保留原始对话记录(默认),请不要设置该标志,或提供一个 handoff_input_filter(或 handoff_history_mapper)以按你的需要精确转发对话。若要在不编写自定义 mapper 的情况下更改生成摘要所用的包装文本,请调用 set_conversation_history_wrappers(以及用 reset_conversation_history_wrappers 恢复默认值)。
对话/聊天线程
调用任意 run 方法都可能导致一个或多个智能体运行(因此会有一次或多次 LLM 调用),但它表示聊天对话中的单个逻辑回合。例如:
- 用户回合:用户输入文本
- Runner 运行:第一个智能体调用 LLM、运行工具、任务转移到第二个智能体;第二个智能体运行更多工具,然后生成输出。
在智能体运行结束时,你可以选择向用户展示什么。例如,你可以展示智能体生成的每个新条目,或只展示最终输出。无论哪种方式,用户之后可能会提出后续问题,这时你可以再次调用 run 方法。
手动对话管理
你可以使用 RunResultBase.to_input_list() 方法获取下一回合的输入,从而手动管理对话历史:
async def main():
agent = Agent(name="Assistant", instructions="Reply very concisely.")
thread_id = "thread_123" # Example thread ID
with trace(workflow_name="Conversation", group_id=thread_id):
# First turn
result = await Runner.run(agent, "What city is the Golden Gate Bridge in?")
print(result.final_output)
# San Francisco
# Second turn
new_input = result.to_input_list() + [{"role": "user", "content": "What state is it in?"}]
result = await Runner.run(agent, new_input)
print(result.final_output)
# California
使用 Sessions 自动管理对话
为简化流程,你可以使用 Sessions 自动处理对话历史,而无需手动调用 .to_input_list():
from agents import Agent, Runner, SQLiteSession
async def main():
agent = Agent(name="Assistant", instructions="Reply very concisely.")
# Create session instance
session = SQLiteSession("conversation_123")
thread_id = "thread_123" # Example thread ID
with trace(workflow_name="Conversation", group_id=thread_id):
# First turn
result = await Runner.run(agent, "What city is the Golden Gate Bridge in?", session=session)
print(result.final_output)
# San Francisco
# Second turn - agent automatically remembers previous context
result = await Runner.run(agent, "What state is it in?", session=session)
print(result.final_output)
# California
Sessions 会自动:
- 在每次运行前检索对话历史
- 在每次运行后存储新消息
- 为不同的 session ID 维护彼此独立的对话
更多细节请参阅 Sessions 文档。
由服务端管理的对话
你也可以让 OpenAI 对话状态功能在服务端管理对话状态,而不是在本地用 to_input_list() 或 Sessions 处理。这可以让你在无需手动重发所有历史消息的情况下保留对话历史。更多细节见 OpenAI Conversation state guide。
OpenAI 提供两种方式来跨回合跟踪状态:
1. 使用 conversation_id
你先用 OpenAI Conversations API 创建一个对话,然后在每次后续调用中复用该 ID:
from agents import Agent, Runner
from openai import AsyncOpenAI
client = AsyncOpenAI()
async def main():
agent = Agent(name="Assistant", instructions="Reply very concisely.")
# Create a server-managed conversation
conversation = await client.conversations.create()
conv_id = conversation.id
while True:
user_input = input("You: ")
result = await Runner.run(agent, user_input, conversation_id=conv_id)
print(f"Assistant: {result.final_output}")
2. 使用 previous_response_id
另一种选项是响应串联,即每个回合都显式链接到上一回合的 response ID。
from agents import Agent, Runner
async def main():
agent = Agent(name="Assistant", instructions="Reply very concisely.")
previous_response_id = None
while True:
user_input = input("You: ")
# Setting auto_previous_response_id=True enables response chaining automatically
# for the first turn, even when there's no actual previous response ID yet.
result = await Runner.run(
agent,
user_input,
previous_response_id=previous_response_id,
auto_previous_response_id=True,
)
previous_response_id = result.last_response_id
print(f"Assistant: {result.final_output}")
Call model input filter
使用 call_model_input_filter 在模型调用前编辑模型输入。该钩子会接收当前智能体、上下文以及合并后的输入项(包含会话历史(如有)),并返回新的 ModelInputData。
from agents import Agent, Runner, RunConfig
from agents.run import CallModelData, ModelInputData
def drop_old_messages(data: CallModelData[None]) -> ModelInputData:
# Keep only the last 5 items and preserve existing instructions.
trimmed = data.model_data.input[-5:]
return ModelInputData(input=trimmed, instructions=data.model_data.instructions)
agent = Agent(name="Assistant", instructions="Answer concisely.")
result = Runner.run_sync(
agent,
"Explain quines",
run_config=RunConfig(call_model_input_filter=drop_old_messages),
)
你可以通过 run_config 为每次运行设置该钩子,或在你的 Runner 上设置为默认值,以便对敏感数据进行脱敏、裁剪过长历史,或注入额外的系统指导。
错误处理器
所有 Runner 入口点都接受 error_handlers,这是一个以错误类型为键的 dict。目前支持的键是 "max_turns"。当你希望返回一个可控的最终输出而不是抛出 MaxTurnsExceeded 时使用它。
from agents import (
Agent,
RunErrorHandlerInput,
RunErrorHandlerResult,
Runner,
)
agent = Agent(name="Assistant", instructions="Be concise.")
def on_max_turns(_data: RunErrorHandlerInput[None]) -> RunErrorHandlerResult:
return RunErrorHandlerResult(
final_output="I couldn't finish within the turn limit. Please narrow the request.",
include_in_history=False,
)
result = Runner.run_sync(
agent,
"Analyze this long transcript",
max_turns=3,
error_handlers={"max_turns": on_max_turns},
)
print(result.final_output)
当你不希望将兜底输出追加到对话历史时,将 include_in_history=False。
长时间运行的智能体与 human-in-the-loop
关于工具审批的暂停/恢复模式,请参阅专门的 Human-in-the-loop guide。
Temporal
你可以使用 Agents SDK 的 Temporal 集成来运行持久、长时间运行的工作流,包括 human-in-the-loop 任务。观看 Temporal 与 Agents SDK 协同完成长时任务的演示视频:in this video,并在此查看文档:view docs here。
Restate
你可以使用 Agents SDK 的 Restate 集成来构建轻量、持久的智能体,包括人工审批、任务转移和会话管理。该集成需要 Restate 的单二进制运行时作为依赖,并支持以进程/容器或无服务器函数运行智能体。 阅读概览或查看文档了解更多。
DBOS
你可以使用 Agents SDK 的 DBOS 集成来运行可靠的智能体,在失败与重启之间保留进度。它支持长时间运行的智能体、human-in-the-loop 工作流以及任务转移。同时支持同步和异步方法。该集成只需要 SQLite 或 Postgres 数据库。查看集成 repo 和文档了解更多。
异常
SDK 会在特定情况下抛出异常。完整列表见 agents.exceptions. 概览如下:
AgentsException:这是 SDK 内所有异常的基类。它作为通用类型,其他所有特定异常都从它派生。MaxTurnsExceeded:当智能体运行超过传给Runner.run、Runner.run_sync或Runner.run_streamed方法的max_turns限制时抛出。它表示智能体无法在指定的交互回合数内完成任务。ModelBehaviorError:当底层模型(LLM)产生意外或无效输出时发生。可能包括:- JSON 格式错误:当模型为工具调用或直接输出提供了格式错误的 JSON 结构时,尤其是在定义了特定
output_type的情况下。 - 与工具相关的意外失败:当模型未按预期方式使用工具时
- JSON 格式错误:当模型为工具调用或直接输出提供了格式错误的 JSON 结构时,尤其是在定义了特定
ToolTimeoutError:当某次工具调用超过其配置的超时时间且工具使用timeout_behavior="raise_exception"时抛出。UserError:当你(使用 SDK 编写代码的人)在使用 SDK 时出错会抛出。通常源于代码实现不正确、配置无效或误用 SDK 的 API。InputGuardrailTripwireTriggered、OutputGuardrailTripwireTriggered:当输入安全防护措施或输出安全防护措施分别满足触发条件时抛出。输入安全防护措施会在处理前检查传入消息,而输出安全防护措施会在交付前检查智能体的最终响应。