Skip to content

Add OpenRouter as a gateway for pstack model roles #7

Description

@thisguymartin

What I want

Let me assign pstack roles to models through OpenRouter using one OpenRouter key, alongside the direct DeepSeek, MiniMax, Claude, Codex, and Grok routes.

I want to pick a model for a job and know that it actually ran. If that model is unavailable, report the failure. Do not quietly switch to a cheaper model or another model family.

Why this needs work

We already have a gateway runner that starts the stock claude binary with an isolated configuration directory, an endpoint, a key, and model pins. OpenRouter should fit at that boundary without adding another agent loop or copying skills for each provider.

docs/LANES.md currently says OpenRouter has no Anthropic-compatible endpoint and needs a local translator. That is out of date. OpenRouter documents a direct Claude Code connection using:

  • ANTHROPIC_BASE_URL=https://openrouter.ai/api
  • ANTHROPIC_AUTH_TOKEN from OPENROUTER_API_KEY
  • An explicitly empty ANTHROPIC_API_KEY

There is a catch: OpenRouter only guarantees this integration with Anthropic's first-party provider. That does not establish that DeepSeek, MiniMax, or every other model in its catalog works through our Claude-based runner.

Sources:

Start by proving the route

Use a scratch workspace with synthetic files and the existing runner. Test one supported Anthropic model first, then investigate the DeepSeek and MiniMax models we actually want to use.

For each model, check:

  • The account can access the exact model ID.
  • A file-reading tool call succeeds. Put a random value in the file and keep it out of the prompt so a guessed answer cannot pass.
  • A second turn can use the tool result, including any required thinking blocks.
  • Requested effort settings reach the endpoint and unsupported settings fail clearly. A CLI accepting --effort is not proof that the API applies it.
  • The returned model identity can be compared with the requested model without accepting a different model by accident.

Record supported combinations and failures. If non-Anthropic models do not work on this path, keep the first implementation limited to the proven models and describe the missing work. Do not add a proxy or a new runtime as a side effect of this issue.

Implementation

  • Add openrouter to the existing gateway provider types and environment configuration. Read OPENROUTER_API_KEY at launch time and use a separate configuration directory.
  • Keep the current credential isolation. Strip inherited Anthropic credentials and routing settings before injecting OpenRouter's settings, including its explicitly empty API-key field. Never write keys into model sheets, receipts, or logs.
  • Support namespaced OpenRouter model IDs in the model matrix, setup validation, runner arguments, and receipts. Audit assumptions that IDs contain only letters, digits, dots, and hyphens.
  • Add only verified model choices to setup. Preserve existing assignments and probe each selected model separately.
  • Keep routing in the parent. Children receive their assigned route and do not choose another provider.
  • Keep requested and reported model IDs in receipts. Document any verified translation between them. Do not strip arbitrary prefixes or loosen matching until unrelated models pass.
  • Keep costUsd null unless it comes from reliable OpenRouter usage data. Claude Code's Anthropic price estimate is not OpenRouter billing.
  • Update the outdated OpenRouter section and document setup, supported models, access requirements, and billing limitations.

Provider diversity needs an explicit rule

OpenRouter is the gateway, but the model can come from Anthropic, DeepSeek, MiniMax, or another lab. Counting every OpenRouter entry as the same model provider would lose useful diversity. Counting a direct DeepSeek call and the same DeepSeek model through OpenRouter as two independent providers would also be wrong.

Keep transport separate from model-family ownership when checking panel diversity. Use an explicit mapping for supported models rather than guessing from arbitrary model strings. Routing the same model across hosting providers must not count as another independent model family.

Also distinguish OpenRouter's same-model hosting failover from switching models. Do not use automatic model selection, a fallback model list, or a weaker-model fallback. Confirm that routing settings preserve the selected model.

Done when

  • OpenRouter works through the existing gateway runner with an explicitly supported set of models.
  • Setup accepts those model IDs, probes each selected pair, and preserves the active sheet when a probe fails.
  • Missing keys, denied model access, unsupported effort, and reported-model mismatches produce useful failures without substitution.
  • Panel diversity handles direct and OpenRouter routes consistently.
  • Tests cover namespaced IDs, environment isolation, model verification, and both parent routes.
  • Bun tests, strict typecheck, static invariants, and plugin validation pass.
  • The exact candidate is installed and tested from the real Claude Code and Codex user surfaces. Record installed version, action, and observed result in the PR.

A successful standalone API request or a runner test is useful evidence, but it does not replace the installed setup tests. Keep the PR in draft until those pass.

OpenCode as a parent is separate work in #3. This issue should not depend on adding it.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions