Update package name

This commit is contained in:
2025-03-14 16:03:46 -05:00
parent f8d856f04d
commit 795c639e6a
53 changed files with 230 additions and 230 deletions
+2 -2
View File
@@ -9,14 +9,14 @@ assignees: ''
### Please read this first
- **Have you read the docs?**[Agents SDK docs](https://openai.github.io/openai-agents-python/)
- **Have you read the docs?**[Agent SDK docs](https://openai.github.io/openai-agents-python/)
- **Have you searched for related issues?** Others may have faced similar issues.
### Describe the bug
A clear and concise description of what the bug is.
### Debug information
- Agents SDK version: (e.g. `v0.0.3`)
- Agent SDK version: (e.g. `v0.0.3`)
- Python version (e.g. Python 3.10)
### Repro steps
+1 -1
View File
@@ -9,7 +9,7 @@ assignees: ''
### Please read this first
- **Have you read the docs?**[Agents SDK docs](https://openai.github.io/openai-agents-python/)
- **Have you read the docs?**[Agent SDK docs](https://openai.github.io/openai-agents-python/)
- **Have you searched for related issues?** Others may have had similar requesrs
### Describe the feature
+2 -2
View File
@@ -1,6 +1,6 @@
---
name: Custom model providers
about: Questions or bugs about using non-OpenAI models
about: Questions or bugs about using non-Hanzo AI models
title: ''
labels: bug
assignees: ''
@@ -16,7 +16,7 @@ assignees: ''
A clear and concise description of what the question or bug is.
### Debug information
- Agents SDK version: (e.g. `v0.0.3`)
- Agent SDK version: (e.g. `v0.0.3`)
- Python version (e.g. Python 3.10)
### Repro steps
+1 -1
View File
@@ -9,7 +9,7 @@ assignees: ''
### Please read this first
- **Have you read the docs?**[Agents SDK docs](https://openai.github.io/openai-agents-python/)
- **Have you read the docs?**[Agent SDK docs](https://openai.github.io/openai-agents-python/)
- **Have you searched for related issues?** Others may have had similar requesrs
### Question
+1 -1
View File
@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2025 OpenAI
Copyright (c) 2025 Hanzo Industries, Inc
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+9 -9
View File
@@ -1,6 +1,6 @@
# OpenAI Agents SDK
# Hanzo AI Agent SDK
The OpenAI Agents SDK is a lightweight yet powerful framework for building multi-agent workflows.
The Hanzo AI Agent SDK is a lightweight yet powerful framework for building multi-agent workflows.
<img src="https://cdn.openai.com/API/docs/images/orchestration.png" alt="Image of the Agents Tracing UI" style="max-height: 803px;">
@@ -13,7 +13,7 @@ The OpenAI Agents SDK is a lightweight yet powerful framework for building multi
Explore the [examples](examples) directory to see the SDK in action, and read our [documentation](https://openai.github.io/openai-agents-python/) for more details.
Notably, our SDK [is compatible](https://openai.github.io/openai-agents-python/models/) with any model providers that support the OpenAI Chat Completions API format.
Notably, our SDK [is compatible](https://openai.github.io/openai-agents-python/models/) with any model providers that support the Open AI Chat Completions API format.
## Get started
@@ -24,16 +24,16 @@ python -m venv env
source env/bin/activate
```
2. Install Agents SDK
2. Install Hanzo AI SDK
```
pip install openai-agents
pip install hanzoai
```
## Hello world example
```python
from agents import Agent, Runner
from hanzoai import Agent, Runner
agent = Agent(name="Assistant", instructions="You are a helpful assistant")
@@ -138,11 +138,11 @@ As a result, the mental model for the agent loop is:
## Common agent patterns
The Agents SDK is designed to be highly flexible, allowing you to model a wide range of LLM workflows including deterministic flows, iterative loops, and more. See examples in [`examples/agent_patterns`](examples/agent_patterns).
The Agent SDK is designed to be highly flexible, allowing you to model a wide range of LLM workflows including deterministic flows, iterative loops, and more. See examples in [`examples/agent_patterns`](examples/agent_patterns).
## Tracing
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).
The Agent 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).
## Development (only needed if you need to edit the SDK/examples)
@@ -175,4 +175,4 @@ We'd like to acknowledge the excellent work of the open-source community, especi
- [Griffe](https://github.com/mkdocstrings/griffe)
- [uv](https://github.com/astral-sh/uv) and [ruff](https://github.com/astral-sh/ruff)
We're committed to continuing to build the Agents SDK as an open source framework so others in the community can expand on our approach.
We're committed to continuing to build the Agent SDK as an open source framework so others in the community can expand on our approach.
+5 -5
View File
@@ -10,17 +10,17 @@ 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()][agents.set_default_openai_client] function.
Alternatively, you can also configure an Hanzo AI client to be used. By default, the SDK creates an `AsyncHanzo AI` 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()][agents.set_default_openai_client] function.
```python
from openai import AsyncOpenAI
from openai import AsyncHanzo AI
from agents import set_default_openai_client
custom_client = AsyncOpenAI(base_url="...", api_key="...")
custom_client = AsyncHanzo AI(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()][agents.set_default_openai_api] function.
Finally, you can also customize the Hanzo AI API that is used. By default, we use the Hanzo AI Responses API. You can override this to use the Chat Completions API by using the [set_default_openai_api()][agents.set_default_openai_api] function.
```python
from agents import set_default_openai_api
@@ -30,7 +30,7 @@ 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`][agents.set_tracing_export_api_key] function.
Tracing is enabled by default. It uses the Hanzo AI 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`][agents.set_tracing_export_api_key] function.
```python
from agents import set_tracing_export_api_key
+1 -1
View File
@@ -8,7 +8,7 @@ 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.
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.
You can create a handoff using the [`handoff()`][agents.handoffs.handoff] function provided by the Agent SDK. This function allows you to specify the agent to hand off to, along with optional overrides and input filters.
### Basic Usage
+4 -4
View File
@@ -1,6 +1,6 @@
# OpenAI Agents SDK
# Hanzo AI Agent SDK
The [OpenAI Agents SDK](https://github.com/openai/openai-agents-python) 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](https://github.com/openai/swarm/tree/main). The Agents SDK has a very small set of primitives:
The [Hanzo AI Agent SDK](https://github.com/openai/openai-agents-python) 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](https://github.com/openai/swarm/tree/main). The Agent SDK has a very small set of primitives:
- **Agents**, which are LLMs equipped with instructions and tools
- **Handoffs**, which allow agents to delegate to other agents for specific tasks
@@ -8,7 +8,7 @@ The [OpenAI Agents SDK](https://github.com/openai/openai-agents-python) enables
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.
## Why use the Agents SDK
## Why use the Agent SDK
The SDK has two driving design principles:
@@ -22,7 +22,7 @@ Here are the main features of the SDK:
- 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.
- 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: Built-in tracing that lets you visualize, debug and monitor your workflows, as well as use the Hanzo AI suite of evaluation, fine-tuning and distillation tools.
## Installation
+14 -14
View File
@@ -1,24 +1,24 @@
# Models
The Agents SDK comes with out-of-the-box support for OpenAI models in two flavors:
The Agent SDK comes with out-of-the-box support for Hanzo AI models in two flavors:
- **Recommended**: the [`OpenAIResponsesModel`][agents.models.openai_responses.OpenAIResponsesModel], which calls OpenAI APIs using the new [Responses API](https://platform.openai.com/docs/api-reference/responses).
- The [`OpenAIChatCompletionsModel`][agents.models.openai_chatcompletions.OpenAIChatCompletionsModel], which calls OpenAI APIs using the [Chat Completions API](https://platform.openai.com/docs/api-reference/chat).
- **Recommended**: the [`Hanzo AIResponsesModel`][agents.models.openai_responses.Hanzo AIResponsesModel], which calls Hanzo AI APIs using the new [Responses API](https://platform.openai.com/docs/api-reference/responses).
- The [`Hanzo AIChatCompletionsModel`][agents.models.openai_chatcompletions.Hanzo AIChatCompletionsModel], which calls Hanzo AI APIs using the [Chat Completions API](https://platform.openai.com/docs/api-reference/chat).
## 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`][agents.Agent], you can select a specific model by either:
1. Passing the name of an OpenAI model.
1. Passing the name of an Hanzo AI model.
2. Passing any model name + a [`ModelProvider`][agents.models.interface.ModelProvider] that can map that name to a Model instance.
3. Directly providing a [`Model`][agents.models.interface.Model] implementation.
!!!note
While our SDK supports both the [`OpenAIResponsesModel`][agents.models.openai_responses.OpenAIResponsesModel] and the [`OpenAIChatCompletionsModel`][agents.models.openai_chatcompletions.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.
While our SDK supports both the [`Hanzo AIResponsesModel`][agents.models.openai_responses.Hanzo AIResponsesModel] and the [`Hanzo AIChatCompletionsModel`][agents.models.openai_chatcompletions.Hanzo AIChatCompletionsModel] 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.
```python
from agents import Agent, Runner, AsyncOpenAI, OpenAIChatCompletionsModel
from agents import Agent, Runner, AsyncHanzo AI, Hanzo AIChatCompletionsModel
import asyncio
spanish_agent = Agent(
@@ -30,9 +30,9 @@ spanish_agent = Agent(
english_agent = Agent(
name="English agent",
instructions="You only speak English",
model=OpenAIChatCompletionsModel( # (2)!
model=Hanzo AIChatCompletionsModel( # (2)!
model="gpt-4o",
openai_client=AsyncOpenAI()
openai_client=AsyncHanzo AI()
),
)
@@ -48,14 +48,14 @@ async def main():
print(result.final_output)
```
1. Sets the name of an OpenAI model directly.
1. Sets the name of an Hanzo AI model directly.
2. Provides a [`Model`][agents.models.interface.Model] implementation.
## Using other LLM providers
You can use other LLM providers in 3 ways (examples [here](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/)):
1. [`set_default_openai_client`][agents.set_default_openai_client] is useful in cases where you want to globally use an instance of `AsyncOpenAI` as the LLM client. This is for cases where the LLM provider has an OpenAI compatible API endpoint, and you can set the `base_url` and `api_key`. See a configurable example in [examples/model_providers/custom_example_global.py](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/custom_example_global.py).
1. [`set_default_openai_client`][agents.set_default_openai_client] is useful in cases where you want to globally use an instance of `AsyncHanzo AI` as the LLM client. This is for cases where the LLM provider has an Hanzo AI compatible API endpoint, and you can set the `base_url` and `api_key`. See a configurable example in [examples/model_providers/custom_example_global.py](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/custom_example_global.py).
2. [`ModelProvider`][agents.models.interface.ModelProvider] is at the `Runner.run` level. This lets you say "use a custom model provider for all agents in this run". See a configurable example in [examples/model_providers/custom_example_provider.py](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/custom_example_provider.py).
3. [`Agent.model`][agents.agent.Agent.model] lets you specify the model on a specific Agent instance. This enables you to mix and match different providers for different agents. See a configurable example in [examples/model_providers/custom_example_agent.py](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/custom_example_agent.py).
@@ -69,18 +69,18 @@ In cases where you do not have an API key from `platform.openai.com`, we recomme
### Tracing client error 401
If you get errors related to tracing, this is because traces are uploaded to OpenAI servers, and you don't have an OpenAI API key. You have three options to resolve this:
If you get errors related to tracing, this is because traces are uploaded to Hanzo AI servers, and you don't have an Hanzo AI API key. You have three options to resolve this:
1. Disable tracing entirely: [`set_tracing_disabled(True)`][agents.set_tracing_disabled].
2. Set an OpenAI key for tracing: [`set_tracing_export_api_key(...)`][agents.set_tracing_export_api_key]. This API key will only be used for uploading traces, and must be from [platform.openai.com](https://platform.openai.com/).
3. Use a non-OpenAI trace processor. See the [tracing docs](tracing.md#custom-tracing-processors).
2. Set an Hanzo AI key for tracing: [`set_tracing_export_api_key(...)`][agents.set_tracing_export_api_key]. This API key will only be used for uploading traces, and must be from [platform.openai.com](https://platform.openai.com/).
3. Use a non-Hanzo AI trace processor. See the [tracing docs](tracing.md#custom-tracing-processors).
### Responses API support
The SDK uses the Responses API by default, but most other LLM providers don't yet support it. You may see 404s or similar issues as a result. To resolve, you have two options:
1. Call [`set_default_openai_api("chat_completions")`][agents.set_default_openai_api]. This works if you are setting `OPENAI_API_KEY` and `OPENAI_BASE_URL` via environment vars.
2. Use [`OpenAIChatCompletionsModel`][agents.models.openai_chatcompletions.OpenAIChatCompletionsModel]. There are examples [here](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/).
2. Use [`Hanzo AIChatCompletionsModel`][agents.models.openai_chatcompletions.Hanzo AIChatCompletionsModel]. There are examples [here](https://github.com/openai/openai-agents-python/tree/main/examples/model_providers/).
### Structured outputs support
+4 -4
View File
@@ -18,15 +18,15 @@ Do this every time you start a new terminal session.
source .venv/bin/activate
```
### Install the Agents SDK
### Install the Agent SDK
```bash
pip install openai-agents # or `uv add openai-agents`, etc
```
### Set an OpenAI API key
### Set an Hanzo AI API key
If you don't have one, follow [these instructions](https://platform.openai.com/docs/quickstart#create-and-export-an-api-key) to create an OpenAI API key.
If you don't have one, follow [these instructions](https://platform.openai.com/docs/quickstart#create-and-export-an-api-key) to create an Hanzo AI API key.
```bash
export OPENAI_API_KEY=sk-...
@@ -178,7 +178,7 @@ if __name__ == "__main__":
## View your traces
To review what happened during your agent run, navigate to the [Trace viewer in the OpenAI Dashboard](https://platform.openai.com/traces) to view traces of your agent runs.
To review what happened during your agent run, navigate to the [Trace viewer in the Hanzo AI Dashboard](https://platform.openai.com/traces) to view traces of your agent runs.
## Next steps
+1 -1
View File
@@ -1,3 +1,3 @@
# `OpenAI Chat Completions model`
# `Hanzo AI Chat Completions model`
::: agents.models.openai_chatcompletions
+1 -1
View File
@@ -1,3 +1,3 @@
# `OpenAI Responses model`
# `Hanzo AI Responses model`
::: agents.models.openai_responses
+2 -2
View File
@@ -23,7 +23,7 @@ Read more in the [results guide](results.md).
## 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.
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 Hanzo AI Responses API.
The runner then runs a loop:
@@ -47,7 +47,7 @@ Streaming allows you to additionally receive streaming events as the LLM runs. O
The `run_config` parameter lets you configure some global settings for the agent run:
- [`model`][agents.run.RunConfig.model]: Allows setting a global LLM model to use, irrespective of what `model` each Agent has.
- [`model_provider`][agents.run.RunConfig.model_provider]: A model provider for looking up model names, which defaults to OpenAI.
- [`model_provider`][agents.run.RunConfig.model_provider]: A model provider for looking up model names, which defaults to Hanzo AI.
- [`model_settings`][agents.run.RunConfig.model_settings]: Overrides agent-specific settings. For example, you can set a global `temperature` or `top_p`.
- [`input_guardrails`][agents.run.RunConfig.input_guardrails], [`output_guardrails`][agents.run.RunConfig.output_guardrails]: A list of input or output guardrails to include on all runs.
- [`handoff_input_filter`][agents.run.RunConfig.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`][agents.handoffs.Handoff.input_filter] for more details.
+1 -1
View File
@@ -6,7 +6,7 @@ To stream, you can call [`Runner.run_streamed()`][agents.run.Runner.run_streamed
## Raw response events
[`RawResponsesStreamEvent`][agents.stream_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`][agents.stream_events.RawResponsesStreamEvent] are raw events passed directly from the LLM. They are in Hanzo AI 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.
For example, this will output the text generated by the LLM token-by-token.
+18 -18
View File
@@ -1,72 +1,72 @@
@font-face {
font-display: swap;
font-family: "OpenAI Sans";
font-family: "Hanzo AI Sans";
font-style: normal;
font-weight: 400;
src: url("https://cdn.openai.com/common/fonts/openai-sans/OpenAISans-Regular.woff2")
src: url("https://cdn.openai.com/common/fonts/openai-sans/Hanzo AISans-Regular.woff2")
format("woff2");
}
@font-face {
font-display: swap;
font-family: "OpenAI Sans";
font-family: "Hanzo AI Sans";
font-style: italic;
font-weight: 400;
src: url("https://cdn.openai.com/common/fonts/openai-sans/OpenAISans-RegularItalic.woff2")
src: url("https://cdn.openai.com/common/fonts/openai-sans/Hanzo AISans-RegularItalic.woff2")
format("woff2");
}
@font-face {
font-display: swap;
font-family: "OpenAI Sans";
font-family: "Hanzo AI Sans";
font-style: normal;
font-weight: 500;
src: url("https://cdn.openai.com/common/fonts/openai-sans/OpenAISans-Medium.woff2")
src: url("https://cdn.openai.com/common/fonts/openai-sans/Hanzo AISans-Medium.woff2")
format("woff2");
}
@font-face {
font-display: swap;
font-family: "OpenAI Sans";
font-family: "Hanzo AI Sans";
font-style: italic;
font-weight: 500;
src: url("https://cdn.openai.com/common/fonts/openai-sans/OpenAISans-MediumItalic.woff2")
src: url("https://cdn.openai.com/common/fonts/openai-sans/Hanzo AISans-MediumItalic.woff2")
format("woff2");
}
@font-face {
font-display: swap;
font-family: "OpenAI Sans";
font-family: "Hanzo AI Sans";
font-style: normal;
font-weight: 600;
src: url("https://cdn.openai.com/common/fonts/openai-sans/OpenAISans-Semibold.woff2")
src: url("https://cdn.openai.com/common/fonts/openai-sans/Hanzo AISans-Semibold.woff2")
format("woff2");
}
@font-face {
font-display: swap;
font-family: "OpenAI Sans";
font-family: "Hanzo AI Sans";
font-style: italic;
font-weight: 600;
src: url("https://cdn.openai.com/common/fonts/openai-sans/OpenAISans-SemiboldItalic.woff2")
src: url("https://cdn.openai.com/common/fonts/openai-sans/Hanzo AISans-SemiboldItalic.woff2")
format("woff2");
}
@font-face {
font-display: swap;
font-family: "OpenAI Sans";
font-family: "Hanzo AI Sans";
font-style: normal;
font-weight: 700;
src: url("https://cdn.openai.com/common/fonts/openai-sans/OpenAISans-Bold.woff2")
src: url("https://cdn.openai.com/common/fonts/openai-sans/Hanzo AISans-Bold.woff2")
format("woff2");
}
@font-face {
font-display: swap;
font-family: "OpenAI Sans";
font-family: "Hanzo AI Sans";
font-style: italic;
font-weight: 700;
src: url("https://cdn.openai.com/common/fonts/openai-sans/OpenAISans-BoldItalic.woff2")
src: url("https://cdn.openai.com/common/fonts/openai-sans/Hanzo AISans-BoldItalic.woff2")
format("woff2");
}
@@ -77,9 +77,9 @@
*/
:root {
/* Font families */
--md-text-font: "OpenAI Sans", -apple-system, system-ui, Helvetica, Arial,
--md-text-font: "Hanzo AI Sans", -apple-system, system-ui, Helvetica, Arial,
sans-serif;
--md-typeface-heading: "OpenAI Sans", -apple-system, system-ui, Helvetica,
--md-typeface-heading: "Hanzo AI Sans", -apple-system, system-ui, Helvetica,
Arial, sans-serif;
/* Global color variables */
+4 -4
View File
@@ -2,16 +2,16 @@
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:
- Hosted tools: these run on LLM servers alongside the AI models. OpenAI offers retrieval, web search and computer use as hosted tools.
- Hosted tools: these run on LLM servers alongside the AI models. Hanzo AI 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 tools
OpenAI offers a few built-in tools when using the [`OpenAIResponsesModel`][agents.models.openai_responses.OpenAIResponsesModel]:
Hanzo AI offers a few built-in tools when using the [`Hanzo AIResponsesModel`][agents.models.openai_responses.Hanzo AIResponsesModel]:
- 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 [`FileSearchTool`][agents.tool.FileSearchTool] allows retrieving information from your Hanzo AI Vector Stores.
- The [`ComputerTool`][agents.tool.ComputerTool] allows automating computer use tasks.
```python
@@ -35,7 +35,7 @@ async def main():
## Function tools
You can use any Python function as a tool. The Agents SDK will setup the tool automatically:
You can use any Python function as a tool. The Agent SDK will setup the tool automatically:
- The name of the tool will be the name of the Python function (or you can provide a name)
- Tool description will be taken from the docstring of the function (or you can provide a description)
+4 -4
View File
@@ -1,6 +1,6 @@
# 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](https://platform.openai.com/traces), you can debug, visualize, and monitor your workflows during development and in production.
The Agent 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](https://platform.openai.com/traces), you can debug, visualize, and monitor your workflows during development and in production.
!!!note
@@ -81,12 +81,12 @@ Some spans track potentially sensitive data. For example, the `generation_span()
The high level architecture for tracing is:
- At initialization, we create a global [`TraceProvider`][agents.tracing.setup.TraceProvider], which is responsible for creating traces.
- We configure the `TraceProvider` with a [`BatchTraceProcessor`][agents.tracing.processors.BatchTraceProcessor] that sends traces/spans in batches to a [`BackendSpanExporter`][agents.tracing.processors.BackendSpanExporter], which exports the spans and traces to the OpenAI backend in batches.
- We configure the `TraceProvider` with a [`BatchTraceProcessor`][agents.tracing.processors.BatchTraceProcessor] that sends traces/spans in batches to a [`BackendSpanExporter`][agents.tracing.processors.BackendSpanExporter], which exports the spans and traces to the Hanzo AI backend in batches.
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()`][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.
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.
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 Hanzo AI's backend.
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 Hanzo AI backend unless you include a `TracingProcessor` that does so.
External trace processors include:
+1 -1
View File
@@ -47,7 +47,7 @@ See the [`parallelization.py`](./parallelization.py) file for an example of this
Related to parallelization, you often want to run input guardrails to make sure the inputs to your agents are valid. For example, if you have a customer support agent, you might want to make sure that the user isn't trying to ask for help with a math problem.
You can definitely do this without any special Agents SDK features by using parallelization, but we support a special guardrail primitive. Guardrails can have a "tripwire" - if the tripwire is triggered, the agent execution will immediately stop and a `GuardrailTripwireTriggered` exception will be raised.
You can definitely do this without any special Agent SDK features by using parallelization, but we support a special guardrail primitive. Guardrails can have a "tripwire" - if the tripwire is triggered, the agent execution will immediately stop and a `GuardrailTripwireTriggered` exception will be raised.
This is really useful for latency: for example, you might have a very fast model that runs the guardrail and a slow model that runs the actual agent. You wouldn't want to wait for the slow model to finish, so guardrails let you quickly reject invalid inputs.
+1 -1
View File
@@ -1,6 +1,6 @@
# Custom LLM providers
The examples in this directory demonstrate how you might use a non-OpenAI LLM provider. To run them, first set a base URL, API key and model.
The examples in this directory demonstrate how you might use a non-Hanzo AI LLM provider. To run them, first set a base URL, API key and model.
```bash
export EXAMPLE_BASE_URL="..."
@@ -1,9 +1,9 @@
import asyncio
import os
from openai import AsyncOpenAI
from openai import AsyncHanzo AI
from agents import Agent, OpenAIChatCompletionsModel, Runner, function_tool, set_tracing_disabled
from agents import Agent, Hanzo AIChatCompletionsModel, Runner, function_tool, set_tracing_disabled
BASE_URL = os.getenv("EXAMPLE_BASE_URL") or ""
API_KEY = os.getenv("EXAMPLE_API_KEY") or ""
@@ -15,7 +15,7 @@ if not BASE_URL or not API_KEY or not MODEL_NAME:
)
"""This example uses a custom provider for a specific agent. Steps:
1. Create a custom OpenAI client.
1. Create a custom Hanzo AI client.
2. Create a `Model` that uses the custom client.
3. Set the `model` on the Agent.
@@ -23,11 +23,11 @@ Note that in this example, we disable tracing under the assumption that you don'
from platform.openai.com. If you do have one, you can either set the `OPENAI_API_KEY` env var
or call set_tracing_export_api_key() to set a tracing specific key.
"""
client = AsyncOpenAI(base_url=BASE_URL, api_key=API_KEY)
client = AsyncHanzo AI(base_url=BASE_URL, api_key=API_KEY)
set_tracing_disabled(disabled=True)
# An alternate approach that would also work:
# PROVIDER = OpenAIProvider(openai_client=client)
# PROVIDER = Hanzo AIProvider(openai_client=client)
# agent = Agent(..., model="some-custom-model")
# Runner.run(agent, ..., run_config=RunConfig(model_provider=PROVIDER))
@@ -43,7 +43,7 @@ async def main():
agent = Agent(
name="Assistant",
instructions="You only respond in haikus.",
model=OpenAIChatCompletionsModel(model=MODEL_NAME, openai_client=client),
model=Hanzo AIChatCompletionsModel(model=MODEL_NAME, openai_client=client),
tools=[get_weather],
)
@@ -1,7 +1,7 @@
import asyncio
import os
from openai import AsyncOpenAI
from openai import AsyncHanzo AI
from agents import (
Agent,
@@ -24,7 +24,7 @@ if not BASE_URL or not API_KEY or not MODEL_NAME:
"""This example uses a custom provider for all requests by default. We do three things:
1. Create a custom client.
2. Set it as the default OpenAI client, and don't use it for tracing.
2. Set it as the default Hanzo AI client, and don't use it for tracing.
3. Set the default API as Chat Completions, as most LLM providers don't yet support Responses API.
Note that in this example, we disable tracing under the assumption that you don't have an API key
@@ -32,7 +32,7 @@ from platform.openai.com. If you do have one, you can either set the `OPENAI_API
or call set_tracing_export_api_key() to set a tracing specific key.
"""
client = AsyncOpenAI(
client = AsyncHanzo AI(
base_url=BASE_URL,
api_key=API_KEY,
)
@@ -3,13 +3,13 @@ from __future__ import annotations
import asyncio
import os
from openai import AsyncOpenAI
from openai import AsyncHanzo AI
from agents import (
Agent,
Model,
ModelProvider,
OpenAIChatCompletionsModel,
Hanzo AIChatCompletionsModel,
RunConfig,
Runner,
function_tool,
@@ -26,9 +26,9 @@ if not BASE_URL or not API_KEY or not MODEL_NAME:
)
"""This example uses a custom provider for some calls to Runner.run(), and direct calls to OpenAI for
"""This example uses a custom provider for some calls to Runner.run(), and direct calls to Hanzo AI for
others. Steps:
1. Create a custom OpenAI client.
1. Create a custom Hanzo AI client.
2. Create a ModelProvider that uses the custom client.
3. Use the ModelProvider in calls to Runner.run(), only when we want to use the custom LLM provider.
@@ -36,13 +36,13 @@ Note that in this example, we disable tracing under the assumption that you don'
from platform.openai.com. If you do have one, you can either set the `OPENAI_API_KEY` env var
or call set_tracing_export_api_key() to set a tracing specific key.
"""
client = AsyncOpenAI(base_url=BASE_URL, api_key=API_KEY)
client = AsyncHanzo AI(base_url=BASE_URL, api_key=API_KEY)
set_tracing_disabled(disabled=True)
class CustomModelProvider(ModelProvider):
def get_model(self, model_name: str | None) -> Model:
return OpenAIChatCompletionsModel(model=model_name or MODEL_NAME, openai_client=client)
return Hanzo AIChatCompletionsModel(model=model_name or MODEL_NAME, openai_client=client)
CUSTOM_MODEL_PROVIDER = CustomModelProvider()
@@ -65,7 +65,7 @@ async def main():
)
print(result.final_output)
# If you uncomment this, it will use OpenAI directly, not the custom provider
# If you uncomment this, it will use Hanzo AI directly, not the custom provider
# result = await Runner.run(
# agent,
# "What's the weather in Tokyo?",
+1 -1
View File
@@ -1,4 +1,4 @@
site_name: OpenAI Agents SDK
site_name: Hanzo AI Agent SDK
theme:
name: material
features:
+7 -7
View File
@@ -1,12 +1,12 @@
[project]
name = "openai-agents"
name = "hanzoai"
version = "0.0.4"
description = "OpenAI Agents SDK"
description = "Hanzo AI SDK"
readme = "README.md"
requires-python = ">=3.9"
license = "MIT"
authors = [
{ name = "OpenAI", email = "support@openai.com" },
{ name = "Hanzo AI", email = "support@hanzo.ai" },
]
dependencies = [
"openai>=1.66.2",
@@ -31,8 +31,8 @@ classifiers = [
]
[project.urls]
Homepage = "https://github.com/openai/openai-agents-python"
Repository = "https://github.com/openai/openai-agents-python"
Homepage = "https://github.com/hanzoai/sdk"
Repository = "https://github.com/hanzoai/sdk"
[dependency-groups]
dev = [
@@ -108,7 +108,7 @@ exclude_also = [
]
[tool.pytest.ini_options]
asyncio_mode = "auto"
asyncio_mode = "auto"
asyncio_default_fixture_loop_scope = "session"
filterwarnings = [
# This is a warning that is expected to happen: we have an async filter that raises an exception
@@ -116,4 +116,4 @@ filterwarnings = [
]
markers = [
"allow_call_model_methods: mark test as allowing calls to real model implementations",
]
]
+15 -15
View File
@@ -2,7 +2,7 @@ import logging
import sys
from typing import Literal
from openai import AsyncOpenAI
from openai import AsyncHanzo AI
from . import _config
from .agent import Agent
@@ -41,9 +41,9 @@ from .items import (
from .lifecycle import AgentHooks, RunHooks
from .model_settings import ModelSettings
from .models.interface import Model, ModelProvider, ModelTracing
from .models.openai_chatcompletions import OpenAIChatCompletionsModel
from .models.openai_provider import OpenAIProvider
from .models.openai_responses import OpenAIResponsesModel
from .models.openai_chatcompletions import Hanzo AIChatCompletionsModel
from .models.openai_provider import Hanzo AIProvider
from .models.openai_responses import Hanzo AIResponsesModel
from .result import RunResult, RunResultStreaming
from .run import RunConfig, Runner
from .run_context import RunContextWrapper, TContext
@@ -93,26 +93,26 @@ from .usage import Usage
def set_default_openai_key(key: str, use_for_tracing: bool = True) -> None:
"""Set the default OpenAI API key to use for LLM requests (and optionally tracing(). This is
"""Set the default Hanzo AI API key to use for LLM requests (and optionally tracing(). This is
only necessary if the OPENAI_API_KEY environment variable is not already set.
If provided, this key will be used instead of the OPENAI_API_KEY environment variable.
Args:
key: The OpenAI key to use.
use_for_tracing: Whether to also use this key to send traces to OpenAI. Defaults to True
key: The Hanzo AI key to use.
use_for_tracing: Whether to also use this key to send traces to Hanzo AI. Defaults to True
If False, you'll either need to set the OPENAI_API_KEY environment variable or call
set_tracing_export_api_key() with the API key you want to use for tracing.
"""
_config.set_default_openai_key(key, use_for_tracing)
def set_default_openai_client(client: AsyncOpenAI, use_for_tracing: bool = True) -> None:
"""Set the default OpenAI client to use for LLM requests and/or tracing. If provided, this
client will be used instead of the default OpenAI client.
def set_default_openai_client(client: AsyncHanzo AI, use_for_tracing: bool = True) -> None:
"""Set the default Hanzo AI client to use for LLM requests and/or tracing. If provided, this
client will be used instead of the default Hanzo AI client.
Args:
client: The OpenAI client to use.
client: The Hanzo AI client to use.
use_for_tracing: Whether to use the API key from this client for uploading traces. If False,
you'll either need to set the OPENAI_API_KEY environment variable or call
set_tracing_export_api_key() with the API key you want to use for tracing.
@@ -121,7 +121,7 @@ def set_default_openai_client(client: AsyncOpenAI, use_for_tracing: bool = True)
def set_default_openai_api(api: Literal["chat_completions", "responses"]) -> None:
"""Set the default API to use for OpenAI LLM requests. By default, we will use the responses API
"""Set the default API to use for Hanzo AI LLM requests. By default, we will use the responses API
but you can set this to use the chat completions API instead.
"""
_config.set_default_openai_api(api)
@@ -141,9 +141,9 @@ __all__ = [
"ModelProvider",
"ModelTracing",
"ModelSettings",
"OpenAIChatCompletionsModel",
"OpenAIProvider",
"OpenAIResponsesModel",
"Hanzo AIChatCompletionsModel",
"Hanzo AIProvider",
"Hanzo AIResponsesModel",
"AgentOutputSchema",
"Computer",
"AsyncComputer",
+2 -2
View File
@@ -1,4 +1,4 @@
from openai import AsyncOpenAI
from openai import AsyncHanzo AI
from typing_extensions import Literal
from .models import _openai_shared
@@ -12,7 +12,7 @@ def set_default_openai_key(key: str, use_for_tracing: bool) -> None:
set_tracing_export_api_key(key)
def set_default_openai_client(client: AsyncOpenAI, use_for_tracing: bool) -> None:
def set_default_openai_client(client: AsyncHanzo AI, use_for_tracing: bool) -> None:
_openai_shared.set_default_openai_client(client)
if use_for_tracing:
+1 -1
View File
@@ -5,7 +5,7 @@ if TYPE_CHECKING:
class AgentsException(Exception):
"""Base class for all exceptions in the Agents SDK."""
"""Base class for all exceptions in the Agent SDK."""
class MaxTurnsExceeded(AgentsException):
+1 -1
View File
@@ -2,7 +2,7 @@
# similar instructions in any agents that use handoffs.
RECOMMENDED_PROMPT_PREFIX = (
"# System context\n"
"You are part of a multi-agent system called the Agents SDK, designed to make agent "
"You are part of a multi-agent system called the Agent SDK, designed to make agent "
"coordination and execution easy. Agents uses two primary abstraction: **Agents** and "
"**Handoffs**. An agent encompasses instructions and tools and can hand off a "
"conversation to another agent when appropriate. "
+1 -1
View File
@@ -202,7 +202,7 @@ def function_schema(
use_docstring_info: If True, uses the docstring to generate the description and parameter
descriptions.
strict_json_schema: Whether the JSON schema is in strict mode. If True, we'll ensure that
the schema adheres to the "strict" standard the OpenAI API expects. We **strongly**
the schema adheres to the "strict" standard the Hanzo AI API expects. We **strongly**
recommend setting this to True, as it increases the likelihood of the LLM providing
correct JSON input.
+4 -4
View File
@@ -30,16 +30,16 @@ if TYPE_CHECKING:
from .agent import Agent
TResponse = Response
"""A type alias for the Response type from the OpenAI SDK."""
"""A type alias for the Response type from the Hanzo AI SDK."""
TResponseInputItem = ResponseInputItemParam
"""A type alias for the ResponseInputItemParam type from the OpenAI SDK."""
"""A type alias for the ResponseInputItemParam type from the Hanzo AI SDK."""
TResponseOutputItem = ResponseOutputItem
"""A type alias for the ResponseOutputItem type from the OpenAI SDK."""
"""A type alias for the ResponseOutputItem type from the Hanzo AI SDK."""
TResponseStreamEvent = ResponseStreamEvent
"""A type alias for the ResponseStreamEvent type from the OpenAI SDK."""
"""A type alias for the ResponseStreamEvent type from the Hanzo AI SDK."""
T = TypeVar("T", bound=Union[TResponseOutputItem, TResponseInputItem])
+4 -4
View File
@@ -1,9 +1,9 @@
from __future__ import annotations
from openai import AsyncOpenAI
from openai import AsyncHanzo AI
_default_openai_key: str | None = None
_default_openai_client: AsyncOpenAI | None = None
_default_openai_client: AsyncHanzo AI | None = None
_use_responses_by_default: bool = True
@@ -16,12 +16,12 @@ def get_default_openai_key() -> str | None:
return _default_openai_key
def set_default_openai_client(client: AsyncOpenAI) -> None:
def set_default_openai_client(client: AsyncHanzo AI) -> None:
global _default_openai_client
_default_openai_client = client
def get_default_openai_client() -> AsyncOpenAI | None:
def get_default_openai_client() -> AsyncHanzo AI | None:
return _default_openai_client
+1 -1
View File
@@ -1,5 +1,5 @@
FAKE_RESPONSES_ID = "__fake_id__"
"""This is a placeholder ID used to fill in the `id` field in Responses API related objects. It's
useful when you're creating Responses objects from non-Responses APIs, e.g. the OpenAI Chat
useful when you're creating Responses objects from non-Responses APIs, e.g. the Hanzo AI Chat
Completions API or other LLM providers.
"""
+3 -3
View File
@@ -49,7 +49,7 @@ class Model(abc.ABC):
Args:
system_instructions: The system instructions to use.
input: The input items to the model, in OpenAI Responses format.
input: The input items to the model, in Hanzo AI Responses format.
model_settings: The model settings to use.
tools: The tools available to the model.
output_schema: The output schema to use.
@@ -76,7 +76,7 @@ class Model(abc.ABC):
Args:
system_instructions: The system instructions to use.
input: The input items to the model, in OpenAI Responses format.
input: The input items to the model, in Hanzo AI Responses format.
model_settings: The model settings to use.
tools: The tools available to the model.
output_schema: The output schema to use.
@@ -84,7 +84,7 @@ class Model(abc.ABC):
tracing: Tracing configuration.
Returns:
An iterator of response stream events, in OpenAI Responses format.
An iterator of response stream events, in Hanzo AI Responses format.
"""
pass
+5 -5
View File
@@ -7,7 +7,7 @@ from collections.abc import AsyncIterator, Iterable
from dataclasses import dataclass, field
from typing import TYPE_CHECKING, Any, Literal, cast, overload
from openai import NOT_GIVEN, AsyncOpenAI, AsyncStream, NotGiven
from openai import NOT_GIVEN, AsyncHanzo AI, AsyncStream, NotGiven
from openai.types import ChatModel
from openai.types.chat import (
ChatCompletion,
@@ -87,11 +87,11 @@ class _StreamingState:
function_calls: dict[int, ResponseFunctionToolCall] = field(default_factory=dict)
class OpenAIChatCompletionsModel(Model):
class Hanzo AIChatCompletionsModel(Model):
def __init__(
self,
model: str | ChatModel,
openai_client: AsyncOpenAI,
openai_client: AsyncHanzo AI,
) -> None:
self.model = model
self._client = openai_client
@@ -549,9 +549,9 @@ class OpenAIChatCompletionsModel(Model):
)
return response, ret
def _get_client(self) -> AsyncOpenAI:
def _get_client(self) -> AsyncHanzo AI:
if self._client is None:
self._client = AsyncOpenAI()
self._client = AsyncHanzo AI()
return self._client
+12 -12
View File
@@ -1,12 +1,12 @@
from __future__ import annotations
import httpx
from openai import AsyncOpenAI, DefaultAsyncHttpxClient
from openai import AsyncHanzo AI, DefaultAsyncHttpxClient
from . import _openai_shared
from .interface import Model, ModelProvider
from .openai_chatcompletions import OpenAIChatCompletionsModel
from .openai_responses import OpenAIResponsesModel
from .openai_chatcompletions import Hanzo AIChatCompletionsModel
from .openai_responses import Hanzo AIResponsesModel
DEFAULT_MODEL: str = "gpt-4o"
@@ -23,13 +23,13 @@ def shared_http_client() -> httpx.AsyncClient:
return _http_client
class OpenAIProvider(ModelProvider):
class Hanzo AIProvider(ModelProvider):
def __init__(
self,
*,
api_key: str | None = None,
base_url: str | None = None,
openai_client: AsyncOpenAI | None = None,
openai_client: AsyncHanzo AI | None = None,
organization: str | None = None,
project: str | None = None,
use_responses: bool | None = None,
@@ -38,7 +38,7 @@ class OpenAIProvider(ModelProvider):
assert api_key is None and base_url is None, (
"Don't provide api_key or base_url if you provide openai_client"
)
self._client: AsyncOpenAI | None = openai_client
self._client: AsyncHanzo AI | None = openai_client
else:
self._client = None
self._stored_api_key = api_key
@@ -51,11 +51,11 @@ class OpenAIProvider(ModelProvider):
else:
self._use_responses = _openai_shared.get_use_responses_by_default()
# We lazy load the client in case you never actually use OpenAIProvider(). Otherwise
# AsyncOpenAI() raises an error if you don't have an API key set.
def _get_client(self) -> AsyncOpenAI:
# We lazy load the client in case you never actually use Hanzo AIProvider(). Otherwise
# AsyncHanzo AI() raises an error if you don't have an API key set.
def _get_client(self) -> AsyncHanzo AI:
if self._client is None:
self._client = _openai_shared.get_default_openai_client() or AsyncOpenAI(
self._client = _openai_shared.get_default_openai_client() or AsyncHanzo AI(
api_key=self._stored_api_key or _openai_shared.get_default_openai_key(),
base_url=self._stored_base_url,
organization=self._stored_organization,
@@ -72,7 +72,7 @@ class OpenAIProvider(ModelProvider):
client = self._get_client()
return (
OpenAIResponsesModel(model=model_name, openai_client=client)
Hanzo AIResponsesModel(model=model_name, openai_client=client)
if self._use_responses
else OpenAIChatCompletionsModel(model=model_name, openai_client=client)
else Hanzo AIChatCompletionsModel(model=model_name, openai_client=client)
)
+6 -6
View File
@@ -5,7 +5,7 @@ from collections.abc import AsyncIterator
from dataclasses import dataclass
from typing import TYPE_CHECKING, Any, Literal, overload
from openai import NOT_GIVEN, APIStatusError, AsyncOpenAI, AsyncStream, NotGiven
from openai import NOT_GIVEN, APIStatusError, AsyncHanzo AI, AsyncStream, NotGiven
from openai.types import ChatModel
from openai.types.responses import (
Response,
@@ -44,15 +44,15 @@ IncludeLiteral = Literal[
]
class OpenAIResponsesModel(Model):
class Hanzo AIResponsesModel(Model):
"""
Implementation of `Model` that uses the OpenAI Responses API.
Implementation of `Model` that uses the Hanzo AI Responses API.
"""
def __init__(
self,
model: str | ChatModel,
openai_client: AsyncOpenAI,
openai_client: AsyncHanzo AI,
) -> None:
self.model = model
self._client = openai_client
@@ -244,9 +244,9 @@ class OpenAIResponsesModel(Model):
text=response_format,
)
def _get_client(self) -> AsyncOpenAI:
def _get_client(self) -> AsyncHanzo AI:
if self._client is None:
self._client = AsyncOpenAI()
self._client = AsyncHanzo AI()
return self._client
+1 -1
View File
@@ -142,7 +142,7 @@ class RunResultStreaming(RunResultBase):
async def stream_events(self) -> AsyncIterator[StreamEvent]:
"""Stream deltas for new items as they are generated. We're using the types from the
OpenAI Responses API, so these are semantic events: each event has a `type` field that
Hanzo AI Responses API, so these are semantic events: each event has a `type` field that
describes the type of the event, along with the data for that event.
This will raise:
+3 -3
View File
@@ -34,7 +34,7 @@ from .lifecycle import RunHooks
from .logger import logger
from .model_settings import ModelSettings
from .models.interface import ModelProvider
from .models.openai_provider import OpenAIProvider
from .models.openai_provider import Hanzo AIProvider
from .result import RunResult, RunResultStreaming
from .run_context import RunContextWrapper, TContext
from .stream_events import AgentUpdatedStreamEvent, RawResponsesStreamEvent
@@ -54,8 +54,8 @@ class RunConfig:
agent. The model_provider passed in below must be able to resolve this model name.
"""
model_provider: ModelProvider = field(default_factory=OpenAIProvider)
"""The model provider to use when looking up string model names. Defaults to OpenAI."""
model_provider: ModelProvider = field(default_factory=Hanzo AIProvider)
"""The model provider to use when looking up string model names. Defaults to Hanzo AI."""
model_settings: ModelSettings | None = None
"""Configure global model settings. Any non-null values will override the agent-specific model
+1 -1
View File
@@ -19,7 +19,7 @@ def ensure_strict_json_schema(
schema: dict[str, Any],
) -> dict[str, Any]:
"""Mutates the given JSON schema to ensure it conforms to the `strict` standard
that the OpenAI API expects.
that the Hanzo AI API expects.
"""
if schema == {}:
return _EMPTY_SCHEMA
+2 -2
View File
@@ -62,7 +62,7 @@ class FunctionTool:
@dataclass
class FileSearchTool:
"""A hosted tool that lets the LLM search through a vector store. Currently only supported with
OpenAI models, using the Responses API.
Hanzo AI models, using the Responses API.
"""
vector_store_ids: list[str]
@@ -87,7 +87,7 @@ class FileSearchTool:
@dataclass
class WebSearchTool:
"""A hosted tool that lets the LLM search the web. Currently only supported with OpenAI models,
"""A hosted tool that lets the LLM search the web. Currently only supported with Hanzo AI models,
using the Responses API.
"""
+1 -1
View File
@@ -83,7 +83,7 @@ def set_tracing_disabled(disabled: bool) -> None:
def set_tracing_export_api_key(api_key: str) -> None:
"""
Set the OpenAI API key for the backend exporter.
Set the Hanzo AI API key for the backend exporter.
"""
default_exporter().set_api_key(api_key)
+1 -1
View File
@@ -199,7 +199,7 @@ def response_span(
`with response_span() ...` or call `span.start()` + `span.finish()` manually.
Args:
response: The OpenAI Response object.
response: The Hanzo AI Response object.
span_id: The ID of the span. Optional. If not provided, we will generate an ID. We
recommend using `util.gen_span_id()` to generate a span ID, to guarantee that IDs are
correctly formatted.
+5 -5
View File
@@ -41,9 +41,9 @@ class BackendSpanExporter(TracingExporter):
Args:
api_key: The API key for the "Authorization" header. Defaults to
`os.environ["OPENAI_API_KEY"]` if not provided.
organization: The OpenAI organization to use. Defaults to
organization: The Hanzo AI organization to use. Defaults to
`os.environ["OPENAI_ORG_ID"]` if not provided.
project: The OpenAI project to use. Defaults to
project: The Hanzo AI project to use. Defaults to
`os.environ["OPENAI_PROJECT_ID"]` if not provided.
endpoint: The HTTP endpoint to which traces/spans are posted.
max_retries: Maximum number of retries upon failures.
@@ -62,10 +62,10 @@ class BackendSpanExporter(TracingExporter):
self._client = httpx.Client(timeout=httpx.Timeout(timeout=60, connect=5.0))
def set_api_key(self, api_key: str):
"""Set the OpenAI API key for the exporter.
"""Set the Hanzo AI API key for the exporter.
Args:
api_key: The OpenAI API key to use. This is the same key used by the OpenAI Python
api_key: The Hanzo AI API key to use. This is the same key used by the Hanzo AI Python
client.
"""
self.api_key = api_key
@@ -84,7 +84,7 @@ class BackendSpanExporter(TracingExporter):
headers = {
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json",
"OpenAI-Beta": "traces=v1",
"Hanzo AI-Beta": "traces=v1",
}
# Exponential backoff loop
+1 -1
View File
@@ -116,7 +116,7 @@ class ResponseSpanData(SpanData):
input: str | list[ResponseInputItemParam] | None = None,
) -> None:
self.response = response
# This is not used by the OpenAI trace processors, but is useful for other tracing
# This is not used by the Hanzo AI trace processors, but is useful for other tracing
# processor implementations
self.input = input
+6 -6
View File
@@ -3,8 +3,8 @@ from __future__ import annotations
import pytest
from agents.models import _openai_shared
from agents.models.openai_chatcompletions import OpenAIChatCompletionsModel
from agents.models.openai_responses import OpenAIResponsesModel
from agents.models.openai_chatcompletions import Hanzo AIChatCompletionsModel
from agents.models.openai_responses import Hanzo AIResponsesModel
from agents.tracing import set_trace_processors
from agents.tracing.setup import GLOBAL_TRACE_PROVIDER
@@ -49,7 +49,7 @@ def disable_real_model_clients(monkeypatch, request):
def failing_version(*args, **kwargs):
pytest.fail("Real models should not be used in tests!")
monkeypatch.setattr(OpenAIResponsesModel, "get_response", failing_version)
monkeypatch.setattr(OpenAIResponsesModel, "stream_response", failing_version)
monkeypatch.setattr(OpenAIChatCompletionsModel, "get_response", failing_version)
monkeypatch.setattr(OpenAIChatCompletionsModel, "stream_response", failing_version)
monkeypatch.setattr(Hanzo AIResponsesModel, "get_response", failing_version)
monkeypatch.setattr(Hanzo AIResponsesModel, "stream_response", failing_version)
monkeypatch.setattr(Hanzo AIChatCompletionsModel, "get_response", failing_version)
monkeypatch.setattr(Hanzo AIChatCompletionsModel, "stream_response", failing_version)
+16 -16
View File
@@ -4,61 +4,61 @@ import openai
import pytest
from agents import set_default_openai_api, set_default_openai_client, set_default_openai_key
from agents.models.openai_chatcompletions import OpenAIChatCompletionsModel
from agents.models.openai_provider import OpenAIProvider
from agents.models.openai_responses import OpenAIResponsesModel
from agents.models.openai_chatcompletions import Hanzo AIChatCompletionsModel
from agents.models.openai_provider import Hanzo AIProvider
from agents.models.openai_responses import Hanzo AIResponsesModel
def test_cc_no_default_key_errors(monkeypatch):
monkeypatch.delenv("OPENAI_API_KEY", raising=False)
with pytest.raises(openai.OpenAIError):
OpenAIProvider(use_responses=False).get_model("gpt-4")
with pytest.raises(openai.Hanzo AIError):
Hanzo AIProvider(use_responses=False).get_model("gpt-4")
def test_cc_set_default_openai_key():
set_default_openai_key("test_key")
chat_model = OpenAIProvider(use_responses=False).get_model("gpt-4")
chat_model = Hanzo AIProvider(use_responses=False).get_model("gpt-4")
assert chat_model._client.api_key == "test_key" # type: ignore
def test_cc_set_default_openai_client():
client = openai.AsyncOpenAI(api_key="test_key")
client = openai.AsyncHanzo AI(api_key="test_key")
set_default_openai_client(client)
chat_model = OpenAIProvider(use_responses=False).get_model("gpt-4")
chat_model = Hanzo AIProvider(use_responses=False).get_model("gpt-4")
assert chat_model._client.api_key == "test_key" # type: ignore
def test_resp_no_default_key_errors(monkeypatch):
monkeypatch.delenv("OPENAI_API_KEY", raising=False)
assert os.getenv("OPENAI_API_KEY") is None
with pytest.raises(openai.OpenAIError):
OpenAIProvider(use_responses=True).get_model("gpt-4")
with pytest.raises(openai.Hanzo AIError):
Hanzo AIProvider(use_responses=True).get_model("gpt-4")
def test_resp_set_default_openai_key():
set_default_openai_key("test_key")
resp_model = OpenAIProvider(use_responses=True).get_model("gpt-4")
resp_model = Hanzo AIProvider(use_responses=True).get_model("gpt-4")
assert resp_model._client.api_key == "test_key" # type: ignore
def test_resp_set_default_openai_client():
client = openai.AsyncOpenAI(api_key="test_key")
client = openai.AsyncHanzo AI(api_key="test_key")
set_default_openai_client(client)
resp_model = OpenAIProvider(use_responses=True).get_model("gpt-4")
resp_model = Hanzo AIProvider(use_responses=True).get_model("gpt-4")
assert resp_model._client.api_key == "test_key" # type: ignore
def test_set_default_openai_api():
assert isinstance(OpenAIProvider().get_model("gpt-4"), OpenAIResponsesModel), (
assert isinstance(Hanzo AIProvider().get_model("gpt-4"), Hanzo AIResponsesModel), (
"Default should be responses"
)
set_default_openai_api("chat_completions")
assert isinstance(OpenAIProvider().get_model("gpt-4"), OpenAIChatCompletionsModel), (
assert isinstance(Hanzo AIProvider().get_model("gpt-4"), Hanzo AIChatCompletionsModel), (
"Should be chat completions model"
)
set_default_openai_api("responses")
assert isinstance(OpenAIProvider().get_model("gpt-4"), OpenAIResponsesModel), (
assert isinstance(Hanzo AIProvider().get_model("gpt-4"), Hanzo AIResponsesModel), (
"Should be responses model"
)
+1 -1
View File
@@ -153,7 +153,7 @@ def test_tool_call_output_item_constructs_function_call_output_dict():
# The following tests ensure that every possible output item type defined by
# OpenAI's API can be converted back into an input item dict via
# Hanzo AI's API can be converted back into an input item dict via
# ModelResponse.to_input_items. The output and input schema for each item are
# intended to be symmetric, so given any ResponseOutputItem, its model_dump
# should produce a dict that can satisfy the corresponding TypedDict input
+15 -15
View File
@@ -26,8 +26,8 @@ from agents import (
ModelResponse,
ModelSettings,
ModelTracing,
OpenAIChatCompletionsModel,
OpenAIProvider,
Hanzo AIChatCompletionsModel,
Hanzo AIProvider,
generation_span,
)
from agents.models.fake_id import FAKE_RESPONSES_ID
@@ -56,8 +56,8 @@ async def test_get_response_with_text_message(monkeypatch) -> None:
async def patched_fetch_response(self, *args, **kwargs):
return chat
monkeypatch.setattr(OpenAIChatCompletionsModel, "_fetch_response", patched_fetch_response)
model = OpenAIProvider(use_responses=False).get_model("gpt-4")
monkeypatch.setattr(Hanzo AIChatCompletionsModel, "_fetch_response", patched_fetch_response)
model = Hanzo AIProvider(use_responses=False).get_model("gpt-4")
resp: ModelResponse = await model.get_response(
system_instructions=None,
input="",
@@ -104,8 +104,8 @@ async def test_get_response_with_refusal(monkeypatch) -> None:
async def patched_fetch_response(self, *args, **kwargs):
return chat
monkeypatch.setattr(OpenAIChatCompletionsModel, "_fetch_response", patched_fetch_response)
model = OpenAIProvider(use_responses=False).get_model("gpt-4")
monkeypatch.setattr(Hanzo AIChatCompletionsModel, "_fetch_response", patched_fetch_response)
model = Hanzo AIProvider(use_responses=False).get_model("gpt-4")
resp: ModelResponse = await model.get_response(
system_instructions=None,
input="",
@@ -153,8 +153,8 @@ async def test_get_response_with_tool_call(monkeypatch) -> None:
async def patched_fetch_response(self, *args, **kwargs):
return chat
monkeypatch.setattr(OpenAIChatCompletionsModel, "_fetch_response", patched_fetch_response)
model = OpenAIProvider(use_responses=False).get_model("gpt-4")
monkeypatch.setattr(Hanzo AIChatCompletionsModel, "_fetch_response", patched_fetch_response)
model = Hanzo AIProvider(use_responses=False).get_model("gpt-4")
resp: ModelResponse = await model.get_response(
system_instructions=None,
input="",
@@ -177,9 +177,9 @@ async def test_get_response_with_tool_call(monkeypatch) -> None:
@pytest.mark.asyncio
async def test_fetch_response_non_stream(monkeypatch) -> None:
"""
Verify that `_fetch_response` builds the correct OpenAI API call when not
Verify that `_fetch_response` builds the correct Hanzo AI API call when not
streaming and returns the ChatCompletion object directly. We supply a
dummy ChatCompletion through a stubbed OpenAI client and inspect the
dummy ChatCompletion through a stubbed Hanzo AI client and inspect the
captured kwargs.
"""
@@ -208,7 +208,7 @@ async def test_fetch_response_non_stream(monkeypatch) -> None:
)
completions = DummyCompletions()
dummy_client = DummyClient(completions)
model = OpenAIChatCompletionsModel(model="gpt-4", openai_client=dummy_client) # type: ignore
model = Hanzo AIChatCompletionsModel(model="gpt-4", openai_client=dummy_client) # type: ignore
# Execute the private fetch with a system instruction and simple string input.
with generation_span(disabled=True) as span:
result = await model._fetch_response(
@@ -223,7 +223,7 @@ async def test_fetch_response_non_stream(monkeypatch) -> None:
stream=False,
)
assert result is chat
# Ensure expected args were passed through to OpenAI client.
# Ensure expected args were passed through to Hanzo AI client.
kwargs = completions.kwargs
assert kwargs["stream"] is False
assert kwargs["model"] == "gpt-4"
@@ -241,7 +241,7 @@ async def test_fetch_response_non_stream(monkeypatch) -> None:
async def test_fetch_response_stream(monkeypatch) -> None:
"""
When `stream=True`, `_fetch_response` should return a bare `Response`
object along with the underlying async stream. The OpenAI client call
object along with the underlying async stream. The Hanzo AI client call
should include `stream_options` to request usage-delimited chunks.
"""
@@ -264,7 +264,7 @@ async def test_fetch_response_stream(monkeypatch) -> None:
completions = DummyCompletions()
dummy_client = DummyClient(completions)
model = OpenAIChatCompletionsModel(model="gpt-4", openai_client=dummy_client) # type: ignore
model = Hanzo AIChatCompletionsModel(model="gpt-4", openai_client=dummy_client) # type: ignore
with generation_span(disabled=True) as span:
response, stream = await model._fetch_response(
system_instructions=None,
@@ -277,7 +277,7 @@ async def test_fetch_response_stream(monkeypatch) -> None:
tracing=ModelTracing.DISABLED,
stream=True,
)
# Check OpenAI client was called for streaming
# Check Hanzo AI client was called for streaming
assert completions.kwargs["stream"] is True
assert completions.kwargs["stream_options"] == {"include_usage": True}
# Response is a proper openai Response
@@ -1,4 +1,4 @@
# Copyright (c) OpenAI
# Copyright (c) Hanzo AI
#
# Licensed under the MIT License.
# See LICENSE file in the project root for full license information.
@@ -8,12 +8,12 @@ Unit tests for the internal `_Converter` class defined in
`agents.models.openai_chatcompletions`. The converter is responsible for
translating between internal "item" structures (e.g., `ResponseOutputMessage`
and related types from `openai.types.responses`) and the ChatCompletion message
structures defined by the OpenAI client library.
structures defined by the Hanzo AI client library.
These tests exercise both conversion directions:
- `_Converter.message_to_output_items` turns a `ChatCompletionMessage` (as
returned by the OpenAI API) into a list of `ResponseOutputItem` instances.
returned by the Hanzo AI API) into a list of `ResponseOutputItem` instances.
- `_Converter.items_to_messages` takes in either a simple string prompt, or a
list of input/output items such as `ResponseOutputMessage` and
+8 -8
View File
@@ -19,8 +19,8 @@ from openai.types.responses import (
from agents.model_settings import ModelSettings
from agents.models.interface import ModelTracing
from agents.models.openai_chatcompletions import OpenAIChatCompletionsModel
from agents.models.openai_provider import OpenAIProvider
from agents.models.openai_chatcompletions import Hanzo AIChatCompletionsModel
from agents.models.openai_provider import Hanzo AIProvider
@pytest.mark.allow_call_model_methods
@@ -68,8 +68,8 @@ async def test_stream_response_yields_events_for_text_content(monkeypatch) -> No
)
return resp, fake_stream()
monkeypatch.setattr(OpenAIChatCompletionsModel, "_fetch_response", patched_fetch_response)
model = OpenAIProvider(use_responses=False).get_model("gpt-4")
monkeypatch.setattr(Hanzo AIChatCompletionsModel, "_fetch_response", patched_fetch_response)
model = Hanzo AIProvider(use_responses=False).get_model("gpt-4")
output_events = []
async for event in model.stream_response(
system_instructions=None,
@@ -157,8 +157,8 @@ async def test_stream_response_yields_events_for_refusal_content(monkeypatch) ->
)
return resp, fake_stream()
monkeypatch.setattr(OpenAIChatCompletionsModel, "_fetch_response", patched_fetch_response)
model = OpenAIProvider(use_responses=False).get_model("gpt-4")
monkeypatch.setattr(Hanzo AIChatCompletionsModel, "_fetch_response", patched_fetch_response)
model = Hanzo AIProvider(use_responses=False).get_model("gpt-4")
output_events = []
async for event in model.stream_response(
system_instructions=None,
@@ -244,8 +244,8 @@ async def test_stream_response_yields_events_for_tool_call(monkeypatch) -> None:
)
return resp, fake_stream()
monkeypatch.setattr(OpenAIChatCompletionsModel, "_fetch_response", patched_fetch_response)
model = OpenAIProvider(use_responses=False).get_model("gpt-4")
monkeypatch.setattr(Hanzo AIChatCompletionsModel, "_fetch_response", patched_fetch_response)
model = Hanzo AIProvider(use_responses=False).get_model("gpt-4")
output_events = []
async for event in model.stream_response(
system_instructions=None,
+2 -2
View File
@@ -1,4 +1,4 @@
# Copyright (c) OpenAI
# Copyright (c) Hanzo AI
#
# Licensed under the MIT License.
# See LICENSE file in the project root for full license information.
@@ -7,7 +7,7 @@
Unit tests for the `Converter` class defined in
`agents.models.openai_responses`. The converter is responsible for
translating various agent tool types and output schemas into the parameter
structures expected by the OpenAI Responses API.
structures expected by the Hanzo AI Responses API.
We test the following aspects:
+8 -8
View File
@@ -1,8 +1,8 @@
import pytest
from openai import AsyncOpenAI
from openai import AsyncHanzo AI
from openai.types.responses import ResponseCompletedEvent
from agents import ModelSettings, ModelTracing, OpenAIResponsesModel, trace
from agents import ModelSettings, ModelTracing, Hanzo AIResponsesModel, trace
from agents.tracing.span_data import ResponseSpanData
from tests import fake_model
@@ -39,7 +39,7 @@ class DummyResponse:
async def test_get_response_creates_trace(monkeypatch):
with trace(workflow_name="test"):
# Create an instance of the model
model = OpenAIResponsesModel(model="test-model", openai_client=AsyncOpenAI(api_key="test"))
model = Hanzo AIResponsesModel(model="test-model", openai_client=AsyncHanzo AI(api_key="test"))
# Mock _fetch_response to return a dummy response with a known id
async def dummy_fetch_response(
@@ -67,7 +67,7 @@ async def test_get_response_creates_trace(monkeypatch):
async def test_non_data_tracing_doesnt_set_response_id(monkeypatch):
with trace(workflow_name="test"):
# Create an instance of the model
model = OpenAIResponsesModel(model="test-model", openai_client=AsyncOpenAI(api_key="test"))
model = Hanzo AIResponsesModel(model="test-model", openai_client=AsyncHanzo AI(api_key="test"))
# Mock _fetch_response to return a dummy response with a known id
async def dummy_fetch_response(
@@ -92,7 +92,7 @@ async def test_non_data_tracing_doesnt_set_response_id(monkeypatch):
async def test_disable_tracing_does_not_create_span(monkeypatch):
with trace(workflow_name="test"):
# Create an instance of the model
model = OpenAIResponsesModel(model="test-model", openai_client=AsyncOpenAI(api_key="test"))
model = Hanzo AIResponsesModel(model="test-model", openai_client=AsyncHanzo AI(api_key="test"))
# Mock _fetch_response to return a dummy response with a known id
async def dummy_fetch_response(
@@ -116,7 +116,7 @@ async def test_disable_tracing_does_not_create_span(monkeypatch):
async def test_stream_response_creates_trace(monkeypatch):
with trace(workflow_name="test"):
# Create an instance of the model
model = OpenAIResponsesModel(model="test-model", openai_client=AsyncOpenAI(api_key="test"))
model = Hanzo AIResponsesModel(model="test-model", openai_client=AsyncHanzo AI(api_key="test"))
# Define a dummy fetch function that returns an async stream with a dummy response
async def dummy_fetch_response(
@@ -151,7 +151,7 @@ async def test_stream_response_creates_trace(monkeypatch):
async def test_stream_non_data_tracing_doesnt_set_response_id(monkeypatch):
with trace(workflow_name="test"):
# Create an instance of the model
model = OpenAIResponsesModel(model="test-model", openai_client=AsyncOpenAI(api_key="test"))
model = Hanzo AIResponsesModel(model="test-model", openai_client=AsyncHanzo AI(api_key="test"))
# Define a dummy fetch function that returns an async stream with a dummy response
async def dummy_fetch_response(
@@ -185,7 +185,7 @@ async def test_stream_non_data_tracing_doesnt_set_response_id(monkeypatch):
async def test_stream_disabled_tracing_doesnt_create_span(monkeypatch):
with trace(workflow_name="test"):
# Create an instance of the model
model = OpenAIResponsesModel(model="test-model", openai_client=AsyncOpenAI(api_key="test"))
model = Hanzo AIResponsesModel(model="test-model", openai_client=AsyncHanzo AI(api_key="test"))
# Define a dummy fetch function that returns an async stream with a dummy response
async def dummy_fetch_response(