/v1/infer also speaks the Anthropic Messages API, on the same model as the OpenAI routes. The Anthropic SDKs work with two changes: the base URL, and your B3OS key as the credential.

Where your code runsBase URLKey
Anywherehttps://beta-api.b3os.org/v1/inferYour B3OS key
Inside a B3OS sandboxhttp://127.0.0.1:7700/v1/inferNot checked; pass any string

The SDKs add /v1/messages, so requests go to /v1/infer/v1/messages. The key works as a bearer token (ANTHROPIC_AUTH_TOKEN, authToken, auth_token) and as x-api-key (ANTHROPIC_API_KEY), so SDK releases that send either header authenticate.

bash
export ANTHROPIC_BASE_URL="https://beta-api.b3os.org/v1/infer"export ANTHROPIC_AUTH_TOKEN="$B3OS_API_KEY"export B3OS_MODEL=$(curl -s https://beta-api.b3os.org/v1/infer/models \ -H "Authorization: Bearer $B3OS_API_KEY" | jq -r '[.data[] | select(.b3os.kind == "chat")][0].id')
bash
curl -s https://beta-api.b3os.org/v1/infer/v1/messages \ -H "Authorization: Bearer $B3OS_API_KEY" \ -H "anthropic-version: 2023-06-01" \ -H "Content-Type: application/json" \ -d "{\"model\": \"$B3OS_MODEL\", \"max_tokens\": 256, \"messages\": [{\"role\": \"user\", \"content\": \"Name one river in Oregon.\"}]}"

Messages shows streaming, tools and thinking with both SDKs.

Request fields

Supported

FieldOn this node
model, max_tokensBoth required. max_tokens caps the answer, and admission reserves it against your token limit
messagestext, image (base64, or a url source the node fetches through its egress guard), tool_use, tool_result and thinking blocks. A trailing assistant turn that ends in text is continued
systemA string or text blocks, joined with blank lines
tools, tool_choiceCustom tools (name, description, input_schema, strict), up to 128; tool_choice auto, any, tool or none, with disable_parallel_tool_use
thinkingenabled with budget_tokens (from 1,024, below max_tokens), adaptive or disabled. The reasoning comes back in thinking blocks
output_config.formatJSON Schema output (json_schema)
stop_sequencesUp to 4
temperature, top_p, top_kPassed to the model's runtime (temperature and top_p from 0 to 1). Older SDK releases and agents still send them, so they are kept
streamThe Messages event stream, message_start to message_stop

POST /v1/infer/v1/messages/count_tokens counts a request's input tokens with the model's own chat template, for free.

Accepted and ignored

FieldWhy
cache_control, on any block or toolThe runtime caches prompt prefixes on its own, per organization
context_managementNothing is cleared from the conversation: the model sees every turn you send (see long sessions)
citations on text blocks, metadata.user_id, service_tierNo effect on this node
output_config.effortNo effect; thinking controls the reasoning
thinking.displayThe reasoning is always returned

Refused with 400 and the B3OS code unsupported_parameter, naming the field

FieldWhy
Tools Anthropic defines or runs (web_search, bash, code_execution, computer, text_editor and the like)The node runs custom tools only
mcp_servers, containerNot available on this node
document blocks and file sources (the Files API)Send text, or the image as base64 or a URL
Any other fieldThe request is closed, as Anthropic refuses extra inputs

A system message inside messages is refused too (400, invalid_request): instructions go in the top-level system.

Errors

Errors use Anthropic's shape, {"type": "error", "error": {"type", "message"}}, with the B3OS code and the offending field under b3os. That holds for errors raised before the request reaches the model service too (authentication, scopes, body size), on the node and at the edge, so the SDKs raise the same exception classes they raise for Anthropic's API. Nothing maps another provider's model name to the node's model, so code that names a Claude model gets a 404:

bash
curl -s -X POST 'https://beta-api.b3os.org/v1/infer/v1/messages' \ -H "Authorization: Bearer $B3OS_API_KEY" \ -H 'content-type: application/json' \ -H 'anthropic-version: 2023-06-01' \ -d '{"model":"claude-sonnet-4-5","max_tokens":256,"messages":[{"role":"user","content":"Name one river in Oregon."}]}'

Captured 2026-10-31 from commit 6bd0d80a , label dev (recorded on a dev node before this reached production). Case infer/messages-unknown-model .

Status (error.type)When
400 invalid_request_errorA malformed value (invalid_request), a refused field, or a prompt longer than the model's context (context_length_exceeded)
401 authentication_errorNo key, or a key that is not valid
403 permission_errorA key without the infer:run scope, or an image URL on a private address (egress_denied)
404 not_found_errorA model the node does not serve (model_not_available); there is no gateway route here
429 rate_limit_errorOver your organization's tokens or requests per minute (rate_limited), with Retry-After
503 overloaded_errorThe model runtime is restarting or busy (infer_backend_unavailable), with Retry-After

Per-model token and request limits are on Infer limits.

json
{ "model": "b3os/qwen3.5-9b", "max_tokens": 256, "messages": [{ "role": "user", "content": "Name one river in Oregon." }]}

Try it in the playground

Opens the dashboard playground with this request filled in ( POST /v1/infer/v1/messages ). The link carries no key.

Ask a question... ⌘I