nookins / docs

Models and provider fallback

Configure Codex and OpenRouter with explicit privacy and spending limits.

Documentation for Nookins 0.42.1-alpha.1 · Public alpha

Nookins keeps the default model chain, provider permissions and spending limits in ~/.nookins/config/nookins.yaml. Agent files are in ~/.nookins/config/agents.d/. The operator interface exposes the same settings in Settings → Overview → Default reasoning and Settings → Agents. Changing the listening address requires a restart; changing model policy applies to subsequent work.

OpenRouter starts disabled. A populated example does not send prompts to a new provider. You choose which serving providers may receive prompts and tool results.

1. Store your API key

Create an API key in your OpenRouter account. Edit ~/.nookins/secrets.env locally and add or replace this entry:

NOOKINS_OPENROUTER_API_KEY=YOUR_ACTUAL_KEY

This is the only key setting Nookins needs for OpenRouter. Keep the file private (mode 600). Do not put the key in nookins.yaml, an agent file, a chat message, a screenshot, or a Git commit. Restart Nookins after adding or changing it.

2. Choose serving providers

provider: openrouter selects Nookins’ adapter. model: openrouter/free is the native router model ID. allowed_providers is different: it lists the companies behind OpenRouter that you permit to process the request.

Use OpenRouter's provider list for exact slug values. On an individual model's page, the provider-name copy button also supplies its exact endpoint slug; see provider routing. For the free router, select serving providers that currently offer eligible free models. A slug is not a model ID: do not put openrouter/free in this list.

To let the free router choose across providers without maintaining a list, set allowed_providers: ["*"]. The wildcard must appear alone. It explicitly permits any serving provider that meets the request's privacy, capability and cost requirements; it does not allow paid inference when both budgets are "0". Empty lists are invalid. Use named slugs when you want to restrict which companies receive context. REPLACE_WITH_SERVING_PROVIDER_SLUG below is a placeholder, not a working provider; replace it with a real slug or "*".

3. Set the main policy and chain

Replace the existing reasoning section in ~/.nookins/config/nookins.yaml with the following, after replacing the provider placeholder. Do not append a second reasoning key; Nookins rejects duplicate keys.

reasoning:
  model_chain:
    - provider: codex
      model: default
      reasoning_effort: medium
    - provider: openrouter
      model: openrouter/free
  openrouter:
    allowed_providers: [REPLACE_WITH_SERVING_PROVIDER_SLUG]
    data_collection: deny
    zero_data_retention: true
    max_run_cost_usd: "0"
    max_daily_cost_usd: "0"

This attempts Codex first and the free router on eligible availability failures. Both budgets are zero: Nookins allows only requests quoted at zero cost. The daily budget covers all agents combined. The router may choose a different underlying free model for each request; see OpenRouter's free-router contract. Leave the router's reasoning effort at Provider default unless you know an eligible model supports the requested effort.

A free route may not satisfy your provider, tool-support, context-size and privacy requirements. Nookins fails closed in that case. Changing data_collection or zero_data_retention changes your privacy policy; it is not a required setup step. For a paid model, explicitly choose its native model ID and nonzero budgets.

To keep OpenRouter disabled, use the materialized default:

reasoning:
  model_chain:
    - provider: codex
      model: default
      reasoning_effort: medium
  openrouter: null

4. Apply the chain to an agent

Existing agents keep the explicit chains they had before migration. Updating the main default does not replace those chains.

For an agent that should use the main chain, select Use main defaults under Settings → Agents, or set this in that agent's YAML:

model_chain: []

An agent with no model_chain also inherits. Remove its openrouter override if you want it to inherit the main provider policy. Keep a narrower override if that restriction is intentional. A nonempty agent chain replaces the entire main chain; to retain an agent's existing Codex choice, append the OpenRouter entry to that agent's chain instead of choosing inheritance.

Do not change all agents merely to test the integration. Start with the agent whose conversation you want to use.

5. Validate and activate

After editing YAML files:

nookins config validate
nookins config apply
nookins service restart
nookins service status
nookins config status

Validation must succeed before activation. The restart loads the host key; expect all configured roles ready and every configuration projection in sync. In the UI, review and activate the draft, then restart for a changed key.

For a different Nookins home, pass --home /path/to/home before the command. For a nondefault listening port, pass --url http://127.0.0.1:PORT to commands that talk to the control API. With an IPv6 wildcard bind, use http://[::1]:PORT. A concrete non-loopback bind uses that concrete address instead.

6. Test the free router directly

In an owner/trusted conversation with the configured agent:

/model
/model list
/model openrouter openrouter/free

/model must show the router in the effective chain. After selecting it, send a small text request such as “Reply with the word ready.” This makes a real provider request under your configured policy. No need to exhaust Codex quota to test it.

Restore your normal configured order afterward:

/model auto

Selection affects subsequent turns, not a turn already in progress. Automatic fallback stops on refusals, invalid requests, uncertain failures, exhausted Nookins budgets, cancellation, or any failure after a tool was dispatched.

Troubleshooting

SymptomWhat to check
OpenRouter is disabledMain reasoning.openrouter is absent/null. Enable it with real provider slugs and explicit limits.
/model says the target is unavailable/not authorizedThe agent still has an explicit Codex-only chain. Inherit main defaults or add the router to that chain.
Authentication failsCheck the key locally in secrets.env, restart, and explicitly activate configuration after repairing credentials to reset the provider circuit.
No qualified route / incompatible providerCheck available free models, allowed providers, privacy constraints, tools and context size. Do not silently relax privacy to bypass this.
A zero-budget request is rejectedA fixed selected model may be paid, or zero pricing/cost could not be verified. Keep zero budgets for free-only use.
The endpoint is rate-limitedFree access still has rate limits. Wait or choose another explicitly authorized target; a restart does not erase provider limits.
Changing main defaults had no effectAn agent chain or sticky conversation override still applies. Check /model, the agent file, and /model auto.

Listener configuration

The complete address belongs in the same main file:

listen: 127.0.0.1:8790

Use 0.0.0.0:8790 to bind all IPv4 interfaces, [::]:8790 for IPv6, or a specific local interface address. Quote IPv6 values in YAML. A wildcard changes which interfaces accept connections; it does not disable login, bearer authentication or CSRF protection. Direct HTTP does not encrypt traffic; use an HTTPS reverse proxy or a protected tunnel when accessing the operator outside a trusted network.

An authored listen value wins. For older files that omit it, Nookins still uses --listen, then NOOKINS_LISTEN, then 127.0.0.1:8790. Once materialized in YAML, edit the YAML value. Review and activate the change, then restart; a browser on the old address will need to open the new one. If changing ports through the CLI, use the old running URL for config apply and the new URL after restart.

Free models and structured answers

Nookins uses openrouter-rs protocol types and complete JSON responses, with bounded HTTP reads. For openrouter/free, a final answer may be a private function call or a JSON object matching the requested schema. Nookins validates the presentation before publishing it. The private function cannot execute an action; mixing it with ordinary actions is rejected.

An invalid final format gets at most one formatting-only request, with action tools removed. It keeps the original deadline, privacy rules, and spending limits, and does not repeat completed actions. If that fails, the warning identifies an invalid response format instead of an unknown interruption. Do not replay a request whose actions need reconciliation.

Free capacity and upstream rate limits still apply. An unsupported permitted route fails without relaxing privacy or spending policy. A completed acknowledgement reaction alone is not reported as completed requested work.

On this page