Commit graph

104 commits

Author SHA1 Message Date
pakrym-oai
0cf503e1c2
Allow replacing AgentRunner and TraceProvider (#720) 2025-06-17 17:41:10 -07:00
Rohan Mehta
2b9b8f7e73
Prompts support (#876)
Add support for the new openai prompts feature.
2025-06-16 15:47:48 -04:00
Rohan Mehta
6d2806f10c
Fix function_schema name override bug (#872)
## Summary
- ensure `name_override` is always used in `function_schema`
- test name override when docstring info is disabled

## Testing
- `make format`
- `make lint`
- `make mypy`
- `make tests`

Resolves #860
------
https://chatgpt.com/codex/tasks/task_i_684f1cf885b08321b4dd3f4294e24ca2
2025-06-16 10:50:20 -04:00
Rohan Mehta
0eee6b8305
Allow arbitrary kwargs in model (#842)
Sometimes users want to provide parameters specific to a model provider.
This is an escape hatch.
2025-06-10 18:14:34 -04:00
Niv Hertz
8dfd6ff35c
Added support for passing tool_call_id via the RunContextWrapper (#766)
This PR fixes issue:
https://github.com/openai/openai-agents-python/issues/559

By adding the tool_call_id to the RunContextWrapper prior to calling
tools. This gives the ability to access the tool_call_id in the
implementation of the tool.
2025-06-09 11:08:50 -04:00
James Hills
c98e234845
Fix handoff transfer message JSON (#818)
## Summary
- ensure `Handoff.get_transfer_message` emits valid JSON
- test transfer message validity

## Testing
- `make format`
- `make lint`
- `make mypy`
- `make tests`


------
https://chatgpt.com/codex/tasks/task_i_68432f925b048324a16878d28e850841
2025-06-09 10:13:43 -04:00
Rohan Mehta
4a529e6c16
Add REPL run_demo_loop helper (#811) 2025-06-04 11:53:17 -04:00
Rohan Mehta
4046fcb3fa
Add is_enabled to FunctionTool (#808)
### Summary:
Allows a user to do `function_tool(is_enabled=<some_callable>)`; the
callable is called when the agent runs.

This allows you to dynamically enable/disable a tool based on the
context/env.

The meta-goal is to allow `Agent` to be effectively immutable. That
enables some nice things down the line, and this allows you to
dynamically modify the tools list without mutating the agent.

### Test Plan:
Unit tests
2025-06-03 13:44:16 -04:00
Rohan Mehta
d4c7a23e1d
Don't cache agent tools during a run (#803)
### Summary:
Towards #767. We were caching the list of tools for an agent, so if you
did `agent.tools.append(...)` from a tool call, the next call to the
model wouldn't include the new tool. THis is a bug.

### Test Plan:
Unit tests. Note that now MCP tools are listed each time the agent runs
(users can still cache the `list_tools` however).
2025-06-02 14:49:16 -04:00
Daniele Morotti
71968625cc
Added RunErrorDetails object for MaxTurnsExceeded exception (#743)
### Summary

Introduced the `RunErrorDetails` object to get partial results from a
run interrupted by `MaxTurnsExceeded` exception. In this proposal the
`RunErrorDetails` object contains all the fields from `RunResult` with
`final_output` set to `None` and `output_guardrail_results` set to an
empty list. We can decide to return less information.

@rm-openai At the moment the exception doesn't return the
`RunErrorDetails` object for the streaming mode. Do you have any
suggestions on how to deal with it? In the `_check_errors` function of
`agents/result.py` file.

### Test plan

I have not implemented any tests currently, but if needed I can
implement a basic test to retrieve partial data.

### Issue number

This PR is an attempt to solve issue #719 

### Checks

- [ ] I've added new tests (if relevant)
- [ ] I've added/updated the relevant documentation
- [ ] I've run `make lint` and `make format`
- [ ] I've made sure tests pass
2025-05-29 16:11:33 -04:00
Rohan Mehta
6e078bf7a9
Fix Gemini API content filter handling (#746)
## Summary
- avoid AttributeError when Gemini API returns `None` for chat message
- return empty output if message is filtered
- add regression test

## Testing
- `make format`
- `make lint`
- `make mypy`
- `make tests`

Towards #744
2025-05-23 13:00:30 -04:00
Rohan Mehta
db462e32a3
Fix visualization recursion with cycle detection (#737)
## Summary
- avoid infinite recursion in visualization by tracking visited agents
- test cycle detection in graph utility

## Testing
- `make mypy`
- `make tests` 

Resolves #668
2025-05-23 13:00:10 -04:00
Rohan Mehta
ce2e2a4571
Upgrade openAI sdk version (#730)
---
[//]: # (BEGIN SAPLING FOOTER)
* #732
* #731
* __->__ #730
2025-05-21 15:17:58 -04:00
WJPBProjects
466b44df18
Dev/add usage details to Usage class (#726)
PR to enhance the `Usage` object and related logic, to support more
granular token accounting, matching the details available in the [OpenAI
Responses API](https://platform.openai.com/docs/api-reference/responses)
. Specifically, it:

- Adds `input_tokens_details` and `output_tokens_details` fields to the
`Usage` dataclass, storing detailed token breakdowns (e.g.,
`cached_tokens`, `reasoning_tokens`).
- Flows this change through
- Updates and extends tests to match
- Adds a test for the Usage.add method

### Motivation
- Aligns the SDK’s usage with the latest OpenAI responses API Usage
object
- Supports downstream use cases that require fine-grained token usage
data (e.g., billing, analytics, optimization) requested by startups

---------

Co-authored-by: Wulfie Bain <wulfie@openai.com>
2025-05-20 18:23:56 +01:00
Ashok Saravanan
1994f9d4c4
feat: pass extra_body through to LiteLLM acompletion (#638)
**Purpose**  
Allow arbitrary `extra_body` parameters (e.g. `cached_content`) to be
forwarded into the LiteLLM call. Useful for context caching in Gemini
models
([docs](https://ai.google.dev/gemini-api/docs/caching?lang=python)).

**Example usage**  
```python
import os
from agents import Agent, ModelSettings
from agents.extensions.models.litellm_model import LitellmModel

cache_name = "cachedContents/34jopukfx5di"  # previously stored context

gemini_model = LitellmModel(
    model="gemini/gemini-1.5-flash-002",
    api_key=os.getenv("GOOGLE_API_KEY")
)

agent = Agent(
    name="Cached Gemini Agent",
    model=gemini_model,
    model_settings=ModelSettings(
        extra_body={"cached_content": cache_name}
    )
)
2025-05-14 12:34:27 -04:00
Rohan Mehta
8fd7773a5e
Add usage to context in streaming (#595) 2025-04-24 18:20:35 -04:00
Rohan Mehta
45eb41f1e6
More tests for cancelling streamed run (#590) 2025-04-24 14:45:03 -04:00
Daniele Morotti
e11b822d5f
Fix stream error using LiteLLM (#589)
In response to issue #587 , I implemented a solution to first check if
`refusal` and `usage` attributes exist in the `delta` object.

I added a unit test similar to `test_openai_chatcompletions_stream.py`.

Let me know if I should change something.

---------

Co-authored-by: Rohan Mehta <rm@openai.com>
2025-04-24 12:53:39 -04:00
Nathan Brake
af80e3a971
Prevent MCP ClientSession hang (#580)
Per
https://modelcontextprotocol.io/specification/draft/basic/lifecycle#timeouts

"Implementations SHOULD establish timeouts for all sent requests, to
prevent hung connections and resource exhaustion. When the request has
not received a success or error response within the timeout period, the
sender SHOULD issue a cancellation notification for that request and
stop waiting for a response.

SDKs and other middleware SHOULD allow these timeouts to be configured
on a per-request basis."

I picked 5 seconds since that's the default for SSE
2025-04-24 12:12:46 -04:00
Rohan Mehta
3755ea8658
Create to_json_dict for ModelSettings (#582)
Now that `ModelSettings` has `Reasoning`, a non-primitive object,
`dataclasses.as_dict()` wont work. It will raise an error when you try
to serialize (e.g. for tracing). This ensures the object is actually
serializable.
2025-04-23 20:39:07 -04:00
Andrew Han
a113fea0ee
Allow cancel out of the streaming result (#579)
Fix for #574 

@rm-openai I'm not sure how to add a test within the repo but I have
pasted a test script below that seems to work

```python
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.")
    num_visible_event = 0
    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)
            num_visible_event += 1
            print(num_visible_event)
            if num_visible_event == 3:
                result.cancel()


if __name__ == "__main__":
    asyncio.run(main())
````
2025-04-23 19:51:10 -04:00
Jonny Kalambay
111fc9ee66
Adding extra_headers parameters to ModelSettings (#550) 2025-04-22 22:26:47 -04:00
Rohan Mehta
942ba9840b
Docs and tests for litellm (#561) 2025-04-21 16:59:01 -04:00
Rohan Mehta
616d8e7f4b
Start and finish streaming trace in impl metod (#540)
Closes #435 and closes #538.

Unit tests.
2025-04-21 13:08:38 -04:00
Rohan Mehta
e3698f32b1
Enable non-strict output types (#539)
See #528, some folks are having issues because their output types are
not strict-compatible.

My approach was:
1. Create `AgentOutputSchemaBase`, which represents the base methods for
an output type - the json schema + validation
2. Make the existing `AgentOutputSchema` subclass
`AgentOutputSchemaBase`
3. Allow users to pass a `AgentOutputSchemaBase` to
`Agent(output_type=...)`
2025-04-21 11:58:36 -04:00
Rohan Mehta
bd404e0f87
Litellm integration (#524)
litellm is a library that abstracts away details/differences for a lot
of model providers. Adding an extension, so that any provider can easily
be integrated.

---
[//]: # (BEGIN SAPLING FOOTER)
* #532
* __->__ #524
2025-04-16 18:48:41 -04:00
Rohan Mehta
80de53e879
Extract chat completions conversion code into helper (#522)
Small refactor for rest of stack.

---
[//]: # (BEGIN SAPLING FOOTER)
* #524
* #523
* __->__ #522
2025-04-15 18:31:17 -04:00
Rohan Mehta
f329eef7e8
Examples and tests for previous_response_id (#512)
Examples + tests
2025-04-15 12:46:31 -04:00
Rohan Mehta
92d6e3e66c
Previous response id (#509)
Allows passing in the previous_response_id to reduce sending the same
data again and again.

Test plan:
Examples. Adding tests in next PR shortly.

---
[//]: # (BEGIN SAPLING FOOTER)
* __->__ #509
* #508
2025-04-14 22:02:47 -04:00
Rohan Mehta
d6f5190d53
Replace referencable_id with response_id (#508)
Minor change - naming. So that it doesn't pollute the next PR.

---
[//]: # (BEGIN SAPLING FOOTER)
* #509
* __->__ #508
2025-04-14 21:37:18 -04:00
Kazuhiro Sera
25f97f979b
Fix typos and misspellings (#486)
Detected typos using typos-cli (https://crates.io/crates/typos-cli). It
detected "occured" in a string constant "handoff_occured" too, but I
didn't change the part this time because it could be a minor breaking
change.


Full outputs:
```
% typos .
error: `Supresses` should be `Suppresses`
  --> ./src/agents/function_schema.py:134:7
    |
134 |     # Supresses warnings about missing annotations for params
    |       ^^^^^^^^^
    |
error: `typ` should be `typo`, `type`
  --> ./src/agents/strict_schema.py:51:5
   |
51 |     typ = json_schema.get("type")
   |     ^^^
   |
error: `typ` should be `typo`, `type`
  --> ./src/agents/strict_schema.py:52:8
   |
52 |     if typ == "object" and "additionalProperties" not in json_schema:
   |        ^^^
   |
error: `typ` should be `typo`, `type`
  --> ./src/agents/strict_schema.py:55:9
   |
55 |         typ == "object"
   |         ^^^
   |
error: `occured` should be `occurred`
  --> ./src/agents/stream_events.py:34:18
   |
34 |         "handoff_occured",
   |                  ^^^^^^^
   |
error: `occured` should be `occurred`
  --> ./src/agents/_run_impl.py:723:69
    |
723 |                 event = RunItemStreamEvent(item=item, name="handoff_occured")
    |                                                                     ^^^^^^^
    |
error: `desitnation` should be `destination`
  --> ./src/agents/tracing/span_data.py:171:25
    |
171 |     Includes source and desitnation agents.
    |                         ^^^^^^^^^^^
    |
error: `exmaples` should be `examples`
  --> ./docs/scripts/translate_docs.py:71:145
   |
71 |         "* The term 'examples' must be code examples when the page mentions the code examples in the repo, it can be translated as either 'code exmaples' or 'sample code'.",
   |                                                                                                                                                 ^^^^^^^^
   |
error: `structed` should be `structured`
  --> ./tests/test_agent_hooks.py:227:16
    |
227 | async def test_structed_output_non_streamed_agent_hooks():
    |                ^^^^^^^^
    |
error: `structed` should be `structured`
  --> ./tests/test_agent_hooks.py:298:16
    |
298 | async def test_structed_output_streamed_agent_hooks():
    |                ^^^^^^^^
    |
```
2025-04-14 10:37:13 -04:00
Ddper
8ded8a9981
add overwrite mechanism for stream_options (#465)
fix issue https://github.com/openai/openai-agents-python/issues/442

below is an example to overwrite include_usage


```
    result = Runner.run_streamed(
        agent,
        "Write a haiku about recursion in programming.",
        run_config=RunConfig(
            model_provider=CUSTOM_MODEL_PROVIDER,
            model_settings=ModelSettings(include_usage=True)
        ),
    )
```
2025-04-10 16:54:00 -04:00
Rohan Mehta
2bcc864b81
Don't send the "store" param unless its hitting OpenAI (#455)
Summary: See #443. Causes issues with Gemini.

Test Plan: Tests. Also tested with Gemini to ensure it works.
2025-04-07 19:13:08 -04:00
Rohan Mehta
50bbfdd8be
Ensure MCP works when inputSchema.properties is missing (#454)
Resolves #449 - TLDR, [OpenAI's
API](https://platform.openai.com/docs/api-reference/responses/create)
expects the properties field to be present, whereas the MCP schema
explicitly allows omitting the properties field. [MCP
Spec](https://github.com/modelcontextprotocol/specification/blob/main/schema/2025-03-26/schema.json)
2025-04-07 18:38:36 -04:00
Rohan Mehta
7c2d7f4abd
Misc small fixes - mcp version, test for function_schema, version gen (#429)
Summary:
1. Use <2 for MCP version so it doesn't break if the MCP sdk upgrades.
2. Test the func schema extraction logic.
3. Fix the logic to get the version nuber of the framework

Test Plan:
unit tests
2025-04-03 12:08:01 -04:00
Rohan Mehta
01f5e86ea5
Convert MCP schemas to strict where possible (#414)
## Summary:
Towards #404. I made this configurable because it's not clear this is
always a good thing to do. I also made it default to False because I'm
not sure if this could cause errors.

If it works out well, we can switch the default in the future as a small
breaking changes

## Test Plan:
Unit tests
2025-04-01 16:50:13 -04:00
Steven Heidel
aad8accc86
Expose the "store" parameter through ModelSettings (#357)
Closes https://github.com/openai/openai-agents-python/issues/173

This will also set stored completions to True by default, encouraging a
best practice.
2025-03-26 19:01:28 -04:00
Rohan Mehta
4854a745e8
Raise error on more invalid function schemas (#356)
Towards #345

## Summary:
Using a `dict` or `Mapping` isn't strict-mode compliant. But we were
checking for the literal `True` whereas the value can also be an array,
for example. Fix that.

## Test Plan:

Unit tests
2025-03-26 15:52:19 -04:00
pakrym-oai
6d95a3f191
Mark handoff span as errored when multiple handoffs are requested (#344)
Also includes the set of requested agents in the error data.
<img width="968" alt="image"
src="https://github.com/user-attachments/assets/0c5c2e81-08f7-445c-bbb0-3e169ef744a5"
/>
2025-03-26 10:44:59 -04:00
Rohan Mehta
b5ba22904a
[5/n] MCP tracing (#342)
## Summary:

Adds tracing and tests for tracing.
- Tools are added to the agents
- Theres a span for the mcp tools lookup
- Functions have MCP data

## Test Plan:

Unit tests
.
2025-03-25 19:54:28 -04:00
Rohan Mehta
010022777b [5/n] MCP tracing
## Summary:

Adds tracing and tests for tracing.
- Tools are added to the agents
- Theres a span for the mcp tools lookup
- Functions have MCP data

## Test Plan:

Unit tests
.
2025-03-25 19:28:48 -04:00
Rohan Mehta
dd881eed9a
feat: Add Graphviz-based agent visualization functionality (#147)
This pull request introduces functionality for visualizing agent
structures using Graphviz. The changes include adding a new dependency,
implementing functions to generate and draw graphs, and adding tests for
these functions.

New functionality for visualizing agent structures:

* Added `graphviz` as a new dependency in `pyproject.toml`.
* Implemented functions in `src/agents/visualizations.py` to generate
and draw graphs for agents using Graphviz. These functions include
`get_main_graph`, `get_all_nodes`, `get_all_edges`, and `draw_graph`.

Testing the new visualization functionality:

* Added tests in `tests/test_visualizations.py` to verify the
correctness of the graph generation and drawing functions. The tests
cover `get_main_graph`, `get_all_nodes`, `get_all_edges`, and
`draw_graph`.

For example, given the following code:

```python
from agents import Agent, function_tool
from agents.visualizations import draw_graph


@function_tool
def get_weather(city: str) -> str:
    return f"The weather in {city} is sunny."


spanish_agent = Agent(
    name="Spanish agent",
    instructions="You only speak Spanish.",
)

english_agent = Agent(
    name="English agent",
    instructions="You only speak English",
)

triage_agent = Agent(
    name="Triage agent",
    instructions="Handoff to the appropriate agent based on the language of the request.",
    handoffs=[spanish_agent, english_agent],
    tools=[get_weather],
)


draw_graph(triage_agent)
```

Generates the following image:

<img width="614" alt="Screenshot 2025-03-13 at 18 36 23"
src="https://github.com/user-attachments/assets/d01fe502-6886-4efb-aaf8-c92e4524b0fe"
/>
2025-03-25 19:22:58 -04:00
Martín Bravo
351b6074e5 Refactor visualization functions to improve formatting and streamline edge generation 2025-03-25 19:12:40 +01:00
Martín Bravo
5ad53d8000 Add start and end nodes to graph visualization and update edge generation 2025-03-25 19:11:43 +01:00
Martín Bravo
2f2606e5ea Add graphviz as a dependency and update import statements 2025-03-25 18:46:23 +01:00
Rohan Mehta
6fb5792b77 Make the reset behavior on tool use configurable
## Summary:

#263 added this behavior. The goal was to prevent infinite loops when tool choice was set. The key change I'm making is:
1. Making it configurable on the agent.
2. Doing bookkeeping in the Runner to track this, to prevent mutating agents.
3. Not resetting the global tool choice in RunConfig.

## Test Plan:
Unit tests.
.
2025-03-25 13:29:32 -04:00
Martín Bravo
48fad9e2d3 Merge branch 'main' of https://github.com/openai/openai-agents-python into feat/draw_graph 2025-03-25 18:02:51 +01:00
Rohan Mehta
4f8cbfa676
[2/n] Add MCP support to Runner (#321)
### Summary:
This enables users to **use** MCP inside the SDK.
1. You add a list of MCP servers to `Agent`, via `mcp_server=[...]`
2. When an agent runs, we look up its MCP tools and add them to the list
of tools.
3. When a tool call occurs, we call the relevant MCP server.

Notes:
1. There's some refactoring to make sure we send the full list of tools
to the Runner/Model etc.
2. Right now, you could have a locally defined tool that conflicts with
an MCP defined tool. I didn't add errors for that, will do in a
followup.

### Test Plan:
See unit tests. Also has an end to end example next PR.

---
[//]: # (BEGIN SAPLING FOOTER)
* #324
* #322
* __->__ #321
* #320
2025-03-25 12:53:29 -04:00
Martín Bravo
900a97fa55 Merge branch 'main' of https://github.com/openai/openai-agents-python into feat/draw_graph 2025-03-25 16:58:01 +01:00
Rohan Mehta
927a29c56b
Fix potential infinite tool call loop by resetting tool_choice after … (#263)
# Fix potential infinite tool call loop by resetting tool_choice after
tool execution

## Summary

This PR fixes an issue where setting `tool_choice` to "required" or a
specific function name could cause models to get stuck in an infinite
tool call loop.

When `tool_choice` is set to force tool usage, this setting persists
across model invocations. This PR automatically resets `tool_choice` to
"auto" after tool execution, allowing the model to decide whether to
make additional tool calls in subsequent turns.

Unlike using `tool_use_behavior="stop_on_first_tool"`, this approach
lets the model continue processing tool results while preventing forced
repeated tool calls.

## Test plan

- Added tests to verify tool_choice reset behavior for both agent and
run_config settings
- Added integration test to verify the solution prevents infinite loops
- All tests pass

## Checks

- [x] I've added new tests for the fix
- [x] I've updated the relevant documentation (added comment in code)
- [x] I've run `make lint` and `make format`
- [x] I've made sure tests pass
2025-03-25 11:30:53 -04:00