Metadata-Version: 2.5
Name: hanzo-agent
Version: 0.1.2
Summary: Hanzo Agent SDK
Project-URL: Homepage, https://github.com/hanzoai/agent
Project-URL: Repository, https://github.com/hanzoai/agent
Author-email: Hanzo AI <support@hanzo.ai>
License-Expression: MIT
License-File: LICENSE
License-File: NOTICE
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.9
Requires-Dist: griffe<2,>=1.5.6
Requires-Dist: httpx<1,>=0.23.0
Requires-Dist: numpy>=1.26; python_version < '3.10'
Requires-Dist: numpy>=2.1.0; python_version >= '3.10'
Requires-Dist: openai>=1.66.2
Requires-Dist: pydantic<3,>=2.10
Requires-Dist: requests<3,>=2.0
Requires-Dist: types-requests<3,>=2.0
Requires-Dist: typing-extensions<5,>=4.12.2
Provides-Extra: cli
Requires-Dist: click<9,>=8.1.0; extra == 'cli'
Requires-Dist: rich<14,>=13.0.0; extra == 'cli'
Provides-Extra: full
Requires-Dist: aiohttp<4,>=3.11.11; extra == 'full'
Requires-Dist: click<9,>=8.1.0; extra == 'full'
Requires-Dist: cryptography<50,>=44.0.0; extra == 'full'
Requires-Dist: eth-account<1,>=0.10.0; extra == 'full'
Requires-Dist: eth-utils<5,>=2.0.0; extra == 'full'
Requires-Dist: eval-type-backport>=0.2.0; (python_version < '3.10') and extra == 'full'
Requires-Dist: redis<6,>=5.0.0; extra == 'full'
Requires-Dist: rich<14,>=13.0.0; extra == 'full'
Requires-Dist: web3<7,>=6.20.2; extra == 'full'
Provides-Extra: marketplace
Requires-Dist: aiohttp<4,>=3.11.11; extra == 'marketplace'
Requires-Dist: redis<6,>=5.0.0; extra == 'marketplace'
Provides-Extra: tee
Requires-Dist: cryptography<50,>=44.0.0; extra == 'tee'
Provides-Extra: web3
Requires-Dist: eth-account<1,>=0.10.0; extra == 'web3'
Requires-Dist: eth-utils<5,>=2.0.0; extra == 'web3'
Requires-Dist: eval-type-backport>=0.2.0; (python_version < '3.10') and extra == 'web3'
Requires-Dist: web3<7,>=6.20.2; extra == 'web3'
Provides-Extra: zap
Description-Content-Type: text/markdown

<p align="center"><img src=".github/hero.svg" alt="agent" width="880"></p>

# Hanzo Agent SDK

`hanzo-agent` runs agents in Python. An agent is a model reached over an
OpenAI-compatible `/v1` API, its instructions, and the Python functions it may
call as tools. It installs as `hanzo-agent` and imports as `agents`.

## Install

Python 3.9 or newer.

```bash
pip install hanzo-agent
```

## First agent

```python
from openai import AsyncOpenAI
from agents import Agent, Runner, set_default_openai_api, set_default_openai_client

set_default_openai_client(AsyncOpenAI(base_url="http://localhost:11434/v1", api_key="ollama"))
set_default_openai_api("chat_completions")

agent = Agent(name="Assistant", instructions="You are a helpful assistant.", model="qwen3:0.6b")
result = Runner.run_sync(agent, "Write a haiku about recursion in programming.")
print(result.final_output)
```

One run printed:

```
Recursive function deferring calls,
A loop unrolled with grace,
Ends with a loop.
```

The two calls before the agent decide where it runs:

- `set_default_openai_client` names the endpoint and the key. Above it is a
  local server on port 11434, Ollama with `qwen3:0.6b` pulled. For the hosted
  API pass `base_url="https://api.hanzo.ai/v1"`, a Hanzo API key as `api_key`,
  and a model id from `https://api.hanzo.ai/v1/models`.
- `set_default_openai_api("chat_completions")` sends `POST /v1/chat/completions`.
  Without it the SDK sends `POST /v1/responses` instead.

## Tools

A decorated function becomes a tool the model can call:

```python
from agents import function_tool

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

agent = Agent(
    name="Weather",
    instructions="Answer with the get_weather tool.",
    tools=[get_weather],
    model="qwen3:0.6b",
)
print(Runner.run_sync(agent, "What is the weather in Tokyo?").final_output)
```

With the setup above it printed `The weather in Tokyo is sunny.`

## Errors and retries

Model calls go through the `openai` client and follow its rules. A 401, 402 or
403 raises on the first answer (`AuthenticationError`, `APIStatusError`,
`PermissionDeniedError`). A 429 or 5xx is retried twice and then raises;
`AsyncOpenAI(..., max_retries=0)` sends it once. A 200 whose body is an error
object raises `openai.APIError` carrying the server's message, as the client
does for an error inside a stream. A `<think>…</think>` block at the start of a
reply is dropped from `final_output` and from the history the next turn sends;
`result.raw_responses` keeps it.

## Tracing

Runs create traces and spans and send them nowhere. To export them, add a
processor:

```python
from agents import add_trace_processor
from agents.tracing.processors import BackendSpanExporter, BatchTraceProcessor

exporter = BackendSpanExporter(endpoint="https://collector.example/ingest", api_key="...")
add_trace_processor(BatchTraceProcessor(exporter))
```

The exporter posts batches of JSON to that endpoint with the key as a bearer
token. `set_tracing_disabled(True)` or `OPENAI_AGENTS_DISABLE_TRACING=1` stops
creating them.

## Extras

```bash
pip install "hanzo-agent[web3]"   # agents.extensions.web3: AgentWallet, Web3Wallet, MpcClient
pip install "hanzo-agent[tee]"    # agents.extensions.tee: ConfidentialAgent, TEEProvider
```

`agents.network` routes a request among several agents and
`agents.orchestration` runs workflows over registered agents; both are in the
base package.

## This repository

The root is also a Go module, `github.com/hanzoai/agent`, and `sdk/` holds
Python, TypeScript and Go clients published under other names. This README
covers `hanzo-agent` only.

## Development

```bash
make sync    # uv sync --all-extras --all-packages --group dev
make tests   # uv run pytest
```
