# Coding agents

Claude Code, Codex, Cursor and OpenCode run on GraphN's models. GraphN serves the API each agent already speaks at `https://model.graphn.ai`, so you change the agent's base URL and key, and nothing else: no proxy, no plugin.

| Agent                                      | API it uses                                      | Base URL                     |
| ------------------------------------------ | ------------------------------------------------ | ---------------------------- |
| Claude Code                                | Anthropic Messages (`/v1/messages`)              | `https://model.graphn.ai`    |
| Codex                                      | OpenAI Responses (`/v1/responses`)               | `https://model.graphn.ai/v1` |
| Cursor                                     | OpenAI Chat Completions (`/v1/chat/completions`) | `https://model.graphn.ai/v1` |
| OpenCode and other OpenAI-compatible tools | OpenAI Chat Completions (`/v1/chat/completions`) | `https://model.graphn.ai/v1` |

All three APIs stream and support tool calls, thinking and image input, with the same key, models and per-token billing. Every request shows in your workspace's **Logs** with its tokens, cache hits and cost.

To build GraphN workflows with these agents instead, see [Developing with agents](/docs/developing-with-agents).

## Before you start

Every agent needs a workspace API key. Create one under **API keys** in your workspace (see [Create an API key](/docs/inference-quickstart#2-create-an-api-key)), export it, and check it with one request:

```bash
export GRAPHN_API_KEY="gn_..."

curl https://model.graphn.ai/v1/messages \
  -H "x-api-key: $GRAPHN_API_KEY" \
  -H "content-type: application/json" \
  -d '{"model": "deepseek-v4.1-flash", "max_tokens": 64,
       "messages": [{"role": "user", "content": "Say hi"}]}'
```

The examples below use `deepseek-v4.1-flash`. To use another model, swap in its ID and context window:

| Model                 | Context window | Images |
| --------------------- | -------------: | :----: |
| `glm-5.3`             |      1,048,576 |   No   |
| `deepseek-v4.1-flash` |      1,048,576 |  Yes   |
| `kimi-k2.5`           |        256,000 |  Yes   |
| `qwen3.8-27b`         |        262,144 |  Yes   |
| `gpt-oss-120b`        |        131,072 |   No   |

Prices and the full catalog are in the [models reference](/docs/models). A model needs tool calling to drive an agent.

## Claude Code

```bash
export ANTHROPIC_BASE_URL=https://model.graphn.ai
export ANTHROPIC_API_KEY="$GRAPHN_API_KEY"
export ANTHROPIC_MODEL=deepseek-v4.1-flash
export ANTHROPIC_DEFAULT_OPUS_MODEL=deepseek-v4.1-flash
export ANTHROPIC_DEFAULT_SONNET_MODEL=deepseek-v4.1-flash
export ANTHROPIC_DEFAULT_HAIKU_MODEL=deepseek-v4.1-flash
export CLAUDE_CODE_MAX_CONTEXT_TOKENS=1048576
export CLAUDE_CODE_AUTO_MODE_SERVER=0
claude
```

- **Set every model variable.** Claude Code sends background work, such as titles and summaries, to its Haiku model, and subagents launched with the Task tool use its Opus model. Any of those left unset asks for a `claude-` model and gets `404 model not found`, so a subagent fails while the main session keeps working.
- **Tell it the real context window.** Claude Code assumes 200K tokens for a model it doesn't know and compacts the conversation at that point. `CLAUDE_CODE_MAX_CONTEXT_TOKENS` sets the model's actual window, so DeepSeek gets its full 1M and gpt-oss-120b compacts before 131K.
- **Turn off server-side auto mode checks.** In auto mode, Claude Code normally asks Anthropic's servers to check each action. Those checks don't exist on GraphN, so without `CLAUDE_CODE_AUTO_MODE_SERVER=0` Claude Code pauses on a notice saying the session "isn't eligible". With it set, Claude Code runs its own checks on your GraphN model, billed at GraphN's rates.
- **Ignore its cost readout.** Claude Code estimates cost at Anthropic's prices. Your GraphN usage page shows what you are actually billed.

## Codex

Add a provider to `~/.codex/config.toml`:

```toml
model = "deepseek-v4.1-flash"
model_provider = "graphn"
model_context_window = 1048576

[model_providers.graphn]
name = "GraphN"
base_url = "https://model.graphn.ai/v1"
env_key = "GRAPHN_API_KEY"
wire_api = "responses"
```

Then run `codex` with `GRAPHN_API_KEY` exported. `env_key` names the environment variable that holds the key; it is not the key itself.

To keep a second model one flag away, put it in a profile file next to the config, such as `~/.codex/kimi.config.toml`:

```toml
model = "kimi-k2.5"
model_context_window = 256000
```

and start it with `codex --profile kimi`.

- **`Model metadata for … not found` is harmless.** Codex prints it for any model outside OpenAI's catalog. `model_context_window` gives Codex what it needs to compact a long session at the right point.
- **The Responses API on GraphN is stateless.** Nothing is stored between requests, so `previous_response_id`, `conversation` and `background` are refused. Codex sends the full conversation every turn, so it is unaffected.

## Cursor

1. Open **Cursor Settings > Models** and expand **API Keys**.
2. Paste your GraphN key into **OpenAI API Key** and turn it on.
3. Turn on **Override OpenAI Base URL** and set it to `https://model.graphn.ai/v1`.
4. Add each model by its GraphN ID, such as `deepseek-v4.1-flash`, then pick it in Chat or Agent.

- **Pick an ID Cursor doesn't also ship.** Cursor sends the model name you choose, so a name that exists in its own catalog, such as `kimi-k2.5`, goes to Cursor's copy rather than GraphN's and fails with a not-found or "model is deprecated" error. `deepseek-v4.1-flash` doesn't collide.
- **Cursor calls GraphN from its own servers**, so a request from Cursor shows in your Logs like any other.
- **Your key covers Chat and Agent.** Tab completion keeps using Cursor's models.
- **The base URL override is global.** It applies to every OpenAI model in Cursor, so turn it off when you want Cursor's built-in OpenAI models back.
- **Check your plan.** Cursor's Free and Plus plans don't allow your own API key.

## OpenCode

Add GraphN as a provider in `opencode.json`:

```json
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "graphn": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "GraphN",
      "options": {
        "baseURL": "https://model.graphn.ai/v1",
        "apiKey": "{env:GRAPHN_API_KEY}"
      },
      "models": {
        "deepseek-v4.1-flash": { "name": "DeepSeek V4.1 Flash" },
        "glm-5.3": {
          "name": "GLM-5.3",
          "options": { "reasoningEffort": "high" }
        }
      }
    }
  }
}
```

Then run `opencode -m graphn/deepseek-v4.1-flash`. Any other tool that takes an OpenAI-compatible base URL is set up the same way.

- **Bound GLM-5.3's thinking.** Without a reasoning effort, GLM-5.3 can think until it hits the output limit, and OpenCode then ends the session without a word. `"reasoningEffort": "high"` keeps its thinking bounded.

## Troubleshooting

| What you see                                      | Why                                                    | Fix                                                                                         |
| ------------------------------------------------- | ------------------------------------------------------ | ------------------------------------------------------------------------------------------- |
| `404 model not found` naming a `claude-` model    | Claude Code fell back to one of its default models     | Set `ANTHROPIC_MODEL` and all three `ANTHROPIC_DEFAULT_*_MODEL` variables to a GraphN model |
| Claude Code compacts too early, or hits the limit | It assumes a 200K window                               | Set `CLAUDE_CODE_MAX_CONTEXT_TOKENS` to the model's context window                          |
| Claude Code says auto mode "isn't eligible"       | Anthropic's server-side checks don't run on GraphN     | Set `CLAUDE_CODE_AUTO_MODE_SERVER=0` before starting Claude Code                            |
| `401 Unauthorized`                                | The key is missing, mistyped or revoked                | Run the `curl` check above; in Codex, `env_key` must name the variable, not the key         |
| `previous_response_id` is refused                 | GraphN's Responses API stores nothing between requests | Send the full conversation as `input`, as Codex does                                        |
| Cursor's own OpenAI models stop working           | The base URL override applies to all OpenAI models     | Turn the override off while you use them                                                    |
| Cursor says "Model is deprecated" or not found    | The name collides with a model Cursor ships itself     | Pick a GraphN ID Cursor doesn't also ship, such as `deepseek-v4.1-flash`                    |
| OpenCode stops after a long pause with no change  | The model thought until it hit the output limit        | For `glm-5.3`, set `"reasoningEffort": "high"` in the model's `options`                     |

## Next steps

- [Coding Agent Support Is Now Available on GraphN](/blog/coding-agents-graphn) compares the agents on a real bug fix across these models, with cost per session.
- [Getting started with inference](/docs/inference-quickstart) covers the API itself: streaming, thinking and parameters.
