# Coding agents (/integrations/coding-agents)



Most coding agents already speak the OpenAI wire format and let you point them at a custom base URL. That is all Zumik needs. Set the base URL to `https://api.zumik.ai/v1`, use a Zumik API key, and pick a model - the agent keeps working unchanged, and you get provider prompt caching and a cheaper service tier on latency-tolerant traffic without touching the request body.

This page is the drop-in configuration. For a deeper integration that pins a stable repo policy and tool bundle as reused state on `/v2`, see the [coding-agent example](/examples/coding-agent).

## Three settings [#three-settings]

Any OpenAI-compatible agent needs the same three values:

| Setting  | Value                                                                                                        |
| -------- | ------------------------------------------------------------------------------------------------------------ |
| Base URL | `https://api.zumik.ai/v1`                                                                                    |
| API key  | your Zumik key (`zk_...`)                                                                                    |
| Model    | a Zumik [alias](/concepts/model-aliases) (`code.fast`, `code.balanced`, ...) or a concrete provider model id |

The `model` field accepts either a concrete provider model id (`gpt-4o`, a Fireworks `accounts/fireworks/models/...` id) or a Zumik routing alias. An alias resolves server-side to a pinned provider release and reports the resolved release on the response headers, so a vanilla OpenAI client ignores the extra signal cleanly. The seeded aliases are `code.fast`, `code.balanced`, `code.cheapest`, `auto.fast`, `auto.balanced`, `auto.cheapest`, `reasoning.best`, `vision.balanced`, and the semantic-routing `auto.semantic`.

<Tip>
  Never hardcode the key. Read it from an environment variable or your agent's secret store.
</Tip>

## Cline [#cline]

Cline accepts an OpenAI-compatible provider. In **Settings -> API Provider**:

<Steps>
  <Step title="Choose the provider">
    Set **API Provider** to **OpenAI Compatible**.
  </Step>

  <Step title="Set the base URL">
    **Base URL**: `https://api.zumik.ai/v1`
  </Step>

  <Step title="Set the key">
    **API Key**: your Zumik key (`zk_...`).
  </Step>

  <Step title="Set the model">
    **Model ID**: a Zumik alias such as `code.balanced`, or a concrete model id such as `gpt-4o`.
  </Step>
</Steps>

Roo Code uses the same **OpenAI Compatible** provider with the identical three fields.

## Continue [#continue]

Continue is configured in `~/.continue/config.yaml`. Add Zumik as an OpenAI-compatible model:

```yaml title="~/.continue/config.yaml"
models:
  - name: Zumik (code.balanced)
    provider: openai
    model: code.balanced
    apiBase: https://api.zumik.ai/v1
    apiKey: ${{ secrets.ZUMIK_API_KEY }}
```

`provider: openai` tells Continue to use the OpenAI wire format; `apiBase` redirects it to Zumik. The `model` is a Zumik alias or a concrete provider model id.

## Aider and the OpenAI SDKs [#aider-and-the-openai-sdks]

Aider and the official OpenAI SDKs read the standard OpenAI environment variables, so the change is the base URL and the key.

```bash
export ZUMIK_API_KEY="zk_..."
```

<CodeGroup>
  ```bash title="curl"
  curl https://api.zumik.ai/v1/chat/completions \
    -H "Authorization: Bearer $ZUMIK_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "code.balanced",
      "messages": [
        {"role": "user", "content": "Write a Python function that reverses a linked list."}
      ]
    }'
  ```

  ```python title="Python"
  import os
  from openai import OpenAI

  client = OpenAI(
      base_url="https://api.zumik.ai/v1",   # point at Zumik
      api_key=os.environ["ZUMIK_API_KEY"],
  )

  resp = client.chat.completions.create(
      model="code.balanced",                # a Zumik alias or a concrete model id
      messages=[{"role": "user", "content": "Refactor this loop into a comprehension."}],
  )
  print(resp.choices[0].message.content)
  ```

  ```typescript title="Node"
  import OpenAI from "openai";

  const client = new OpenAI({
    baseURL: "https://api.zumik.ai/v1",     // point at Zumik
    apiKey: process.env.ZUMIK_API_KEY,
  });

  const resp = await client.chat.completions.create({
    model: "code.balanced",
    messages: [{ role: "user", content: "Refactor this loop into a comprehension." }],
  });
  console.log(resp.choices[0].message.content);
  ```

  ```bash title="Aider"
  aider \
    --openai-api-base https://api.zumik.ai/v1 \
    --openai-api-key "$ZUMIK_API_KEY" \
    --model code.balanced
  ```
</CodeGroup>

The chat endpoint is `POST /v1/chat/completions`. The same `/v1` base URL also serves `/v1/responses`, `/v1/embeddings`, and `/v1/batches` for agents that use them.

## Full request fidelity [#full-request-fidelity]

Whatever your agent already sends, Zumik forwards to the resolved provider. The body shape stays exactly OpenAI's:

* **Function calling** - `tools` and `tool_choice` pass through, so an agent's tool loop works unchanged.
* **Multimodal content** - multi-part / structured `content` (text plus image parts) passes through.
* **Structured output** - `response_format` (including JSON schema) passes through.
* **Sampling** - `temperature`, `top_p`, `max_tokens`, `stop`, `seed`, and the rest pass through.
* **Streaming** - `stream: true` returns an SSE token stream. Set `stream_options.include_usage` to get the trailing usage chunk.

This is the [OpenAI compatibility](/openai-compatibility) contract: no proprietary fields in the request or response body, so a vanilla OpenAI client stays correct.

## Cheaper automatically [#cheaper-automatically]

You do not change the request to get the savings. On every eligible call Zumik engages provider-native prompt caching for you: Anthropic `cache_control` breakpoints on stable blocks, and an OpenAI `prompt_cache_key` derived from the system prompt. A latency-tolerant request can also ride a cheaper service tier, while interactive traffic is never slowed for it. Where reuse applies, the discount is reflected in the standard `usage.prompt_tokens_details.cached_tokens` field, so it stays measurable with a stock client.

<Note>
  Caching rewards a stable prefix. Keep system instructions, tools, and schema at the front of the request and push volatile content to the end. The [prompt caching guide](/guides/prompt-caching) explains the per-provider mechanics.
</Note>

### Optional cost levers [#optional-cost-levers]

When you want explicit control, these request-body fields are forwarded to the resolved provider when set:

| Field              | Values                                                         |
| ------------------ | -------------------------------------------------------------- |
| `service_tier`     | `auto`, `default`, `flex`, `scale`, `priority`                 |
| `verbosity`        | `low`, `medium`, `high`                                        |
| `reasoning_effort` | `minimal`, `low`, `medium`, `high`                             |
| `prompt_cache_key` | any string; pins the cache key instead of the auto-derived one |

A caller-supplied `service_tier` always wins; leave it unset and Zumik picks a cheaper tier only for latency-tolerant work. An out-of-vocabulary value is rejected with a `400` naming the field rather than burning a provider round trip.

<CardGroup cols="2">
  <Card title="Model aliases" icon="layer-group" href="/concepts/model-aliases">
    How `code.fast` and `auto.balanced` resolve to a pinned provider release.
  </Card>

  <Card title="Coding-agent example" icon="arrow-right-arrow-left" href="/examples/coding-agent">
    Pin a repo policy and tool bundle as reused state on `/v2`.
  </Card>
</CardGroup>
