Skip to main content
This quickstart uses proxy mode because it is the fastest path to coverage. If you need to gate non-LLM actions too, continue with the Xenovia Python SDK after this.

1. Collect the two values you need

From the Xenovia platform:
  1. Create a proxy and note the proxy ID.
  2. Generate an API key (xe_...) scoped to that proxy.
Set them as environment variables:
export XENOVIA_API_KEY=xe_...
export XENOVIA_PROXY_ID=your-proxy-id

2. Point your client at Xenovia

pip install openai
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"
)

3. Send your first governed request

response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[{"role": "user", "content": "Summarise AI governance in one sentence."}]
)
print(response.choices[0].message.content)
The request now flows through Xenovia for authentication, provider routing, session handling, policy checks, and trace recording.

4. Add a stable session ID

Group related calls into a session so multi-turn conversations appear together in Traces.
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())}
)
The session ID must be a valid UUID. Xenovia validates the format and returns a 400 if it is malformed.

5. Confirm the trace exists

After the request completes, check the platform and confirm:
  • A trace exists for the request
  • The trace shows the expected model and proxy
  • The response includes X-Xenovia-Session-Id and X-Xenovia-Trace-Id

6. Attach a first policy

Start with one policy that proves enforcement is working. This example blocks a destructive tool name:
package xenovia.policy

default allow = true

deny if {
    some tool in input.tool_names
    tool == "delete_database"
}
Policies are evaluated per request. You can attach request-stage and response-stage rules independently.

7. Handle a policy block

When a request is blocked, the runtime returns 403 Forbidden. The OpenAI SDK raises this as PermissionDeniedError.
from openai import PermissionDeniedError

try:
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[{"role": "user", "content": "Delete the database."}],
        tools=[{
            "type": "function",
            "function": {
                "name": "delete_database",
                "description": "Delete all records",
                "parameters": {"type": "object", "properties": {}}
            }
        }]
    )
except PermissionDeniedError as e:
    print(f"Blocked by policy: {e.message}")

8. Add trace metadata

Tag traces with business context so they stay useful as traffic grows.
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-environment": "dev",
        "X-Xenovia-Property-workflow": "docs-quickstart"
    }
)

What to do next

After this first pass, move on to:
If your real workflow performs risky actions after the model call, add the Xenovia Python SDK so those actions are governed too.