Skip to content

Capabilities

Models & providers

One streaming client, every backend — and an honest note about which paths have actually run.

Providers

Arcturn drives every model through a single client interface, so a provider change is a --model flag rather than a code change. Adapters register themselves into a provider registry, which is why adding a backend never touches dispatch code.

The last two rows matter more than they look: most third-party inference services speak one of those two protocols, so Arcturn reaches them without a bespoke adapter each. Endpoint presets ship as remembered { baseUrl, apiKeyEnv, protocol } triples — run arcturn --list-providers for the current set. A preset is a convenience, not a gate: any endpoint works by URL without one.

  • openai-compatible

    Any OpenAI-shaped endpoint, credentials per endpoint. Has completed real multi-turn tool-calling sessions.

    Proven
  • anthropic

    Claude, direct — ANTHROPIC_API_KEY, or an OAuth subscription sign-in. Verified live on Claude Haiku 4.5.

    Proven
  • openai

    GPT via Chat Completions — OPENAI_API_KEY. Verified live on GPT-5 nano.

    Proven
  • openai-responses

    GPT via the Responses API — OPENAI_API_KEY. Verified live on GPT-5 nano.

    Proven
  • google

    Gemini, direct — GOOGLE_API_KEY (GEMINI_API_KEY also works). Verified live on Gemini 3.5 Flash Lite.

    Proven
  • anthropic-compatible

    Any Anthropic-Messages endpoint, credentials per endpoint. Verified live against a canonical Messages API; no third-party implementation exercised yet.

    Proven
  • bedrock

    Claude, Nova, Llama, Mistral and Titan on AWS — the standard AWS provider chain.

    Not reached
  • vertex

    Gemini and Claude on Google Cloud — application-default credentials.

    Not reached
  • azure

    GPT on Azure OpenAI, addressed by deployment — AZURE_OPENAI_API_KEY or Entra ID.

    Not reached

Status means exactly what it says. Proven is a real request to a real endpoint, correct across streaming, a tool call whose result is fed back and answered on a second turn, and cost accounting that matches the published rates. Six paths clear that bar: first-party Anthropic, Google, and OpenAI on both its Chat Completions and Responses surfaces, plus both compatibility adapters. Bedrock, Vertex and Azure have never reached their endpoints at all. Each compatibility adapter was verified against one implementation of its protocol — openai-compatible against Z.AI, anthropic-compatible against a canonical Messages API — which proves the adapter, not any particular third-party service.

The distinction is drawn because it earned itself. Each of those live runs found a bug the test suite could not: a --print that hung forever on the inherited stdin every CI runner supplies, Gemini rejecting every second turn of tool use over a dropped signature, and a Responses adapter that was registered and documented but had no catalog entry, so nobody could select it. Three providers, three bugs, all in code with passing tests.

Model ids and switching

Model ids are <provider>/<model>. Pass one with --model, or switch mid-session with /model <id>. Model names pass through verbatim, so anything the endpoint serves works.

A bare wire model name resolves too when it is unambiguous across the catalog, and a miss triggers the extended preset table to register itself once before retrying — so a fresh process never pays for the whole table unless something needs it.

arcturn --model anthropic/claude-sonnet-4-5
arcturn --model openai/gpt-5.1
arcturn --model google/gemini-3-pro-preview

arcturn --list-models        # the catalog, then exit
arcturn --list-providers     # every provider and preset endpoint

Routing and failover

Two of the four route kinds reach a live call site today: main for the conversation loop, and subagent for delegated work — sub-agents, scouts and /team members alike — so a mechanical subtask need not run on the model steering the session. compaction and title are accepted in config and reserved; a session title is derived from the task text directly today and makes no model call at all. A missing route falls back to whatever main resolved to, and a bad id is caught rather than thrown — the kind falls back and records a warning, because a stale model id in a config file must never be the reason Arcturn fails to start.

A model string can also be an array, which builds a failover chain. The rule that matters: failover only happens before output starts. Once a single delta reaches the consumer the turn is committed to that model, because splicing two half-answers together would corrupt the message. Only transient errors — rate limits, overload, network — trigger a switch; a bad key or a user abort fails identically on every link.

main         the main conversation loop
subagent     delegated sub-agent work — sub-agents, scouts and /team members
compaction   summarizing history when the context window fills — accepted in config, reserved
title        session-title suggestions — reserved; today's title is derived from the task text

Live catalog

The curated catalog is hand-maintained, which means it goes stale the moment a provider ships a new generation. /model refresh queries each preset’s own list-models endpoint — for whichever presets already have a key set — and registers anything new it finds without ever overwriting a curated entry.

Results are cached at ~/.arcturn/live-models.json for 24 hours. A model discovered this way gets conservative defaults until a curated entry supersedes it, and a preset whose refresh fails falls back to its last cached result rather than dropping its models for that round.

Cost

Costs are tracked per request whenever a model’s pricing is known. Where a price could not be sourced confidently it is omitted rather than guessed, so the cost field is simply absent instead of quietly wrong.

Prompt caching is supported through the same interface, and --max-cost turns live spend into an enforcement mechanism: the run is aborted at the next turn boundary once cumulative cost reaches the ceiling, not flagged after the fact.

Every turn counts.

Start a session, watch every tool call ask first, then go back and read exactly what happened.

npm install -g arcturn