Documentation Index
Fetch the complete documentation index at: https://docs.xenovia.io/llms.txt
Use this file to discover all available pages before exploring further.
Setup
export XENOVIA_API_KEY=xe_...
export XENOVIA_PROXY_ID=your-proxy-id
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["XENOVIA_API_KEY"],
base_url=f"https://runtime.xenovia.io/a/{os.environ['XENOVIA_PROXY_ID']}/openai/v1"
)
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "Hello"}]
)
print(response.choices[0].message.content)
import OpenAI from "openai"
const client = new OpenAI({
apiKey: process.env.XENOVIA_API_KEY,
baseURL: `https://runtime.xenovia.io/a/${process.env.XENOVIA_PROXY_ID}/openai/v1`
})
const response = await client.chat.completions.create({
model: "gpt-4o-mini",
messages: [{ role: "user", content: "Hello" }]
})
console.log(response.choices[0].message.content)
Streaming
Streaming works without any additional configuration. The runtime stamps X-Xenovia-Session-Id and X-Xenovia-Trace-Id into the response headers before the first byte.
stream = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "Count to 5"}],
stream=True
)
for chunk in stream:
print(chunk.choices[0].delta.content or "", end="")
const stream = await client.chat.completions.create({
model: "gpt-4o-mini",
messages: [{ role: "user", content: "Count to 5" }],
stream: true
})
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? "")
}
Tool definitions pass through unchanged. Xenovia records tool call names and arguments in the trace and evaluates them against your request-stage Rego policy before forwarding.
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the current weather for a location",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string"}
},
"required": ["location"]
}
}
}
]
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "What's the weather in London?"}],
tools=tools
)
If a tool name matches a block rule in your Rego policy, the request returns 403 before reaching the upstream LLM.
Sessions
Pass X-Xenovia-Session-Id (a valid UUID) to group related calls into a session. All turns under that session ID appear together in Traces with a per-session turn counter.
import uuid
client = OpenAI(
api_key=os.environ["XENOVIA_API_KEY"],
base_url=f"https://runtime.xenovia.io/a/{os.environ['XENOVIA_PROXY_ID']}/openai/v1",
default_headers={"X-Xenovia-Session-Id": str(uuid.uuid4())}
)
import { randomUUID } from "crypto"
const client = new OpenAI({
apiKey: process.env.XENOVIA_API_KEY,
baseURL: `https://runtime.xenovia.io/a/${process.env.XENOVIA_PROXY_ID}/openai/v1`,
defaultHeaders: { "X-Xenovia-Session-Id": randomUUID() }
})
If you omit the header, Xenovia resolves a session automatically using message fingerprinting or the user field. See Runtime Architecture for the full five-strategy chain.
Custom trace properties
Attach up to 20 X-Xenovia-Property-* headers to tag traces with application context. Keys must be ≤ 64 chars; values ≤ 512 chars; the policy_ prefix is reserved.
client = OpenAI(
api_key=os.environ["XENOVIA_API_KEY"],
base_url=f"https://runtime.xenovia.io/a/{os.environ['XENOVIA_PROXY_ID']}/openai/v1",
default_headers={
"X-Xenovia-Session-Id": str(uuid.uuid4()),
"X-Xenovia-Property-user-tier": "enterprise",
"X-Xenovia-Property-feature": "document-summary",
"X-Xenovia-Session-Path": "workflows/summarise"
}
)
Policy blocks
When a request is blocked by policy, the runtime returns 403 Forbidden. The OpenAI SDK raises this as PermissionDeniedError. The X-Xenovia-Trace-Id response header identifies the blocking trace.
from openai import PermissionDeniedError
try:
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "Delete everything"}],
tools=tools
)
except PermissionDeniedError as e:
print(f"Blocked by policy: {e.message}")
import { PermissionDeniedError } from "openai"
try {
const response = await client.chat.completions.create({
model: "gpt-4o-mini",
messages: [{ role: "user", content: "Delete everything" }],
tools
})
} catch (e) {
if (e instanceof PermissionDeniedError) {
console.log("Blocked by policy:", e.message)
}
}
The response always includes trace headers you can log for correlation:
import httpx
from openai import OpenAI
# Use httpx to access response headers
with httpx.Client() as http:
resp = http.post(
f"https://runtime.xenovia.io/a/{os.environ['XENOVIA_PROXY_ID']}/openai/v1/chat/completions",
headers={
"Authorization": f"Bearer {os.environ['XENOVIA_API_KEY']}",
"Content-Type": "application/json"
},
json={
"model": "gpt-4o-mini",
"messages": [{"role": "user", "content": "Hello"}]
}
)
trace_id = resp.headers.get("X-Xenovia-Trace-Id")
session_id = resp.headers.get("X-Xenovia-Session-Id")
print(f"Trace: {trace_id}, Session: {session_id}")