Anthropic SDK
The exchange serves Anthropic Messages, so the official Python and TypeScript clients work without changes. Set the origin of the exchange and your key.
Use this SDK for direct Messages API calls. To run Claude Code and its tools from your application, use the Claude Agent SDK.
Print the setup with the Liquid CLI
The Liquid CLI prints the setup for the Anthropic SDK with your model filled in. To run your own program with the exchange in its environment, use liquid exec. It sets OPENAI_BASE_URL, ANTHROPIC_BASE_URL and the keys for that process only.
curl -fsSL https://inference.ai.exchange/cli/install.sh | bash
liquid login
liquid connect anthropic-sdk
liquid exec -- python app.py
To set up the Anthropic SDK yourself, follow the steps below.
Before you start
-
A workspace with a balance and a
spendkey. See API keys. -
The key exported in your shell:
export LIQUID_API_KEY=sk-liquid-...
1. Point the client at the exchange
Use the origin without /v1, because this client adds /v1/messages itself. If the URL ends in /v1, the client requests /v1/v1/messages.
Python
import os
from anthropic import Anthropic
client = Anthropic(
base_url="https://router.inference.ai.exchange",
api_key=os.environ["LIQUID_API_KEY"],
)
client.messages.create(
model="liquid.auto",
max_tokens=1024,
messages=[{"role": "user", "content": "hello"}],
)
TypeScript
import Anthropic from '@anthropic-ai/sdk'
const client = new Anthropic({
baseURL: 'https://router.inference.ai.exchange',
apiKey: process.env.LIQUID_API_KEY,
})
const message = await client.messages.create({
model: 'liquid.auto',
max_tokens: 1024,
messages: [{ role: 'user', content: 'hello' }],
})
The client sends the key in the x-api-key header, which the exchange accepts. Use any model, router model or preset on the book. GET /v1/anthropic/models lists the names. See Market data.
2. Read the cap before the first token
The x-liquid-job-id and x-liquid-cap-usd headers arrive before any token. cap_usd is the maximum charge for the job.
Read the headers from the raw response: with_raw_response (Python) or .asResponse() (TypeScript).
3. Cache a prompt prefix
cache_control works as it does with Anthropic. Mark the last block of the prefix to cache. The exchange changes your markers into the cache plan of the job, for the winning provider.
client.messages.create(
model="liquid.auto",
max_tokens=1024,
system=[
{"type": "text", "text": "You are terse."},
{
"type": "text",
"text": long_reference_document,
"cache_control": {"type": "ephemeral", "ttl": "1h"},
},
],
messages=[{"role": "user", "content": "what changed in section 4?"}],
)
| Marked block | Becomes |
|---|---|
A block of system |
A breakpoint at the end of the system prompt |
| A tool definition | A breakpoint after the last tool |
| A block inside a turn | A breakpoint at the end of that turn |
Top-level cache_control |
A breakpoint after the last message |
Rules for breakpoints:
- Each breakpoint caches at least the prefix that you marked.
- The exchange sends four breakpoints at most. If there are more, it drops the shallowest, because a deeper one caches more of the prompt.
"ttl": "1h"asks for the one-hour write. All other values are five minutes. The exchange prices the two separately.- The price cap includes cache writes up to the deepest breakpoint, so a write cannot charge more than your cap.
The usage block reports cached input separately from fresh input:
{
"input_tokens": 412,
"cache_read_input_tokens": 10000,
"cache_creation_input_tokens": 0,
"output_tokens": 128
}
input_tokens counts only the input that the cache did not read or write, so the sum of the three does not count cached input two times.
If a request has no markers, the exchange places its own breakpoints. It does this only if both conditions are true:
- The request declares tools or continues a conversation.
- The estimated prompt is 512 tokens or more.
To keep only your own markers, or no markers, send exchange.cache.mode as buyer or off:
client.messages.create(
model="liquid.auto",
max_tokens=1024,
messages=[{"role": "user", "content": "hello"}],
extra_body={"exchange": {"cache": {"mode": "buyer"}}},
)
See Prompt caching for how the exchange places breakpoints, prices cached input, and keeps your cache separate from other buyers.
Limits and details
Output limit
The Anthropic format requires max_tokens.
- If no offer allows that many output tokens, the exchange lowers
max_tokensto the largest limit of the offers that can take the job. A longer answer then stops withstop_reason: "max_tokens". - The exchange does not lower
max_tokensto fit your balance or cap. It refuses the request instead. See Errors.
Hosted tools
The exchange does not run hosted tools.
- To search the web, add
:web(beta) to the model name. The exchange then removesweb_searchfrom the request and runs its own search. - It refuses a request with a tool such as
web_search,web_fetchorcode_execution. The error is400 unsupported_parameter, andparamistools[N]. - Send a tool with a name and an
input_schema, which your client runs. The typed client toolsbash,text_editor,computerandmemoryare accepted.
Reasoning blocks
The reasoning of a model comes back as thinking blocks before the answer. This is also true for models that are not Claude. Encrypted reasoning comes back as redacted_thinking.
- Send these blocks back unchanged, as the Anthropic API requires in a tool-use loop.
- A block from a model that does not sign its reasoning has an empty
signature. The exchange does not send that block to Claude.
Cost control
- To set a cost cap or service floor for each request, send the
exchangeblock in the body, or the same rules asx-liquid-*headers. See Purchasing rules. - To limit total spend across many requests, set a spending limit on the key. See API keys.
Next steps
- Prompt caching: breakpoints, retention and reporting.
- Modalities: send images and documents as content blocks.
- Claude Code: Anthropic's terminal agent, using this format.
- OpenAI SDK: the same idea in the OpenAI format.
- Purchasing rules: every field of the
exchangeblock.