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

# Providers

# Pi provider templates

Issue #309 ships one complete `pi_providers` file per provider in [`templates/pi-providers`](https://github.com/orbi-build/orbi/tree/main/templates/pi-providers). Each file is valid JSON in Pi's `models.json` shape: copy the whole file to `.orbi/pi-providers.json`, or copy its single entry into the `providers` object of an existing file. Set the two selectors in `orbi.toml`:

```toml theme={null}
pi_providers = ".orbi/pi-providers.json"
pi_provider = "z-ai"
pi_model = "glm-5.3-flash"
```

## Catalog

| Provider              | Template                     | Environment variable     | Model                                | Status                                                                  | #305 link                                             |
| --------------------- | ---------------------------- | ------------------------ | ------------------------------------ | ----------------------------------------------------------------------- | ----------------------------------------------------- |
| Google Gemini         | `gemini.json`                | `GOOGLE_API_KEY`         | `gemini-3.8-flash`                   | Tested 2026-09-04: full Pi chain passed in 7s                           | [#305](https://github.com/orbi-build/orbi/issues/305) |
| z.ai GLM              | `z-ai.json`                  | `ZAI_API_KEY`            | `glm-5.3-flash`                      | Tested 2026-09-04: real task #303 reached PR #304                       | [#305](https://github.com/orbi-build/orbi/issues/305) |
| OpenRouter free       | `openrouter.json`            | `OPENROUTER_API_KEY`     | `google/gemma-4-31b-it:free`         | Not tested; free catalog availability is not promised                   | [#305](https://github.com/orbi-build/orbi/issues/305) |
| DeepSeek              | `deepseek.json`              | `DEEPSEEK_API_KEY`       | `deepseek-chat`                      | Not tested                                                              | [#305](https://github.com/orbi-build/orbi/issues/305) |
| xAI                   | `xai.json`                   | `XAI_API_KEY`            | `grok-4.20-0309`                     | Model ID verified against xAI docs; not quota-tested                    | [#305](https://github.com/orbi-build/orbi/issues/305) |
| Groq Free Plan        | `groq.json`                  | `GROQ_API_KEY`           | `groq/compound`                      | Free Plan limits verified 2026-09-04; real request/usage/429 not tested | [#305](https://github.com/orbi-build/orbi/issues/305) |
| Local Qwen            | `local-qwen.json`            | None (dummy key `local`) | `Qwen3.8-27B`                        | Local zero-cost example; requires a local OpenAI-compatible server      | [#305](https://github.com/orbi-build/orbi/issues/305) |
| Cloudflare Workers AI | `cloudflare-workers-ai.json` | `CLOUDFLARE_API_TOKEN`   | `@cf/meta/llama-3.1-8b-instruct-fp8` | Hosted free allocation; quota must be checked in the account            | [#318](https://github.com/orbi-build/orbi/issues/318) |

A template being listed is not a promise of quota, availability, speed, or model support. The `Not tested` labels are intentional.

## Add a new provider

1. Copy the closest template and give it one provider id. Keep `baseUrl`, `api`, `apiKey`, and a non-empty `models` list together. The selected `pi_model` **must exactly match** one `models[].id`.

2. Use `openai-completions` for OpenAI-compatible endpoints. Google Gemini uses `google-generative-ai`; keep its `baseUrl` at `https://generativelanguage.googleapis.com/v1beta`.

3. Put the real key in `.orbi/env` (gitignored, mode `600`) and use only `$VAR` or `${VAR}` in the committed JSON:

   ```bash theme={null}
   mkdir -p .orbi
   printf '%s\n' 'ZAI_API_KEY=replace-me' > .orbi/env
   chmod 600 .orbi/env
   ```

   The installed `orbi@.service` loads this file through `EnvironmentFile`; it never belongs in Git or a template. Literal keys are a last-resort downgrade: keep the file gitignored and understand that the value can leak through local files and process tooling.

4. For a manual tick, systemd is not loading `.orbi/env`. Export it first, or source it into the current shell:

   ```bash theme={null}
   set -a
   . .orbi/env
   set +a
   PYTHONPATH=src python3 -m orbi.runner --config orbi.toml
   ```

5. Select only the provider/model in `orbi.toml`; do not maintain commented provider blocks there. Run the loader/runner validation before a real task. It fails fast when the selected provider, model, endpoint, API, or selected key reference is invalid.

### `thinkingLevelMap`

Do not invent a complete map for a provider. Gemini's known-safe template form is exactly `{"off": null}`: other thinking levels use the provider default mapping. A copied `null` mapping for every level can send an unsupported value and produce a provider `400`. For another provider, omit the field unless its Pi provider contract has been verified.

### Google Gemini: AI Studio free tier

Use Google's [AI Studio API key page](https://aistudio.google.com/app/apikey) to create an API key. Keep the key local: the committed template references `GOOGLE_API_KEY`, so the literal value never belongs in Git, an Issue, a PR, or a journal.

1. Create or select a key in AI Studio, then add it to the gitignored environment file used by Orbi:

   ```bash theme={null}
   mkdir -p .orbi
   printf '%s\n' 'GOOGLE_API_KEY=replace-me' > .orbi/env
   chmod 600 .orbi/env
   ```

   The installed systemd unit loads `.orbi/env`. For a manual tick, export it first as described in [Getting started](/getting-started#path-b-a-pi_providers-file-orbi).

2. Copy [`templates/pi-providers/gemini.json`](https://github.com/orbi-build/orbi/blob/main/templates/pi-providers/gemini.json) to `.orbi/pi-providers.json`. Its complete selected entry is:

   ```json theme={null}
   {
     "providers": {
       "google": {
         "baseUrl": "https://generativelanguage.googleapis.com/v1beta",
         "api": "google-generative-ai",
         "apiKey": "$GOOGLE_API_KEY",
         "models": [
           {
             "id": "gemini-3.8-flash",
             "name": "Gemini 3.8 Flash",
             "contextWindow": 1048576,
             "maxTokens": 65536,
             "thinkingLevelMap": {"off": null}
           }
         ]
       }
     }
   }
   ```

3. Select the exact provider and model in `orbi.toml`:

   ```toml theme={null}
   pi_providers = ".orbi/pi-providers.json"
   pi_provider = "google"
   pi_model = "gemini-3.8-flash"
   ```

   The `api`, `baseUrl`, model ID, and `$GOOGLE_API_KEY` reference are part of the validated template. Keep Gemini's `thinkingLevelMap` exactly as `{"off": null}` unless the installed Pi/Gemini contract is re-verified; mapping every thinking level to `null` can cause an upstream `400`.

#### Free-tier limits and observed behavior

As checked on **2026-09-04**, AI Studio's Gemini API free tier is rate-limited by RPM, RPD, and TPM. The official [rate-limit page](https://ai.google.dev/gemini-api/docs/rate-limits) is dynamic, so this guide does not copy a changing promotional number. The real daily RPD/TPD ceiling for this account was **not measured**; treat it as **not tested**, not as unlimited.

A local setup using provider `google` and model `gemini-3.8-flash` started a real Pi request in about 15 seconds. After a burst, the upstream returned HTTP `429` with `You exceeded your current quota`; after roughly 50 minutes it returned HTTP `200` again. This dated observation indicates transient rate limiting, not proof that the key was invalid or that the daily allowance was exhausted. It is one account's evidence, not a quota guarantee.

Orbi does not silently retry or switch providers mid-session. Preserve the failed run evidence, wait for the transient limit to recover, or manually select another configured provider for the next run:

```toml theme={null}
pi_providers = ".orbi/pi-providers.json"
pi_provider = "z-ai"       # or another provider in the catalog
pi_model = "glm-5.3-flash"
```

Replace the provider file and matching environment variable, validate the exact provider/model/key again, and then run one real `pi --print` check. Switching is manual; the automatic per-provider rotation tracked in [#313](https://github.com/orbi-build/orbi/issues/313) is not current behavior.

### z.ai GLM: experience/free quota

Use this path when you have a z.ai account with an experience or free allowance. z.ai documents an OpenAI-compatible API; Orbi's template uses the direct endpoint `https://api.z.ai/api/paas/v4` and Pi's `openai-completions` API. See z.ai's [API quick start](https://docs.z.ai/guides/overview/quick-start) and [API-key management](https://z.ai/manage-apikey/apikey-list) for the current account and key-creation flow. The links and UI may change; do not paste the key into a repository, Issue, PR, or journal.

1. Create an API key in the z.ai console, then keep it in the local, gitignored environment file:

   ```bash theme={null}
   mkdir -p .orbi
   printf '%s\n' 'ZAI_API_KEY=replace-me' > .orbi/env
   chmod 600 .orbi/env
   ```

   The systemd service loads this file through `EnvironmentFile`. A manual tick does not: export it first with `set -a; . .orbi/env; set +a`, then run the command in [Getting started](/getting-started#6-run-one-tick-manually).
2. Copy [`templates/pi-providers/z-ai.json`](https://github.com/orbi-build/orbi/blob/main/templates/pi-providers/z-ai.json) to `.orbi/pi-providers.json`, or copy its provider entry. Select the exact IDs:

   ```toml theme={null}
   pi_providers = ".orbi/pi-providers.json"
   pi_provider = "z-ai"
   pi_model = "glm-5.3-flash"
   ```

   The complete `models` entry currently is:

   ```json theme={null}
   {
     "id": "glm-5.3-flash",
     "name": "GLM 5.3 Flash",
     "contextWindow": 131072,
     "maxTokens": 32768
   }
   ```

   `reasoning` is an optional Pi model-catalog field indicating reasoning support. `thinkingLevelMap` maps Pi thinking levels to provider-specific values. The committed z.ai template intentionally omits both: this document does not assert a provider-specific reasoning or thinking-level mapping without verified Pi/z.ai contract evidence. Do not copy Gemini's `{"off": null}` mapping to z.ai.
3. Validate the selected entry before dispatching work. The Runner's `_load_pi_providers` check requires the provider, exact model ID, endpoint/API, and a non-empty `ZAI_API_KEY`; it does not test or promise quota availability.

#### What is known about the free allowance

* **Verified 2026-09-04:** a real Orbi delivery using `glm-5.3-flash` completed the task from Issue [#303](https://github.com/orbi-build/orbi/issues/303) through commit [`b81f77a`](https://github.com/orbi-build/orbi/commit/b81f77a) and PR [#304](https://github.com/orbi-build/orbi/pull/304). This proves one successful run, not a quota guarantee.
* z.ai does not statically publish a universal experience/free upper limit in the material used for this guide. Exact allowance, reset time, concurrency and model availability depend on the account and current z.ai policy; **not measured here**.
* No controlled measurement of exhaustion or rate-limit response is available for this guide; **rate-limit behavior: not tested**. Treat upstream HTTP authentication/rate-limit errors as the source of truth and avoid retry loops or invented numbers.

#### Switch when the allowance is exhausted

There is no automatic fallback. Keep the same `orbi.toml` selector fields, but change `pi_provider` and `pi_model` to match another provider from the [catalog](#catalog); replace the provider file/key, then validate again. For example, switch to the existing OpenRouter template and its selected model:

```toml theme={null}
pi_providers = ".orbi/pi-providers.json"
pi_provider = "openrouter"
pi_model = "google/gemma-4-31b-it:free"
```

Copy [`openrouter.json`](https://github.com/orbi-build/orbi/blob/main/templates/pi-providers/openrouter.json), set `OPENROUTER_API_KEY` in `.orbi/env`, and run one real `pi --print` check before dispatching. OpenRouter's `z-ai/glm-5.2:free` listing is a separate provider route; its availability and quota are **not tested or promised** here.

### Cloudflare Workers AI

Cloudflare's OpenAI-compatible endpoint is account-scoped. Copy [`cloudflare-workers-ai.json`](https://github.com/orbi-build/orbi/blob/main/templates/pi-providers/cloudflare-workers-ai.json), replace `REPLACE_WITH_ACCOUNT_ID` in `baseUrl` with the Cloudflare account ID, and create an API token with both the `Workers AI - Read` and `Workers AI - Edit` permissions (the permissions required by Cloudflare's REST API guide). Keep the token in `.orbi/env`:

```bash theme={null}
printf '%s\n' 'CLOUDFLARE_API_TOKEN=replace-me' >> .orbi/env
chmod 600 .orbi/env
```

Select it in `orbi.toml`:

```toml theme={null}
pi_providers = ".orbi/pi-providers.json"
pi_provider = "cloudflare-workers-ai"
pi_model = "@cf/meta/llama-3.1-8b-instruct-fp8"
```

The model ID is the current FP8 variant documented in Cloudflare's [Workers AI model catalog](https://developers.cloudflare.com/workers-ai/models/llama-3.1-8b-instruct-fp8/); the endpoint path is from the [Workers AI configuration guide](https://developers.cloudflare.com/workers-ai/configuration/). Cloudflare's [official pricing page](https://developers.cloudflare.com/workers-ai/platform/pricing/) documents **10,000 Neurons per day at no charge**, resetting at **00:00 UTC** (information checked 2026-09-04). After the free allocation, further operations fail unless billing is enabled. Limits and pricing can change, so check the official pages before a run.

#### Measure a real Orbi task

Record the Workers AI account's Neurons usage immediately before dispatching one Issue and immediately after the PR is opened (same UTC day). The measured task consumption is `after - before`; retain the dashboard/API timestamps, model, Issue and PR URL, but never retain the token. Orbi's journal proves the selected provider/model, not Neurons usage. **This repository has not run a Cloudflare-account-backed Orbi task; the request and Neurons consumption are not tested and must not be inferred.**

```text theme={null}
journal: provider=cloudflare-workers-ai model=@cf/meta/llama-3.1-8b-instruct-fp8 run_id=<run-id>
Cloudflare Workers AI usage: before=<n> neurons at <UTC>, after=<n> neurons at <UTC>, delta=<n>
PR: https://github.com/OWNER/REPO/pull/<number>
```

#### Hosted versus local Qwen

Workers AI is hosted: Cloudflare provides inference and the account's Neurons allocation, so it is convenient for a machine without a capable GPU but depends on network access, account quota and Cloudflare model availability. `local-qwen` is self-hosted: it avoids provider quota and sends requests to a local OpenAI-compatible server, but the operator supplies the hardware, model runtime and electricity. Use Cloudflare for lightweight hosted execution; use local Qwen when data locality and predictable local availability matter.

### Local providers

A local OpenAI-compatible server still needs a non-empty `apiKey` field to satisfy the provider shape; the local template uses the non-secret dummy value `local`. Its model id must match the server's advertised id (for llama.cpp, set it with `--alias`).

## Codex OAuth: use a ChatGPT/Codex subscription

This path uses Pi's native `openai-codex` provider and OAuth credentials. It does **not** use `OPENAI_API_KEY` and it does **not** need a second `pi_providers` JSON file. It is subscription/Codex quota, not OpenAI API billing.

### First login: do this in order

1. Start an interactive Pi session with `pi`.
2. At the Pi prompt, run **`/login codex`**.
3. Complete the Codex OAuth authorization in the browser.
4. Return to Pi and verify the login with the command supported by the current Pi CLI:

   ```bash theme={null}
   pi auth check --provider openai-codex --model gpt-5.6-luna --json
   ```

   A successful check reports `"status":"ready"` and `"authType":"oauth"`. This command refreshes expired OAuth credentials by default; do not use `--credentials` in a shared terminal or transcript.
5. Only after the check succeeds, configure Orbi and run a real Issue.

### Minimal Orbi configuration

Delete `pi_providers` if it exists; leave it **unset**. Do not copy or create an `openai-codex` provider entry. Pi supplies the catalog from its own `models.json`, and Orbi's per-run agent directory reuses Pi's native auth.

```toml theme={null}
source_repos = ["OWNER/YOUR-REPO"]
# The Orbi checkout supplies the CLI, prompts, labels, and systemd templates.
repo_dir = "/path/to/your-repo"
deploy_home = "/path/to/orbi"
workspace_root = "/path/to"
base_branch = "main"
max_concurrency = 1

# No pi_providers = ... line.
pi_provider = "openai-codex"
pi_model = "gpt-5.6-luna"
```

Pi's catalog checked on **2026-09-07** lists this model as `openai-codex-responses` at `https://chatgpt.com/backend-api`, with reasoning enabled, text/image input, a 1,000,000-token context window, and a 128,000-token output limit. Its catalog thinking map supports `minimal → low`, `xhigh → xhigh`, and `max → max`; leave `pi_thinking` unset for the default, or set one of those verified levels. These are Pi request limits, not a promise about subscription quota.

### Quota and billing boundary

The OAuth credential consumes the user's Codex/ChatGPT subscription allowance. It is separate from an OpenAI API key, API organization billing, and any `OPENAI_API_KEY` balance. Pi's catalog `cost` fields are routing metadata, **not a bill or quota counter**. Allowance, reset time, rate limits, model availability, and error messages depend on the account plan and can change. The 2026-09-05 real-run evidence was from one local account; the account plan and its exact allowance were not recorded, so this guide makes no universal quota claim. On exhaustion or throttling, expect an upstream auth/rate-limit failure in the Pi session and consult the account's current Codex UI/help; do not infer remaining quota from the catalog.

### Real Issue evidence to retain

Run the first Issue in the user's own repository, then retain the non-secret evidence. A successful run should show all of these:

```text theme={null}
journal: provider=openai-codex model=gpt-5.6-luna run_id=<run-id>
PR: https://github.com/OWNER/YOUR-REPO/pull/<number>
elapsed: <duration>
result: PR opened (then review/merge according to the normal Orbi flow)
```

A redacted, non-secret record from the completed Orbi run for this guide (2026-09-07) is:

```text theme={null}
journal: provider=openai-codex model=gpt-5.6-luna run_id=f3e26f87
PR: https://github.com/orbi-build/orbi/pull/487
elapsed: 4m 06s (09:11:18Z–09:15:24Z)
result: PR opened
```

This is evidence of one local account and does not establish a quota guarantee; the account plan and exact allowance were not recorded. Never paste the session JSONL wholesale: redact credentials and prompts that contain secrets.

### Switch providers when quota or auth fails

Remove or replace only the selectors. For a provider from an Orbi template, add its file back because the fallback is no longer Pi-native:

```diff theme={null}
-# no pi_providers line
-pi_provider = "openai-codex"
-pi_model = "gpt-5.6-luna"
+pi_providers = ".orbi/pi-providers.json"
+pi_provider = "local-qwen"       # or "z-ai"
+pi_model = "Qwen3.8-27B"        # or the model id in that file
```

Use the matching template and secret setup in this guide; never put an OAuth token or API key in the repository, an Issue, a PR body, or a journal. For an auth failure, fix/re-login with `/login codex` first; switching providers does not repair an expired Codex session.

## Groq Free Plan

Copy [`groq.json`](https://github.com/orbi-build/orbi/blob/main/templates/pi-providers/groq.json) as `.orbi/pi-providers.json`, then set the selectors and key reference:

```toml theme={null}
pi_providers = ".orbi/pi-providers.json"
pi_provider = "groq"
pi_model = "groq/compound"
```

The template uses Groq's OpenAI-compatible endpoint (`api: "openai-completions"`) and `$GROQ_API_KEY`; put the key in the gitignored `.orbi/env`, never in the JSON or a commit.

According to Groq's [rate-limit table](https://console.groq.com/docs/rate-limits), the Free Plan row for `groq/compound` is **30 RPM / 250 RPD / 70K TPM** (checked 2026-09-04). These are account limits, not an Orbi guarantee; check the official table again before relying on them. The [model catalog](https://console.groq.com/docs/models) lists a 131,072-token context window and 8,192-token maximum completion for this model. The low TPM makes short, bounded coding Issues and small fixes a better fit than long-context repository analysis.

A quota hit is returned upstream as HTTP `429`; Orbi does not silently retry or switch provider mid-session. Treat the run as failed, preserve the Issue/worktree evidence, and manually select another configured provider for the next run. The planned per-provider budget and automatic run-boundary rotation is tracked in [#313](https://github.com/orbi-build/orbi/issues/313); it is not yet a promise of current behavior. Real Groq requests, usage measurements, and 429 responses are **not tested** in this guide; do not claim a successful Groq Issue run without recording redacted evidence.

See [Getting started](/getting-started#path-b-a-pi_providers-file-orbi) for the existing OpenAI-compatible setup and [Issue #305](https://github.com/orbi-build/orbi/issues/305) for the provider article series.


## Related topics

- [Getting started](/getting-started.md)
- [Quickstart](/quickstart.md)
- [Ollama pro](/ollama-pro.md)
- [Zai glm 5 3 flash](/zai-glm-5-3-flash.md)
- [Release v0.3.1](/release-v0.3.1.md)
