Excel-to-JSON 2.1.0 Your Privacy-First Excel Add-in for JSON Conversion

Introduction

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:

  • Custom nested delimiters (/, _, .)
  • Flexible empty cell handling options
  • Multiple boolean format conversions
  • Advanced date formatting options

Example Usage

Consider this Excel data:

1
2
3
4
5
6
7
8
[{
"id": 1,
"student": {
"name": "Meimei",
"familyname": "Han",
"age": 12
}
}]

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!

RGBA像素值提取工具v1.0.0发布

工具介绍

我们很高兴地宣布RGBA像素值提取工具v1.0.0版本正式发布!这个在线工具可以帮助您轻松提取图像中每个像素的RGBA值,并导出为CSV文件。

主要功能

  • 支持JPG、PNG等多种常见图像格式
  • 快速提取每个像素的RGBA值
  • 一键导出为CSV文件,方便数据分析
  • 支持多种输出格式选择:
    • RGBA(r,g,b,a)格式
    • 十六进制#RRGGBBAA格式
    • 纯数字逗号分隔r,g,b,a格式
  • 完全在浏览器中运行,无需上传到服务器,保护您的隐私

使用方法

  1. 访问工具页面:https://s.wtsolutions.cn/image-pixel-rgba.html
  2. 点击”选择文件”按钮上传您的图像
  3. 选择您需要的输出格式(RGBA、十六进制或纯数字格式)
  4. 等待处理完成后,浏览器自动下载CSV文件获取结果

应用场景

  • 图像处理算法开发
  • 色彩分析
  • 图像质量检测
  • 学术研究

立即体验:https://s.wtsolutions.cn/image-pixel-rgba.html

RGBA Pixel Extractor Tool v1.0.0 Released

Tool Introduction

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

How to Use

  1. Visit tool page: https://s.wtsolutions.cn/image-pixel-rgba.html
  2. Click “Choose File” to upload your image
  3. Select your preferred output format (RGBA, hexadecimal or numeric values)
  4. After processing, CSV file will automatically downloaded to get results

Use Cases

  • Image processing algorithm development
  • Color analysis
  • Image quality inspection
  • Academic research

Try it now: https://s.wtsolutions.cn/image-pixel-rgba.html

OpenAI Agents SDK Python Docs 中文文档 (1)

说明:本文档为 OpenAI Agents SDK Python 文档的中文翻译,原文档地址为https://github.com/openai/openai-agents-python
在本文档中,是中英一段一段翻译的,英文为原文档内容,中文是通过翻译软件翻译的中文版本。如果发现翻译有问题,请结合中英文互相对照,避免翻译中存在的问题。

OpenAI Agents SDK

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 有两个驱动设计原则:

  1. Enough features to be worth using, but few enough primitives to make
    it quick to learn.
    功能足够丰富以值得使用,但基础元素足够少以便快速学习。
  2. 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

async def main():
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.
你可以定义在输入或输出上运行的自定义护栏。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from agents import GuardrailFunctionOutput, Agent, Runner
from pydantic import BaseModel

class HomeworkOutput(BaseModel):
is_homework: bool
reasoning: str

guardrail_agent = Agent(
name="Guardrail check",
instructions="Check if the user is asking about homework.",
output_type=HomeworkOutput,
)

async def homework_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,
)

Put it all together 将它们结合起来

Let's put it all together and run the entire workflow, using handoffs
and the input guardrail.
让我们把它们都结合起来,使用转交和输入护栏来运行整个工作流。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
from agents import Agent, InputGuardrail,GuardrailFunctionOutput, Runner
from pydantic import BaseModel
import asyncio

class HomeworkOutput(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.",
)


async def homework_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),
],
)

async def main():
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
def get_weather(city: str) -> str:
return f"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。

1
2
3
4
5
6
7
8
9
10
11
12
@dataclass
class UserContext:
uid: str
is_pro_user: bool

async def fetch_purchases() -> list[Purchase]:
return ...

agent = Agent[UserContext](
...,
)

Output types  输出类型

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


class CalendarEvent(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
def dynamic_instructions(
context: RunContextWrapper[UserContext], agent: Agent[UserContext]
) -> str:
return f"The user's name is . Help them with their questions."


agent = Agent[UserContext](
name="Triage agent",
instructions=dynamic_instructions,
)

Lifecycle events (hooks) 生命周期事件(钩子)

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 种选择:

  1. Runner.run(), which runs async and returns a
    RunResult.
    Runner.run() ,这会异步运行并返回一个 RunResult
  2. Runner.run_sync(), which is a sync method and just runs .run()
    under the hood.
    Runner.run_sync() ,这是一个同步方法,只是在后台运行 .run()
  3. 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

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.

Read more in the results guide.
在结果指南中阅读更多内容。

The agent loop  代理循环

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:
然后运行器运行一个循环:

  1. We call the LLM for the current agent, with the current input.
    当前代理调用LLM,并带上当前输入。
  2. The LLM produces its output.
    LLM生成其输出。
    1. If the LLM returns a final_output, the loop ends and we return
      the result.
      如果LLM返回一个 final_output ,则循环结束并返回结果。
    2. If the LLM does a handoff, we update the current agent and
      input, and re-run the loop.
      如果LLM进行转接,我们将更新当前坐席和输入,并重新运行循环。
    3. If the LLM produces tool calls, we run those tool calls, append
      the results, and re-run the loop.
      如果LLM生成了工具调用,我们将运行这些工具调用,追加结果,并重新运行循环。
  3. 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 : 覆盖特定代理的设置。例如,你可以设置一个全局
    temperaturetop_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调用),但这代表聊天对话中的一个单一逻辑回合。例如:

  1. User turn: user enter text
    用户回合: user enter text
  2. 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
async def main():
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
    时发生错误时抛出的。
  • InputGuardrailTripwireTriggered,
    OutputGuardrailTripwireTriggered is raised when a
    guardrail is tripped.
    InputGuardrailTripwireTriggered
    OutputGuardrailTripwireTriggered 是当护栏被触发时抛出的。

Results  结果

When you call the Runner.run methods, you either get a:
调用 Runner.run 方法时,您会得到一个:

  • RunResult if you call run or run_sync
    RunResult 如果您调用 runrun_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_outputAny
类型。我们无法静态类型化这一点,因为存在手递。如果发生手递,这意味着任何代理都可能是最后一个代理,所以我们无法静态知道可能的输出类型集合。

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_resultsoutput_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

async def main():
agent = Agent(
name="Joker",
instructions="You are a helpful assistant.",
)

result = Runner.run_streamed(agent, input="Please tell me 5 jokes.")
async for event in result.stream_events():
if event.type == "raw_response_event" and isinstance(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.
例如,这将忽略原始事件并将更新流式传输给用户。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import asyncio
import random
from agents import Agent, ItemHelpers, Runner, function_tool

@function_tool
def how_many_jokes() -> int:
return random.randint(1, 10)


async def main():
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 ===")

async for 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

agent = Agent(
name="Assistant",
tools=[
WebSearchTool(),
FileSearchTool(
max_num_results=3,
vector_store_ids=["VECTOR_STORE_ID"],
),
],
)

async def main():
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 来创建模式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import json

from typing_extensions import TypedDict, Any

from agents import Agent, FunctionTool, RunContextWrapper, function_tool


class Location(TypedDict):
lat: float
long: float

@function_tool
async def fetch_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")
def read_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>"


agent = Agent(
name="Assistant",
tools=[fetch_weather, read_file],
)

for tool in agent.tools:
if isinstance(tool, FunctionTool):
print(tool.name)
print(tool.description)
print(json.dumps(tool.params_json_schema, indent=2))
print()

Expand to see output
展开以查看输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
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
    字符串的参数,并且必须返回工具输出的字符串。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
from typing import Any

from pydantic import BaseModel

from agents import RunContextWrapper, FunctionTool



def do_some_work(data: str) -> str:
return "done"


class FunctionArgs(BaseModel):
username: str
age: int


async def run_function(ctx: RunContextWrapper[Any], args: str) -> str:
parsed = FunctionArgs.model_validate_json(args)
return do_some_work(data=f" is years old")


tool = FunctionTool(
name="process_user",
description="Processes extracted user data",
params_json_schema=FunctionArgs.model_json_schema(),
on_invoke_tool=run_function,
)

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:
如前所述,我们自动解析函数签名以提取工具的模式,并解析文档字符串以提取工具及其个别参数的描述。关于这一点的一些注意事项:

  1. 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 等。
  2. 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
    sphinxnumpy
    。我们尝试自动检测文档字符串格式,但这只是尽力而为,您可以在调用
    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.
在某些工作流程中,您可能希望有一个中央代理来协调一组专门的代理,而不是转交控制权。您可以通过将代理建模为工具来实现这一点。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
from agents import Agent, Runner
import asyncio

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",
),
],
)

async def main():
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:

1
2
3
4
5
6
7
8
from agents import Agent, handoff

billing_agent = Agent(name="Billing agent")
refund_agent = Agent(name="Refund agent")


triage_agent = Agent(name="Triage agent", handoffs=[billing_agent, handoff(refund_agent)])

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

def on_handoff(ctx: RunContextWrapper[None]):
print("Handoff called")

agent = Agent(name="My agent")

handoff_obj = handoff(
agent=agent,
on_handoff=on_handoff,
tool_name_override="custom_handoff_tool",
tool_description_override="Custom description",
)

Handoff inputs  手递输入

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

class EscalationData(BaseModel):
reason: str

async def on_handoff(ctx: RunContextWrapper[None], input_data: EscalationData):
print(f"Escalation agent called with reason: ")

agent = Agent(name="Escalation agent")

handoff_obj = handoff(
agent=agent,
on_handoff=on_handoff,
input_type=EscalationData,
)

Input filters  输入过滤器

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

agent = Agent(name="FAQ agent")

handoff_obj = handoff(
agent=agent,
input_filter=handoff_filters.remove_all_tools,
)

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:
跟踪默认启用。有两种方法可以禁用跟踪:

  1. You can globally disable tracing by setting the env var
    OPENAI_AGENTS_DISABLE_TRACING=1
    您可以通过设置环境变量 OPENAI_AGENTS_DISABLE_TRACING=1
    全局禁用跟踪。
  2. You can disable tracing for a single run by setting
    agents.run.RunConfig.tracing_disabled to True
    可以通过设置 agents.run.RunConfig.tracing_disabledTrue
    来禁用单次运行的跟踪

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()
中来实现这一点。

1
2
3
4
5
6
7
8
9
10
11
from agents import Agent, Runner, trace

async def main():
agent = Agent(name="Joke generator", instructions="Tell funny jokes.")

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()
函数来创建一个跟踪。跟踪需要开始和结束。您有以下两种选择:

  1. 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
    。这将在正确的时间自动开始和结束跟踪。
  2. You can also manually call
    trace.start() and
    trace.finish().
    您也可以手动调用 trace.start()trace.finish()

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_currentreset_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:
要自定义此默认设置,将跟踪发送到替代或附加后端或修改导出程序行为,您有两个选项:

  1. 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 后端的同时进行自己的处理。
  2. 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 后端。

External trace processors include:
外部跟踪处理器包括:

Context management  上下文管理

Context is an overloaded term. There are two main classes of context you
might care about:
上下文是一个被过度使用的术语。你可能关心的上下文主要有两类:

  1. 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
    、生命周期钩子等期间可能需要的数据和依赖。
  2. 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
属性来表示的。这种方式的工作原理是:

  1. You create any Python object you want. A common pattern is to use a
    dataclass or a Pydantic object.
    你可以创建任意的 Python 对象。常见的模式是使用数据类或 Pydantic
    对象。
  2. You pass that object to the various run methods (e.g.
    Runner.run(..., **context=whatever**)).
    你可以将该对象传递给各种 run 方法(例如
    Runner.run(..., **context=whatever**)) 。)
  3. 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。它是一个纯粹的本地对象,你可以从中读取、写入并调用其方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import asyncio
from dataclasses import dataclass
from agents import Agent, RunContextWrapper, Runner, function_tool

@dataclass
class UserInfo:
name: str
uid: int

@function_tool
async def fetch_user_age(wrapper: RunContextWrapper[UserInfo]) -> str:
return f"User is 47 years old"

async def main():
user_info = UserInfo(name="John", uid=123)

agent = Agent[UserInfo](
name="Assistant",
tools=[fetch_user_age],
)

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访问一些新数据,你必须以这种方式使其在历史记录中可用。有几种方法可以做到这一点:

  1. 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
    中。这通常被称为”系统提示”或”开发者消息”。系统提示可以是静态字符串,也可以是动态函数,接收上下文并输出一个字符串。这是一种常见的策略,用于始终有用的信息(例如用户的姓名或当前日期)。
  2. 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
    策略类似,但允许你有较低层级的消息。
  3. 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决定何时需要某些数据,并可以调用工具来获取这些数据。
  4. 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:
有两种类型的护栏:

  1. Input guardrails run on the initial user input
    输入护栏基于初始用户输入运行
  2. Output guardrails run on the final agent output
    输出 guardrails 运行在最终代理输出上

Input guardrails  输入护栏

Input guardrails run in 3 steps:
输入护栏分为 3 步:

  1. First, the guardrail receives the same input passed to the agent.
    首先,护栏会接收与代理相同的输入。
  2. Next, the guardrail function runs to produce a
    GuardrailFunctionOutput, which is then wrapped in an
    InputGuardrailResult
    接着,运行护栏功能以生成一个 GuardrailFunctionOutput
    ,然后将其包裹在 InputGuardrailResult 中。
  3. 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 个步骤中:

  1. First, the guardrail receives the same input passed to the agent.
    首先,护栏会接收与代理相同的输入。
  2. Next, the guardrail function runs to produce a
    GuardrailFunctionOutput, which is then wrapped in an
    OutputGuardrailResult
    接着,运行护栏功能以生成一个 GuardrailFunctionOutput
    ,然后将其包裹在 OutputGuardrailResult 中。
  3. 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 来实现这一点。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
from pydantic import BaseModel
from agents import (
Agent,
GuardrailFunctionOutput,
InputGuardrailTripwireTriggered,
RunContextWrapper,
Runner,
TResponseInputItem,
input_guardrail,
)

class MathHomeworkOutput(BaseModel):
is_math_homework: bool
reasoning: str

guardrail_agent = Agent(
name="Guardrail check",
instructions="Check if the user is asking you to do their math homework.",
output_type=MathHomeworkOutput,
)


@input_guardrail
async def math_guardrail(
ctx: RunContextWrapper[None], agent: Agent, input: str | list[TResponseInputItem]
) -> GuardrailFunctionOutput:
result = await Runner.run(guardrail_agent, input, context=ctx.context)

return GuardrailFunctionOutput(
output_info=result.final_output,
tripwire_triggered=result.final_output.is_math_homework,
)


agent = Agent(
name="Customer support agent",
instructions="You are a customer support agent. You help customers with their questions.",
input_guardrails=[math_guardrail],
)

async def main():
# 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")

except InputGuardrailTripwireTriggered:
print("Math homework guardrail tripped")

Output guardrails are similar.
输出 guardrails 是类似的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
from pydantic import BaseModel
from agents import (
Agent,
GuardrailFunctionOutput,
OutputGuardrailTripwireTriggered,
RunContextWrapper,
Runner,
output_guardrail,
)
class MessageOutput(BaseModel):
response: str

class MathOutput(BaseModel):
is_math: bool
reasoning: str

guardrail_agent = Agent(
name="Guardrail check",
instructions="Check if the output includes any math.",
output_type=MathOutput,
)

@output_guardrail
async def math_guardrail(
ctx: RunContextWrapper, agent: Agent, output: MessageOutput
) -> GuardrailFunctionOutput:
result = await Runner.run(guardrail_agent, output.response, context=ctx.context)

return GuardrailFunctionOutput(
output_info=result.final_output,
tripwire_triggered=result.final_output.is_math,
)

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,
)

async def main():
# 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")

except OutputGuardrailTripwireTriggered:
print("Math output guardrail tripped")

Orchestrating multiple agents orchestrating 多个智能体

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:
编排是指您应用程序中代理的流程。哪些代理运行,顺序如何,以及它们如何决定下一步该做什么?主要有两种编排代理的方式:

  1. 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的智能来规划、推理并决定应采取哪些步骤。
  2. 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:
当任务开放且您希望依赖代理的智能时,这种模式非常有用。这里最重要的策略是:

  1. Invest in good prompts. Make it clear what tools are available, how
    to use them, and what parameters it must operate within.
    投入良好的提示。明确说明可用的工具、如何使用它们以及必须在其范围内运行的参数。
  2. Monitor your app and iterate on it. See where things go wrong, and
    iterate on your prompts.
    监控你的应用程序并进行迭代。看看哪里出了问题,并迭代你的提示。
  3. 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.
    允许代理进行自我反省和改进。例如,将其放在循环中,并让它自我批评;或者,提供错误消息并让它改进。
  4. Have specialized agents that excel in one task, rather than having a
    general purpose agent that is expected to be good at anything.
    有专门擅长一项任务的代理,而不是期望一个通用代理在任何事情上都做得很好。
  5. 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 模型:

Mixing and matching models 混合使用模型

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 时,您可以通过以下方式选择特定的模型:

  1. Passing the name of an OpenAI model.
    传递一个 OpenAI 模型的名称。
  2. Passing any model name + a
    ModelProvider that can map that name to a Model instance.
    传递任何模型名称加上一个 ModelProvider ,该 ModelProvider
    可以将该名称映射到一个 Model 实例。
  3. 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
两种形状,但我们建议为每个工作流使用单一的模型形状,因为这两种形状支持不同的功能和工具。如果您的工作流需要混合使用不同的模型形状,请确保您使用的所有功能在两种形状中都是可用的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
from agents import Agent, Runner, AsyncOpenAI, OpenAIChatCompletionsModel
import asyncio

spanish_agent = Agent(
name="Spanish agent",
instructions="You only speak Spanish.",
model="o3-mini",
)

english_agent = Agent(
name="English agent",
instructions="You only speak English",
model=OpenAIChatCompletionsModel(
model="gpt-4o",
openai_client=AsyncOpenAI()
),
)

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",
)

async def main():
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)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
external_client = AsyncOpenAI(
api_key="EXTERNAL_API_KEY",
base_url="https://api.external.com/v1/",
)

spanish_agent = Agent(
name="Spanish agent",
instructions="You only speak Spanish.",
model=OpenAIChatCompletionsModel(
model="EXTERNAL_MODEL_NAME",
openai_client=external_client,
),
model_settings=ModelSettings(temperature=0.5),
)

Configuring the SDK  配置 SDK

API keys and clients API 密钥和客户端

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

custom_client = AsyncOpenAI(base_url="...", api_key="...")
set_default_openai_client(custom_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:
要禁用工具输入和输出的日志记录:

1
2
export OPENAI_AGENTS_DONT_LOG_TOOL_DATA=1

Excel-to-JSON v2.0.0发布,可以在Excel内部,把Excel表格转换成JSON,嵌套的JSON也能转

本文是Excel-to-JSON插件的官方文档 https://excel-to-json.wtsolutions.cn 简化浓缩翻译的中文版,仅供参考。详细的还请查看官方文档。

在数据处理和交换的过程中,将Excel文件转换为JSON格式是一项常见需求。Excel-to-JSON作为一款Microsoft Excel插件,为我们提供了便捷的解决方案。本文将详细介绍如何使用Excel-to-JSON以及它的特点。

插件简介

Excel-to-JSON是由WTSolutions维护的一款Excel插件,它允许用户在Excel环境内将Excel文件转换为JSON格式,适用于网页开发、数据交换等多种应用场景。

Excel-to-JSON是一款简单实用的Excel插件,它能够帮助开发者和数据分析师快速将Excel数据转换为JSON格式。无论是简单的扁平结构还是复杂的嵌套结构,它都能轻松应对。如果你经常需要处理Excel到JSON的转换工作,不妨试试这款插件,相信它会成为你的得力助手。

该插件支持两种转换模式:

  1. Flat JSON模式:直接将Excel表格转换为扁平结构的JSON
  2. Nested JSON模式:支持将带有分隔符(如”.”)的键转换为嵌套结构的JSON

插件版本

20250303发布v2.0.0版本。注:本文基于Excel-to-JSON 2.0.0版本编写,更多详细信息请参考官方文档。

系统要求

本插件支持以下Excel版本:

  • Excel 2013 Service Pack 1及更高版本
  • Excel 2016 for Mac
  • Excel 2016及更高版本
  • Excel Online
  • Office 365

安装步骤

  1. 打开Excel 2013/2016或更高版本、Excel Online或Office 365的新数据表。
  2. 点击“插入”选项卡或“开始”选项卡中的“加载项”。
  3. 在加载项搜索框中输入“Excel-to-JSON”。
  4. 点击该加载项以启动它,此时Excel的“开始”选项卡会新增一个“Excel-to-JSON”按钮,插件即可使用。

使用方法

  1. 准备数据:准备好Excel工作表,注意至少选择两行数据,因为第一行将被视为表头。
  2. 选择数据:选中想要转换的数据。
  3. 选择转换模式:有两种转换模式可供选择。
    • 扁平JSON模式:直接将Excel数据表转换为扁平的JSON。
    • 嵌套JSON模式:先将Excel数据表转换为扁平的JSON,然后使用“Flat”将带有分隔键的对象展开,分隔符为“.”,覆盖选项为true。
  4. 执行转换:点击“开始”按钮,转换后的JSON将显示在“开始”按钮下方。
  5. 保存JSON:有几种方式可以将生成的JSON保存到本地计算机。
    • 复制粘贴:生成JSON后,在插件中可以看到,直接复制粘贴到需要的地方。
    • 复制到剪贴板(不适用于Mac用户):生成JSON后,点击“复制到剪贴板”按钮,JSON就会被复制到剪贴板。

例子

示例 Excel sheet 1

Name Age Company
David 27 WTSolutions
Ton 26 WTSolutions
Kitty 30 Microsoft
Linda 30 Microsoft
Joe 40 Github

使用 Flat JSON mode

示例 JSON

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[
{
"Name": "David",
"Age": 27,
"Company": "WTSolutions"
},
{
"Name": "Ton",
"Age": 26,
"Company": "WTSolutions"
},
{
"Name": "Kitty",
"Age": 30,
"Company": "Microsoft"
},
{
"Name": "Linda",
"Age": 30,
"Company": "Microsoft"
},
{
"Name": "Joe",
"Age": 40,
"Company": "Github"
}
]

示例 Excel sheet 2

id student.name student.familyname student.age
1 Meimei Han 12
2 Lily Jaskson 15
3 Elon Mask 18

使用 Flat JSON Mode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[{
"id": 1,
"student.name": "Meimei",
"student.familyname": "Han",
"student.age": 12
}, {
"id": 2,
"student.name": "Lily",
"student.familyname": "Jaskson",
"student.age": 15
}, {
"id": 3,
"student.name": "Elon",
"student.familyname": "Mask",
"student.age": 18
}]

使用 Nested JSON mode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[{
"id": 1,
"student": {
"name": "Meimei",
"familyname": "Han",
"age": 12
}
}, {
"id": 2,
"student": {
"name": "Lily",
"familyname": "Jaskson",
"age": 15
}
}, {
"id": 3,
"student": {
"name": "Elon",
"familyname": "Mask",
"age": 18
}
}]

插件特点

数据隐私保护

Excel-to-JSON服务承诺保护用户隐私。通过该服务处理的Excel文件数据不会被存储、共享或用于其他目的,仅用于提供服务。而且,数据处理完全在本地Microsoft Excel应用程序中进行,不会发送到服务器或第三方服务器。

多种转换模式

提供扁平JSON模式和嵌套JSON模式,满足不同用户的需求。用户可以根据实际情况选择合适的转换模式。

操作简单

插件的使用流程清晰,只需几个简单的步骤就能完成Excel到JSON的转换,即使是没有编程经验的用户也能轻松上手。

数据兼容性

该插件需要用户安装有效的Microsoft Excel,并且确保Excel版本与插件兼容,保证了在常见的Excel环境中都能正常使用。

服务协议和隐私政策

在使用Excel-to-JSON服务时,用户需要遵守服务协议和隐私政策。服务协议规定了用户的使用要求、许可证和限制等内容;隐私政策则说明了数据处理的方式和范围。如果用户有任何疑问,可以通过邮箱[email protected]联系WTSolutions。