# OpenAI-format tools

URL: https://docs.router.ezat.io/tools/openai-tools

> Point tools and libraries that take a custom OpenAI base URL (Cline, Continue, LangChain, the Vercel AI SDK, LiteLLM) at EZAT Router.

## When to use this page

You use a tool or library that speaks OpenAI's API format and lets you change its base URL. This page gives the three values every such tool needs, then the settings for tools we have checked. For your own code, see [OpenAI-compatible API](https://docs.router.ezat.io/openai/base-url.md).

## The three values

| Setting | Value |
| --- | --- |
| Base URL (also called API base, endpoint or server URL) | `https://api.router.ezat.io/openai/v1` |
| API key | Your EZAT key (`ezat_sk_…`) |
| Model | An id from [Models](https://docs.router.ezat.io/models.md), for example `anthropic/claude-sonnet-5-5` |

- The base URL ends in `/v1`. Tools add `/chat/completions` to it themselves.
- The tool must use **Chat Completions**. EZAT doesn't have OpenAI's Responses API yet, so a tool that only calls `/responses` gets `404`. OpenAI's Codex CLI is one: its custom providers support only the Responses API.
- Tools that ask for a model's context window or output limit: take them from [Models](https://docs.router.ezat.io/models.md).
- Tool calling, streaming and images work. Embeddings, image generation and audio don't exist on EZAT.

To check the three values before you configure a tool, list the models with them:

```bash tab="curl" test
curl --fail-with-body https://api.router.ezat.io/openai/v1/models \
  -H "Authorization: Bearer $EZAT_API_KEY"
```

## Cline

In the Cline panel in your editor, open the settings (the gear icon):

| Field | Value |
| --- | --- |
| API Provider | OpenAI Compatible |
| Base URL | `https://api.router.ezat.io/openai/v1` |
| API Key | Your EZAT key |
| Model ID | `anthropic/claude-sonnet-5-5`, or another id from [Models](https://docs.router.ezat.io/models.md) |

Under Model Configuration, set Context Window and Max Output Tokens from the [Models](https://docs.router.ezat.io/models.md) page, and turn on Image Support if you send images.

## Continue

Add a model to your Continue `config.yaml`:

```yaml title="config.yaml"
models:
  - name: EZAT Router
    provider: openai
    model: anthropic/claude-sonnet-5-5
    apiBase: https://api.router.ezat.io/openai/v1
    apiKey: ezat_sk_…
    useResponsesApi: false
```

`useResponsesApi: false` keeps Continue on Chat Completions. Keep a file with your key out of version control.

## LangChain

Python, with the `langchain-openai` package:

```python
import os

from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
    model="anthropic/claude-sonnet-5-5",
    base_url="https://api.router.ezat.io/openai/v1",
    api_key=os.environ["EZAT_API_KEY"],
)
print(llm.invoke("Say hello in five words.").content)
```

- Don't set `use_responses_api=True`, and avoid the features that make `ChatOpenAI` switch to the Responses API.
- LangChain's docs say `ChatOpenAI` targets OpenAI's own API and doesn't keep non-standard response fields from other providers. The answer, tool calls and standard token counts are all standard fields.

## Vercel AI SDK

With `@ai-sdk/openai`, create a provider with EZAT's base URL and use `.chat()`: the provider's default model factory calls the Responses API, `.chat()` calls Chat Completions.

```ts
import { createOpenAI } from "@ai-sdk/openai";
import { generateText } from "ai";

const ezat = createOpenAI({
  baseURL: "https://api.router.ezat.io/openai/v1",
  apiKey: process.env.EZAT_API_KEY,
});

const { text } = await generateText({
  model: ezat.chat("anthropic/claude-sonnet-5-5"),
  prompt: "Say hello in five words.",
});
console.log(text);
```

`@ai-sdk/openai-compatible` works too, and always uses Chat Completions. Its `includeUsage: true` option asks for token counts in streams:

```ts
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";

const ezat = createOpenAICompatible({
  name: "ezat",
  baseURL: "https://api.router.ezat.io/openai/v1",
  apiKey: process.env.EZAT_API_KEY,
  includeUsage: true,
});
const model = ezat("anthropic/claude-sonnet-5-5");
```

## LiteLLM

In the Python SDK, prefix the model with `openai/` so LiteLLM treats EZAT as an OpenAI-compatible endpoint, and pass the base URL as `api_base`:

```python
import os

from litellm import completion

response = completion(
    model="openai/anthropic/claude-sonnet-5-5",
    api_base="https://api.router.ezat.io/openai/v1",
    api_key=os.environ["EZAT_API_KEY"],
    messages=[{"role": "user", "content": "Say hello in five words."}],
)
print(response.choices[0].message.content)
```

In the LiteLLM proxy's `config.yaml`, `os.environ/…` reads the key from an environment variable:

```yaml title="config.yaml"
model_list:
  - model_name: ezat-default
    litellm_params:
      model: openai/anthropic/claude-sonnet-5-5
      api_base: https://api.router.ezat.io/openai/v1
      api_key: os.environ/EZAT_API_KEY
```

Keep `api_base` as it is, ending in `/v1`; LiteLLM adds the rest of the path.

## Tools not listed here

Any tool that lets you set a custom OpenAI base URL, an API key and a model name, and calls Chat Completions, should work with the three values above. If a tool also offers an Anthropic provider with a custom base URL, you can use that with `https://api.router.ezat.io` instead (see [Anthropic Messages API](https://docs.router.ezat.io/anthropic/messages.md)).

## For AI agents

1. Base URL `https://api.router.ezat.io/openai/v1`, key from `EZAT_API_KEY`, model id from `GET https://api.router.ezat.io/openai/v1/models`.
2. Configure the tool for Chat Completions. Don't pick a Responses API mode; tools that only support the Responses API (OpenAI's Codex CLI among them) won't work.
3. Don't write the key into a file that is committed. Prefer the tool's environment-variable or secret reference where it has one.
4. Confirm with the curl request above before blaming the tool.