Excel-to-JSON is a powerful Microsoft Excel add-in that seamlessly converts Excel data into JSON format. Version 2.1.0 brings enhanced features while maintaining our commitment to data privacy and cross-platform accessibility.
Zero-Installation, Instant Access
One of the most compelling features of Excel-to-JSON is its seamless integration with Microsoft Excel. There’s:
No download required
No installation needed
Direct access through Microsoft Excel
Available directly from Microsoft AppSource
Simply open Excel, search for “Excel-to-JSON” in the Add-ins section, and you’re ready to go!
Cross-Platform Compatibility
Excel-to-JSON works flawlessly across multiple platforms:
Windows (Excel 2013 or higher)
macOS
Excel Online
Office 365
Web browsers
Core Features
1. Conversion Modes
Flat JSON Mode: Direct conversion of Excel data to simple JSON structure
Nested JSON Mode: Creates hierarchical JSON using dot notation
Supports delimiter-based nesting (default: “.”)
Automatic key structure recognition
2. Data Processing
First row automatically treated as headers
Line breaks in Excel cells preserved as \n
Multiple export options:
Copy and paste functionality
Direct clipboard copy (Windows)
Privacy-First Approach
We take your data privacy seriously. Excel-to-JSON operates with:
100% local processing
No Excel data transmission to external servers
All conversions performed within your Excel environment
Pro Features
For users requiring advanced functionality, our Pro subscription offers:
This simple example demonstrates how Excel-to-JSON can transform tabular data into structured JSON with nested objects, making it perfect for API integration and data exchange.
Conclusion
Excel-to-JSON 2.1.0 continues to provide a secure, efficient, and user-friendly solution for Excel-to-JSON conversion needs. With its privacy-first approach, cross-platform compatibility, and zero-installation requirement, it’s the ideal tool for developers, data analysts, and business professionals working with Excel data.
Visit our documentation for detailed information and start converting your Excel data to JSON today!
We are excited to announce the official release of RGBA Pixel Extractor Tool v1.0.0! This online tool helps you easily extract RGBA values of each pixel from images and export them as CSV files.
Key Features
Supports common image formats like JPG, PNG
Quickly extracts RGBA values of each pixel
Supports multiple output formats: RGBA, hexadecimal and numeric values
RGBA(r,g,b,a) format
Hexadecimal #RRGGBBAA format
Plain numbers comma separated r,g,b,a format
One-click export to CSV for data analysis
Runs completely in browser - no server upload needed, protecting your privacy
The OpenAI Agents SDK enables you to build agentic AI apps in a lightweight, easy-to-use package with very few abstractions. It's a production-ready upgrade of our previous experimentation for agents, Swarm. The Agents SDK has a very small set of primitives: OpenAI 智能代理 SDK 使您能够使用极少的抽象,在轻量级、易于使用的包中构建智能代理应用程序。它是我们之前针对代理的实验 Swarm 的生产级升级。代理 SDK 具有非常小的一组原语:
Agents, which are LLMs equipped with instructions and tools 代理,它们配备了指令和工具
Handoffs, which allow agents to delegate to other agents for specific tasks 传递,允许代理将特定任务委托给其他代理
Guardrails, which enable the inputs to agents to be validated 保障措施,可以验证代理的输入
In combination with Python, these primitives are powerful enough to express complex relationships between tools and agents, and allow you to build real-world applications without a steep learning curve. In addition, the SDK comes with built-in tracing that lets you visualize and debug your agentic flows, as well as evaluate them and even fine-tune models for your application. 结合 Python,这些原语足够强大,可以表达工具和代理之间的复杂关系,并允许您在没有陡峭的学习曲线的情况下构建实际应用。此外,SDK 还包含内置跟踪功能,可以让您可视化和调试代理流程,甚至评估和微调模型以适应您的应用。
Why use the Agents SDK 为什么使用代理 SDK
The SDK has two driving design principles: SDK 有两个驱动设计原则:
Enough features to be worth using, but few enough primitives to make it quick to learn. 功能足够丰富以值得使用,但基础元素足够少以便快速学习。
Works great out of the box, but you can customize exactly what happens. 开箱即用效果极佳,但你可以完全自定义具体操作。
Here are the main features of the SDK: 这是 SDK 的主要功能:
Agent loop: Built-in agent loop that handles calling tools, sending results to the LLM, and looping until the LLM is done. 代理循环:内置代理循环处理调用工具、将结果发送到LLM以及在LLM完成之前循环执行。
Python-first: Use built-in language features to orchestrate and chain agents, rather than needing to learn new abstractions. Python 优先:使用内置的语言特性来协调和链接代理,而不是需要学习新的抽象概念。
Handoffs: A powerful feature to coordinate and delegate between multiple agents. 手动交接:一个强大的功能,用于协调和委托给多个代理。
Guardrails: Run input validations and checks in parallel to your agents, breaking early if the checks fail. 护栏:在运行输入验证和检查的同时,如果检查失败则提前中断。
Function tools: Turn any Python function into a tool, with automatic schema generation and Pydantic-powered validation. 函数工具:将任何 Python 函数转换为工具,并自动生成模式并使用 Pydantic 进行验证。
Tracing: Built-in tracing that lets you visualize, debug and monitor your workflows, as well as use the OpenAI suite of evaluation, fine-tuning and distillation tools. Tracing: 内置跟踪功能,让您能够可视化、调试和监控工作流,同时还可以使用 OpenAI 套件中的评估、微调和精简工具。
Installation 安装
1 2
pip install openai-agents
Hello world example Hello world 示例
1 2 3 4 5 6 7 8 9 10 11
from agents import Agent, Runner agent = Agent(name="Assistant", instructions="You are a helpful assistant") result = Runner.run_sync(agent, "Write a haiku about recursion in programming.") print(result.final_output) # Code within the code, # Functions calling themselves, # Infinite loop's dance.
(If running this, ensure you set the OPENAI_API_KEY environment variable) (如果运行此代码,请确保设置 OPENAI_API_KEY 环境变量)
1 2
export OPENAI_API_KEY=sk-...
Quickstart 快速开始
Create a project and virtual environment 创建一个项目和虚拟环境
You'll only need to do this once. 你只需要这样做一次。
1 2 3 4
mkdir my_project cd my_project python -m venv .venv
Activate the virtual environment 激活虚拟环境
Do this every time you start a new terminal session. 每次启动新的终端会话时都执行此操作。
1 2
source .venv/bin/activate
Install the Agents SDK 安装代理 SDK
1 2
pip install openai-agents # or `uv add openai-agents`, etc
Set an OpenAI API key 设置 OpenAI API 密钥
If you don't have one, follow these instructions to create an OpenAI API key. 如果没有,请按照这些步骤创建一个 OpenAI API 密钥。
1 2
export OPENAI_API_KEY=sk-...
Create your first agent 创建您的第一个代理
Agents are defined with instructions, a name, and optional config (such as model_config) 代理通过指令、名称和可选配置(如 model_config )来定义。
1 2 3 4 5 6 7
from agents import Agent agent = Agent( name="Math Tutor", instructions="You provide help with math problems. Explain your reasoning at each step and include examples", )
Add a few more agents 添加几个更多的代理
Additional agents can be defined in the same way. handoff_descriptions provide additional context for determining handoff routing 附加代理可以同样定义。 handoff_descriptions 为确定转交路由提供额外上下文
1 2 3 4 5 6 7 8 9 10 11 12 13 14
from agents import Agent history_tutor_agent = Agent( name="History Tutor", handoff_description="Specialist agent for historical questions", instructions="You provide assistance with historical queries. Explain important events and context clearly.", ) math_tutor_agent = Agent( name="Math Tutor", handoff_description="Specialist agent for math questions", instructions="You provide help with math problems. Explain your reasoning at each step and include examples", )
Define your handoffs 定义您的交接内容
On each agent, you can define an inventory of outgoing handoff options that the agent can choose from to decide how to make progress on their task. 在每个代理上,您可以定义一组可供代理选择的传出转交选项,以决定如何推进其任务。
1 2 3 4 5 6
triage_agent = Agent( name="Triage Agent", instructions="You determine which agent to use based on the user's homework question", handoffs=[history_tutor_agent, math_tutor_agent] )
Run the agent orchestration 运行代理编排
Let's check that the workflow runs and the triage agent correctly routes between the two specialist agents. 让我们检查工作流是否运行以及分诊代理是否正确将任务路由到两个专家代理。
1 2 3 4 5 6
from agents import Runner asyncdefmain(): result = await Runner.run(triage_agent, "What is the capital of France?") print(result.final_output)
Add a guardrail 添加一个防撞栏
You can define custom guardrails to run on the input or output. 你可以定义在输入或输出上运行的自定义护栏。
from agents import Agent, InputGuardrail,GuardrailFunctionOutput, Runner from pydantic import BaseModel import asyncio classHomeworkOutput(BaseModel): is_homework: bool reasoning: str guardrail_agent = Agent( name="Guardrail check", instructions="Check if the user is asking about homework.", output_type=HomeworkOutput, ) math_tutor_agent = Agent( name="Math Tutor", handoff_description="Specialist agent for math questions", instructions="You provide help with math problems. Explain your reasoning at each step and include examples", ) history_tutor_agent = Agent( name="History Tutor", handoff_description="Specialist agent for historical questions", instructions="You provide assistance with historical queries. Explain important events and context clearly.", ) asyncdefhomework_guardrail(ctx, agent, input_data): result = await Runner.run(guardrail_agent, input_data, context=ctx.context) final_output = result.final_output_as(HomeworkOutput) return GuardrailFunctionOutput( output_info=final_output, tripwire_triggered=not final_output.is_homework, ) triage_agent = Agent( name="Triage Agent", instructions="You determine which agent to use based on the user's homework question", handoffs=[history_tutor_agent, math_tutor_agent], input_guardrails=[ InputGuardrail(guardrail_function=homework_guardrail), ], ) asyncdefmain(): result = await Runner.run(triage_agent, "who was the first president of the united states?") print(result.final_output) result = await Runner.run(triage_agent, "what is life") print(result.final_output) if __name__ == "__main__": asyncio.run(main())
View your traces 查看您的跟踪
To review what happened during your agent run, navigate to the Trace viewer in the OpenAI Dashboard to view traces of your agent runs. 为了回顾您的智能体运行期间发生了什么,请导航到 OpenAI 控制台中的跟踪查看器以查看智能体运行的跟踪。
Agents 代理
Agents are the core building block in your apps. An agent is a large language model (LLM), configured with instructions and tools. 代理是您应用程序中的核心构建块。代理是一个大型语言模型(LLM),配置有指令和工具。
Basic configuration 基本配置
The most common properties of an agent you'll configure are: 你将配置的代理最常见的属性是:
instructions: also known as a developer message or system prompt. instructions :也被称为开发人员消息或系统提示。
model: which LLM to use, and optional model_settings to configure model tuning parameters like temperature, top_p, etc. model :选择LLM,以及可选的 model_settings 来配置模型调优参数,如温度、top_p 等。
tools: Tools that the agent can use to achieve its tasks. tools : 代理人可以使用的工具以完成其任务。
1 2 3 4 5 6 7 8 9 10 11 12 13
from agents import Agent, ModelSettings, function_tool @function_tool defget_weather(city: str) -> str: returnf"The weather in is sunny" agent = Agent( name="Haiku agent", instructions="Always respond in haiku form", model="o3-mini", tools=[get_weather], )
Context 上下文
Agents are generic on their context type. Context is a dependency-injection tool: it's an object you create and pass to Runner.run(), that is passed to every agent, tool, handoff etc, and it serves as a grab bag of dependencies and state for the agent run. You can provide any Python object as the context. 代理对其 context 类型是通用的。Context 是一个依赖注入工具:它是一个你创建并传递给 Runner.run() 的对象,该对象会传递给每一个代理、工具、转交等,并作为代理运行时依赖和状态的集合。你可以提供任何 Python 对象作为 Context。
By default, agents produce plain text (i.e. str) outputs. If you want the agent to produce a particular type of output, you can use the output_type parameter. A common choice is to use Pydantic objects, but we support any type that can be wrapped in a Pydantic TypeAdapter - dataclasses, lists, TypedDict, etc. 默认情况下,代理生成的是纯文本(即 str )输出。如果您希望代理生成特定类型的输出,可以使用 output_type 参数。常见的选择是使用 Pydantic 对象,但我们支持任何可以被包装在 Pydantic TypeAdapter 中的类型——数据类、列表、TypedDict 等。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
from pydantic import BaseModel from agents import Agent classCalendarEvent(BaseModel): name: str date: str participants: list[str] agent = Agent( name="Calendar extractor", instructions="Extract calendar events from text", output_type=CalendarEvent, )
Note 注意
When you pass an output_type, that tells the model to use structured outputs instead of regular plain text responses. 当您传递一个 output_type 时,这告诉模型使用结构化输出而不是常规的纯文本响应。
Handoffs 手递手
Handoffs are sub-agents that the agent can delegate to. You provide a list of handoffs, and the agent can choose to delegate to them if relevant. This is a powerful pattern that allows orchestrating modular, specialized agents that excel at a single task. Read more in the documentation. 手递手操作是代理可以委派的子代理。您提供一个手递手操作列表,如果相关,代理可以选择委派给他们。这是一个强大的模式,允许协调模块化、专业化的代理,这些代理在单一任务上表现出色。更多详情请参阅手递手操作文档。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
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, handoff to the booking agent." "If they ask about refunds, handoff to the refund agent." ), handoffs=[booking_agent, refund_agent], )
Dynamic instructions 动态指令
In most cases, you can provide instructions when you create the agent. However, you can also provide dynamic instructions via a function. The function will receive the agent and context, and must return the prompt. Both regular and async functions are accepted. 在大多数情况下,您可以在创建代理时提供指令。但是,您也可以通过一个函数提供动态指令。该函数将接收代理和上下文,并必须返回提示。常规函数和 async 函数都接受。
1 2 3 4 5 6 7 8 9 10 11
defdynamic_instructions( context: RunContextWrapper[UserContext], agent: Agent[UserContext] ) -> str: returnf"The user's name is . Help them with their questions."
Sometimes, you want to observe the lifecycle of an agent. For example, you may want to log events, or pre-fetch data when certain events occur. You can hook into the agent lifecycle with the hooks property. Subclass the class, and override the methods you're interested in. 有时,您希望观察代理的生命周期。例如,您可能希望记录事件,或者在某些事件发生时预取数据。您可以使用 hooks 属性钩入代理生命周期。从 AgentHooks 类派生,并覆盖您感兴趣的任何方法。
Guardrails 守护措施
Guardrails allow you to run checks/validations on user input, in parallel to the agent running. For example, you could screen the user's input for relevance. Read more in the documentation. 限制措施允许您在代理运行的同时对用户输入进行检查/验证。例如,您可以筛选用户输入的相关性。有关更多信息,请参阅限制措施文档。
Cloning/copying agents 克隆/复制代理
By using the clone() method on an agent, you can duplicate an Agent, and optionally change any properties you like. 通过在代理上使用 clone() 方法,您可以复制一个代理,并可选地更改任何属性。
1 2 3 4 5 6 7 8 9 10 11
pirate_agent = Agent( name="Pirate", instructions="Write like a pirate", model="o3-mini", )
robot_agent = pirate_agent.clone( name="Robot", instructions="Write like a robot", )
Running agents 运行代理
You can run agents via the class. You have 3 options: 您可以通过 Runner 类来运行代理。您有 3 种选择:
Runner.run(), which runs async and returns a RunResult. Runner.run() ,这会异步运行并返回一个 RunResult 。
Runner.run_sync(), which is a sync method and just runs .run() under the hood. Runner.run_sync() ,这是一个同步方法,只是在后台运行 .run() 。
Runner.run_streamed(), which runs async and returns a RunResultStreaming. It calls the LLM in streaming mode, and streams those events to you as they are received. Runner.run_streamed() ,这是一个异步方法并返回一个 RunResultStreaming 。它以流式模式调用LLM,并将接收到的事件实时流式传输给您。
1 2 3 4 5 6 7 8 9 10 11
from agents import Agent, Runner asyncdefmain(): 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.
When you use the run method in Runner, you pass in a starting agent and input. The input can either be a string (which is considered a user message), or a list of input items, which are the items in the OpenAI Responses API. 当你在 Runner 中使用 run 方法时,你需要传入一个起始代理和输入。输入可以是一个字符串(被视为用户消息),或者是一个输入项列表,这些项是 OpenAI Responses API 中的项目。
The runner then runs a loop: 然后运行器运行一个循环:
We call the LLM for the current agent, with the current input. 当前代理调用LLM,并带上当前输入。
The LLM produces its output. LLM生成其输出。
If the LLM returns a final_output, the loop ends and we return the result. 如果LLM返回一个 final_output ,则循环结束并返回结果。
If the LLM does a handoff, we update the current agent and input, and re-run the loop. 如果LLM进行转接,我们将更新当前坐席和输入,并重新运行循环。
If the LLM produces tool calls, we run those tool calls, append the results, and re-run the loop. 如果LLM生成了工具调用,我们将运行这些工具调用,追加结果,并重新运行循环。
If we exceed the max_turns passed, we raise a MaxTurnsExceeded exception. 如果超过 max_turns 传递的次数,我们将抛出一个 MaxTurnsExceeded 异常。
Note 注意
The rule for whether the LLM output is considered as a "final output" is that it produces text output with the desired type, and there are no tool calls. LLM 输出被视为”最终输出”的规则是它生成了所需类型的文字输出,并且没有调用工具。
Streaming 流式传输
Streaming allows you to additionally receive streaming events as the LLM runs. Once the stream is done, the RunResultStreaming will contain the complete information about the run, including all the new outputs produces. You can call .stream_events() for the streaming events. Read more in the streaming guide. 流式传输允许你在 LLM 运行时额外接收流式事件。一旦流式传输结束, RunResultStreaming 将包含关于运行的完整信息,包括所有新生成的输出。你可以调用 .stream_events() 获取流式事件。更多详情请参阅流式传输指南。
Run config 运行配置
The run_config parameter lets you configure some global settings for the agent run: run_config 参数允许您为代理运行配置一些全局设置:
model: Allows setting a global LLM model to use, irrespective of what model each Agent has. model :允许设置一个全局的LLM 模型,无论每个代理使用什么 model 。
model_provider: A model provider for looking up model names, which defaults to OpenAI. model_provider :用于查找模型名称的模型提供者,默认为 OpenAI。
model_settings: Overrides agent-specific settings. For example, you can set a global temperature or top_p. model_settings : 覆盖特定代理的设置。例如,你可以设置一个全局 temperature 或 top_p 。
input_guardrails, output_guardrails: A list of input or output guardrails to include on all runs. input_guardrails , output_guardrails : 包含在所有运行中的输入或输出护栏列表。
handoff_input_filter: A global input filter to apply to all handoffs, if the handoff doesn't already have one. The input filter allows you to edit the inputs that are sent to the new agent. See the documentation in Handoff.input_filter for more details. handoff_input_filter : 如果代理转交没有自己的输入过滤器,则应用于所有转交的全局输入过滤器。输入过滤器允许你编辑发送到新代理的输入。有关详细信息,请参阅 Handoff.input_filter 中的文档。
tracing_disabled: Allows you to disable tracing for the entire run. tracing_disabled : 允许你禁用整个运行过程中的跟踪。
trace_include_sensitive_data: Configures whether traces will include potentially sensitive data, such as LLM and tool call inputs/outputs. trace_include_sensitive_data : 配置跟踪是否包含可能敏感的数据,例如LLM 和工具调用的输入/输出。
workflow_name, trace_id, group_id: Sets the tracing workflow name, trace ID and trace group ID for the run. We recommend at least setting workflow_name. The session ID is an optional field that lets you link traces across multiple runs. workflow_name , trace_id , group_id : 设置运行的跟踪工作流名称、跟踪 ID 和跟踪组 ID。我们建议至少设置 workflow_name 。会话 ID 是一个可选字段,可以让你在多个运行之间链接跟踪。
trace_metadata: Metadata to include on all traces. trace_metadata : 在所有跟踪中包含的元数据。
Conversations/chat threads 对话/聊天线程
Calling any of the run methods can result in one or more agents running (and hence one or more LLM calls), but it represents a single logical turn in a chat conversation. For example: 调用任何运行方法可能会导致一个或多个代理运行(因此可能会导致一个或多个LLM调用),但这代表聊天对话中的一个单一逻辑回合。例如:
User turn: user enter text 用户回合: user enter text
Runner run: first agent calls LLM, runs tools, does a handoff to a second agent, second agent runs more tools, and then produces an output. 运行代理:第一个代理调用LLM,运行工具,然后将工作转交给第二个代理,第二个代理运行更多工具,最后生成输出。
At the end of the agent run, you can choose what to show to the user. For example, you might show the user every new item generated by the agents, or just the final output. Either way, the user might then ask a followup question, in which case you can call the run method again. 在代理运行结束时,您可以选择向用户展示什么内容。例如,您可以向用户展示代理生成的每个新项目,或者只展示最终输出。无论哪种方式,用户可能会提出后续问题,这时您可以再次调用运行方法。
You can use the base RunResultBase.to_input_list() method to get the inputs for the next turn. 您可以使用基础 RunResultBase.to_input_list() 方法获取下一次轮次的输入。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
asyncdefmain(): agent = Agent(name="Assistant", instructions="Reply very concisely.")
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() + [] result = await Runner.run(agent, new_input) print(result.final_output) # California
Exceptions 异常
The SDK raises exceptions in certain cases. The full list is in agents.exceptions. As an overview: 该 SDK 在某些情况下会抛出异常。完整的列表在 agents.exceptions 中。总体来说:
AgentsException is the base class for all exceptions raised in the SDK. AgentsException 是 SDK 中所有抛出的异常的基类。
MaxTurnsExceeded is raised when the run exceeds the max_turns passed to the run methods. 当运行超出 max_turns 中传递给 run 方法的值时,会抛出 MaxTurnsExceeded 。
ModelBehaviorError is raised when the model produces invalid outputs, e.g. malformed JSON or using non-existent tools. ModelBehaviorError 是当模型产生无效输出时抛出的,例如生成格式错误的 JSON 或使用不存在的工具。
UserError is raised when you (the person writing code using the SDK) make an error using the SDK. UserError 是当您(使用 SDK 编写代码的人)使用 SDK 时发生错误时抛出的。
When you call the Runner.run methods, you either get a: 调用 Runner.run 方法时,您会得到一个:
RunResult if you call run or run_sync RunResult 如果您调用 run 或 run_sync
RunResultStreaming if you call run_streamed RunResultStreaming 如果你调用 run_streamed
Both of these inherit from RunResultBase, which is where most useful information is present. 这两个都继承自 RunResultBase ,大多数有用的信息都在这里。
Final output 最终输出
The final_output property contains the final output of the last agent that ran. This is either: final_output 属性包含最后一个运行的代理的最终输出。这可能是:
a str, if the last agent didn't have an output_type defined str ,如果最后一个代理没有定义 output_type
an object of type last_agent.output_type, if the agent had an output type defined. 类型为 last_agent.output_type 的对象,如果代理定义了输出类型。
Note 注意
final_output is of type Any. We can't statically type this, because of handoffs. If handoffs occur, that means any Agent might be the last agent, so we don't statically know the set of possible output types. final_output 是 Any 类型。我们无法静态类型化这一点,因为存在手递。如果发生手递,这意味着任何代理都可能是最后一个代理,所以我们无法静态知道可能的输出类型集合。
Inputs for the next turn 下一次轮次的输入
You can use result.to_input_list() to turn the result into an input list that concatenates the original input you provided, to the items generated during the agent run. This makes it convenient to take the outputs of one agent run and pass them into another run, or to run it in a loop and append new user inputs each time. 你可以使用 result.to_input_list() 将结果转换为一个输入列表,该列表将你提供的原始输入与代理运行期间生成的项连接起来。这使得可以方便地将一个代理运行的输出传递给另一个运行,或者在循环中运行并每次追加新的用户输入。
Last agent 最后一个代理
The last_agent property contains the last agent that ran. Depending on your application, this is often useful for the next time the user inputs something. For example, if you have a frontline triage agent that hands off to a language-specific agent, you can store the last agent, and re-use it the next time the user messages the agent. last_agent 属性包含最近运行的代理。根据您的应用程序,这在用户下次输入时通常很有用。例如,如果您有一个前线分诊代理,将转交给特定语言的代理,您可以存储最后一个代理,并在用户下次与代理通信时重用它。
New items 新项目
The new_items property contains the new items generated during the run. The items are RunItems. A run item wraps the raw item generated by the LLM. new_items 属性包含运行期间生成的新项目。项目是 RunItem 。运行项目包装了由LLM生成的原始项目。
MessageOutputItem indicates a message from the LLM. The raw item is the message generated. MessageOutputItem 表示来自 LLM 的消息。原始项是生成的消息。
HandoffCallItem indicates that the LLM called the handoff tool. The raw item is the tool call item from the LLM. HandoffCallItem 表示 LLM 调用了转接工具。原始项是从 LLM 获取的转接工具调用项。
HandoffOutputItem indicates that a handoff occurred. The raw item is the tool response to the handoff tool call. You can also access the source/target agents from the item. HandoffOutputItem 表示发生了转接。原始项是转接工具调用的响应。您还可以从项中访问源/目标代理。
ToolCallItem indicates that the LLM invoked a tool. ToolCallItem 表示 LLM 调用了工具。
ToolCallOutputItem indicates that a tool was called. The raw item is the tool response. You can also access the tool output from the item. ToolCallOutputItem 表示调用了一个工具。原始项是工具的响应。你也可以从项中访问工具输出。
ReasoningItem indicates a reasoning item from the LLM. The raw item is the reasoning generated. ReasoningItem 表示 LLM 的推理项。原始项是生成的推理。
Other information 其他信息
Guardrail results 护栏结果
The input_guardrail_results and output_guardrail_results properties contain the results of the guardrails, if any. Guardrail results can sometimes contain useful information you want to log or store, so we make these available to you. input_guardrail_results 和 output_guardrail_results 属性包含防护栏的结果(如果有)。防护栏结果有时包含您想要记录或存储的有用信息,因此我们把这些信息提供给您。
Raw responses 原始响应
The raw_responses property contains the ModelResponse generated by the LLM. The raw_responses 属性包含由 LLM 生成的 ModelResponse 。
Original input
The input property contains the original input you provided to the run method. In most cases you won't need this, but it's available in case you do. input 属性包含您提供的原始输入。在大多数情况下您不需要这个属性,但在需要时它是可用的。 run
Streaming 流式传输
Streaming lets you subscribe to updates of the agent run as it proceeds. This can be useful for showing the end-user progress updates and partial responses. 实时流让你可以订阅代理运行过程中产生的更新。这对于向最终用户显示进度更新和部分响应非常有用。
To stream, you can call Runner.run_streamed(), which will give you a RunResultStreaming. Calling result.stream_events() gives you an async stream of StreamEvent objects, which are described below. 要实现流式传输,可以调用 Runner.run_streamed() ,这将给你一个 RunResultStreaming 。调用 result.stream_events() 会给你一个异步流式的 StreamEvent 对象,其描述如下。
Raw response events 原始响应事件
RawResponsesStreamEvent are raw events passed directly from the LLM. They are in OpenAI Responses API format, which means each event has a type (like response.created, response.output_text.delta, etc) and data. These events are useful if you want to stream response messages to the user as soon as they are generated. RawResponsesStreamEvent 是直接从LLM获取的原始事件。它们遵循 OpenAI Responses API 格式,这意味着每个事件都有一个类型(如 response.created , response.output_text.delta 等)和数据。这些事件在您希望尽快向用户输出生成的消息时非常有用。
For example, this will output the text generated by the LLM token-by-token. 例如,这将逐个输出LLM生成的文本。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
import asyncio from openai.types.responses import ResponseTextDeltaEvent from agents import Agent, Runner
asyncdefmain(): agent = Agent( name="Joker", instructions="You are a helpful assistant.", )
result = Runner.run_streamed(agent, input="Please tell me 5 jokes.") asyncfor event in result.stream_events(): if event.type == "raw_response_event"andisinstance(event.data, ResponseTextDeltaEvent): print(event.data.delta, end="", flush=True)
if __name__ == "__main__": asyncio.run(main())
Run item events and agent events 运行项目事件和代理事件
RunItemStreamEvent are higher level events. They inform you when an item has been fully generated. This allows you to push progress updates at the level of "message generated", "tool ran", etc, instead of each token. Similarly, AgentUpdatedStreamEvent gives you updates when the current agent changes (e.g. as the result of a handoff). RunItemStreamEvent 是更高层次的事件。它们告诉您项目已完全生成。这允许您在”消息生成”、”工具运行”等层面推送进度更新,而不是每个标记。同样, AgentUpdatedStreamEvent 在当前代理发生变化时(例如,作为移交的结果)为您提供更新。
For example, this will ignore raw events and stream updates to the user. 例如,这将忽略原始事件并将更新流式传输给用户。
asyncdefmain(): agent = Agent( name="Joker", instructions="First call the `how_many_jokes` tool, then tell that many jokes.", tools=[how_many_jokes], )
result = Runner.run_streamed( agent, input="Hello", ) print("=== Run starting ===")
asyncfor event in result.stream_events(): # We'll ignore the raw responses event deltas if event.type == "raw_response_event": continue # When the agent updates, print that elif event.type == "agent_updated_stream_event": print(f"Agent updated: ") continue # When items are generated, print them elif event.type == "run_item_stream_event": if event.item.type == "tool_call_item": print("-- Tool was called") elif event.item.type == "tool_call_output_item": print(f"-- Tool output: ") elif event.item.type == "message_output_item": print(f"-- Message output:\n ") else: pass# Ignore other event types
print("=== Run complete ===")
if __name__ == "__main__": asyncio.run(main())
Tools 工具
Tools let agents take actions: things like fetching data, running code, calling external APIs, and even using a computer. There are three classes of tools in the Agent SDK: 工具可以让代理执行操作:比如获取数据、运行代码、调用外部 API,甚至使用计算机。代理 SDK 中有三类工具:
Hosted tools: these run on LLM servers alongside the AI models. OpenAI offers retrieval, web search and computer use as hosted tools. 托管工具:这些工具在LLM服务器上与 AI 模型一同运行。OpenAI 提供了检索、网络搜索和计算机使用作为托管工具。
Function calling: these allow you to use any Python function as a tool. 函数调用:这些允许您使用任何 Python 函数作为工具。
Agents as tools: this allows you to use an agent as a tool, allowing Agents to call other agents without handing off to them. 作为工具的代理:这允许你将代理作为工具使用,使代理能够调用其他代理而无需将其转交给其他代理。
Hosted tools 托管工具
OpenAI offers a few built-in tools when using the OpenAIResponsesModel{.autorefs .autorefs-internal}: 使用 OpenAIResponsesModel 时,OpenAI 提供了几种内置工具。
The WebSearchTool lets an agent search the web. The WebSearchTool 让智能体搜索网络。
The FileSearchTool allows retrieving information from your OpenAI Vector Stores. The FileSearchTool 允许从您的 OpenAI 向量存储中检索信息。
The ComputerTool allows automating computer use tasks. The ComputerTool 允许自动化计算机使用任务。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
from agents import Agent, FileSearchTool, Runner, WebSearchTool
asyncdefmain(): result = await Runner.run(agent, "Which coffee shop should I go to, taking into account my preferences and the weather today in SF?") print(result.final_output)
Function tools 功能工具
You can use any Python function as a tool. The Agents SDK will setup the tool automatically: 你可以使用任何 Python 函数作为工具。Agents SDK 会自动设置该工具:
The name of the tool will be the name of the Python function (or you can provide a name) 工具的名称将是 Python 函数的名称(或者你可以提供一个名称)
Tool description will be taken from the docstring of the function (or you can provide a description) 工具描述将从函数的文档字符串中获取(或者你可以提供描述)
The schema for the function inputs is automatically created from the function's arguments 函数输入的模式会自动从函数的参数创建
Descriptions for each input are taken from the docstring of the function, unless disabled 每个输入的描述会从函数的文档字符串中获取,除非禁用
We use Python's inspect module to extract the function signature, along with griffe to parse docstrings and pydantic for schema creation. 我们使用 Python 的 inspect 模块来提取函数签名,使用 griffe 来解析文档字符串,并使用 pydantic 来创建模式。
from agents import Agent, FunctionTool, RunContextWrapper, function_tool
classLocation(TypedDict): lat: float long: float
@function_tool asyncdeffetch_weather(location: Location) -> str: """Fetch the weather for a given location. Args: location: The location to fetch the weather for. """ # In real life, we'd fetch the weather from a weather API return"sunny"
@function_tool(name_override="fetch_data") defread_file(ctx: RunContextWrapper[Any], path: str, directory: str | None = None) -> str: """Read the contents of a file. Args: path: The path to the file to read. directory: The directory to read the file from. """ # In real life, we'd read the file from the file system return"<file contents>"
fetch_weather Fetch the weather for a given location. { "$defs": { "Location": { "properties": { "lat": { "title": "Lat", "type": "number" }, "long": { "title": "Long", "type": "number" } }, "required": [ "lat", "long" ], "title": "Location", "type": "object" } }, "properties": { "location": { "$ref": "#/$defs/Location", "description": "The location to fetch the weather for." } }, "required": [ "location" ], "title": "fetch_weather_args", "type": "object" }
fetch_data Read the contents of a file. { "properties": { "path": { "description": "The path to the file to read.", "title": "Path", "type": "string" }, "directory": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null, "description": "The directory to read the file from.", "title": "Directory" } }, "required": [ "path" ], "title": "fetch_data_args", "type": "object" }
Custom function tools 自定义函数工具
Sometimes, you don't want to use a Python function as a tool. You can directly create a FunctionTool if you prefer. You'll need to provide: 有时,你不想使用 Python 函数作为工具。如果你愿意,可以直接创建一个 FunctionTool 。你需要提供:
name
description
params_json_schema, which is the JSON schema for the arguments params_json_schema ,这是参数的 JSON 模式
on_invoke_tool, which is an async function that receives the context and the arguments as a JSON string, and must return the tool output as a string. on_invoke_tool ,这是一个异步函数,接收上下文和作为 JSON 字符串的参数,并且必须返回工具输出的字符串。
Automatic argument and docstring parsing 自动参数和文档字符串解析
As mentioned before, we automatically parse the function signature to extract the schema for the tool, and we parse the docstring to extract descriptions for the tool and for individual arguments. Some notes on that: 如前所述,我们自动解析函数签名以提取工具的模式,并解析文档字符串以提取工具及其个别参数的描述。关于这一点的一些注意事项:
The signature parsing is done via the inspect module. We use type annotations to understand the types for the arguments, and dynamically build a Pydantic model to represent the overall schema. It supports most types, including Python primitives, Pydantic models, TypedDicts, and more. 签名解析是通过 inspect 模块完成的。我们使用类型注解来理解参数的类型,并动态构建 Pydantic 模型来表示整体模式。它支持大多数类型,包括 Python 原语、Pydantic 模型、TypedDicts 等。
We use griffe to parse docstrings. Supported docstring formats are google, sphinx and numpy. We attempt to automatically detect the docstring format, but this is best-effort and you can explicitly set it when calling function_tool. You can also disable docstring parsing by setting use_docstring_info to False. 我们使用 griffe 来解析文档字符串。支持的文档字符串格式有 google , sphinx 和 numpy 。我们尝试自动检测文档字符串格式,但这只是尽力而为,您可以在调用 function_tool 时明确设置它。您还可以通过将 use_docstring_info 设置为 False 来禁用文档字符串解析。
The code for the schema extraction lives in agents.function_schema{.autorefs .autorefs-internal}. 作为工具的代理代码位于 agents.function_schema 中。
Agents as tools 代理作为工具
In some workflows, you may want a central agent to orchestrate a network of specialized agents, instead of handing off control. You can do this by modeling agents as tools. 在某些工作流程中,您可能希望有一个中央代理来协调一组专门的代理,而不是转交控制权。您可以通过将代理建模为工具来实现这一点。
spanish_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", )
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." ), 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", ), ], )
asyncdefmain(): result = await Runner.run(orchestrator_agent, input="Say 'Hello, how are you?' in Spanish.") print(result.final_output)
Handling errors in function tools 处理函数工具中的错误
When you create a function tool via @function_tool, you can pass a failure_error_function. This is a function that provides an error response to the LLM in case the tool call crashes. 当您通过 @function_tool 创建一个函数工具时,可以传递一个 failure_error_function 。这是一个在工具调用崩溃时提供错误响应的LLM函数。
By default (i.e. if you don't pass anything), it runs a default_tool_error_function which tells the LLM an error occurred.
If you pass your own error function, it runs that instead, and sends the response to the LLM.
If you explicitly pass None, then any tool call errors will be re-raised for you to handle. This could be a ModelBehaviorError if the model produced invalid JSON, or a UserError if your code crashed, etc.
If you are manually creating a FunctionTool object, then you must handle errors inside the on_invoke_tool function. 如果手动创建一个 FunctionTool 对象,那么必须在 on_invoke_tool 函数内部处理错误。
Handoffs 手递手
Handoffs allow an agent to delegate tasks to another agent. This is particularly useful in scenarios where different agents specialize in distinct areas. For example, a customer support app might have agents that each specifically handle tasks like order status, refunds, FAQs, etc. 手递包括一个代理将任务委派给另一个代理。这在不同代理在特定领域专业化的情景中特别有用。例如,一个客户服务应用程序可能有专门处理订单状态、退款、常见问题解答等任务的代理。
Handoffs are represented as tools to the LLM. So if there's a handoff to an agent named Refund Agent, the tool would be called transfer_to_refund_agent. Handoffs 作为工具由 LLM 提供。所以如果有一个交给名为 Refund Agent 的代理的手递,那么这个工具将被称为 transfer_to_refund_agent 。
Creating a handoff 创建一个交接
All agents have a handoffs param, which can either take an Agent directly, or a Handoff object that customizes the Handoff. 所有代理都有一个 handoffs 参数,它可以接受一个 Agent 直接或一个 Handoff 对象来自定义 Handoff。
You can create a handoff using the handoff() function provided by the Agents SDK. This function allows you to specify the agent to hand off to, along with optional overrides and input filters. 您可以使用代理 SDK 提供的 handoff() 函数创建 Handoff。此函数允许您指定要转交的代理,以及可选的覆盖和输入过滤。
Basic Usage 基本用法
Here's how you can create a simple handoff: 这里是如何创建一个简单的手 off:
Customizing handoffs via the handoff() function 通过 handoff() 函数自定义手 offs
The handoff(){.autorefs .autorefs-internal} function lets you customize things. handoff() 函数允许您自定义内容。
agent: This is the agent to which things will be handed off. agent : 这是将要接收内容的代理。
tool_name_override: By default, the Handoff.default_tool_name() function is used, which resolves to transfer_to_<agent_name>. You can override this. tool_name_override : 默认情况下,使用 Handoff.default_tool_name() 函数,该函数解析为 transfer_to_<agent_name> 。您可以覆盖此设置。
tool_description_override: Override the default tool description from Handoff.default_tool_description() tool_description_override : 从 Handoff.default_tool_description() 覆盖默认工具描述
on_handoff: A callback function executed when the handoff is invoked. This is useful for things like kicking off some data fetching as soon as you know a handoff is being invoked. This function receives the agent context, and can optionally also receive LLM generated input. The input data is controlled by the input_type param. on_handoff : 在交接被调用时执行的回调函数。这在你知道一个交接即将被调用时,比如启动一些数据获取等非常有用。此函数接收代理上下文,并可选地接收LLM 生成的输入。输入数据由 input_type 参数控制。
input_type: The type of input expected by the handoff (optional). input_type : 交接期望的输入类型(可选)。
input_filter: This lets you filter the input received by the next agent. See below for more. input_filter : 这可以让您过滤下一个代理接收到的输入。更多内容请参见下方。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
from agents import Agent, handoff, RunContextWrapper
In certain situations, you want the LLM to provide some data when it calls a handoff. For example, imagine a handoff to an "Escalation agent". You might want a reason to be provided, so you can log it. 在某些情况下,您希望LLM在呼叫转接时提供一些数据。例如,假设有一个转接到”升级代理”的转接。您可能希望提供一个原因,以便记录。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
from pydantic import BaseModel
from agents import Agent, handoff, RunContextWrapper
classEscalationData(BaseModel): reason: str
asyncdefon_handoff(ctx: RunContextWrapper[None], input_data: EscalationData): print(f"Escalation agent called with reason: ")
When a handoff occurs, it's as though the new agent takes over the conversation, and gets to see the entire previous conversation history. If you want to change this, you can set an input_filter. An input filter is a function that receives the existing input via a HandoffInputData, and must return a new HandoffInputData. 当发生转接时,新代理就像接管了对话,并能看到整个之前的对话历史。如果您想改变这一点,可以设置一个 input_filter 。输入过滤器是一个函数,它通过 HandoffInputData 接收现有的输入,并必须返回一个新的 HandoffInputData 。
There are some common patterns (for example removing all tool calls from the history), which are implemented for you in agents.extensions.handoff_filters{.autorefs .autorefs-internal} 有一些常见的模式(例如,从历史记录中移除所有工具调用),这些模式在 agents.extensions.handoff_filters 中为你实现了
1 2 3 4 5 6 7 8 9 10
from agents import Agent, handoff from agents.extensions import handoff_filters
To make sure that LLMs understand handoffs properly, we recommend including information about handoffs in your agents. We have a suggested prefix in agents.extensions.handoff_prompt.RECOMMENDED_PROMPT_PREFIX, or you can call agents.extensions.handoff_prompt.prompt_with_handoff_instructions to automatically add recommended data to your prompts. 为了确保LLMs正确理解交接,我们建议在你的代理中包含关于交接的信息。我们有一个建议的前缀在 agents.extensions.handoff_prompt.RECOMMENDED_PROMPT_PREFIX 中,或者你可以调用 agents.extensions.handoff_prompt.prompt_with_handoff_instructions 以自动将推荐的数据添加到你的提示中。
1 2 3 4 5 6 7 8 9
from agents import Agent from agents.extensions.handoff_prompt import RECOMMENDED_PROMPT_PREFIX
billing_agent = Agent( name="Billing agent", instructions=f""" <Fill in the rest of your prompt here>.""", )
Tracing 跟踪
The Agents SDK includes built-in tracing, collecting a comprehensive record of events during an agent run: LLM generations, tool calls, handoffs, guardrails, and even custom events that occur. Using the Traces dashboard, you can debug, visualize, and monitor your workflows during development and in production. Agents SDK 包含内置的跟踪功能,收集代理运行期间的全面事件记录:LLM 生成、工具调用、传递、护栏,甚至发生的自定义事件。通过 Traces 控制面板,您可以在开发和生产环境中调试、可视化和监控工作流。
Note 注意
Tracing is enabled by default. There are two ways to disable tracing: 跟踪默认启用。有两种方法可以禁用跟踪:
You can globally disable tracing by setting the env var OPENAI_AGENTS_DISABLE_TRACING=1 您可以通过设置环境变量 OPENAI_AGENTS_DISABLE_TRACING=1 全局禁用跟踪。
You can disable tracing for a single run by setting agents.run.RunConfig.tracing_disabled to True 可以通过设置 agents.run.RunConfig.tracing_disabled 为 True 来禁用单次运行的跟踪
Traces and spans 跟踪和跨度
Traces represent a single end-to-end operation of a "workflow". They're composed of Spans. Traces have the following properties: 跟踪代表一个”工作流”的端到端操作。它们由跨度组成。跟踪具有以下属性:
workflow_name: This is the logical workflow or app. For example "Code generation" or "Customer service". 这是逻辑工作流或应用。例如”代码生成”或”客户服务”。
trace_id: A unique ID for the trace. Automatically generated if you don't pass one. Must have the format trace_<32_alphanumeric>. 这是跟踪的唯一 ID。如果没有传递,将自动生成。必须具有 trace_<32_alphanumeric> 的格式。
group_id: Optional group ID, to link multiple traces from the same conversation. For example, you might use a chat thread ID. 可选的组 ID,用于链接同一对话中的多个跟踪。例如,你可能会使用聊天线程 ID。
disabled: If True, the trace will not be recorded. 如果为 True,将不会记录跟踪。
metadata: Optional metadata for the trace. 可选的跟踪元数据。
Spans represent operations that have a start and end time. Spans have: 范围代表具有开始和结束时间的操作。范围包含:
started_at and ended_at timestamps. started_at 和 ended_at 时间戳。
trace_id, to represent the trace they belong to trace_id ,以表示它们所属的跟踪
parent_id, which points to the parent Span of this Span (if any) parent_id ,指向此 Span 的父 Span(如果有)
span_data, which is information about the Span. For example, AgentSpanData contains information about the Agent, GenerationSpanData contains information about the LLM generation, etc. span_data ,这是关于 Span 的信息。例如, AgentSpanData 包含关于 Agent 的信息, GenerationSpanData 包含关于 LLM 生成的信息,等等。
Default tracing 默认跟踪
By default, the SDK traces the following: 默认情况下,SDK 会跟踪以下内容:
The entire Runner.() is wrapped in a trace(). 整个 Runner.() 被包裹在 trace() 中。
Each time an agent runs, it is wrapped in agent_span() 每次运行一个代理时,它会被包裹在 agent_span() 中。
LLM generations are wrapped in generation_span() 生成代数被包裹在 generation_span()
Function tool calls are each wrapped in function_span() 函数工具调用各自被包裹在 function_span()
Guardrails are wrapped in guardrail_span() 守护 rails 被包裹在 guardrail_span()
Handoffs are wrapped in handoff_span() 手递手操作包含在 handoff_span()
By default, the trace is named "Agent trace". You can set this name if you use trace, or you can can configure the name and other properties with the RunConfig. 默认情况下,跟踪命名为”Agent 跟踪”。如果你使用 trace ,你可以设置这个名称,或者你可以使用 RunConfig 来配置名称和其他属性。
In addition, you can set up custom trace processors to push traces to other destinations (as a replacement, or secondary destination). 此外,你可以设置自定义跟踪处理器将跟踪推送到其他目的地(作为替代目的地或次要目的地)。
Higher level traces 更高级的跟踪
Sometimes, you might want multiple calls to run() to be part of a single trace. You can do this by wrapping the entire code in a trace(). 有时,你可能希望多个对 run() 的调用属于同一个跟踪。你可以通过将整个代码包裹在 trace() 中来实现这一点。
with trace("Joke workflow"): first_result = await Runner.run(agent, "Tell me a joke") second_result = await Runner.run(agent, f"Rate this joke: ") print(f"Joke: ") print(f"Rating: ")
Creating traces 创建跟踪
You can use the trace(){.autorefs .autorefs-internal} function to create a trace. Traces need to be started and finished. You have two options to do so: 可以使用 trace() 函数来创建一个跟踪。跟踪需要开始和结束。您有以下两种选择:
Recommended: use the trace as a context manager, i.e. with trace(...) as my_trace. This will automatically start and end the trace at the right time. 推荐:使用 trace 作为上下文管理器,即 with trace(...) as my_trace 。这将在正确的时间自动开始和结束跟踪。
The current trace is tracked via a Python contextvar. This means that it works with concurrency automatically. If you manually start/end a trace, you'll need to pass mark_as_current and reset_current to start()/finish() to update the current trace. 当前跟踪通过 Python contextvar 进行跟踪。这意味着它会自动处理并发。如果你手动开始/结束一个跟踪,你需要将 mark_as_current 和 reset_current 传递给 start() / finish() 以更新当前跟踪。
Creating spans 创建跨度
You can use the various *_span(){.autorefs .autorefs-internal} methods to create a span. In general, you don't need to manually create spans. A custom_span(){.autorefs .autorefs-internal} function is available for tracking custom span information. 你可以使用各种 *_span() 方法来创建一个跨度。一般来说,你不需要手动创建跨度。有一个 custom_span() 函数可以用来跟踪自定义的跨度信息。
Spans are automatically part of the current trace, and are nested under the nearest current span, which is tracked via a Python contextvar. Spans 是自动成为当前跟踪的一部分,并嵌套在最近的当前 Span 下,这通过 Python contextvar 跟踪。
Sensitive data 敏感数据
Some spans track potentially sensitive data. For example, the generation_span() stores the inputs/outputs of the LLM generation, and function_span() stores the inputs/outputs of function calls. These may contain sensitive data, so you can disable capturing that data via RunConfig.trace_include_sensitive_data. 某些跨度跟踪可能敏感的数据。例如, generation_span() 存储了LLM 生成的输入/输出, function_span() 存储了函数调用的输入/输出。这些可能包含敏感数据,因此你可以通过 RunConfig.trace_include_sensitive_data 禁用捕获这些数据。
Custom tracing processors 自定义跟踪处理器
The high level architecture for tracing is: 跟踪的高级架构是:
At initialization, we create a global TraceProvider, which is responsible for creating traces. 在初始化时,我们创建一个全局的 TraceProvider ,它负责创建跟踪。
We configure the TraceProvider with a BatchTraceProcessor that sends traces/spans in batches to a BackendSpanExporter, which exports the spans and traces to the OpenAI backend in batches. 我们将 TraceProvider 配置为一个 BatchTraceProcessor ,它以批次的方式将跟踪/跨度发送到 BackendSpanExporter ,后者以批次的方式将跨度和跟踪导出到 OpenAI 后端。
To customize this default setup, to send traces to alternative or additional backends or modifying exporter behavior, you have two options: 要自定义此默认设置,将跟踪发送到替代或附加后端或修改导出程序行为,您有两个选项:
add_trace_processor() lets you add an additional trace processor that will receive traces and spans as they are ready. This lets you do your own processing in addition to sending traces to OpenAI's backend. add_trace_processor() 可以添加一个附加跟踪处理器,该处理器将在跟踪和跨度准备好时接收它们。这使您可以在发送跟踪到 OpenAI 后端的同时进行自己的处理。
set_trace_processors() lets you replace the default processors with your own trace processors. This means traces will not be sent to the OpenAI backend unless you include a TracingProcessor that does so. set_trace_processors() 可以用您自己的跟踪处理器替换默认处理器。这意味着除非您包含一个 TracingProcessor ,否则跟踪将不会发送到 OpenAI 后端。
Context is an overloaded term. There are two main classes of context you might care about: 上下文是一个被过度使用的术语。你可能关心的上下文主要有两类:
Context available locally to your code: this is data and dependencies you might need when tool functions run, during callbacks like on_handoff, in lifecycle hooks, etc. 本地代码可用的上下文:这是工具函数运行、回调函数如 on_handoff 、生命周期钩子等期间可能需要的数据和依赖。
Context available to LLMs: this is data the LLM sees when generating a response. LLMs可用的上下文:这是LLM在生成响应时看到的数据。
Local context 本地上下文
This is represented via the RunContextWrapper class and the context property within it. The way this works is: 这是通过 RunContextWrapper 类及其内部的 context 属性来表示的。这种方式的工作原理是:
You create any Python object you want. A common pattern is to use a dataclass or a Pydantic object. 你可以创建任意的 Python 对象。常见的模式是使用数据类或 Pydantic 对象。
You pass that object to the various run methods (e.g. Runner.run(..., **context=whatever**)). 你可以将该对象传递给各种 run 方法(例如 Runner.run(..., **context=whatever**)) 。)
All your tool calls, lifecycle hooks etc will be passed a wrapper object, RunContextWrapper[T], where T represents your context object type which you can access via wrapper.context. 所有你的工具调用、生命周期钩子等都将传递一个包装对象 RunContextWrapper[T] ,其中 T 代表你的上下文对象类型,你可以通过 wrapper.context 访问它。
The most important thing to be aware of: every agent, tool function, lifecycle etc for a given agent run must use the same type of context. 需要注意的是:对于给定的代理运行,每个代理、工具函数、生命周期等都必须使用相同的上下文类型。
You can use the context for things like: 你可以使用上下文来进行:
Contextual data for your run (e.g. things like a username/uid or other information about the user) 运行的上下文数据(例如用户名/uid 或其他用户信息)
Dependencies (e.g. logger objects, data fetchers, etc) 依赖项(例如日志记录对象、数据获取器等)
Helper functions 辅助函数
Note 注意
The context object is not sent to the LLM. It is purely a local object that you can read from, write to and call methods on it. 上下文对象不会发送到LLM。它是一个纯粹的本地对象,你可以从中读取、写入并调用其方法。
result = await Runner.run( starting_agent=agent, input="What is the age of the user?", context=user_info, )
print(result.final_output) # The user John is 47 years old.
if __name__ == "__main__": asyncio.run(main())
Agent/LLM context
When an LLM is called, the only data it can see is from the conversation history. This means that if you want to make some new data available to the LLM, you must do it in a way that makes it available in that history. There are a few ways to do this: 当调用LLM时,它只能看到对话历史中的数据。这意味着如果你想让LLM访问一些新数据,你必须以这种方式使其在历史记录中可用。有几种方法可以做到这一点:
You can add it to the Agent instructions. This is also known as a "system prompt" or "developer message". System prompts can be static strings, or they can be dynamic functions that receive the context and output a string. This is a common tactic for information that is always useful (for example, the user's name or the current date). 你可以将其添加到 Agent instructions 中。这通常被称为”系统提示”或”开发者消息”。系统提示可以是静态字符串,也可以是动态函数,接收上下文并输出一个字符串。这是一种常见的策略,用于始终有用的信息(例如用户的姓名或当前日期)。
Add it to the input when calling the Runner.run functions. This is similar to the instructions tactic, but allows you to have messages that are lower in the chain of command. 在调用 Runner.run 函数时将其添加到 input 中。这与 instructions 策略类似,但允许你有较低层级的消息。
Expose it via function tools. This is useful for on-demand context - the LLM decides when it needs some data, and can call the tool to fetch that data. 通过函数工具暴露它。这对于按需上下文非常有用——LLM决定何时需要某些数据,并可以调用工具来获取这些数据。
Use retrieval or web search. These are special tools that are able to fetch relevant data from files or databases (retrieval), or from the web (web search). This is useful for "grounding" the response in relevant contextual data. 使用检索或网络搜索。这些是特殊工具,能够从文件或数据库中检索相关数据(检索),或从网络中检索相关数据(网络搜索)。这对于使响应基于相关上下文数据非常有用。
Guardrails 守护措施
Guardrails run in parallel to your agents, enabling you to do checks and validations of user input. For example, imagine you have an agent that uses a very smart (and hence slow/expensive) model to help with customer requests. You wouldn't want malicious users to ask the model to help them with their math homework. So, you can run a guardrail with a fast/cheap model. If the guardrail detects malicious usage, it can immediately raise an error, which stops the expensive model from running and saves you time/money. 护栏与您的代理并行运行,使您能够检查和验证用户输入。例如,假设您有一个使用非常智能(因此较慢且昂贵)的模型来帮助处理客户请求的代理。您不希望恶意用户请求该模型帮助他们做数学作业。因此,您可以运行一个护栏,使用一个快速且便宜的模型。如果护栏检测到恶意使用,它会立即引发错误,从而阻止昂贵的模型运行并节省您时间和金钱。
There are two kinds of guardrails: 有两种类型的护栏:
Input guardrails run on the initial user input 输入护栏基于初始用户输入运行
Output guardrails run on the final agent output 输出 guardrails 运行在最终代理输出上
Input guardrails 输入护栏
Input guardrails run in 3 steps: 输入护栏分为 3 步:
First, the guardrail receives the same input passed to the agent. 首先,护栏会接收与代理相同的输入。
Next, the guardrail function runs to produce a GuardrailFunctionOutput, which is then wrapped in an InputGuardrailResult 接着,运行护栏功能以生成一个 GuardrailFunctionOutput ,然后将其包裹在 InputGuardrailResult 中。
Finally, we check if .tripwire_triggered is true. If true, an InputGuardrailTripwireTriggered exception is raised, so you can appropriately respond to the user or handle the exception. 最后,我们检查 .tripwire_triggered 是否为真。如果为真,则会抛出一个 InputGuardrailTripwireTriggered 异常,以便您可以适当地向用户做出响应或处理异常。
Note 注意
Input guardrails are intended to run on user input, so an agent's guardrails only run if the agent is the first agent. You might wonder, why is the guardrails property on the agent instead of passed to Runner.run? It's because guardrails tend to be related to the actual Agent - you'd run different guardrails for different agents, so colocating the code is useful for readability. 输入护栏旨在运行在用户输入上,因此只有当代理是第一个代理时,代理的护栏才会运行。你可能会好奇,为什么 guardrails 属性在代理上而不是传递给 Runner.run ?这是因为护栏通常与实际的代理相关——你会为不同的代理运行不同的护栏,因此将代码放在一起有助于提高可读性。
Output guardrails 输出护栏
Output guardrails run in 3 steps: 输出护栏运行在 3 个步骤中:
First, the guardrail receives the same input passed to the agent. 首先,护栏会接收与代理相同的输入。
Next, the guardrail function runs to produce a GuardrailFunctionOutput, which is then wrapped in an OutputGuardrailResult 接着,运行护栏功能以生成一个 GuardrailFunctionOutput ,然后将其包裹在 OutputGuardrailResult 中。
Finally, we check if .tripwire_triggered is true. If true, an OutputGuardrailTripwireTriggered exception is raised, so you can appropriately respond to the user or handle the exception. 最后,我们检查 .tripwire_triggered 是否为真。如果为真,则会抛出一个 OutputGuardrailTripwireTriggered 异常,以便您可以适当地向用户做出响应或处理该异常。
Note 注意
Output guardrails are intended to run on the final agent input, so an agent's guardrails only run if the agent is the last agent. Similar to the input guardrails, we do this because guardrails tend to be related to the actual Agent - you'd run different guardrails for different agents, so colocating the code is useful for readability. 输出 guardrails 旨在运行在最终代理输入上,因此只有当代理是最后一个代理时,代理的 guardrails 才会运行。类似于输入 guardrails,我们这样做是因为 guardrails 往往与实际的代理相关——你会为不同的代理运行不同的 guardrails,因此将代码放在一起有助于提高可读性。
Tripwires 触发线
If the input or output fails the guardrail, the Guardrail can signal this with a tripwire. As soon as we see a guardrail that has triggered the tripwires, we immediately raise a GuardrailTripwireTriggered exception and halt the Agent execution. 如果输入或输出违反了护栏规则,护栏可以通过触发警报线来指示这一点。一旦我们发现触发了护栏警报线,我们将立即抛出一个 GuardrailTripwireTriggered 异常并停止 Agent 的执行。
Implementing a guardrail 实现护栏
You need to provide a function that receives input, and returns a GuardrailFunctionOutput{.autorefs .autorefs-internal}. In this example, we'll do this by running an Agent under the hood. 你需要提供一个接收输入并返回一个 GuardrailFunctionOutput 的函数。在这个例子中,我们将通过在后台运行一个 Agent 来实现这一点。
guardrail_agent = Agent( name="Guardrail check", instructions="Check if the user is asking you to do their math homework.", output_type=MathHomeworkOutput, )
agent = Agent( name="Customer support agent", instructions="You are a customer support agent. You help customers with their questions.", input_guardrails=[math_guardrail], )
asyncdefmain(): # This should trip the guardrail try: await Runner.run(agent, "Hello, can you help me solve for x: 2x + 3 = 11?") print("Guardrail didn't trip - this is unexpected")
agent = Agent( name="Customer support agent", instructions="You are a customer support agent. You help customers with their questions.", output_guardrails=[math_guardrail], output_type=MessageOutput, )
asyncdefmain(): # This should trip the guardrail try: await Runner.run(agent, "Hello, can you help me solve for x: 2x + 3 = 11?") print("Guardrail didn't trip - this is unexpected")
Orchestration refers to the flow of agents in your app. Which agents run, in what order, and how do they decide what happens next? There are two main ways to orchestrate agents: 编排是指您应用程序中代理的流程。哪些代理运行,顺序如何,以及它们如何决定下一步该做什么?主要有两种编排代理的方式:
Allowing the LLM to make decisions: this uses the intelligence of an LLM to plan, reason, and decide on what steps to take based on that. 允许LLM做出决策:这使用了LLM的智能来规划、推理并决定应采取哪些步骤。
Orchestrating via code: determining the flow of agents via your code. 通过代码编排:通过你的代码确定代理的流程。
You can mix and match these patterns. Each has their own tradeoffs, described below. 这些模式可以混合使用。每个模式都有各自的权衡,详情如下。
Orchestrating via LLM
An agent is an LLM equipped with instructions, tools and handoffs. This means that given an open-ended task, the LLM can autonomously plan how it will tackle the task, using tools to take actions and acquire data, and using handoffs to delegate tasks to sub-agents. For example, a research agent could be equipped with tools like: 代理是一个配备了指令、工具和转交的LLM。这意味着,给定一个开放式的任务,LLM可以自主规划如何完成任务,使用工具采取行动并获取数据,以及使用转交将任务委派给子代理。例如,一个研究代理可以配备以下工具:
Web search to find information online 网络搜索以在线查找信息
File search and retrieval to search through proprietary data and connections 文件搜索和检索以搜索内部数据和连接
Computer use to take actions on a computer 计算机用于在计算机上执行动作
Code execution to do data analysis 代码执行以进行数据分析
Handoffs to specialized agents that are great at planning, report writing and more. 将任务转交给擅长规划和报告写作的专业代理。
This pattern is great when the task is open-ended and you want to rely on the intelligence of an LLM. The most important tactics here are: 当任务开放且您希望依赖代理的智能时,这种模式非常有用。这里最重要的策略是:
Invest in good prompts. Make it clear what tools are available, how to use them, and what parameters it must operate within. 投入良好的提示。明确说明可用的工具、如何使用它们以及必须在其范围内运行的参数。
Monitor your app and iterate on it. See where things go wrong, and iterate on your prompts. 监控你的应用程序并进行迭代。看看哪里出了问题,并迭代你的提示。
Allow the agent to introspect and improve. For example, run it in a loop, and let it critique itself; or, provide error messages and let it improve. 允许代理进行自我反省和改进。例如,将其放在循环中,并让它自我批评;或者,提供错误消息并让它改进。
Have specialized agents that excel in one task, rather than having a general purpose agent that is expected to be good at anything. 有专门擅长一项任务的代理,而不是期望一个通用代理在任何事情上都做得很好。
Invest in evals. This lets you train your agents to improve and get better at tasks. 投资于评估。这可以让您的代理提高并更好地完成任务。
Orchestrating via code 通过代码编排
While orchestrating via LLM is powerful, orchestrating via code makes tasks more deterministic and predictable, in terms of speed, cost and performance. Common patterns here are: 虽然通过LLM编排是强大的,但通过代码编排使任务在速度、成本和性能方面更具确定性和可预测性。常见的模式包括:
Using structured outputs to generate well formed data that you can inspect with your code. For example, you might ask an agent to classify the task into a few categories, and then pick the next agent based on the category. 使用结构化的输出生成易于代码检查的格式化数据。例如,你可以让智能体将任务分类到几个类别中,然后根据类别选择下一个智能体。
Chaining multiple agents by transforming the output of one into the input of the next. You can decompose a task like writing a blog post into a series of steps - do research, write an outline, write the blog post, critique it, and then improve it. 通过将一个智能体的输出转换为下一个智能体的输入来串联多个智能体。你可以将撰写博客文章的任务分解为一系列步骤——进行研究,撰写提纲,撰写博客文章,进行批判性评估,然后改进。
Running the agent that performs the task in a while loop with an agent that evaluates and provides feedback, until the evaluator says the output passes certain criteria. 用一个评估并提供反馈的智能体与执行任务的智能体在一个 while 循环中运行,直到评估者认为输出满足某些标准为止。
Running multiple agents in parallel, e.g. via Python primitives like asyncio.gather. This is useful for speed when you have multiple tasks that don't depend on each other. 并发运行多个代理,例如通过 Python 原语 asyncio.gather 实现。当您有多个不依赖于彼此的任务时,这很有用。
We have a number of examples in examples/agent_patterns. 我们有一些示例在 examples/agent_patterns 中。
Models 模型
The Agents SDK comes with out-of-the-box support for OpenAI models in two flavors: 代理 SDK 内置支持两种类型的 OpenAI 模型:
Recommended: the OpenAIResponsesModel, which calls OpenAI APIs using the new Responses API. 推荐: OpenAIResponsesModel ,它使用新的 Responses API 调用 OpenAI API。
Within a single workflow, you may want to use different models for each agent. For example, you could use a smaller, faster model for triage, while using a larger, more capable model for complex tasks. When configuring an Agent, you can select a specific model by either: 在单个工作流中,您可能希望为每个代理使用不同的模型。例如,您可以为初步筛选使用较小且更快的模型,而为复杂任务使用更大且更强大的模型。在配置一个 Agent 时,您可以通过以下方式选择特定的模型:
Passing the name of an OpenAI model. 传递一个 OpenAI 模型的名称。
Passing any model name + a ModelProvider that can map that name to a Model instance. 传递任何模型名称加上一个 ModelProvider ,该 ModelProvider 可以将该名称映射到一个 Model 实例。
Directly providing a Model implementation. 直接提供一个 Model 实现。
Note 注意
While our SDK supports both the OpenAIResponsesModel and the OpenAIChatCompletionsModel shapes, we recommend using a single model shape for each workflow because the two shapes support a different set of features and tools. If your workflow requires mixing and matching model shapes, make sure that all the features you're using are available on both. 虽然我们的 SDK 支持 OpenAIResponsesModel 和 OpenAIChatCompletionsModel 两种形状,但我们建议为每个工作流使用单一的模型形状,因为这两种形状支持不同的功能和工具。如果您的工作流需要混合使用不同的模型形状,请确保您使用的所有功能在两种形状中都是可用的。
triage_agent = Agent( name="Triage agent", instructions="Handoff to the appropriate agent based on the language of the request.", handoffs=[spanish_agent, english_agent], model="gpt-3.5-turbo", )
asyncdefmain(): result = await Runner.run(triage_agent, input="Hola, ¿cómo estás?") print(result.final_output)
Using other LLM providers 使用其他LLM提供商
Many providers also support the OpenAI API format, which means you can pass a base_url to the existing OpenAI model implementations and use them easily. ModelSettings is used to configure tuning parameters (e.g., temperature, top_p) for the model you select. 许多提供商也支持 OpenAI API 格式,这意味着您可以将 base_url 传递给现有的 OpenAI 模型实现并轻松使用它们。 ModelSettings 用于配置模型的调优参数(例如,温度、top_p)。
By default, the SDK looks for the OPENAI_API_KEY environment variable for LLM requests and tracing, as soon as it is imported. If you are unable to set that environment variable before your app starts, you can use the set_default_openai_key(){.autorefs .autorefs-internal} function to set the key. 默认情况下,SDK 在导入时会查找 OPENAI_API_KEY 环境变量以用于 LLM 请求和跟踪。如果你在应用启动前无法设置该环境变量,可以使用 set_default_openai_key() 函数来设置密钥。
1 2 3 4
from agents import set_default_openai_key
set_default_openai_key("sk-...")
Alternatively, you can also configure an OpenAI client to be used. By default, the SDK creates an AsyncOpenAI instance, using the API key from the environment variable or the default key set above. You can change this by using the set_default_openai_client()function. 另外,你也可以配置一个要使用的 OpenAI 客户端。默认情况下,SDK 会创建一个 AsyncOpenAI 实例,使用环境变量中的 API 密钥或上面设置的默认密钥。你可以通过使用 set_default_openai_client() 函数来更改这一点。
1 2 3 4 5 6
from openai import AsyncOpenAI from agents import set_default_openai_client
Finally, you can also customize the OpenAI API that is used. By default, we use the OpenAI Responses API. You can override this to use the Chat Completions API by using the set_default_openai_api(){.autorefs .autorefs-internal} function. 最后,你还可以自定义使用的 OpenAI API。默认情况下,我们使用 OpenAI Responses API。你可以通过使用 set_default_openai_api() 函数将其更改为使用 Chat Completions API。
1 2 3 4
from agents import set_default_openai_api
set_default_openai_api("chat_completions")
Tracing 跟踪
Tracing is enabled by default. It uses the OpenAI API keys from the section above by default (i.e. the environment variable or the default key you set). You can specifically set the API key used for tracing by using the set_tracing_export_api_key{.autorefs .autorefs-internal} function. 跟踪默认是启用的。它默认使用上述部分的 OpenAI API 密钥(即环境变量或您设置的默认密钥)。您可以使用 set_tracing_export_api_key 函数来具体设置用于跟踪的 API 密钥。
1 2 3 4
from agents import set_tracing_export_api_key
set_tracing_export_api_key("sk-...")
You can also disable tracing entirely by using the set_tracing_disabled(){.autorefs .autorefs-internal} function. 您也可以使用 set_tracing_disabled() 函数完全禁用跟踪。
1 2 3 4
from agents import set_tracing_disabled
set_tracing_disabled(True)
Debug logging 调试日志
The SDK has two Python loggers without any handlers set. By default, this means that warnings and errors are sent to stdout, but other logs are suppressed. SDK 没有任何处理器的两个 Python 日志记录器。默认情况下,这意味着警告和错误会被发送到 stdout ,但其他日志被抑制。
To enable verbose logging, use the enable_verbose_stdout_logging() function. 要启用详细日志记录,请使用 enable_verbose_stdout_logging() 函数。
1 2 3 4
from agents import enable_verbose_stdout_logging
enable_verbose_stdout_logging()
Alternatively, you can customize the logs by adding handlers, filters, formatters, etc. You can read more in the Python logging guide. 或者,您可以自定义日志记录,通过添加处理器、过滤器、格式化程序等。您可以在 Python 日志记录指南中阅读更多内容。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
import logging
logger = logging.getLogger("openai.agents") # or openai.agents.tracing for the Tracing logger
# To make all logs show up logger.setLevel(logging.DEBUG) # To make info and above show up logger.setLevel(logging.INFO) # To make warning and above show up logger.setLevel(logging.WARNING) # etc
# You can customize this as needed, but this will output to `stderr` by default logger.addHandler(logging.StreamHandler())
Sensitive data in logs 日志中的敏感数据
Certain logs may contain sensitive data (for example, user data). If you want to disable this data from being logged, set the following environment variables. 某些日志可能包含敏感数据(例如,用户数据)。如果您想禁用此数据的日志记录,请设置以下环境变量。
To disable logging LLM inputs and outputs: 要禁用日志记录LLM 输入和输出:
1 2
export OPENAI_AGENTS_DONT_LOG_MODEL_DATA=1
To disable logging tool inputs and outputs: 要禁用工具输入和输出的日志记录: