Python
Because Serenity* Star exposes OpenAI-compatible endpoints for its self-hosted inference models, you can drive them with the official openai Python package. There is no Serenity-specific SDK to install, and once the client is configured everything else (streaming, client tools) works exactly as it does against OpenAI.
For more information about request and response shapes for the inference OpenAI-compatible endpoints, see the REST API reference.
Install
pip install openai
Configure the client
Two things differ from a plain OpenAI setup:
base_urlmust point at the inference path, including the model (for example.../inference/qwen/qwen3.6). With it set, the SDK appends/chat/completionsand/responsesfor you. Because the model lives in the URL, a client instance talks to a single model. To call a different model, create another client with that model's path.- A
User-Agentheader is required by the Serenity* Star API, and the OpenAI SDK does not send one. Set it yourself viadefault_headers, otherwise the request fails with a403 Forbidden.
Your Serenity API key goes in api_key; the bearer form is accepted, so it is sent as Authorization: Bearer YOUR_API_KEY.
from openai import OpenAI
client = OpenAI(
base_url="https://api.serenitystar.ai/api/v2/inference/qwen/qwen3.6",
api_key="YOUR_API_KEY",
default_headers={"User-Agent": "mySerenityClient/1.0"}, # required
)
Selecting the model
Unlike AIProxy, inference selects the model through the URL path, not through the model field in the request body:
/api/v2/inference/{model}/chat/completions
/api/v2/inference/{model}/responses
{model} must be one of the inference models enabled on your instance (for example qwen/qwen3.6, qwen/qwen3.6-35b-a3b, or qwen/qwen3.6-27b). The OpenAI SDK still requires a model argument on each call, but it is ignored — the path always wins. Set it to the same value to keep things clear.
See the REST API reference for the full rules.
Examples
Simple request
response = client.chat.completions.create(
model="qwen/qwen3.6",
max_completion_tokens=5000,
messages=[
{"role": "user", "content": "Hello! Tell me a fun fact about Valencia."},
],
)
print(response.choices[0].message.content)
Function calling
Inference supports client tools — standard OpenAI function calling: the model asks for a function, you run it, and you send the result back for the model to finish its answer. (Server tools such as web search or image generation are not available, because there is no agent in front of the model.)
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the current weather for a given city",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "The city name"},
},
"required": ["city"],
},
},
}
]
messages = [
{"role": "user", "content": "What is the weather like in Paris right now? Use the tool."},
]
# Step 1 — the model requests the tool.
first = client.chat.completions.create(
model="qwen/qwen3.6",
max_completion_tokens=512,
messages=messages,
tools=tools,
)
tool_call = first.choices[0].message.tool_calls[0]
# Step 2 — run the function and send the result back.
messages.append(first.choices[0].message)
messages.append(
{
"role": "tool",
"tool_call_id": tool_call.id,
"content": '{"city":"Paris","temperature_c":18,"condition":"light rain","humidity":72}',
}
)
second = client.chat.completions.create(
model="qwen/qwen3.6",
max_completion_tokens=512,
messages=messages,
tools=tools,
)
print(second.choices[0].message.content)