- Core Concepts
- Thinking (Reasoning)
Core Concepts
Thinking (Reasoning)
Enable models to reason step-by-step before answering
Pass a thinking object on your message to let the model reason before responding. Omit it or set null to disable. Pass {} for provider defaults.
thinking is a per-turn parameter — pass it on every call where you want reasoning enabled.
import requests
headers = {"X-API-Key": "YOUR_API_KEY"}
thread_id = "your-thread-id"
response = requests.post(
"https://app.backboard.io/api/threads/messages",
headers=headers,
json={
"thread_id": thread_id,
"content": "A driver was going the wrong way down a one-way street. He passed several police officers, but they did not stop him. Why? Think step by step.",
"thinking": {"effort": "high"},
"llm_provider": "openai",
"model_name": "o3",
"stream": False
}
)
result = response.json()
print(result["reasoning"])
print(result["content"])
Fields
| Field | Type | Description |
|---|---|---|
effort | string | Reasoning depth: low, medium, high, or max |
budget_tokens | integer | Max tokens for internal reasoning |
max_tokens | integer | Max tokens for reasoning output |
exclude_reasoning | boolean | Omit reasoning traces from response |
Provider Support
| Provider | Supported Fields | Example |
|---|---|---|
| OpenAI | effort | {"effort": "high"} |
| Anthropic | effort, budget_tokens | {"effort": "high"} |
| AWS Bedrock | effort, budget_tokens | {"effort": "high"} |
| Google (Gemini 2.5) | budget_tokens | {"budget_tokens": 8192} |
| Google (Gemini 3) | effort | {"effort": "high"} |
| xAI | effort | {"effort": "high"} |
| OpenRouter | max_tokens, exclude_reasoning | {"max_tokens": 4096} |
| Cerebras | max_tokens, exclude_reasoning | {"max_tokens": 4096} |
Provider Details
OpenAI: Models: o1, o3, o4, gpt-5 series. Default effort: medium.
Anthropic: Claude Opus 4.7 and newer (including Opus 5 and Fable 5) use adaptive thinking — pass effort (low, medium, high, max); budget_tokens is not accepted for these models. Older models (Claude 3.7 Sonnet, Sonnet 4, Opus 4–4.6) use budget_tokens (min 1,024). Backboard routes to the correct mode automatically.
AWS Bedrock: Bedrock-hosted Anthropic Claude models. Claude Opus 4.7 and newer (including Opus 5 and Fable 5) use adaptive thinking — pass effort; budget_tokens is rejected for these models. Older Bedrock Claude models accept budget_tokens (min 1,024) or effort. Backboard routes to the correct mode automatically.
Google (Gemini 2.5): Max budget: 32,768 (Pro) / 24,576 (others).
Google (Gemini 3): Uses effort (low through max). Thinking is on by default.
xAI: Reasoning models — grok-4.3 and its aliases grok-latest, grok-3*, grok-4*, grok-4-fast-reasoning, grok-4-1-fast-reasoning, grok-3-mini* — accept effort (low, medium, high, max); max maps to xAI’s highest level. Omit thinking to avoid setting a Backboard control (xAI’s own default is low); pass {} for Backboard’s default medium. The *-non-reasoning variants do not support effort.
OpenRouter / Cerebras: Use max_tokens (int > 0) and exclude_reasoning (bool).
Best for complex tasks: math, code generation, multi-step reasoning, analysis.
Thinking uses extra tokens and adds latency. Skip it for simple questions.
Non-Streaming Examples
Replace YOUR_API_KEY and thread_id with your values.
OpenAI
import requests
headers = {"X-API-Key": "YOUR_API_KEY"}
thread_id = "your-thread-id"
response = requests.post(
"https://app.backboard.io/api/threads/messages",
headers=headers,
json={
"thread_id": thread_id,
"content": "A driver was going the wrong way down a one-way street. He passed several police officers, but they did not stop him. Why? Think step by step.",
"thinking": {"effort": "high"},
"llm_provider": "openai",
"model_name": "o3",
"stream": False
}
)
result = response.json()
print(result["reasoning"])
print(result["content"])
Anthropic
Use effort for Claude Opus 4.7+ (adaptive thinking). Use budget_tokens for older models.
response = requests.post(
"https://app.backboard.io/api/threads/messages",
headers=headers,
json={
"thread_id": thread_id,
"content": "A driver was going the wrong way down a one-way street. He passed several police officers, but they did not stop him. Why? Think step by step.",
"thinking": {"effort": "high"},
"llm_provider": "anthropic",
"model_name": "claude-opus-4-7-20250501",
"stream": False
}
)
result = response.json()
print(result["reasoning"])
print(result["content"])
AWS Bedrock
Use effort for Claude Opus 4.7+ on Bedrock. Use budget_tokens for older Bedrock Claude models.
response = requests.post(
"https://app.backboard.io/api/threads/messages",
headers=headers,
json={
"thread_id": thread_id,
"content": "A driver was going the wrong way down a one-way street. He passed several police officers, but they did not stop him. Why? Think step by step.",
"thinking": {"effort": "high"},
"llm_provider": "aws-bedrock",
"model_name": "anthropic.claude-opus-4-7",
"stream": False
}
)
result = response.json()
print(result["reasoning"])
print(result["content"])
Google (Gemini 2.5)
response = requests.post(
"https://app.backboard.io/api/threads/messages",
headers=headers,
json={
"thread_id": thread_id,
"content": "A driver was going the wrong way down a one-way street. He passed several police officers, but they did not stop him. Why? Think step by step.",
"thinking": {"budget_tokens": 8192},
"llm_provider": "google",
"model_name": "gemini-2.5-pro",
"stream": False
}
)
result = response.json()
print(result["reasoning"])
print(result["content"])
Google (Gemini 3)
response = requests.post(
"https://app.backboard.io/api/threads/messages",
headers=headers,
json={
"thread_id": thread_id,
"content": "A driver was going the wrong way down a one-way street. He passed several police officers, but they did not stop him. Why? Think step by step.",
"thinking": {"effort": "high"},
"llm_provider": "google",
"model_name": "gemini-3.1-pro-preview",
"stream": False
}
)
result = response.json()
print(result["reasoning"])
print(result["content"])
xAI
response = requests.post(
"https://app.backboard.io/api/threads/messages",
headers=headers,
json={
"thread_id": thread_id,
"content": "A driver was going the wrong way down a one-way street. He passed several police officers, but they did not stop him. Why? Think step by step.",
"thinking": {"effort": "high"},
"llm_provider": "xai",
"model_name": "grok-4.3",
"stream": False
}
)
result = response.json()
print(result["reasoning"])
print(result["content"])
OpenRouter
response = requests.post(
"https://app.backboard.io/api/threads/messages",
headers=headers,
json={
"thread_id": thread_id,
"content": "A driver was going the wrong way down a one-way street. He passed several police officers, but they did not stop him. Why? Think step by step.",
"thinking": {"max_tokens": 4096},
"llm_provider": "openrouter",
"model_name": "minimax/minimax-m1",
"stream": False
}
)
result = response.json()
print(result["reasoning"])
print(result["content"])
Cerebras
response = requests.post(
"https://app.backboard.io/api/threads/messages",
headers=headers,
json={
"thread_id": thread_id,
"content": "A driver was going the wrong way down a one-way street. He passed several police officers, but they did not stop him. Why? Think step by step.",
"thinking": {},
"llm_provider": "cerebras",
"model_name": "z-ai/glm-4.7",
"stream": False
}
)
result = response.json()
print(result["reasoning"])
print(result["content"])
Streaming Examples
Same as above but with "stream": True. The model thinks first, then streams the response. All Python examples below assume import json, requests and headers/thread_id are already set (see the non-streaming section above).
OpenAI
response = requests.post(
"https://app.backboard.io/api/threads/messages",
headers=headers,
json={
"thread_id": thread_id,
"content": "A driver was going the wrong way down a one-way street. He passed several police officers, but they did not stop him. Why? Think step by step.",
"thinking": {"effort": "high"},
"llm_provider": "openai",
"model_name": "o3",
"stream": True
},
stream=True
)
for line in response.iter_lines():
if line:
decoded = line.decode()
if decoded.startswith("data: "):
event = json.loads(decoded[6:])
t = event.get("type")
if t == "reasoning_streaming":
print(event.get("content", ""), end="", flush=True)
elif t == "reasoning_ended":
print("\n---------Reasoning Ended, Response Started---------")
elif t == "content_streaming":
print(event.get("content", ""), end="", flush=True)
Anthropic
response = requests.post(
"https://app.backboard.io/api/threads/messages",
headers=headers,
json={
"thread_id": thread_id,
"content": "A driver was going the wrong way down a one-way street. He passed several police officers, but they did not stop him. Why? Think step by step.",
"thinking": {"effort": "high"},
"llm_provider": "anthropic",
"model_name": "claude-opus-4-7-20250501",
"stream": True
},
stream=True
)
for line in response.iter_lines():
if line:
decoded = line.decode()
if decoded.startswith("data: "):
event = json.loads(decoded[6:])
t = event.get("type")
if t == "reasoning_streaming":
print(event.get("content", ""), end="", flush=True)
elif t == "reasoning_ended":
print("\n---------Reasoning Ended, Response Started---------")
elif t == "content_streaming":
print(event.get("content", ""), end="", flush=True)
AWS Bedrock
response = requests.post(
"https://app.backboard.io/api/threads/messages",
headers=headers,
json={
"thread_id": thread_id,
"content": "A driver was going the wrong way down a one-way street. He passed several police officers, but they did not stop him. Why? Think step by step.",
"thinking": {"effort": "high"},
"llm_provider": "aws-bedrock",
"model_name": "anthropic.claude-opus-4-7",
"stream": True
},
stream=True
)
for line in response.iter_lines():
if line:
decoded = line.decode()
if decoded.startswith("data: "):
event = json.loads(decoded[6:])
t = event.get("type")
if t == "reasoning_streaming":
print(event.get("content", ""), end="", flush=True)
elif t == "reasoning_ended":
print("\n---------Reasoning Ended, Response Started---------")
elif t == "content_streaming":
print(event.get("content", ""), end="", flush=True)
Google (Gemini 2.5)
response = requests.post(
"https://app.backboard.io/api/threads/messages",
headers=headers,
json={
"thread_id": thread_id,
"content": "A driver was going the wrong way down a one-way street. He passed several police officers, but they did not stop him. Why? Think step by step.",
"thinking": {"budget_tokens": 8192},
"llm_provider": "google",
"model_name": "gemini-2.5-pro",
"stream": True
},
stream=True
)
for line in response.iter_lines():
if line:
decoded = line.decode()
if decoded.startswith("data: "):
event = json.loads(decoded[6:])
t = event.get("type")
if t == "reasoning_streaming":
print(event.get("content", ""), end="", flush=True)
elif t == "reasoning_ended":
print("\n---------Reasoning Ended, Response Started---------")
elif t == "content_streaming":
print(event.get("content", ""), end="", flush=True)
Google (Gemini 3)
response = requests.post(
"https://app.backboard.io/api/threads/messages",
headers=headers,
json={
"thread_id": thread_id,
"content": "A driver was going the wrong way down a one-way street. He passed several police officers, but they did not stop him. Why? Think step by step.",
"thinking": {"effort": "high"},
"llm_provider": "google",
"model_name": "gemini-3.1-pro-preview",
"stream": True
},
stream=True
)
for line in response.iter_lines():
if line:
decoded = line.decode()
if decoded.startswith("data: "):
event = json.loads(decoded[6:])
t = event.get("type")
if t == "reasoning_streaming":
print(event.get("content", ""), end="", flush=True)
elif t == "reasoning_ended":
print("\n---------Reasoning Ended, Response Started---------")
elif t == "content_streaming":
print(event.get("content", ""), end="", flush=True)
xAI
response = requests.post(
"https://app.backboard.io/api/threads/messages",
headers=headers,
json={
"thread_id": thread_id,
"content": "A driver was going the wrong way down a one-way street. He passed several police officers, but they did not stop him. Why? Think step by step.",
"thinking": {"effort": "high"},
"llm_provider": "xai",
"model_name": "grok-4.3",
"stream": True
},
stream=True
)
for line in response.iter_lines():
if line:
decoded = line.decode()
if decoded.startswith("data: "):
event = json.loads(decoded[6:])
t = event.get("type")
if t == "reasoning_streaming":
print(event.get("content", ""), end="", flush=True)
elif t == "reasoning_ended":
print("\n---------Reasoning Ended, Response Started---------")
elif t == "content_streaming":
print(event.get("content", ""), end="", flush=True)
OpenRouter
response = requests.post(
"https://app.backboard.io/api/threads/messages",
headers=headers,
json={
"thread_id": thread_id,
"content": "A driver was going the wrong way down a one-way street. He passed several police officers, but they did not stop him. Why? Think step by step.",
"thinking": {"max_tokens": 4096},
"llm_provider": "openrouter",
"model_name": "minimax/minimax-m1",
"stream": True
},
stream=True
)
for line in response.iter_lines():
if line:
decoded = line.decode()
if decoded.startswith("data: "):
event = json.loads(decoded[6:])
t = event.get("type")
if t == "reasoning_streaming":
print(event.get("content", ""), end="", flush=True)
elif t == "reasoning_ended":
print("\n---------Reasoning Ended, Response Started---------")
elif t == "content_streaming":
print(event.get("content", ""), end="", flush=True)
Cerebras
response = requests.post(
"https://app.backboard.io/api/threads/messages",
headers=headers,
json={
"thread_id": thread_id,
"content": "A driver was going the wrong way down a one-way street. He passed several police officers, but they did not stop him. Why? Think step by step.",
"thinking": {},
"llm_provider": "cerebras",
"model_name": "z-ai/glm-4.7",
"stream": True
},
stream=True
)
for line in response.iter_lines():
if line:
decoded = line.decode()
if decoded.startswith("data: "):
event = json.loads(decoded[6:])
t = event.get("type")
if t == "reasoning_streaming":
print(event.get("content", ""), end="", flush=True)
elif t == "reasoning_ended":
print("\n---------Reasoning Ended, Response Started---------")
elif t == "content_streaming":
print(event.get("content", ""), end="", flush=True)
Check Model Support
import requests
models = requests.get(
"https://app.backboard.io/api/models",
headers={"X-API-Key": "YOUR_API_KEY"},
params={"supports_thinking": True, "model_type": "llm"}
).json()
for m in models["models"]:
print(f"{m['provider']}/{m['name']}")
See Models for details.