> ## Documentation Index
> Fetch the complete documentation index at: https://docs.flexinference.com/llms.txt
> Use this file to discover all available pages before exploring further.

# OpenClaw

> Point OpenClaw at FlexInference through its custom provider onboarding or its config file.

OpenClaw reaches any OpenAI-compatible endpoint through a custom provider. Onboarding writes the entry for you, and the config file holds it afterwards.

OpenClaw has no per-request deadline field of its own, so the deadline goes on the key. Create one first (see [agent keys](/agent-keys)).

## Set this up with an agent

Open the block below and copy it into any coding agent. The prompt never asks for your API key: the agent configures everything else, then prints the one export line for you to run yourself.

<Accordion title="Copy agent setup prompt">
  ```text theme={null}
  Configure OpenClaw to send its requests to FlexInference through a custom provider. Use the OpenClaw CLI, not hand-edited JSON, so every write is schema-validated.

  You will never see or handle my API key. OpenClaw will read it from the `FLEXINFERENCE_API_KEY` environment variable through a secret reference, and I export that myself. Do not ask me for the key, do not pass it on any command line, and do not read it from my environment.

  Ask whether to use my default OpenClaw profile or a separate one. A separate profile isolates config, state, gateway port, and workspace, and is the safe way to try this. Prefix every command with `--profile flex` if I choose one.

  1. Confirm which config file is active with `openclaw config file`.

  2. Tell me to export the key first, and stop until I confirm. Print this line; do not run it and do not ask for the value:

  export FLEXINFERENCE_API_KEY=<paste your key here>

  3. Write the provider entry. It carries no credential. The model row is required, because OpenClaw refuses a third-party provider that declares no `models`; step 5 replaces it with the full catalog:

  openclaw config set models.providers.flexinference --merge --strict-json '{"baseUrl":"https://api.flexinference.com/v1","api":"openai-completions","models":[{"id":"gpt-5.6-sol","name":"GPT-5.6 Sol","compat":{"supportsUsageInStreaming":true}}]}'

  4. Declare an environment secrets provider, then point the provider's apiKey at it. Both commands pass only the VARIABLE NAME, never the value:

  openclaw config set secrets.providers.default \
    --provider-source env --provider-allowlist FLEXINFERENCE_API_KEY

  openclaw config set models.providers.flexinference.apiKey \
    --ref-provider default --ref-source env --ref-id FLEXINFERENCE_API_KEY

  5. Fill the model list from the live FlexInference catalog rather than by hand:

  curl -s https://api.flexinference.com/v1/models \
    -H "Authorization: Bearer $FLEXINFERENCE_API_KEY" \
  | jq '{models:{providers:{flexinference:{models:
      [.data[] | {id, name: .id, compat: {supportsUsageInStreaming: true}}]}}}}' \
  | openclaw config patch --stdin

  Run every write with `--dry-run` first and show me the diff before applying it.

  6. Verify with `openclaw models list --provider flexinference`, then run `openclaw security audit`.

  Rules that matter, do not deviate:
  - Never pass my key as an argument to an `openclaw` command, and never write it into a config file. `openclaw onboard --custom-api-key` does both, which is why step 4 uses a reference instead.
  - Step 5 is the one place the key expands, into curl's `-H` argument, where a same-user process can read it. That is a deliberate trade for a single catalog read. Do not extend it to any other command.
  - The provider id must be `flexinference` in every command. If an earlier setup derived `custom-api-flexinference-com` from the host, tell me, and use that id consistently instead of creating a second provider.
  - `api` must be `openai-completions`. That is the only adapter FlexInference's Chat Completions surface works with here.
  - The base URL must end in `/v1`.
  - You MUST list models explicitly. OpenClaw only lets its own built-in provider ids omit `models`, and it will never call `GET /v1/models` for a provider defined in config. Model discovery is a plugin capability and does not apply here.
  - Every model row needs `compat: { supportsUsageInStreaming: true }`. OpenClaw makes streaming usage opt-in for third-party endpoints, and without it every streamed turn reports zero tokens and no cost.
  - Leave `"mode": "merge"` alone so my existing providers survive.
  - Step 4 resolves the reference at write time, so it fails if I have not exported the variable yet. That failure is expected, not a reason to fall back to a literal key.
  - FlexInference's catalog publishes no context window or token ceiling, so generated rows carry neither. Do not invent values; leave them out unless I give you numbers.

  Report what you changed and which config file you wrote.
  ```
</Accordion>

## Onboard a custom provider

1. Start the guided setup.

   ```bash theme={null}
   openclaw onboard
   ```

2. Pick the custom provider option when it asks about auth. That is `custom-api-key`.

3. Enter the router as the base URL, including the `/v1` suffix.

   ```text theme={null}
   https://api.flexinference.com/v1
   ```

4. Paste your agent key.

5. Leave the compatibility mode on `openai`. That is our Chat Completions surface.

6. Enter a model id we run, such as `gpt-5.6-sol`.

The prompt never puts your key on a command line, which is why it's the path shown here.

`openclaw onboard --non-interactive` exists too, but its `custom-api-key` auth mode reads the credential from `--custom-api-key`, so the secret ends up in your shell history and in process arguments. Script the setup with [config commands and a secret reference](#keep-the-key-out-of-the-config-file) instead, which is the same result without the exposure.

Whichever route you take, set the provider id yourself:

```bash theme={null}
openclaw config set models.providers.flexinference --merge --strict-json \
  '{"baseUrl":"https://api.flexinference.com/v1","api":"openai-completions","models":[{"id":"gpt-5.6-sol","name":"GPT-5.6 Sol","compat":{"supportsUsageInStreaming":true}}]}'
```

Left to itself, OpenClaw derives the id from the host and ends up with `custom-api-flexinference-com`, and every later command on this page would need that name instead.

The write includes a model row because it has to. OpenClaw refuses a third-party provider that declares no `models`, so a `baseUrl`-only write fails schema validation. Replace the whole row in the next section.

The compatibility mode maps to `api`. `openai` writes `openai-completions`, which is the one our Chat Completions endpoint works with. The other choices are `openai-responses` and `anthropic`.

## The config file

Onboarding writes into `~/.openclaw/openclaw.json` under `models.providers`. Print the path OpenClaw is using with `openclaw config file`.

```json theme={null}
{
  "models": {
    "mode": "merge",
    "providers": {
      "flexinference": {
        "baseUrl": "https://api.flexinference.com/v1",
        "api": "openai-completions",
        "apiKey": {
          "source": "env",
          "provider": "default",
          "id": "FLEXINFERENCE_API_KEY"
        },
        "models": [
          {
            "id": "gpt-5.6-sol",
            "name": "GPT-5.6 Sol",
            "contextWindow": 400000,
            "maxTokens": 128000,
            "input": ["text", "image"],
            "compat": { "supportsUsageInStreaming": true }
          }
        ]
      }
    }
  }
}
```

`"mode": "merge"` keeps your built-in providers and adds this one beside them.

`api` must be `openai-completions`. The onboarding `openai` compatibility mode writes exactly that.

`apiKey` takes a plain string too, which is what onboarding writes. The reference shown here keeps the secret out of the file. See [keep the key out of the config file](#keep-the-key-out-of-the-config-file).

**List your models yourself.** Only OpenClaw's built-in provider ids may leave `models` out. A third-party id must declare both `baseUrl` and `models`, so add a row per model you want in the picker.

**Set `compat.supportsUsageInStreaming`.** OpenClaw makes streaming usage opt-in for a third-party endpoint, because some servers refuse it. Without this flag we never get the request for a usage frame, so every streamed turn reports zero tokens and no cost.

## Fill the model list from our catalog

OpenClaw won't call `GET /v1/models` for a provider you define in config. Model discovery is a plugin capability, and the bundled plugins that have it are the only ones that use it. A config-defined provider reads its `models` array and nothing else.

Generate that array from our catalog instead, and write it in one command.

```bash theme={null}
export FLEXINFERENCE_API_KEY=<your agent key>

curl -s https://api.flexinference.com/v1/models \
  -H "Authorization: Bearer $FLEXINFERENCE_API_KEY" \
| jq '{models:{providers:{flexinference:{models:
    [.data[] | {id, name: .id, compat: {supportsUsageInStreaming: true}}]}}}}' \
| openclaw config patch --stdin
```

`config patch` merges objects and replaces arrays, so this swaps the model list and leaves `baseUrl` and `apiKey` untouched. Add `--dry-run` to see the write first.

Keep only the models that race the cheaper tier by filtering on the catalog's own flag.

```bash theme={null}
jq '[.data[] | select(.flexinference.flex_race) | {id, name: .id}]'
```

Our catalog publishes no context window and no token ceiling, so rows made this way have neither. Add `contextWindow` and `maxTokens` yourself where OpenClaw's defaults don't fit the model.

Re-run the command whenever our catalog changes. Check the result:

```bash theme={null}
openclaw models list --provider flexinference
```

## Global config and profiles

OpenClaw keeps one config per profile, not one per folder. The working directory never changes which file it reads.

| Scope    | Config path                 | How to select it       |
| -------- | --------------------------- | ---------------------- |
| Default  | `~/.openclaw/openclaw.json` | the default            |
| Named    | `~/.openclaw-<name>/`       | `--profile <name>`     |
| Dev      | `~/.openclaw-dev/`          | `--dev`                |
| Explicit | any path                    | `OPENCLAW_CONFIG_PATH` |

Use a named profile to try FlexInference without touching your usual setup.

```bash theme={null}
openclaw --profile flex onboard
```

A profile isolates state as well as config, so its gateway port and workspace are separate too.

## Keep the key out of the config file

Onboarding writes the key into `openclaw.json` in plain text. Set `apiKey` to a secret reference instead, and the config stores the variable's name rather than its value.

1. Export the key in the shell you will run these commands from.

   ```bash theme={null}
   export FLEXINFERENCE_API_KEY=<your agent key>
   ```

2. Declare an environment secrets provider and allow that one variable.

   ```bash theme={null}
   openclaw config set secrets.providers.default \
     --provider-source env --provider-allowlist FLEXINFERENCE_API_KEY
   ```

3. Point the provider's `apiKey` at it.

   ```bash theme={null}
   openclaw config set models.providers.flexinference.apiKey \
     --ref-provider default --ref-source env --ref-id FLEXINFERENCE_API_KEY
   ```

The config then holds `{"source": "env", "provider": "default", "id": "FLEXINFERENCE_API_KEY"}` and no secret. The key never reaches a command line either, because step 3 passes only the variable's name.

OpenClaw resolves the reference when you run step 3, so export the variable first. A missing or empty variable fails the write with `SecretRefResolutionError` rather than storing something broken. Add `--dry-run` to check without writing.

Check what's exposed with the built-in audit.

```bash theme={null}
openclaw security audit
```

## Confirm the key applied

Every response comes with `x-flexinference-defaults-applied`. OpenClaw doesn't show response headers, so read the request in the dashboard under **Logs** instead.

## Troubleshooting

**The model picker is short, or a model is missing.** A config-defined provider never calls `GET /v1/models`, so it shows only the rows you wrote. Regenerate the list from our catalog.

**Turns report zero tokens and no cost.** OpenClaw didn't ask us for streaming usage, so we sent no usage frame. Set `compat.supportsUsageInStreaming` to `true` on each model row.

**A model id is refused.** Rows you wrote by hand can drift from what we run, since the `id` goes out exactly as written. Regenerate the list from our catalog rather than editing ids.

**Config edits don't take effect.** The gateway holds the old config. Restart it, and confirm you edited the file that `openclaw config file` prints.

See [errors](/errors) for every refusal we return, and [agent keys](/agent-keys#troubleshooting-faq) for the ones that are not specific to OpenClaw.
