Integrations: coding agents, SDKs and chat apps
Every OpenAI-compatible tool needs three values. Coding agents with their own guides, LangChain, LlamaIndex, the Vercel AI SDK, and chat apps.
Updated: 22 Sep 2026
Anything that speaks "OpenAI-compatible" works with uttapen and needs three values: the URL https://api.uttapen.ir/v1, a key that starts with sk-up-, and a model id in the form provider/model from the model list. This page is the map; each coding agent has a guide of its own.
Coding tools
| Tool | Status | Guide |
|---|---|---|
| opencode | Works | Guide |
| Cline (VS Code) | Works | Guide |
| Kilo Code | Works | Guide |
| Continue | Works (project no longer maintained) | Guide |
| Cursor | Works with caveats | Guide |
| Zed | Works | Guide |
| VS Code chat (Custom Endpoint) | Works | Guide |
| Aider | Works | Guide |
| Crush | Works | Guide |
| Goose | Works, except GPT-5 and o-series ids | Guide |
| Qwen Code | Works | Guide |
| Roo Code | Only if you already have it (discontinued) | Guide |
| Codex CLI | Does not work | Why |
| Claude Code | No direct route | Why |
Three rules that apply to every agent:
- Set the output ceiling yourself. uttapen reserves the cost of the full
max_tokensbefore the request goes out and charges only real usage afterwards (pricing). Some agents send 32,000 tokens when they don't know better, and since they fire several requests at once, the holds add up and a healthy balance can still return402. - Point side jobs at a cheap model. Session titles, commit messages and summaries don't belong on your most expensive model.
- Give each tool its own key with a monthly cap, so their spend is separated in Dashboard → Usage (API keys).
LangChain (Python)
pip install langchain-openai
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
model="openai/gpt-5-mini",
base_url="https://api.uttapen.ir/v1",
api_key="sk-up-...",
max_tokens=500,
)
print(llm.invoke("Name three advantages of Postgres.").content)
for chunk in llm.stream("Write one short motivational sentence."):
print(chunk.content, end="", flush=True)
Tool calling with llm.bind_tools([...]) and structured output with llm.with_structured_output(Schema) behave exactly as they do against OpenAI. In LangChain.js the same values go to new ChatOpenAI({ model, apiKey, configuration: { baseURL } }). If you use embeddings, OpenAIEmbeddings needs check_embedding_ctx_length=False — otherwise it chunks text with OpenAI's local tokenizer — and the model id has to exist on the model list.
LlamaIndex (Python)
pip install llama-index-llms-openai-like
from llama_index.llms.openai_like import OpenAILike
from llama_index.core.llms import ChatMessage
llm = OpenAILike(
model="openai/gpt-5-mini",
api_base="https://api.uttapen.ir/v1",
api_key="sk-up-...",
is_chat_model=True,
is_function_calling_model=True,
context_window=128000,
)
print(llm.complete("Name three advantages of Postgres.").text)
for chunk in llm.stream_chat([ChatMessage(role="user", content="Hello")]):
print(chunk.delta, end="", flush=True)
Use OpenAILike, not OpenAI: the latter validates the model id against a fixed list of OpenAI models and rejects anything shaped like openai/…. is_chat_model=True is mandatory.
Vercel AI SDK (Node and Next.js)
npm install ai @ai-sdk/openai-compatible
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
import { generateText, streamText } from "ai";
const uttapen = createOpenAICompatible({
name: "uttapen",
baseURL: "https://api.uttapen.ir/v1",
apiKey: process.env.UTTAPEN_API_KEY,
includeUsage: true,
});
const { text, usage } = await generateText({
model: uttapen("openai/gpt-5-mini"),
prompt: "Name three advantages of Postgres.",
maxOutputTokens: 300,
});
const result = streamText({ model: uttapen("anthropic/claude-sonnet-5"), prompt: "Hello" });
for await (const delta of result.textStream) process.stdout.write(delta);
In a Next.js route handler, return result.toUIMessageStreamResponse() (or toTextStreamResponse()) and use useChat on the client, so the key never leaves the server. For reasoning and other provider-specific fields use providerOptions: { uttapen: { reasoning: { effort: "low" } } }. @ai-sdk/openai also accepts a baseURL, but parts of it are built on the Responses API and won't work here; openai-compatible is the safe choice.
Chat apps and automation
Field labels in these apps change between versions; if you don't see the one we name, look for the closest equivalent on the same screen.
Open WebUI — Settings → Admin → Connections → Manage OpenAI API Connections → add a connection with https://api.uttapen.ir/v1 and your key. Leave the Model IDs field empty and it pulls the list from /v1/models, which means 400+ entries in the picker; list the few ids you actually use instead. Under Settings → Admin → Interface, set External Task Model to something cheap, or title and tag generation runs on your main model. In Docker you can pass the same two values as OPENAI_API_BASE_URL and OPENAI_API_KEY (read on first start only).
LibreChat — in librechat.yaml:
endpoints:
custom:
- name: "uttapen"
apiKey: "${UTTAPEN_API_KEY}"
baseURL: "https://api.uttapen.ir/v1"
models:
default: ["openai/gpt-5-mini"]
fetch: true
titleConvo: true
titleModel: "openai/gpt-5-nano"
modelDisplayLabel: "uttapen"
Always set titleModel: the default points at a model that doesn't exist in our catalogue, so titling would 404. Don't reuse a built-in endpoint name such as openAI either.
LobeHub (LobeChat) — in settings, AI Providers → create a custom provider with Request Format set to OpenAI, the URL https://api.uttapen.ir/v1 and your key. If you instead repoint the built-in OpenAI provider with OPENAI_PROXY_URL, turn that provider's Responses switch off — it is on by default. For automatic titles, pick a cheap model under Settings → Service Model.
Chatbox — Settings → Model Provider → Add, and choose OpenAI API Compatible as the API mode (not the Responses one). Set API Host to https://api.uttapen.ir/v1 and leave API Path empty so it appends /chat/completions itself. The Fetch button pulls the model list. Under Default Models, pick a cheap thread-naming model.
Jan — Settings → Model Providers → Add Provider, API format OpenAI-compatible, Base URL including /v1, plus the key; without /v1 requests 404. On save it fetches models from /v1/models. Jan doesn't detect capabilities (tools, vision) for custom providers.
AnythingLLM — set the LLM provider to Generic OpenAI: Base URL with /v1, the key, the model name, and do fill in both numeric fields — the defaults (4096 context, 1024 max tokens) are small enough to truncate answers. The environment equivalents are LLM_PROVIDER='generic-openai', GENERIC_OPEN_AI_BASE_PATH, GENERIC_OPEN_AI_API_KEY and GENERIC_OPEN_AI_MODEL_PREF.
n8n — in the OpenAI credential, set Base URL to https://api.uttapen.ir/v1 and paste your sk-up-… key. Then, in the OpenAI Chat Model node, turn off "Use Responses API": recent node versions default it on and uttapen doesn't serve that path. The general OpenAI node (the "Message a Model" operation) always uses that path and can't be used with us — use the Chat Model node. Avoid ids whose name contains codex or ends in -pro in this node too; the underlying library routes those to Responses on its own.
Dify — Model Provider → install OpenAI-API-compatible → Add Model. Model Name is our id, API Base URL is the /v1 address, Completion mode is Chat. The "model context size" and "upper bound for max tokens" fields both default to 4096, so correct them. For agents and tools, set Function Call Type to Tool Call (it defaults to Not Support). Dify doesn't fetch the model list; add each model by hand. The model for system tasks is set under Default Models.
Flowise — use the OpenAI Custom Model node: type the Model Name, and under Additional Parameters set Base Path to https://api.uttapen.ir/v1; the credential is the usual OpenAI API type. The plain ChatOpenAI node has its own model catalogue, which doesn't include our ids.
Rules that apply everywhere
- If the tool appends
/v1itself and you get a404, give it the URL without/v1. A quickcurl https://api.uttapen.ir/v1/modelstells you which form is right. - Wherever you see a Responses API option (or an "OpenAI Responses" provider type), turn it off: uttapen serves Chat Completions, Completions and Embeddings (migration).
- If the tool reads the model list from
GET /v1/models, everything is automatic; if not, type the id exactly and in lowercase. - Any tool that makes background requests — titles, tags, summaries — needs its own cheap model, or it quietly adds to your bill.
- Error codes and what each one means are in errors.
Sign up with a phone number, top up your wallet from 100,000 toman and create a key. Free models work without a top-up — up to 50 requests a day. Create an API key →