# OpenAI Agents SDK

The OpenAI Agents SDK runs an agent in your Python or TypeScript application.
The SDK sends each model request to the exchange through the Responses API.

This SDK controls the agent loop and runs tools. For direct API calls, use the
[OpenAI SDK](https://inference.ai.exchange/docs/connect-openai-sdk.md).

## Print the setup with the Liquid CLI

The [Liquid CLI](https://inference.ai.exchange/docs/cli.md) prints the setup for the OpenAI Agents SDK with your model filled in. To run your own program with the exchange in its environment, use `liquid exec`. It sets `OPENAI_BASE_URL`, `ANTHROPIC_BASE_URL` and the keys for that process only.

```bash
curl -fsSL https://inference.ai.exchange/cli/install.sh | bash
liquid login
liquid connect openai-agents-sdk
liquid exec -- python app.py
```

To set up the OpenAI Agents SDK yourself, follow the steps below.

## Before you start

- Use a workspace with a balance and a key with the `spend` scope. See [API keys](https://inference.ai.exchange/docs/keys.md).
- Export the key in the shell that starts your application:

  ```bash
  export LIQUID_API_KEY=sk-liquid-...
  ```

## 1. Install the SDK

```bash
# Python 3.10 or later
pip install openai-agents

# TypeScript, Node 22 or later
npm install @openai/agents openai zod
```

See the [official SDK quickstart](https://developers.openai.com/api/docs/guides/agents/quickstart).

## 2. Create the agent

**Python**

```python
import asyncio
import os

from agents import Agent, ModelSettings, OpenAIResponsesModel, RunConfig, Runner
from openai import AsyncOpenAI

def create_agent() -> Agent:
    client = AsyncOpenAI(
        base_url="https://router.inference.ai.exchange/v1",
        api_key=os.environ["LIQUID_API_KEY"],
    )
    return Agent(
        name="Assistant",
        model=OpenAIResponsesModel(model="liquid.auto", openai_client=client),
        model_settings=ModelSettings(
            max_tokens=1024,
            store=False,
            extra_body={"exchange": {"cap_usd": 0.50}},
        ),
    )

async def main() -> None:
    result = await Runner.run(
        create_agent(),
        "Say hello.",
        run_config=RunConfig(tracing_disabled=True),
    )
    print(result.final_output)

if __name__ == "__main__":
    asyncio.run(main())
```

**TypeScript**

```typescript
import { Agent, OpenAIResponsesModel, Runner } from '@openai/agents'
import OpenAI from 'openai'

const client = new OpenAI({
  baseURL: 'https://router.inference.ai.exchange/v1',
  apiKey: process.env.LIQUID_API_KEY,
})

const agent = new Agent({
  name: 'Assistant',
  model: new OpenAIResponsesModel(client, 'liquid.auto'),
  modelSettings: {
    maxTokens: 1024,
    store: false,
    providerData: { extra_body: { exchange: { cap_usd: 0.50 } } },
  },
})

const runner = new Runner({ tracingDisabled: true })
const result = await runner.run(agent, 'Say hello.')
console.log(result.finalOutput)
```

The base URL ends in `/v1`. The explicit model adapter uses `/responses` over HTTP.
Choose a model, router model, or preset from `GET /v1/models`. See [Market data](https://inference.ai.exchange/docs/market.md).

The example disables tracing because an exchange key cannot send traces to OpenAI.
It sets `store=False` in Python and `store: false` in TypeScript because the exchange keeps no response state.

The output limit is 1,024 tokens per request. A model that needs more output requires a larger limit and possibly a larger cap.

## Purchasing rules

In Python, put the `exchange` object in `ModelSettings.extra_body`.
In TypeScript, put it in `modelSettings.providerData.extra_body`.
See [Purchasing rules](https://inference.ai.exchange/docs/rules.md) for the fields.

The example sets a $0.50 cap for each request. A run can send several requests, and each has its own cap.
If no offer fits the cap, the exchange refuses the request. It does not reduce the output limit.

To limit the total spend, use a separate key with a spend limit. The exchange refuses more requests after that limit.

## Local function tools

Python functions with `@function_tool` and TypeScript functions with `tool()` run in your application.
Add them to the agent's `tools` list. The exchange sends their definitions to the provider and returns the model's tool calls.
The SDK runs each function and sends the result in the next request.

The exchange does not provide OpenAI-hosted tools such as file search or code interpreter.
It drops hosted web search definitions and refuses other hosted tools by name.
Use local function tools for work that your application can do.

## Continue with the full history

Keep response history in your application. The SDK sends the history between tool calls within a run.
For a later Python turn, use `result.to_input_list()`:

```python
history = result.to_input_list()
history.append({"role": "user", "content": "Explain that answer."})
result = await Runner.run(
    agent, history, run_config=RunConfig(tracing_disabled=True)
)
```

In TypeScript, pass the history from `result.history` to the runner:

```typescript
const history = [...result.history, { role: 'user' as const, content: 'Explain that answer.' }]
const next = await runner.run(agent, history)
```

Do not use `previous_response_id`, `conversation`, or background mode.
The exchange refuses these fields because it keeps no response state.
The exchange does not support the Responses WebSocket transport.

## Chat Completions alternative

To select Chat Completions explicitly in Python, replace the model adapter:

```python
from agents import OpenAIChatCompletionsModel

model = OpenAIChatCompletionsModel(model="liquid.auto", openai_client=client)
```

In TypeScript, use the equivalent adapter with these model settings:

```typescript
import { OpenAIChatCompletionsModel } from '@openai/agents'

const model = new OpenAIChatCompletionsModel(client, 'liquid.auto')
const modelSettings = {
  maxTokens: 1024,
  store: false,
  providerData: { exchange: { cap_usd: 0.5 } },
}
```

Use that adapter as the agent's `model`. In TypeScript, also replace its `modelSettings` with the object above.
The Chat Completions adapter sends `providerData` directly, without the `extra_body` wrapper of the Responses adapter.
Keep the purchasing rules of Python, and disable tracing in both examples.

## Verify the connection

Check the receipts on the **Credits** page. Requests show **OpenAI Agents SDK** as the client.
Use the receipt for the settled charge. The SDK's token usage does not state the exchange's charge.

## Troubleshooting

| Symptom                                    | Cause and action                                                        |
| ------------------------------------------ | ----------------------------------------------------------------------- |
| `401`                                      | Confirm that `LIQUID_API_KEY` is set and the key has the `spend` scope. |
| `model_not_found`                          | Choose a name from `GET /v1/models`.                                    |
| The request exceeds the cap                | Reduce the output limit or increase the cap.                            |
| `unsupported_parameter` for response state | Send the full history without a continuation id.                        |
| A hosted tool is refused                   | Replace it with a local function tool.                                  |
| The request has insufficient funds         | Add funds to the workspace on the **Credits** page.                     |

## Next steps

- [Purchasing rules](https://inference.ai.exchange/docs/rules.md): caps, models, strategy, and service limits.
- [API keys](https://inference.ai.exchange/docs/keys.md): total spend limits for each agent.
- [OpenAI SDK](https://inference.ai.exchange/docs/connect-openai-sdk.md): call the endpoints directly.
