Python SDK
Because Serenity* Star API exposes OpenAI-compatible endpoints for your AIProxy agents, 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, tools) works exactly as it does against OpenAI.
For more information about request and response shapes for the AIProxy OpenAI-Compatible endpoints, see the AIProxy reference.
Install
pip install openai
Configure the client
Two things differ from a plain OpenAI setup:
base_urlmust point at the AIProxy path. With it set, the SDK appends/chat/completionsand/responsesfor you.- 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/aiproxy",
api_key="YOUR_API_KEY",
default_headers={"User-Agent": "mySerenityClient/1.0"}, # required
)
The model identifier
The one other difference is the model field. Instead of a plain model name, AIProxy takes a colon-separated {agentCode}:{vendor}:{model} value that selects which agent to run and which underlying model to route to:
{agentCode}:{vendor}:{model}
For example, my-aiproxy-agent:OpenAI:gpt-5.6-luna runs the my-aiproxy-agent agent against OpenAI's gpt-5.6-luna. To route the same agent to a different vendor, just change the vendor and model parts, for example:
my-aiproxy-agent:Anthropic:claude-fable-5my-aiproxy-agent:GoogleVertex:gemini-3.5-flash
See The model identifier for the full rules.
Examples
Simple request
response = client.chat.completions.create(
model="my-aiproxy-agent:OpenAI:gpt-5.6-luna",
max_completion_tokens=5000,
messages=[
{"role": "user", "content": "Hello! Tell me a fun fact about Valencia."},
],
)
print(response.choices[0].message.content)
Function calling
Client tools are 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. Only the model identifier is specific to AIProxy.
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="my-aiproxy-agent:Anthropic:claude-fable-5",
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="my-aiproxy-agent:Anthropic:claude-fable-5",
max_completion_tokens=512,
messages=messages,
tools=tools,
)
print(second.choices[0].message.content)
Execution metadata
To attribute an execution to a channel, user_identifier, or group_identifier, pass them through the SDK's extra_body parameter. See The extra_body object.
response = client.chat.completions.create(
model="my-aiproxy-agent:GoogleVertex:gemini-3.5-flash",
max_completion_tokens=5000,
messages=[
{"role": "user", "content": "Hello! Tell me a fun fact about Valencia."},
],
extra_body={
"channel": "my-channel",
"user_identifier": "user-123",
"group_identifier": "group-abc",
},
)
print(response.choices[0].message.content)