Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 52 additions & 1 deletion docs/guardrails.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,57 @@ Output guardrails run in 3 steps:

Output guardrails always run after the agent completes, so they don't support the `run_in_parallel` parameter.

## Tool guardrails

Tool guardrails wrap **function tools** and let you validate or block tool calls before and after execution. They are configured on the tool itself and run every time that tool is invoked.

- Input tool guardrails run before the tool executes and can skip the call, replace the output with a message, or raise a tripwire.
- Output tool guardrails run after the tool executes and can replace the output or raise a tripwire.
- Tool guardrails apply only to function tools created with [`function_tool`][agents.function_tool]; hosted tools (`WebSearchTool`, `FileSearchTool`, `HostedMCPTool`, `CodeInterpreterTool`, `ImageGenerationTool`) and local runtime tools (`ComputerTool`, `ShellTool`, `ApplyPatchTool`, `LocalShellTool`) do not use this guardrail pipeline.

```python
import json
from agents import (
Agent,
Runner,
ToolGuardrailFunctionOutput,
function_tool,
tool_input_guardrail,
tool_output_guardrail,
)

@tool_input_guardrail
def block_secrets(data):
args = json.loads(data.context.tool_arguments or "{}")
if "sk-" in json.dumps(args):
return ToolGuardrailFunctionOutput.reject_content(
"Remove secrets before calling this tool."
)
return ToolGuardrailFunctionOutput.allow()


@tool_output_guardrail
def redact_output(data):
text = str(data.output or "")
if "sk-" in text:
return ToolGuardrailFunctionOutput.reject_content("Output contained sensitive data.")
return ToolGuardrailFunctionOutput.allow()


@function_tool(
tool_input_guardrails=[block_secrets],
tool_output_guardrails=[redact_output],
)
def classify_text(text: str) -> str:
"""Classify text for internal routing."""
return f"length:{len(text)}"


agent = Agent(name="Classifier", tools=[classify_text])
result = Runner.run_sync(agent, "hello world")
print(result.final_output)
```

## 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 `{Input,Output}GuardrailTripwireTriggered` exception and halt the Agent execution.
Expand Down Expand Up @@ -161,4 +212,4 @@ async def main():
1. This is the actual agent's output type.
2. This is the guardrail's output type.
3. This is the guardrail function that receives the agent's output, and returns the result.
4. This is the actual agent that defines the workflow.
4. This is the actual agent that defines the workflow.
2 changes: 2 additions & 0 deletions docs/handoffs.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ Handoffs are represented as tools to the LLM. So if there's a handoff to an agen

All agents have a [`handoffs`][agents.agent.Agent.handoffs] param, which can either take an `Agent` directly, or a `Handoff` object that customizes the Handoff.

If you pass plain `Agent` instances, their [`handoff_description`][agents.agent.Agent.handoff_description] (when set) is appended to the default tool description. Use it to hint when the model should pick that handoff without writing a full `handoff()` object.

You can create a handoff using the [`handoff()`][agents.handoffs.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.

### Basic Usage
Expand Down
4 changes: 4 additions & 0 deletions docs/mcp.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,10 @@ The constructor accepts additional options:

## 3. HTTP with SSE MCP servers

!!! warning

The MCP project has deprecated the Server-Sent Events transport. Prefer Streamable HTTP or stdio for new integrations and keep SSE only for legacy servers.

If the MCP server implements the HTTP with SSE transport, instantiate
[`MCPServerSse`][agents.mcp.server.MCPServerSse]. Apart from the transport, the API is identical to the Streamable HTTP server.

Expand Down
10 changes: 10 additions & 0 deletions docs/models/litellm.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,13 @@ agent = Agent(
```

With `include_usage=True`, LiteLLM requests report token and request counts through `result.context_wrapper.usage` just like the built-in OpenAI models.

## Troubleshooting

If you see Pydantic serializer warnings from LiteLLM responses, enable a small compatibility patch by setting:

```bash
export OPENAI_AGENTS_ENABLE_LITELLM_SERIALIZER_PATCH=true
```

This opt-in flag suppresses known LiteLLM serializer warnings while preserving normal behavior. Turn it off (unset or `false`) if you do not need it.
3 changes: 3 additions & 0 deletions docs/ref/apply_diff.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# `Apply Diff`

::: agents.apply_diff
3 changes: 3 additions & 0 deletions docs/ref/editor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# `Editor`

::: agents.editor
3 changes: 3 additions & 0 deletions docs/ref/extensions/memory/async_sqlite_session.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# `Async Sqlite Session`

::: agents.extensions.memory.async_sqlite_session
3 changes: 3 additions & 0 deletions docs/ref/handoffs/history.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# `History`

::: agents.handoffs.history
3 changes: 3 additions & 0 deletions docs/ref/memory/openai_responses_compaction_session.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# `Openai Responses Compaction Session`

::: agents.memory.openai_responses_compaction_session
3 changes: 3 additions & 0 deletions docs/ref/tracing/config.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# `Config`

::: agents.tracing.config
2 changes: 2 additions & 0 deletions docs/results.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ The [`new_items`][agents.result.RunResultBase.new_items] property contains the n

The [`input_guardrail_results`][agents.result.RunResultBase.input_guardrail_results] and [`output_guardrail_results`][agents.result.RunResultBase.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.

Tool guardrail results are available separately as [`tool_input_guardrail_results`][agents.result.RunResultBase.tool_input_guardrail_results] and [`tool_output_guardrail_results`][agents.result.RunResultBase.tool_output_guardrail_results], covering every tool call that ran during the agent workflow.
Comment thread
seratch marked this conversation as resolved.
Outdated
Comment thread
seratch marked this conversation as resolved.
Outdated

### Raw responses

The [`raw_responses`][agents.result.RunResultBase.raw_responses] property contains the [`ModelResponse`][agents.items.ModelResponse]s generated by the LLM.
Expand Down
26 changes: 26 additions & 0 deletions docs/running_agents.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,12 @@ The `run_config` parameter lets you configure some global settings for the agent
- [`nest_handoff_history`][agents.run.RunConfig.nest_handoff_history]: When `True` (the default) the runner collapses the prior transcript into a single assistant message before invoking the next agent. The helper places the content inside a `<CONVERSATION HISTORY>` block that keeps appending new turns as subsequent handoffs occur. Set this to `False` or provide a custom handoff filter if you prefer to pass through the raw transcript. All [`Runner` methods](agents.run.Runner) automatically create a `RunConfig` when you do not pass one, so the quickstarts and examples pick up this default automatically, and any explicit [`Handoff.input_filter`][agents.handoffs.Handoff.input_filter] callbacks continue to override it. Individual handoffs can override this setting via [`Handoff.nest_handoff_history`][agents.handoffs.Handoff.nest_handoff_history].
- [`handoff_history_mapper`][agents.run.RunConfig.handoff_history_mapper]: Optional callable that receives the normalized transcript (history + handoff items) whenever `nest_handoff_history` is `True`. It must return the exact list of input items to forward to the next agent, allowing you to replace the built-in summary without writing a full handoff filter.
- [`tracing_disabled`][agents.run.RunConfig.tracing_disabled]: Allows you to disable [tracing](tracing.md) for the entire run.
- [`tracing`][agents.run.RunConfig.tracing]: Pass a [`TracingConfig`][agents.tracing.TracingConfig] to override exporters, processors, or tracing metadata for this run.
- [`trace_include_sensitive_data`][agents.run.RunConfig.trace_include_sensitive_data]: Configures whether traces will include potentially sensitive data, such as LLM and tool call inputs/outputs.
- [`workflow_name`][agents.run.RunConfig.workflow_name], [`trace_id`][agents.run.RunConfig.trace_id], [`group_id`][agents.run.RunConfig.group_id]: Sets the tracing workflow name, trace ID and trace group ID for the run. We recommend at least setting `workflow_name`. The group ID is an optional field that lets you link traces across multiple runs.
- [`trace_metadata`][agents.run.RunConfig.trace_metadata]: Metadata to include on all traces.
- [`session_input_callback`][agents.run.RunConfig.session_input_callback]: Customize how new user input is merged with session history before each turn when using Sessions.
- [`call_model_input_filter`][agents.run.RunConfig.call_model_input_filter]: Hook to edit the fully prepared model input (instructions and input items) immediately before the model call, e.g., to trim history or inject a system prompt.

By default, the SDK now nests prior turns inside a single assistant summary message whenever an agent hands off to another agent. This reduces repeated assistant messages and keeps the full transcript inside a single block that new agents can scan quickly. If you'd like to return to the legacy behavior, pass `RunConfig(nest_handoff_history=False)` or supply a `handoff_input_filter` (or `handoff_history_mapper`) that forwards the conversation exactly as you need. You can also opt out (or in) for a specific handoff by setting `handoff(..., nest_handoff_history=False)` or `True`. To change the wrapper text used in the generated summary without writing a custom mapper, call [`set_conversation_history_wrappers`][agents.handoffs.set_conversation_history_wrappers] (and [`reset_conversation_history_wrappers`][agents.handoffs.reset_conversation_history_wrappers] to restore the defaults).

Expand Down Expand Up @@ -182,6 +185,29 @@ async def main():
print(f"Assistant: {result.final_output}")
```

## Call model input filter

Use `call_model_input_filter` to edit the model input right before the model call. The hook receives the current agent, context, and the combined input items (including session history when present) and returns a new `ModelInputData`.

```python
from agents import Agent, Runner, RunConfig
from agents.run import CallModelData, ModelInputData

def drop_old_messages(data: CallModelData[None]) -> ModelInputData:
# Keep only the last 5 items and preserve existing instructions.
trimmed = data.model_data.input[-5:]
return ModelInputData(input=trimmed, instructions=data.model_data.instructions)

agent = Agent(name="Assistant", instructions="Answer concisely.")
result = Runner.run_sync(
agent,
"Explain quines",
run_config=RunConfig(call_model_input_filter=drop_old_messages),
)
```

Set the hook per run via `run_config` or as a default on your `Runner` to redact sensitive data, trim long histories, or inject additional system guidance.

## Long running agents & human-in-the-loop

You can use the Agents SDK [Temporal](https://temporal.io/) integration to run durable, long-running workflows, including human-in-the-loop tasks. View a demo of Temporal and the Agents SDK working in action to complete long-running tasks [in this video](https://www.youtube.com/watch?v=fFBZqzT4DD8), and [view docs here](https://github.com/temporalio/sdk-python/tree/main/temporalio/contrib/openai_agents).
Expand Down
59 changes: 53 additions & 6 deletions docs/tools.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
# 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:
Tools let agents take actions: things like fetching data, running code, calling external APIs, and even using a computer. The SDK supports four categories:

- Hosted tools: these run on LLM servers alongside the AI models. OpenAI offers retrieval, web search and computer use as hosted tools.
- Function calling: these allow you to use any Python function as a tool.
- 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 OpenAI tools: run alongside the model on OpenAI servers.
- Local runtime tools: run in your environment (computer use, shell, apply patch).
- Function calling: wrap any Python function as a tool.
- Agents as tools: expose an agent as a callable tool without a full handoff.

## Hosted tools

OpenAI offers a few built-in tools when using the [`OpenAIResponsesModel`][agents.models.openai_responses.OpenAIResponsesModel]:

- The [`WebSearchTool`][agents.tool.WebSearchTool] lets an agent search the web.
- The [`FileSearchTool`][agents.tool.FileSearchTool] allows retrieving information from your OpenAI Vector Stores.
- The [`ComputerTool`][agents.tool.ComputerTool] allows automating computer use tasks.
- The [`CodeInterpreterTool`][agents.tool.CodeInterpreterTool] lets the LLM execute code in a sandboxed environment.
- The [`HostedMCPTool`][agents.tool.HostedMCPTool] exposes a remote MCP server's tools to the model.
- The [`ImageGenerationTool`][agents.tool.ImageGenerationTool] generates images from a prompt.
- The [`LocalShellTool`][agents.tool.LocalShellTool] runs shell commands on your machine.

```python
from agents import Agent, FileSearchTool, Runner, WebSearchTool
Expand All @@ -37,6 +36,54 @@ async def main():
print(result.final_output)
```

## Local runtime tools

Local runtime tools execute in your environment and require you to supply implementations:

- [`ComputerTool`][agents.tool.ComputerTool]: implement the [`Computer`][agents.computer.Computer] or [`AsyncComputer`][agents.computer.AsyncComputer] interface to enable GUI/browser automation.
- [`ShellTool`][agents.tool.ShellTool] or [`LocalShellTool`][agents.tool.LocalShellTool]: provide a shell executor to run commands.
- [`ApplyPatchTool`][agents.tool.ApplyPatchTool]: implement [`ApplyPatchEditor`][agents.editor.ApplyPatchEditor] to apply diffs locally.

```python
from agents import Agent, ApplyPatchTool, ShellTool
from agents.computer import AsyncComputer
from agents.editor import ApplyPatchResult, ApplyPatchOperation, ApplyPatchEditor


class NoopComputer(AsyncComputer):
environment = "browser"
dimensions = (1024, 768)
async def screenshot(self): return ""
async def click(self, x, y, button): ...
async def double_click(self, x, y): ...
async def scroll(self, x, y, scroll_x, scroll_y): ...
async def type(self, text): ...
async def wait(self): ...
async def move(self, x, y): ...
async def keypress(self, keys): ...
async def drag(self, path): ...


class NoopEditor(ApplyPatchEditor):
async def create_file(self, op: ApplyPatchOperation): return ApplyPatchResult(status="completed")
async def update_file(self, op: ApplyPatchOperation): return ApplyPatchResult(status="completed")
async def delete_file(self, op: ApplyPatchOperation): return ApplyPatchResult(status="completed")


async def run_shell(request):
return "shell output"


agent = Agent(
name="Local tools agent",
tools=[
ShellTool(executor=run_shell),
ApplyPatchTool(editor=NoopEditor()),
# ComputerTool expects a Computer/AsyncComputer implementation; omitted here for brevity.
],
)
```

## Function tools

You can use any Python function as a tool. The Agents SDK will setup the tool automatically:
Expand Down
2 changes: 2 additions & 0 deletions docs/tracing.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ The `generation_span()` stores the inputs/outputs of the LLM generation, and `fu

Similarly, Audio spans include base64-encoded PCM data for input and output audio by default. You can disable capturing this audio data by configuring [`VoicePipelineConfig.trace_include_sensitive_audio_data`][agents.voice.pipeline_config.VoicePipelineConfig.trace_include_sensitive_audio_data].

By default, `trace_include_sensitive_data` is `True`. You can set the default without code by exporting the `OPENAI_AGENTS_TRACE_INCLUDE_SENSITIVE_DATA` environment variable to `true/1` or `false/0` before running your app.

## Custom tracing processors

The high level architecture for tracing is:
Expand Down
6 changes: 5 additions & 1 deletion mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,15 @@ plugins:
- ref/lifecycle.md
- ref/items.md
- ref/run_context.md
- ref/tool_context.md
- ref/usage.md
- ref/logger.md
- ref/exceptions.md
- ref/guardrail.md
- ref/prompts.md
- ref/model_settings.md
- ref/strict_schema.md
- ref/tool_guardrails.md
- ref/computer.md
- ref/agent_output.md
- ref/function_schema.md
- ref/models/interface.md
Expand Down