Skip to content

Commit e7c2c19

Browse files
authored
Merge branch 'main' into patch-1
2 parents 333858b + 48ff99b commit e7c2c19

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+1430
-144
lines changed
+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
name: Custom model providers
3+
about: Questions or bugs about using non-OpenAI models
4+
title: ''
5+
labels: bug
6+
assignees: ''
7+
8+
---
9+
10+
### Please read this first
11+
12+
- **Have you read the custom model provider docs, including the 'Common issues' section?** [Model provider docs](https://openai.github.io/openai-agents-python/models/#using-other-llm-providers)
13+
- **Have you searched for related issues?** Others may have faced similar issues.
14+
15+
### Describe the question
16+
A clear and concise description of what the question or bug is.
17+
18+
### Debug information
19+
- Agents SDK version: (e.g. `v0.0.3`)
20+
- Python version (e.g. Python 3.10)
21+
22+
### Repro steps
23+
Ideally provide a minimal python script that can be run to reproduce the issue.
24+
25+
### Expected behavior
26+
A clear and concise description of what you expected to happen.

.github/workflows/tests.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ jobs:
5050
enable-cache: true
5151
- name: Install dependencies
5252
run: make sync
53-
- name: Run tests
54-
run: make tests
53+
- name: Run tests with coverage
54+
run: make coverage
5555

5656
build-docs:
5757
runs-on: ubuntu-latest

Makefile

+17
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,21 @@ mypy:
1818
tests:
1919
uv run pytest
2020

21+
.PHONY: coverage
22+
coverage:
23+
24+
uv run coverage run -m pytest
25+
uv run coverage xml -o coverage.xml
26+
uv run coverage report -m --fail-under=95
27+
28+
.PHONY: snapshots-fix
29+
snapshots-fix:
30+
uv run pytest --inline-snapshot=fix
31+
32+
.PHONY: snapshots-create
33+
snapshots-create:
34+
uv run pytest --inline-snapshot=create
35+
2136
.PHONY: old_version_tests
2237
old_version_tests:
2338
UV_PROJECT_ENVIRONMENT=.venv_39 uv run --python 3.9 -m pytest
@@ -34,4 +49,6 @@ serve-docs:
3449
.PHONY: deploy-docs
3550
deploy-docs:
3651
uv run mkdocs gh-deploy --force --verbose
52+
53+
3754

README.md

+2-10
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ The OpenAI Agents SDK is a lightweight yet powerful framework for building multi
77
### Core concepts:
88

99
1. [**Agents**](https://openai.github.io/openai-agents-python/agents): LLMs configured with instructions, tools, guardrails, and handoffs
10-
2. [**Handoffs**](https://openai.github.io/openai-agents-python/handoffs/): Allow agents to transfer control to other agents for specific tasks
10+
2. [**Handoffs**](https://openai.github.io/openai-agents-python/handoffs/): A specialized tool call used by the Agents SDK for transferring control between agents
1111
3. [**Guardrails**](https://openai.github.io/openai-agents-python/guardrails/): Configurable safety checks for input and output validation
1212
4. [**Tracing**](https://openai.github.io/openai-agents-python/tracing/): Built-in tracking of agent runs, allowing you to view, debug and optimize your workflows
1313

@@ -142,15 +142,7 @@ The Agents SDK is designed to be highly flexible, allowing you to model a wide r
142142

143143
## Tracing
144144

145-
The Agents SDK automatically traces your agent runs, making it easy to track and debug the behavior of your agents. Tracing is extensible by design, supporting custom spans and a wide variety of external destinations, including:
146-
- [AgentOps](https://docs.agentops.ai/v1/integrations/agentssdk)
147-
- [Braintrust](https://braintrust.dev/docs/guides/traces/integrations#openai-agents-sdk)
148-
- [Comet Opik](https://www.comet.com/docs/opik/tracing/integrations/openai_agents)
149-
- [Keywords AI](https://docs.keywordsai.co/integration/development-frameworks/openai-agent)
150-
- [Logfire](https://logfire.pydantic.dev/docs/integrations/llms/openai/#openai-agents)
151-
- [Scorecard](https://docs.scorecard.io/docs/documentation/features/tracing#openai-agents-sdk-integration)
152-
153-
For more details about how to customize or disable tracing, see [Tracing](http://openai.github.io/openai-agents-python/tracing).
145+
The Agents SDK automatically traces your agent runs, making it easy to track and debug the behavior of your agents. Tracing is extensible by design, supporting custom spans and a wide variety of external destinations, including [Logfire](https://logfire.pydantic.dev/docs/integrations/llms/openai/#openai-agents), [AgentOps](https://docs.agentops.ai/v1/integrations/agentssdk), [Braintrust](https://braintrust.dev/docs/guides/traces/integrations#openai-agents-sdk), [Scorecard](https://docs.scorecard.io/docs/documentation/features/tracing#openai-agents-sdk-integration), and [Keywords AI](https://docs.keywordsai.co/integration/development-frameworks/openai-agent). For more details about how to customize or disable tracing, see [Tracing](http://openai.github.io/openai-agents-python/tracing), which also includes a larger list of [external tracing processors](http://openai.github.io/openai-agents-python/tracing/#external-tracing-processors-list).
154146

155147
## Development (only needed if you need to edit the SDK/examples)
156148

docs/guardrails.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,8 @@ class MessageOutput(BaseModel): # (1)!
111111
response: str
112112

113113
class MathOutput(BaseModel): # (2)!
114-
is_math: bool
115114
reasoning: str
115+
is_math: bool
116116

117117
guardrail_agent = Agent(
118118
name="Guardrail check",

docs/tracing.md

+11-5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ The Agents SDK includes built-in tracing, collecting a comprehensive record of e
99
1. You can globally disable tracing by setting the env var `OPENAI_AGENTS_DISABLE_TRACING=1`
1010
2. You can disable tracing for a single run by setting [`agents.run.RunConfig.tracing_disabled`][] to `True`
1111

12+
***For organizations operating under a Zero Data Retention (ZDR) policy using OpenAI's APIs, tracing is unavailable.***
13+
1214
## Traces and spans
1315

1416
- **Traces** represent a single end-to-end operation of a "workflow". They're composed of Spans. Traces have the following properties:
@@ -88,11 +90,15 @@ To customize this default setup, to send traces to alternative or additional bac
8890
1. [`add_trace_processor()`][agents.tracing.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.
8991
2. [`set_trace_processors()`][agents.tracing.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.
9092

91-
External trace processors include:
93+
## External tracing processors list
9294

93-
- [AgentOps](https://docs.agentops.ai/v1/integrations/agentssdk)
95+
- [Arize-Phoenix](https://docs.arize.com/phoenix/tracing/integrations-tracing/openai-agents-sdk)
96+
- [MLflow](https://mlflow.org/docs/latest/tracing/integrations/openai-agent)
9497
- [Braintrust](https://braintrust.dev/docs/guides/traces/integrations#openai-agents-sdk)
95-
- [Comet Opik](https://www.comet.com/docs/opik/tracing/integrations/openai_agents)
96-
- [Scorecard](https://docs.scorecard.io/docs/documentation/features/tracing#openai-agents-sdk-integration))
97-
- [Keywords AI](https://docs.keywordsai.co/integration/development-frameworks/openai-agent)
9898
- [Pydantic Logfire](https://logfire.pydantic.dev/docs/integrations/llms/openai/#openai-agents)
99+
- [AgentOps](https://docs.agentops.ai/v1/integrations/agentssdk)
100+
- [Scorecard](https://docs.scorecard.io/docs/documentation/features/tracing#openai-agents-sdk-integration)
101+
- [Keywords AI](https://docs.keywordsai.co/integration/development-frameworks/openai-agent)
102+
- [LangSmith](https://docs.smith.langchain.com/observability/how_to_guides/trace_with_openai_agents_sdk)
103+
- [Maxim AI](https://www.getmaxim.ai/docs/observe/integrations/openai-agents-sdk)
104+
- [Comet Opik](https://www.comet.com/docs/opik/tracing/integrations/openai_agents)

examples/agent_patterns/input_guardrails.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@
3030

3131
### 1. An agent-based guardrail that is triggered if the user is asking to do math homework
3232
class MathHomeworkOutput(BaseModel):
33-
is_math_homework: bool
3433
reasoning: str
34+
is_math_homework: bool
3535

3636

3737
guardrail_agent = Agent(

examples/agent_patterns/llm_as_a_judge.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323

2424
@dataclass
2525
class EvaluationFeedback:
26-
score: Literal["pass", "needs_improvement", "fail"]
2726
feedback: str
27+
score: Literal["pass", "needs_improvement", "fail"]
2828

2929

3030
evaluator = Agent[None](

examples/basic/agent_lifecycle_example.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ class FinalResult(BaseModel):
7474

7575
start_agent = Agent(
7676
name="Start Agent",
77-
instructions="Generate a random number. If it's even, stop. If it's odd, hand off to the multipler agent.",
77+
instructions="Generate a random number. If it's even, stop. If it's odd, hand off to the multiply agent.",
7878
tools=[random_number],
7979
output_type=FinalResult,
8080
handoffs=[multiply_agent],

examples/basic/hello_world_jupyter.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
agent = Agent(name="Assistant", instructions="You are a helpful assistant")
44

55
# Intended for Jupyter notebooks where there's an existing event loop
6-
result = await Runner.run(agent, "Write a haiku about recursion in programming.") # type: ignore[top-level-await] # noqa: F704
6+
result = await Runner.run(agent, "Write a haiku about recursion in programming.") # type: ignore[top-level-await] # noqa: F704
77
print(result.final_output)
88

99
# Code within code loops,

examples/handoffs/message_filter.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,9 @@ async def main():
6060

6161
print("Step 1 done")
6262

63-
# 2. Ask it to square a number
63+
# 2. Ask it to generate a number
6464
result = await Runner.run(
65-
second_agent,
65+
first_agent,
6666
input=result.to_input_list()
6767
+ [{"content": "Can you generate a random number between 0 and 100?", "role": "user"}],
6868
)

examples/handoffs/message_filter_streaming.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,9 @@ async def main():
6060

6161
print("Step 1 done")
6262

63-
# 2. Ask it to square a number
63+
# 2. Ask it to generate a number
6464
result = await Runner.run(
65-
second_agent,
65+
first_agent,
6666
input=result.to_input_list()
6767
+ [{"content": "Can you generate a random number between 0 and 100?", "role": "user"}],
6868
)

pyproject.toml

+5-1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ dev = [
4747
"mkdocstrings[python]>=0.28.0",
4848
"coverage>=7.6.12",
4949
"playwright==1.50.0",
50+
"inline-snapshot>=0.20.7",
5051
]
5152
[tool.uv.workspace]
5253
members = ["agents"]
@@ -116,4 +117,7 @@ filterwarnings = [
116117
]
117118
markers = [
118119
"allow_call_model_methods: mark test as allowing calls to real model implementations",
119-
]
120+
]
121+
122+
[tool.inline-snapshot]
123+
format-command="ruff format --stdin-filename {filename}"

src/agents/__init__.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
SpanData,
7474
SpanError,
7575
Trace,
76+
TracingProcessor,
7677
add_trace_processor,
7778
agent_span,
7879
custom_span,
@@ -129,10 +130,9 @@ def set_default_openai_api(api: Literal["chat_completions", "responses"]) -> Non
129130

130131
def enable_verbose_stdout_logging():
131132
"""Enables verbose logging to stdout. This is useful for debugging."""
132-
for name in ["openai.agents", "openai.agents.tracing"]:
133-
logger = logging.getLogger(name)
134-
logger.setLevel(logging.DEBUG)
135-
logger.addHandler(logging.StreamHandler(sys.stdout))
133+
logger = logging.getLogger("openai.agents")
134+
logger.setLevel(logging.DEBUG)
135+
logger.addHandler(logging.StreamHandler(sys.stdout))
136136

137137

138138
__all__ = [
@@ -209,6 +209,7 @@ def enable_verbose_stdout_logging():
209209
"set_tracing_disabled",
210210
"trace",
211211
"Trace",
212+
"TracingProcessor",
212213
"SpanError",
213214
"Span",
214215
"SpanData",

src/agents/_run_impl.py

+12-12
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
from openai.types.responses.response_input_param import ComputerCallOutput
2626
from openai.types.responses.response_reasoning_item import ResponseReasoningItem
2727

28-
from . import _utils
2928
from .agent import Agent
3029
from .agent_output import AgentOutputSchema
3130
from .computer import AsyncComputer, Computer
@@ -59,6 +58,7 @@
5958
handoff_span,
6059
trace,
6160
)
61+
from .util import _coro, _error_tracing
6262

6363
if TYPE_CHECKING:
6464
from .run import RunConfig
@@ -293,7 +293,7 @@ def process_model_response(
293293
elif isinstance(output, ResponseComputerToolCall):
294294
items.append(ToolCallItem(raw_item=output, agent=agent))
295295
if not computer_tool:
296-
_utils.attach_error_to_current_span(
296+
_error_tracing.attach_error_to_current_span(
297297
SpanError(
298298
message="Computer tool not found",
299299
data={},
@@ -324,7 +324,7 @@ def process_model_response(
324324
# Regular function tool call
325325
else:
326326
if output.name not in function_map:
327-
_utils.attach_error_to_current_span(
327+
_error_tracing.attach_error_to_current_span(
328328
SpanError(
329329
message="Tool not found",
330330
data={"tool_name": output.name},
@@ -368,7 +368,7 @@ async def run_single_tool(
368368
(
369369
agent.hooks.on_tool_start(context_wrapper, agent, func_tool)
370370
if agent.hooks
371-
else _utils.noop_coroutine()
371+
else _coro.noop_coroutine()
372372
),
373373
func_tool.on_invoke_tool(context_wrapper, tool_call.arguments),
374374
)
@@ -378,11 +378,11 @@ async def run_single_tool(
378378
(
379379
agent.hooks.on_tool_end(context_wrapper, agent, func_tool, result)
380380
if agent.hooks
381-
else _utils.noop_coroutine()
381+
else _coro.noop_coroutine()
382382
),
383383
)
384384
except Exception as e:
385-
_utils.attach_error_to_current_span(
385+
_error_tracing.attach_error_to_current_span(
386386
SpanError(
387387
message="Error running tool",
388388
data={"tool_name": func_tool.name, "error": str(e)},
@@ -502,7 +502,7 @@ async def execute_handoffs(
502502
source=agent,
503503
)
504504
if agent.hooks
505-
else _utils.noop_coroutine()
505+
else _coro.noop_coroutine()
506506
),
507507
)
508508

@@ -520,7 +520,7 @@ async def execute_handoffs(
520520
new_items=tuple(new_step_items),
521521
)
522522
if not callable(input_filter):
523-
_utils.attach_error_to_span(
523+
_error_tracing.attach_error_to_span(
524524
span_handoff,
525525
SpanError(
526526
message="Invalid input filter",
@@ -530,7 +530,7 @@ async def execute_handoffs(
530530
raise UserError(f"Invalid input filter: {input_filter}")
531531
filtered = input_filter(handoff_input_data)
532532
if not isinstance(filtered, HandoffInputData):
533-
_utils.attach_error_to_span(
533+
_error_tracing.attach_error_to_span(
534534
span_handoff,
535535
SpanError(
536536
message="Invalid input filter result",
@@ -591,7 +591,7 @@ async def run_final_output_hooks(
591591
hooks.on_agent_end(context_wrapper, agent, final_output),
592592
agent.hooks.on_end(context_wrapper, agent, final_output)
593593
if agent.hooks
594-
else _utils.noop_coroutine(),
594+
else _coro.noop_coroutine(),
595595
)
596596

597597
@classmethod
@@ -706,7 +706,7 @@ async def execute(
706706
(
707707
agent.hooks.on_tool_start(context_wrapper, agent, action.computer_tool)
708708
if agent.hooks
709-
else _utils.noop_coroutine()
709+
else _coro.noop_coroutine()
710710
),
711711
output_func,
712712
)
@@ -716,7 +716,7 @@ async def execute(
716716
(
717717
agent.hooks.on_tool_end(context_wrapper, agent, action.computer_tool, output)
718718
if agent.hooks
719-
else _utils.noop_coroutine()
719+
else _coro.noop_coroutine()
720720
),
721721
)
722722

0 commit comments

Comments
 (0)