Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.rkat.ai/llms.txt

Use this file to discover all available pages before exploring further.

Meerkat’s auth story has two layers. The fast path is env vars (ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY, or AZURE_OPENAI_API_KEY plus AZURE_OPENAI_ENDPOINT) — set them and rkat run works. The powerful path is realm-scoped bindings: declare a realm in your config, register credentials via rkat auth login or the REST/RPC surfaces, and pass --auth-binding <realm>:<binding> to scope a session or mob member to that specific binding.
Today, CLI rkat auth login is primarily a convenience bootstrap flow for the default dev:* credential namespace. If you need explicit realm/profile-targeted auth persistence such as prod:openai, use the REST/RPC auth surfaces or manage the realm config entries directly.

What this guide is for

Use this guide when you need more than the env-var fast path:
  • explicit realm-scoped bindings
  • OAuth or cloud-IAM-backed auth
  • hot-swapping provider identity
  • per-mob-member credential overrides
Both paths route through the same ProviderRuntimeRegistry. There’s no hidden magic path: the env fallback is a synthesized realm with CredentialSourceSpec::Env, resolved by the same code that handles your configured realms.

The fast path: env vars

export ANTHROPIC_API_KEY=sk-ant-...
rkat run "What's the weather like in 2026?"
That’s it. If the env var is set, Meerkat synthesizes a default realm (env_default) with a binding that reads the key via CredentialSourceSpec::Env, then resolves normally. RKAT_*-prefixed env vars (e.g., RKAT_ANTHROPIC_API_KEY) take precedence over the provider-native names.
ProviderPrimary env varFallback
AnthropicANTHROPIC_API_KEY
OpenAIOPENAI_API_KEY
OpenAI on AzureAZURE_OPENAI_API_KEY plus AZURE_OPENAI_ENDPOINTOptional AZURE_OPENAI_IMAGE_GENERATION_DEPLOYMENT, AZURE_OPENAI_IMAGE_GENERATION_API_VERSION
GeminiGEMINI_API_KEYGOOGLE_API_KEY
If both public OpenAI and unprefixed Azure OpenAI env vars are present, the public OpenAI env default wins. Use RKAT_AZURE_OPENAI_API_KEY plus RKAT_AZURE_OPENAI_ENDPOINT, or an explicit realm binding, to make Azure OpenAI the env default in that case.

The powerful path: realms + bindings

A realm is a named collection of backend profiles, auth profiles, and provider bindings. It lets you:
  • Run multiple sessions against different accounts or tenants
  • Mix OAuth (Claude.ai Pro/Max), api_key (keyed by CI), and cloud IAM (Bedrock/Vertex/Foundry) in one process
  • Hot-swap a session’s active binding mid-conversation
  • Give different mob members different credentials

Realm shape

# ~/.rkat/config.toml (or project-local .rkat/config.toml)

[realm.prod.backend.anthropic_primary]
provider = "anthropic"
backend_kind = "anthropic_api"

[realm.prod.backend.openai_primary]
provider = "openai"
backend_kind = "openai_api"

[realm.prod.auth.anthropic_oauth]
provider = "anthropic"
auth_method = "claude_ai_oauth"
source = { kind = "managed_store" }

[realm.prod.auth.openai_apikey]
provider = "openai"
auth_method = "api_key"
source = { kind = "managed_store" }

[realm.prod.binding.default]
backend_profile = "anthropic_primary"
auth_profile    = "anthropic_oauth"

[realm.prod.binding.openai]
backend_profile = "openai_primary"
auth_profile    = "openai_apikey"
Azure OpenAI uses the same provider id (openai) with an Azure-specific backend/auth pair:
[realm.prod.backend.azure_openai]
provider = "openai"
backend_kind = "azure_openai"
base_url = "https://my-resource.cognitiveservices.azure.com"
options = { image_generation_deployment = "gpt-image-2", image_generation_api_version = "preview" }

[realm.prod.auth.azure_openai_key]
provider = "openai"
auth_method = "azure_api_key"
source = { kind = "managed_store" }

[realm.prod.binding.azure_openai]
backend_profile = "azure_openai"
auth_profile    = "azure_openai_key"
default_model   = "gpt-5.5" # Azure deployment name

Log in

# Interactive OAuth (opens a browser; stores refresh token in the
# local TokenStore credentials file, 0600 on Unix).
rkat auth login anthropic

# Scripted (api_key):
rkat auth login openai --non-interactive --secret "$OPENAI_KEY"
The current CLI login flow is convenient for local setup, but it does not yet let you choose an arbitrary target realm/profile name at login time. It seeds the runtime-managed default dev:* identities and is best thought of as the easiest way to get persisted credentials into Meerkat quickly.

Use the binding

rkat run --auth-binding prod:default "hello"
rkat run --auth-binding prod:openai   "hello"

Subcommands

1

Login and profile management

rkat auth realms                       # list realms defined in config
rkat auth profiles --realm prod        # list profiles/backends/bindings
rkat auth profile --realm prod <id>    # inspect one profile
rkat auth login <provider>             # start OAuth or api_key flow
rkat auth logout <profile_id>          # clear persisted credentials
2

Status and refresh

rkat auth status --realm prod <profile_id>    # TokenStore state + expiry
rkat auth test --realm prod <binding_id>      # dry-run the binding
rkat auth refresh --realm prod <profile_id>   # force-refresh OAuth tokens
rkat auth refresh is a no-op for api_key / azure_api_key / static_bearer auth methods (nothing to refresh). For OAuth-backed methods it exchanges the persisted refresh token for a fresh access token and writes the new bundle back to the TokenStore.
3

Delete

rkat auth profile-delete --realm prod <profile_id> -y

Release auth smoke

make e2e-auth is the CI-safe auth smoke lane. It drives Meerkat’s browser OAuth plumbing against a local OAuth fixture, verifies token-store and AuthMachine lifecycle behavior across login, status, refresh, restart, resolve, and logout, and skips optional live-provider canaries when their seeded credentials are absent. Real third-party browser login pages remain a manual pre-release check. Do not automate provider-hosted OpenAI, Anthropic, or Google login pages in CI; those pages are intentionally subject to MFA, CAPTCHA, account policy, and provider UI changes. Manual browser-login release checklist:
  • Start login for the target provider.
  • Confirm the system browser opens the provider-hosted login or consent page.
  • Complete the callback and confirm Meerkat reports the login complete.
  • Check auth status and confirm the target binding is valid.
  • Run one tiny call through that binding.
  • Logout and confirm auth status is cleared and the credential is gone.

Auth methods

Each provider’s runtime accepts a matrix of (backend_kind, auth_method) pairs. The table below summarizes what’s wired today.
Providerbackend_kindauth_methodNotes
Anthropicanthropic_apiapi_key, static_bearerDirect to api.anthropic.com
Anthropicanthropic_apiclaude_ai_oauthClaude Pro/Max OAuth (PKCE, S256)
Anthropicanthropic_apioauth_to_api_keyConsole OAuth → provisions api_key
Anthropicanthropic_apiexternal_authorizerHost-resolved auth injection
Anthropicbedrockbedrock_bearer, bedrock_aws_sigv4AWS SigV4 / env-bearer
Anthropicvertexvertex_google_authGoogleAuth / Vertex AI
Anthropicfoundryfoundry_api_key, foundry_azure_adAzure AI Foundry
OpenAIopenai_apiapi_key, static_bearer, external_authorizerDirect to api.openai.com or host-resolved auth
OpenAIazure_openaiazure_api_keyAzure OpenAI Responses API; base_url required; session model is the Azure deployment name
OpenAIchatgpt_backendmanaged_chatgpt_oauthChatGPT Plus/Pro OAuth
OpenAIchatgpt_backendexternal_chatgpt_tokensHost-supplied tokens
Googlegoogle_genaiapi_key, bearer_api_key, external_authorizerDirect to Google GenAI or host-resolved auth
Googlevertex_aiapi_key_expressVertex API Express key
Googlevertex_aiadc, compute_adcADC / compute metadata
Googlegoogle_code_assistgoogle_oauthGemini Code Assist OAuth
External commands (CredentialSourceSpec::Command) and file descriptors (CredentialSourceSpec::FileDescriptor) let host applications inject tokens without going through OAuth.

Credential sources

The source field on an auth profile declares where credentials come from.
KindDescription
InlineSecret { secret }Secret stored inline in the TOML (use only for dev/local)
Env { env, fallback }Read env var at resolve time via ResolverEnvironment::env_lookup
ManagedStore { profile }Resolve via the TokenStore; in current provider runtimes, persisted lookup is tied to the active auth-profile identity/binding path
PlatformDefaultUse the host platform’s default credential chain where supported
ExternalResolver { handle }Host-registered JS callback (WASM) or Rust resolver (embedded)
Command { program, args, ... }Run an external binary; cache stdout for refresh_interval_ms
FileDescriptor { fd, scope_override }Read credentials from a host-supplied file descriptor
Storing api keys inline in config files works but shouldn’t be checked into git. Prefer ManagedStore (which writes to the OS keychain or a 0o600 file) or Env.
FileDescriptor is a host-integration seam rather than a plain standalone resolver path. It requires a host-scoped reader/injection path, so treat it as an advanced embedding surface rather than a generic CLI config trick.

Hot-swap mid-session

When a session is created with --auth-binding prod:default, its persisted SessionMetadata.auth_binding carries that binding through resume and hot-swap. Changing the model/provider mid-turn via the RPC turn/start override keeps the binding by default; pass an explicit auth_binding on the turn request to scope the swap to a different realm or binding.
// RPC turn/start — hot-swap to openai binding in the same realm
{
  "method": "turn/start",
  "params": {
    "session_id": "...",
    "prompt": "...",
    "model": "gpt-5.5",
    "auth_binding": {"realm": "prod", "binding": "openai"}
  }
}
The factory re-enters ProviderRuntimeRegistry::resolve with the new binding — no env-default fallback, no cross-realm credential bleed.

Per-mob-member override

Mob members default to env-default / config-realm fallback credentials. Pass auth_binding on the host-side mob spawn surface to scope a member to a specific binding:
{
  "method": "mob/spawn",
  "params": {
    "mob_id": "research",
    "profile": "analyst",
    "agent_identity": "a1",
    "auth_binding": {"realm": "prod", "binding": "openai"}
  }
}
Members in the same mob can use different providers or tenants without cross-contamination. Public wire surfaces accept the structural auth_binding object only; the colon-joined realm:binding[:profile] form is a CLI input convenience and is converted before it crosses the wire boundary.

Refresh coordination

Refresh semantics are owned by the AuthMachine DSL (one instance per <realm>:<binding>). On resolve, the runtime:
  1. Checks expires_at. If present and within 80% of TTL, marks the lease Expiring via the DSL.
  2. Under Expiring, the next resolve triggers BeginRefresh. In-process dedup ensures only one refresh HTTP call per binding even under concurrent resolves; cross-process dedup via filesystem lockfile when refresh-file-lock is enabled.
  3. On successful refresh, fires CompleteRefresh and updates expires_at. On failure, RefreshFailedTransient (retry) or RefreshFailedPermanent (routes to ReauthRequired + emits an [AUTH_REAUTH_REQUIRED] system notice on the session).
The lifecycle is TLC-verified in specs/machines/auth/.

Audit logging

Every accepted lifecycle transition emits a structured tracing event:
  • target = "meerkat::auth::audit"
  • Fields: binding_key, action, from_phase, to_phase
REST and RPC surfaces also emit audit events for user-initiated actions: create_profile, delete_profile, login_oauth_complete, login_device_complete, logout. Filter any tracing::Subscriber on the meerkat::auth::audit target to build a persistent audit log.

Feature flags

The meerkat-providers crate gates optional auth methods behind features so you only pay for what you use:
FeatureEnables
oauthOAuth flows (Claude.ai, ChatGPT, Code Assist)
native-keyringOS keychain storage for tokens
refresh-file-lockCross-process refresh dedup
aws-authBedrock backend + SigV4 signing
google-oauthVertex + Code Assist + ADC
azure-authFoundry backend + Azure AD
The rkat CLI enables anthropic, openai, gemini, and oauth by default; add cloud-specific features at compile time for Bedrock/Vertex/Foundry.

See also

  • Hooks — observe auth events or gate turns on credential state
  • Mobs — per-member auth_binding overrides
  • Machine Authority — rationale behind single-owner runtime state