Skip to main content

Prerequisites

1

A Concentrate AI account with an active API key

Sign up or log in at concentrate.ai and create an API key. Your key should start with sk-cn-v1-.
2

An existing TensorZero integration

This guide assumes you are calling a self-hosted TensorZero gateway from the native tensorzero client (POST /inference), the OpenAI SDK pointed at /openai/v1, fetch, requests, or another HTTP client.

Quick Start for Claude Code users

If you use Claude Code, you can install a skill that walks through this migration interactively. It collapses the base URL, strips tensorzero:: model namespacing and body params, decomposes your tensorzero.toml functions and variants, maps model slugs, and generates a verification script. Drop the skill into your ~/.claude/skills/ directory:
Then start a Claude Code session in your project and ask it to “migrate from TensorZero to Concentrate” or run /migrate-tensorzero. Claude will load the skill and run the steps.

Step 1: Update Your Environment Variables

TensorZero is self-hosted: provider credentials live in your tensorzero.toml, and gateway auth (if enabled) uses TENSORZERO_API_KEY. All of that collapses to a single Concentrate key:
Concentrate is hosted with managed credentials, so there’s no gateway process or tensorzero.toml to maintain, and no OPENAI_API_KEY, ANTHROPIC_API_KEY, or AWS credentials to keep. Comment them out (don’t delete) until you’ve verified the migration end-to-end, then remove them.
TensorZero’s OpenAI-compatible endpoint ignores any api_key sent by the client; it uses credentials from its own config. Concentrate requires a real sk-cn-v1-... key on every request, so make sure your client now sends one (not a placeholder).

Step 2: Update Your Client

Collapse the gateway base URL (both the /openai/v1 and /inference paths) onto https://api.concentrate.ai/v1, and drop the tensorzero:: namespacing and body params. If you used the native tensorzero client, swap to the OpenAI SDK. Concentrate ships no dedicated SDK because the OpenAI-compatible shape covers every endpoint.

Step 3: Remove TensorZero-Specific Headers and Body Params

TensorZero keeps almost all of its distinctiveness in tensorzero::-prefixed body params, not headers. None of them, nor TensorZero’s custom headers, carry over to Concentrate, so they should come out; they’re dead weight and mislead future readers. Expand the tables below for the mapping.
Sent as tensorzero::-prefixed body fields on the OpenAI endpoint (via extra_body), or as top-level fields (episode_id, variant_name, …) on /inference.

Step 4: Decompose Functions, Variants, and Episodes

TensorZero’s defining concept is the function / variant / episode model in tensorzero.toml: you call a named function, the gateway samples a variant (built-in A/B testing and fallbacks), and related inferences group into an episode. Concentrate has none of these primitives. Each behavior is either on by default or a body param. Expand the table for the mapping.

Step 5: Update Model Identifiers

Concentrate accepts model strings in two forms:
  • Bare slug, e.g. gpt-4o, claude-haiku-4-5, auto. Routing picks a provider.
  • provider/model-id, e.g. bedrock/claude-haiku-4-5, openai/gpt-4o. Pins the request to a specific provider.
TensorZero wraps model strings in tensorzero:: namespacing. Strip the tensorzero:: and model_name:: prefixes, and convert the provider::model double-colon to a provider/model slash. A function_name reference has no model string, so use the model its winning variant resolved to (see Step 4). One thing to know about the slashed form: the prefix is the provider that serves the request, not the model’s author. TensorZero’s provider shorthand (e.g. gcp_vertex_anthropic) already encodes the serving provider, so you just rename the prefix. For most popular names author and provider match (openai, anthropic, mistral), but they diverge whenever a model is hosted by something other than its author: Bare slugs work in all of these cases. Use them when you don’t care which provider serves the request. Use the provider/ prefix when you specifically want to pin to one host (for ZDR compliance, contractual reasons, or latency in a specific region). To replace a configured model with provider fallbacks, use routing.model.fallbacks / routing.provider.fallbacks or model: "auto" (see Step 4). For the authoritative list of supported provider/model-id pairs, call GET /v1/models or browse the Model Fortress.

Step 6: Reconnect Observability

TensorZero bundles observability, optimization, evaluations, and experimentation alongside the gateway (backed by ClickHouse). Concentrate’s dashboard covers the gateway-side surfaces; the experimentation and optimization tooling has no direct equivalent.

Exporting your TensorZero history

Because TensorZero is self-hosted, your history lives in your own ClickHouse database and does not import into Concentrate. If your migration is compliance- or audit-driven, snapshot that data before tearing down the gateway.

Step 7 (Optional): Adopt the Responses API

If you used TensorZero’s native /inference endpoint or its episodes, Concentrate’s native Responses API is the closest successor: streaming, tool calling, structured output, multi-modal input, and web search through one normalized shape across every provider, with previous_response_id replacing episode_id-grouped sessions.

Why migrate to Concentrate

TensorZero is a self-hosted gateway configured by tensorzero.toml, exposing several surfaces on one host. Migrating retires the process and config file and collapses every surface onto Concentrate’s single hosted base URL https://api.concentrate.ai/v1.The native /inference endpoint is Responses-style (typed input, multi-step episodes). Its closest one-to-one target is Concentrate’s Responses API, reachable from the standard OpenAI SDK or any HTTP client.
TensorZero is a process you deploy, scale, and keep alive, with tensorzero.toml and provider credentials to maintain. Concentrate is hosted, with no gateway to operate, no config to version, and credentials managed for you.
Concentrate organizes billing around an organization → team → developer → key hierarchy. Set budgets at any level and roll spend up into a single dashboard. Per-team budgets and per-developer attribution come from the key itself, so there’s no per-request tags tagging to maintain.
Beyond ordered model and provider fallbacks (routing.model.fallbacks, routing.provider.fallbacks), Concentrate’s routing layer ships:
  • Uptime gate. Providers whose per-feature success rate drops below 90% are skipped.
  • Feature degradation. If no provider supports the full requested feature set (e.g. json_schema), the request is downgraded to json_object or text instead of failing.
  • Cache-affinity routing. When multiple providers can serve a request, the one where your actor already has cached tokens is preferred.
All on by default. No variants or tensorzero.toml to author, name, or version.
model: "auto" accepts an explicit optimization target via routing.model.sort: cost, latency, or performance (default). See Auto Routing. This replaces hand-authoring a configured model with provider fallbacks in tensorzero.toml.
Like TensorZero’s native /inference endpoint, Concentrate exposes a first-class Responses API. Alongside it you also get OpenAI Chat Completions compatibility and an Anthropic-compatible Messages API.
Concentrate manages provider credentials by default — point at a model and Concentrate owns the upstream credentials. And if you want to keep using the provider keys you wired into tensorzero.toml (or TensorZero’s per-request credentials param), store them once in the dashboard with free BYOK — no gateway config to maintain.

Troubleshooting

Strip the tensorzero:: and model_name:: prefixes and convert the provider::model double-colon to provider/model (e.g. tensorzero::model_name::openai::gpt-4oopenai/gpt-4o). Bare slugs (gpt-4o, claude-haiku-4-5) work too. If you’re using a provider/ prefix and getting a miss, double-check the prefix is a provider (e.g. bedrock, azure, ai-studio) and not just the author (e.g. meta, google). Call GET /v1/models for the authoritative list.
Concentrate keys start with sk-cn-v1-. TensorZero’s OpenAI-compatible endpoint ignored the client key, so your code may have been sending a placeholder (or a sk-t0-... gateway key). Concentrate requires a real sk-cn-v1-... key on every request. Verify the value in your dashboard and confirm there are no extra spaces or quotes.
Confirm the base URL is https://api.concentrate.ai/v1, not localhost:3000. If the client is still pointed at your self-hosted gateway it is logging against your own ClickHouse store, not Concentrate.
tensorzero::function_name::... and tensorzero::variant_name are no-ops on Concentrate; there is no function/variant config. Pin a model with model: "provider/model-id", express fallbacks via routing.model.fallbacks / routing.provider.fallbacks, or use model: "auto". Move function prompt templates into application code. Variant A/B sampling and the /feedback loop have no per-request equivalent, so handle the split in application code.
Concentrate has no episode_id body field or /feedback endpoint. Link related requests with previous_response_id on the Responses API. Evaluation feedback that fed TensorZero’s optimization stack should stay in your own tooling.
Concentrate uses provider-native prompt caching, currently supported on Anthropic and AWS Bedrock. There is no gateway-stored cache and no max_age_s control, so TensorZero’s cache_options does not carry over directly. Caches are seeded per API key by default; pass prompt_cache_key in the request body if you want to set the seed explicitly.
Confirm the base URL is https://api.concentrate.ai/v1 (no /api segment, no /openai/v1 or /inference suffix, no localhost:3000). Test the connection manually:

Next Steps

API Reference

Explore the full API capabilities

Available Models

Browse all supported models

Auto Routing

Optimize model selection automatically

Get Support

Contact our support team

Feedback

If you hit anything that didn’t translate cleanly (especially around functions, variants, episodes, the feedback/experimentation loop, cache_options, or OTLP trace export), email support@concentrate.ai. The capability gaps called out above are tracked, and migration friction reports directly shape what we ship next.