Skip to main content
A coding harness is an agent that edits your code: an editor extension, or a CLI that runs in your repository. Most of them take a custom OpenAI-compatible base URL, and pointing one here is two settings and one edit you would not guess. Most, not all. Which wire protocol a harness speaks is the first thing to settle, because it decides whether the rest of this page applies to yours at all. This page carries the things that are true of every one of them. The per-harness pages carry only the settings and the surprises specific to that harness, which is why they are short. Point your existing OpenAI client at https://ai.uniblock.dev and give it a Uniblock API key. Nothing else about your code changes.
Base URL
Whether the value you paste ends in /v1 differs by harness, and getting it wrong produces a 404 rather than an error about configuration. Each harness page says which form that harness wants and where we checked.

Which wire your harness speaks

Three protocols turn up in coding harnesses, and a base URL is only useful if this site publishes the one your harness sends. OpenAI chat completions is what most of them speak and what this site is mostly about. Cline, Continue, Aider, Zed, OpenCode and Cursor are all here. The OpenAI Responses API is what Codex CLI speaks, and Codex speaks nothing else: the release that could use chat completions is several behind, and its own project removed the setting. This API serves that endpoint too, so Codex has a surface here to talk to, and its page is the one to read. The Anthropic Messages API is what Claude Code speaks, and it has no OpenAI-compatible mode. This site publishes nothing about a Messages endpoint, so Claude Code cannot be pointed here yet. Its page says what would have to change. A harness that only orchestrates other harnesses, like T3 Code, speaks none of them itself and inherits whichever its child does.

Pin the model id before anything else

Every harness ships with a default model name, and every one of those defaults is a bare OpenAI-style name. This API does not accept one. The two forms the refusal below names are provider/model, where the part before the first slash names the provider that will serve the request, and a profile/ slug naming one of your workspace’s routing profiles. They are not a closed list: Models carries every accepted form of a model field and is the page to read before assuming one is invalid. There is a third form, and for a coding harness it is usually the right one: unirouter/auto. It is a fixed string meaning whichever route your workspace made its default, so it goes into a config file once and the model behind it changes on the Routing screen instead. That matters more here than elsewhere, because a harness config file is exactly the kind of thing nobody edits twice. Routing profiles covers it. So gpt-4o is refused, before anything is looked up, with 400 and the code model_id_not_pinned:
400
This is the first thing that will fail, and it fails on the first request. The fix is one edit per harness, and the edit is in a different place in each of them. Two things make it more than one edit. A harness that names several models names them separately: a main model, a smaller model for commit messages or titles, a model for applying edits. Each of those is its own setting and each needs its own pinned id. And a harness that offers a fixed dropdown of vendor model names rather than a free-text field cannot be pointed at an id of this shape at all; the per-harness pages say which kind each one is.

Embeddings are not part of what this site documents

Read that as an absence rather than as a promise in either direction. Earlier versions of this page said a request to an embeddings endpoint is answered with a 404. That was wrong, it has been removed, and nothing has replaced it, because the honest position is that this site does not document the endpoint at all. What follows is still worth knowing, because it decides which of your harness’s features depend on an answer we do not publish. Any harness feature that builds an index of your repository to search it by meaning rather than by text calls an embeddings endpoint, and those are the features to point somewhere you can rely on. In practice that is:
  • Codebase indexing, and whatever the harness calls the question that searches it. A feature you invoke as an at-mention of your codebase is usually this.
  • Retrieval over documentation the harness has ingested.
  • A long-term memory that recalls earlier sessions by similarity.
  • Reranking, on the harnesses that have it, which is usually not an OpenAI-shaped endpoint at all and is not a surface this site documents either.
What does work, and works without touching any of this, is every harness whose context comes from reading files, grepping them, walking the syntax tree, or asking a language server. That is most of what a modern coding agent does. The harnesses documented here fall into three groups, and each page says which one it is in: confirmed to call no embeddings endpoint at all, confirmed to have an embeddings role you must point elsewhere, or no embeddings feature found in its own documentation without our auditing it for one. If your harness configures its embedding model separately from its chat model, which several do, leave that setting pointed wherever it already points and change only the chat model. That is the practical advice on this page whose value does not depend on what our embeddings route does, and it is the one to follow.

A harness spends faster than a chat client

Credit is prepaid, and the limit a coding harness reaches first is the account spend rate cap rather than the balance. Understanding why takes one fact: the cap counts money reserved, not money spent. When a request is admitted we hold the most it could possibly cost. That figure comes from the request’s own max_tokens where it names one, and from the model’s published maximum output length where it does not. The window counts what was reserved and when, and nothing comes back out of it: a request that finished cheaply a moment ago goes on counting for its full 60 seconds. A coding harness is the traffic shape that hits this hardest. It fires several requests at once, on a model with a large published maximum output, often without naming max_tokens at all. Each of those holds that whole published maximum, so the cap can refuse the harness while your real spending is a small fraction of it. The refusal is 429 with the code spend_rate_exceeded, and it clears itself 60 seconds after the earliest reservation it counted. The lever is max_tokens. A harness that names a realistic output ceiling gets several times more requests a minute out of the same cap, and is charged exactly what it was before, because the charge has always been for what was actually produced. Where a harness exposes a maximum-output setting, set it. Rate limits and spend controls covers the cap, its default, and which limits are yours to raise.

Running out part way through a session

Two different things happen, and a harness will tell you about neither in a useful way. A request that starts when the workspace cannot cover its hold is refused with 402 and the code insufficient_credit. Nothing is charged. A stream already running when the credit underneath it runs out is cut. The terminating line carries insufficient_quota and the code balance_exhausted, and you are charged for what was produced before the cut and nothing more. There is no data: [DONE] after it. Streaming documents that line and the two other codes that can end a stream. An agent loop that retries on a 402 will not recover. The condition is a balance, so nothing about waiting or backing off changes the answer, and a loop that treats every non-200 as transient will spend its retry budget discovering that. If you can configure which statuses your harness retries, take 402 off the list. The way out is buying credit.

Every turn is its own billed request

A coding harness is a tool-calling loop. It sends your request with a list of tools, the model replies asking for a tool call, the harness runs the tool locally and sends the whole conversation back with the result appended. That repeats until the model stops asking. Your request body is forwarded as you sent it, so the tool fields travel and the model’s tool_calls come back unchanged. Nothing is executed on our side. We carry a request and a reply; whatever the model asked for is run by the harness on your machine, under whatever approvals you have configured there. The consequence to know before you see it: each turn of that loop is a separate request, separately billed, and lands in Activity as its own row. One instruction you gave a harness can be a dozen rows, each with its own model, tokens and charge, and each resending a conversation slightly longer than the last. That is what an agent session looks like in Activity, and it is not a metering fault.

Prompt caching is worth having here specifically

A coding harness resends a large, stable prefix on every turn: the same system prompt, the same tool definitions, the same files. That is the exact shape caching pays off on, and it is the difference between a long agent session costing what it looks like it should and costing considerably more. Provider caching passes through, and reads from a cache and writes to one are priced as their own kinds of token rather than as plain input. Models covers that rate vocabulary and where a charge’s prices come from. There is nothing of ours to switch on, and whether your harness sends what a provider needs to cache is a question about the harness.

Keys, and where they must not go

A harness config file frequently lives in the repository, and several of the files named on these pages are ones people commit. Read the key from the environment wherever the harness supports it, and check the specific file before you commit it: at least two of the harnesses documented here have a project-local config that is designed to be checked in. Do not assume OPENAI_API_KEY and OPENAI_BASE_URL work. Those are the names the official OpenAI SDKs read, and a harness is not an SDK. Not one of the harnesses documented here takes its base URL from OPENAI_BASE_URL, and how each takes its key differs about as much as it can: some read no shell environment at all and hold the key in their own settings, one CLI reads a similarly named but different variable, several read a variable whose name you choose or interpolate one into their config file, and one reads a variable named after a different vendor entirely. Each page gives the form that harness actually uses, and none of these pages guesses. A key is shown once, we keep only a hash, and a workspace holds up to five at a time. Authentication covers minting, revoking and replacing them. For a coding harness the practical advice that follows from shown-once is to mint a key for the harness rather than reusing one, so revoking it costs you nothing else.

Which models to point it at

We do not recommend models, and the catalog moves. Ask for it:
Every entry carries a capabilities block, and for a coding harness the one that decides everything is tools. A model whose tools does not read yes will behave badly in a harness, and badly rather than cleanly: the harness sends its tool definitions, the model answers in prose instead of a tool call, and the agent loop either stalls or starts inventing file edits in the chat. That is a worse failure than a refusal because it looks like the model being unhelpful. Check streaming too, since most harnesses stream by default, and vision if you paste screenshots at it. Models covers the catalog, the capability vocabulary, and why a model appears in it at all.

What we did not verify

Keep these two halves apart, because they are different kinds of claim. What we checked, and each per-harness page names its source and date. That a harness has a custom base URL setting, what that setting is called, what it takes, whether the harness appends /v1 itself, whether its model field accepts an arbitrary string, and which of its features call which endpoints. These are facts about a public tool and are checkable against that tool’s own documentation or its source. What we did not check, on any of these pages. That a session against this API succeeds. No harness on these pages has been run end to end here, because the hostname every page prints is not the settled customer hostname yet. Nothing here is a report of a working session, and where a page tells you what a setting does it is describing the harness rather than certifying the result. Harness configuration also churns faster than documentation does. These pages prefer the mechanism over the menu path for that reason, and a setting that has moved since the date on the page is likelier than a setting that never existed.

The harnesses

These reach the surface this site publishes. Each page is short because the shared facts are above.

Cline

VS Code. A Base URL field, a model list it fetches from us, and model metadata you have to fill in yourself.

Continue

VS Code and JetBrains. Roles, one of which needs embeddings, and a model name that can change which endpoint it calls.

Aider

A CLI. Three separately configured models, a repository map that needs no embeddings, and a provider prefix that collides with our ids.

Zed

An editor. Models declared in settings, a capability block, and a key it would rather you set in the environment.

OpenCode

A CLI. One config file, a provider package you have to pick correctly, and models you enumerate yourself.

Codex CLI

A CLI, and the only one here on the Responses API. One provider block, a base URL that wants /v1, and no output ceiling to set.

Cursor

An editor. A global override that captures its own models too, and a request path that keeps Cursor’s servers in it.

T3 Code

Not a harness. It runs one of the others for you, so which child you pick decides everything.

Not yet

Claude Code

Speaks the Anthropic Messages API, which this site does not publish. The page says what it needs and what would have to change.