Adjust reasoning effort
Set effort in each protocol and read actual thinking token usage.
The same “low” setting uses different fields in Chat, Messages, and Google. Choose a supported protocol and level, then inspect usage. Effort is a hint; actual consumption comes from usage.
Choose a protocol and level
Open Console → Models, select a model, and find “协议与思考档位” (Protocols and reasoning levels). Expected: supported APIs and thinking options are visible. If disabling is not offered, do not send a setting that disables thinking.
Confirm protocols with supported_apis from GET /model/v1/models. For programmatic Chat checks, use reasoning.supported_efforts and reasoning.mandatory from GET /openai/v1/models?api=chat. On October 13, 2026, the Chat catalog marked glm-5.3, glm-5.3-flash, and kimi-k3 as mandatory=true: thinking cannot be disabled. Recheck the catalog before calling. Not every model supports every level. The usage fields below were returned by the models used here; other models may omit them.
| API | Thinking control | Usage read in this guide |
|---|---|---|
| Chat Completions | reasoning_effort; also accepts a reasoning object | usage.completion_tokens_details.reasoning_tokens |
| Anthropic Messages | thinking selects the mode; output_config.effort selects the level | usage.output_tokens_details.thinking_tokens |
| Google generateContent | thinkingBudget or thinkingLevel inside generationConfig.thinkingConfig | usageMetadata.thoughtsTokenCount |
Chat levels range from none to max, subject to model support. none disables thinking; it does not mean “low.” Messages uses enabled, adaptive, and disabled for budgeted, adaptive, and disabled thinking. The effort field is not thinking.effort. Google budget and level controls depend on the model; do not send both together.
See the field definitions for Chat, Messages, and Google.
1. Prepare your terminal
Use Python 3.10+ and uv. Put your Praxis cloud API Key in PRAXIS_API_KEY; do not put it in source code or logs.
test -n "$PRAXIS_API_KEY"Expected: exit code 0. Exit code 1 means the variable is missing. Examples default to https://api.deepraxis.com. To switch environments, set PRAXIS_API_BASE to the API origin without a trailing slash or API path.
2. Chat: select low and read usage
deepseek-flash supports Chat and low.
Save as reasoning-chat.py and run uv run -q --no-project --with openai --with anthropic --with google-genai python reasoning-chat.py.
import os
from openai import OpenAI
client = OpenAI(api_key=os.environ['PRAXIS_API_KEY'],
base_url=os.environ.get('PRAXIS_API_BASE', 'https://api.deepraxis.com') + '/openai/v1')
response = client.chat.completions.create(
model='deepseek-flash', reasoning_effort='low', max_tokens=2048,
messages=[{'role': 'user', 'content': 'What is 17 times 23? Answer briefly.'}])
assert response.choices[0].finish_reason == 'stop'
assert '391' in (response.choices[0].message.content or '')
details = response.usage.completion_tokens_details
assert details is not None and details.reasoning_tokens is not None, 'Reasoning usage was not reported'
print('X-Request-Id:', response._request_id)
print('answer:', response.choices[0].message.content)
print('reasoning_tokens:', details.reasoning_tokens)Expected: the answer contains 391, the finish reason is stop, and the script prints actual reasoning_tokens. Exit code 0. Counts vary between calls.
3. Messages: select low and read usage
This example uses claude-opus-5 because it returned thinking token details during verification. The Messages response from deepseek-flash omitted them. Missing is not zero; output_tokens is not a substitute.
Save as reasoning-messages.py and run uv run -q --no-project --with openai --with anthropic --with google-genai python reasoning-messages.py.
import os
from anthropic import Anthropic
client = Anthropic(api_key=os.environ['PRAXIS_API_KEY'],
base_url=os.environ.get('PRAXIS_API_BASE', 'https://api.deepraxis.com') + '/anthropic')
raw = client.messages.with_raw_response.create(
model='claude-opus-5', max_tokens=2048,
thinking={'type': 'adaptive'}, output_config={'effort': 'low'},
messages=[{'role': 'user', 'content': 'What is 17 times 23? Answer briefly.'}])
response = raw.parse()
answer = ''.join(block.text for block in response.content if block.type == 'text')
assert response.stop_reason == 'end_turn' and '391' in answer
usage = response.usage.model_dump()
details = usage.get('output_tokens_details') or {}
assert details.get('thinking_tokens') is not None, 'Thinking usage was not reported'
print('X-Request-Id:', raw.headers.get('x-request-id'))
print('answer:', answer)
print('thinking_tokens:', details['thinking_tokens'])Expected: the answer contains 391, the stop reason is end_turn, and the script prints actual thinking_tokens. Exit code 0.
4. Google: select a budget or level by model
This calls two models: gemini-2.5-flash with a budget, then gemini-3.1-flash-lite-preview with low effort. HTTP exposes Google's field names directly.
Save as reasoning-google.py and run uv run -q --no-project --with openai --with anthropic --with google-genai python reasoning-google.py.
import json
import os
import httpx
base = os.environ.get('PRAXIS_API_BASE', 'https://api.deepraxis.com')
with httpx.Client(timeout=120) as client:
for model, thinking in [
('gemini-2.5-flash', {'thinkingBudget': 1024}),
('gemini-3.1-flash-lite-preview', {'thinkingLevel': 'low'}),
]:
response = client.post(base + '/google/v1beta/models/' + model + ':generateContent',
headers={'Authorization': 'Bearer ' + os.environ['PRAXIS_API_KEY']},
json={'contents': [{'role': 'user', 'parts': [{'text': 'What is 17 times 23? Answer briefly.'}]}],
'generationConfig': {'maxOutputTokens': 2048, 'thinkingConfig': thinking}})
print('X-Request-Id:', response.headers.get('x-request-id'))
response.raise_for_status()
data = response.json()
candidate = data['candidates'][0]
answer = ''.join(part.get('text', '') for part in candidate['content']['parts'])
assert candidate['finishReason'] == 'STOP' and '391' in answer
assert 'thoughtsTokenCount' in data['usageMetadata'], 'Thinking usage was not reported'
print(model, answer, json.dumps(data['usageMetadata']))Expected: both answers contain 391, both finish reasons are STOP, and each prints thoughtsTokenCount. Exit code 0.
Compare results
Keep the model and question constant. Sample multiple calls and compare actual thinking tokens, complete answers, latency, and quality. A budget is not a universal hard cap across models. “Low” does not guarantee fewer tokens than “high” on every call or faster responses. Do not infer a monotonic relationship from one response. Preserve missing usage as “not reported,” never zero.
Observed failure and recovery
Setting reasoning_effort="none" on glm-5.3 returned HTTP 400 with code thinking_disable_unsupported:
glm-5.3 cannot disable thinking; omit the thinking setting or choose a level.
Omit the disabling setting or choose a supported level, then retry. Changing to another protocol's disabling field does not remove this restriction.