Create a message (Anthropic Messages API)
The Anthropic Messages API on the node's own model, so Anthropic SDKs and agents built on them run against it with only the base URL and the credential changed: set `ANTHROPIC_BASE_URL` (or `base_url`) to `https://beta-api.b3os.org/v1/infer`, the same base URL as the OpenAI SDKs (`http://127.0.0.1:7700/v1/infer` inside a sandbox; the SDKs add `/v1/messages`), and send the B3OS key as a bearer token (`ANTHROPIC_AUTH_TOKEN`, or `auth_token` in the SDKs). Text, images (`base64`, or `url` sources fetched by the node through its egress guard), custom tools with `tool_use` and `tool_result` blocks, `tool_choice`, `thinking` (the reasoning arrives in `thinking` blocks; `budget_tokens` caps it), JSON Schema output through `output_config.format`, stop sequences, a trailing assistant turn that the model continues, and streaming events (`message_start` ... `message_stop`, exactly as Anthropic sends them). Models are those of `GET /v1/infer/models`; there is no gateway route here. Parameters this node does not take return `400 unsupported_parameter` (tools Anthropic defines or runs, such as `web_search` or `bash`, `container`, `mcp_servers`, document and file sources). `cache_control`, `citations`, `metadata`, `service_tier`, `output_config.effort` and `thinking.display` are accepted and ignored (the runtime caches prompt prefixes on its own). Errors use the Anthropic shape (`{"type": "error", "error": {...}}`, with the B3OS code under `b3os`), except those raised before the request reaches the infer service (authentication, scopes, body size), which use the OpenAI shape of the rest of `/v1/infer`; Anthropic SDKs map both by HTTP status. A stream that fails after it started ends with an `error` event; one that fails before the first token is a plain HTTP error. The response head of a stream waits for the first generated token, so `Server-Timing` can carry `ttft`. Bills input and output tokens, with the admission and limits of chat completions (the estimated prompt plus `max_tokens`, settled with the real counts; an abandoned stream is billed to its last token).
/v1/infer/v1/messages
Authentication
Request Body required
application/jsonmodel
string
REQUIRED
messages
(object | object)[]
REQUIRED
role
string
REQUIRED
usercontent
string | (object | object | object)[]
REQUIRED
role
string
REQUIRED
assistantcontent
string | (object | object | object | object)[]
REQUIRED
max_tokens
integer
REQUIRED
system
string | null | object[]
type
string
REQUIRED
texttext
string
REQUIRED
cache_control
object | null
type
string
ttl
string
citations
object[] | null
tools
object[] | null
type
string | null
custom, nullname
string
REQUIRED
description
string | null
input_schema
object
REQUIRED
strict
boolean | null
cache_control
object | null
type
string
ttl
string
tool_choice
object | object | object | null
type
string
REQUIRED
auto, anydisable_parallel_tool_use
boolean | null
type
string
REQUIRED
toolname
string
REQUIRED
disable_parallel_tool_use
boolean | null
type
string
REQUIRED
nonethinking
object | object | object | null
type
string
REQUIRED
enabledbudget_tokens
integer
REQUIRED
display
string | null
summarized, omitted, updates, nulltype
string
REQUIRED
adaptivedisplay
string | null
summarized, omitted, updates, nulltype
string
REQUIRED
disabledoutput_config
object | null
format
object | null
type
string
REQUIRED
json_schemaschema
object
REQUIRED
effort
string | null
low, medium, high, xhigh, max, nullstop_sequences
string[] | null
stream
boolean | null
temperature
number | null
top_p
number | null
top_k
integer | null
metadata
object | null
user_id
string | null
service_tier
string | null
Responses
application/jsonid
string
REQUIRED
type
string
REQUIRED
messagerole
string
REQUIRED
assistantcontent
object[]
REQUIRED
type
string
REQUIRED
text, tool_use, thinkingtext
string
id
string
name
string
input
object
thinking
string
signature
string
model
string
REQUIRED
stop_reason
string
REQUIRED
end_turn, max_tokens, stop_sequence, tool_use, refusalstop_sequence
string | null
REQUIRED
usage
object
REQUIRED
input_tokens
integer
REQUIRED
output_tokens
integer
REQUIRED
b3os
object
route
string
local, gatewaynode
string
timing
object
ttft_ms
number
model_ms
number
total_ms
number
curl -X POST 'https://beta-api.b3os.org/v1/infer/v1/messages' \ -H 'Authorization: Bearer YOUR_API_TOKEN' \ -H 'Content-Type: application/json' \ -d '{ "model": "string", "messages": [ { "role": "user", "content": "string" } ], "max_tokens": 1, "system": "string", "tools": [ { "type": "custom", "name": "string", "description": "string", "input_schema": {}, "strict": true, "cache_control": { "type": "string", "ttl": "string" } } ], "tool_choice": {}, "thinking": {}, "output_config": { "format": { "type": "json_schema", "schema": {} }, "effort": "low" }, "stop_sequences": [ "string" ], "stream": true, "temperature": 0, "top_p": 0, "top_k": 1, "metadata": { "user_id": "string" }, "service_tier": "string"}'
const response = await fetch('https://beta-api.b3os.org/v1/infer/v1/messages', { method: 'POST', headers: { "Authorization": "Bearer YOUR_API_TOKEN", "Content-Type": "application/json" }, body: JSON.stringify({ "model": "string", "messages": [ { "role": "user", "content": "string" } ], "max_tokens": 1, "system": "string", "tools": [ { "type": "custom", "name": "string", "description": "string", "input_schema": {}, "strict": true, "cache_control": { "type": "string", "ttl": "string" } } ], "tool_choice": {}, "thinking": {}, "output_config": { "format": { "type": "json_schema", "schema": {} }, "effort": "low" }, "stop_sequences": [ "string" ], "stream": true, "temperature": 0, "top_p": 0, "top_k": 1, "metadata": { "user_id": "string" }, "service_tier": "string" })});const data = await response.json();console.log(data);
import requestsheaders = { 'Authorization': 'Bearer YOUR_API_TOKEN'}response = requests.post('https://beta-api.b3os.org/v1/infer/v1/messages', headers=headers, json={ "model": "string", "messages": [ { "role": "user", "content": "string" } ], "max_tokens": 1, "system": "string", "tools": [ { "type": "custom", "name": "string", "description": "string", "input_schema": {}, "strict": true, "cache_control": { "type": "string", "ttl": "string" } } ], "tool_choice": {}, "thinking": {}, "output_config": { "format": { "type": "json_schema", "schema": {} }, "effort": "low" }, "stop_sequences": [ "string" ], "stream": true, "temperature": 0, "top_p": 0, "top_k": 1, "metadata": { "user_id": "string" }, "service_tier": "string"})print(response.json())
{ "id": "msg_9f1c2a7e4b5d4e0f8a6b3c2d1e0f9a8b", "type": "message", "role": "assistant", "model": "b3os/qwen3.5-9b", "content": [ { "type": "tool_use", "id": "chatcmpl-tool-7f3a", "name": "get_weather", "input": { "city": "Eugene" } } ], "stop_reason": "tool_use", "stop_sequence": null, "usage": { "input_tokens": 61, "output_tokens": 18 }, "b3os": { "route": "local", "node": "n1" }}
Try this endpoint
/v1/infer/v1/messages