The same models as the chat, from your own code. The API speaks OpenAI's format, so any OpenAI client, agent framework or tool works by changing two settings: the base URL and the key.
curl https://api.breadai.io/v1/chat/completions \
-H "Authorization: Bearer $BREAD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "bread-auto",
"messages": [{"role": "user", "content": "Summarise why bread rises in one sentence."}]
}'from openai import OpenAI
client = OpenAI(base_url="https://api.breadai.io/v1", api_key="bread_sk_...")
reply = client.chat.completions.create(
model="bread-auto", # the best model with a free host; or name one, e.g. bread-chat-27b
messages=[{"role": "user", "content": "Summarise why bread rises in one sentence."}],
)
print(reply.choices[0].message.content)import OpenAI from "openai";
const client = new OpenAI({ baseURL: "https://api.breadai.io/v1", apiKey: process.env.BREAD_API_KEY });
const stream = await client.chat.completions.create({
model: "bread-chat-8b",
messages: [{ role: "user", content: "Write a haiku about sourdough." }],
stream: true,
});
for await (const chunk of stream) process.stdout.write(chunk.choices[0]?.delta?.content ?? "");from openai import OpenAI
import json
client = OpenAI(base_url="https://api.breadai.io/v1", api_key="bread_sk_...")
tools = [{"type": "function", "function": {
"name": "get_weather",
"description": "Current weather for a city",
"parameters": {"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]},
}}]
messages = [{"role": "user", "content": "What's the weather in Sydney?"}]
reply = client.chat.completions.create(model="bread-chat-8b", messages=messages, tools=tools)
call = reply.choices[0].message.tool_calls[0]
args = json.loads(call.function.arguments) # {"city": "Sydney"}
result = {"temp": 22, "sky": "sunny"} # your code runs the tool, not BREAD
messages += [reply.choices[0].message, {"role": "tool", "tool_call_id": call.id, "content": json.dumps(result)}]
final = client.chat.completions.create(model="bread-chat-8b", messages=messages, tools=tools)
print(final.choices[0].message.content)reply = client.chat.completions.create(
model="bread-chat-8b",
response_format={"type": "json_object"},
messages=[{"role": "user", "content": "Classify: 'the crust was perfect'. Reply as JSON with sentiment and score."}],
)
data = json.loads(reply.choices[0].message.content) # {"sentiment": "positive", "score": 0.95}Prices are fixed in Australian cents and paid in BREAD at the live price, so the cost of a call doesn't move with the token.
Bigger models run on hosts with bigger cards; if none is online for a model you get a 503 at once, so try a smaller one or bread-auto. GET /v1/models lists every model with available, online_hosts and free_hosts right now. Every response carries the usual usage block plus a bread field with the job id and its cost in BREAD.
Unsupported options get a clear 400 error, never a silent wrong answer.
Tool calls come from independent GPU hosts. BREAD checks each one against the tools you declared, but treat them as untrusted input: confirm anything that moves money or deletes data. Hosts can see prompts and tool results, so don't send secrets.
Errors use OpenAI's format ({ error: { message, type, code } }), so SDKs handle them as usual.