GitHubBook a demoStart routing
Browse docs

Add a provider with your own key

Point a TokenTriage upstream at any provider — OpenAI-compatible, Anthropic, Azure, Bedrock, or Vertex — using a BYO credential referenced by environment-variable NAME, never a literal secret.

Last updated

On this page

Add an upstream to your config that authenticates to a provider with your own credential, where the config references the secret by its environment-variable name — so the secret value itself never lives in a file.

Prerequisites

  • A working tokentriage.yaml (see the quickstart).
  • The provider credential exported into your shell/orchestrator environment (e.g. export OPENAI_API_KEY=sk-…). TokenTriage reads the value at boot from the named variable.
  • Basic familiarity with the upstreams and providers model.

The credential model in one line

An upstream carries its BYO key one of two ways, selected by the provider family’s auth kind:

Auth kind Provider families Credential config
bearer OpenAI-compatible (Groq, Together, vLLM, …) api_key_env: — single env-var name
header Anthropic, Azure OpenAI, Gemini (AI Studio) api_key_env: — single env-var name
aws_sigv4 Amazon Bedrock auth: block of env-var names (access_key_id_env, secret_access_key_env, …)
gcp_oauth Google Vertex AI auth: { credentials_file_env: … } — env var holding the SA-key file path

bearer and header both use the single api_key_env carrier; aws_sigv4 and gcp_oauth need the multi-part auth: block. The auth kind is supplied by the provider descriptor (a built-in one you name with provider:, or an inline one you declare) — you rarely set it by hand.

Step 1 — Add an OpenAI-compatible upstream (bearer)

Any upstream that speaks the OpenAI chat-completions wire names a built-in descriptor with provider: and points api_key_env: at your key’s env var. dialect is derived from the descriptor, so omit it.

upstreams:
  together:
    provider: together_ai              # built-in descriptor: openai wire, bearer auth
    base_url: https://api.together.xyz/v1
    api_key_env: TOGETHER_API_KEY      # env var NAME — never a secret literal

base_url is required even with provider: — descriptors carry only relative paths, no host.

Step 2 — Or an Anthropic upstream (header)

The Anthropic family uses a header auth scheme, but the credential is still carried by the single api_key_env field:

upstreams:
  anthropic:
    base_url: https://api.anthropic.com
    dialect: anthropic                 # openai | anthropic
    api_key_env: ANTHROPIC_API_KEY     # env var NAME

An upstream with no api_key_env forwards the inbound Authorization header as-is — useful for a local, keyless server:

upstreams:
  ollama:
    base_url: http://localhost:11434/v1
    dialect: openai
    # no api_key_env → inbound Authorization forwarded unchanged

Step 3 — Or a provider that needs more than a key

Two families carry credential or region facts a single api_key_env cannot.

Amazon Bedrock (aws_sigv4) signs every request, so it needs a region (which also selects the region-class price) and a multi-part credential block — each field an env-var name, never a literal:

upstreams:
  bedrock:
    provider: bedrock
    base_url: https://bedrock-runtime.us-east-1.amazonaws.com
    region: us-east-1                        # REQUIRED: signing + region-class pricing
    auth:
      access_key_id_env: AWS_ACCESS_KEY_ID
      secret_access_key_env: AWS_SECRET_ACCESS_KEY
      session_token_env: AWS_SESSION_TOKEN   # optional (STS / temporary creds)

A Bedrock bearer API key short-circuits SigV4: set api_key_env: alone instead of the auth: block.

Google Vertex AI ships as a built-in vertex_ai provider (Gemini wire dialect, gcp_oauth auth via a self-signed service-account JWT) — you don’t declare a descriptor. Reference it and supply your project and location as upstream params: (they fill the {project} / {location} slots in the descriptor’s URL template). The credential names an env var holding the SA-key file path:

upstreams:
  vertex:
    provider: vertex_ai                 # built-in descriptor (gemini dialect, gcp_oauth)
    base_url: https://us-central1-aiplatform.googleapis.com
    params:
      project: my-gcp-project           # fills the {project} URL slot
      location: us-central1             # fills the {location} URL slot
    auth:
      credentials_file_env: GOOGLE_APPLICATION_CREDENTIALS  # env var holding the SA-key file PATH

Step 4 — Validate strictly

tokentriage validate loads the config with strict decoding (an unknown key is an error) and prints a summary. It does not read the secret — only the reference — so you can validate before the env var is even set.

$ tokentriage validate --config tokentriage.yaml
mode:      shadow
listen:    127.0.0.1:8787   admin: 127.0.0.1:9090
upstreams: 2
  - openai                 https://api.openai.com/v1
  - together               https://api.together.xyz/v1
tiers:     2 (cheapest -> most capable)
  0. cheap      -> together/meta-llama/Llama-3.3-70B-Instruct-Turbo
  1. frontier   -> openai/gpt-4o
rules:     1
OK: configuration is valid

You should see OK: configuration is valid on the last line. A misreferenced credential or an unknown key fails here with a path-named error rather than at request time.

Step 5 — Confirm the model is priced under the right provider

Pricing binds to the provider, not the wire dialect — so a model at your new upstream prices under that provider’s catalog prefix. Look it up with the fully-qualified provider/model key:

$ tokentriage prices show together_ai/meta-llama/Llama-3.3-70B-Instruct-Turbo
model:      together_ai/meta-llama/Llama-3.3-70B-Instruct-Turbo
resolved:   together_ai/together_ai/meta-llama/Llama-3.3-70B-Instruct-Turbo
provider:   together_ai
snapshot:   litellm@2026-07-14#179affb
source:     litellm  fetched 2026-07-14  generator pricegen v2
upstream_sha256: 179affb29103fed8b02a83e22e93209c2c65a393cbf9dd785dbaec0f8748d6f7

RATE         USD / TOKEN          USD / 1M TOKENS
input        8.8e-07              $0.8800
output       8.8e-07              $0.8800
cache_read   (fallback = input)   $0.8800
cache_write  (fallback = input)   $0.8800
reasoning    (fallback = output)  $0.8800

The identical model string routed at an openai-prefix upstream would resolve unpriced (model_unknown) — a different, correct outcome — so a wrong-provider price is impossible by construction.

Why this is honest and safe

  • Secrets stay out of config. Only env-var names are written; the loader’s env-reference guard refuses anything resembling a raw value, so a credential can’t leak into a YAML file, a diff, or a config dump.
  • Strict decoding fails loud. A typo in a credential key or provider name is a validation error, not a silent fallback that would forward with the wrong (or no) credential.
  • Pricing is provider-bound. Your BYO upstream’s costs price under its own catalog prefix; a model the snapshot doesn’t know is honestly unpriced rather than assigned a confident wrong dollar.