Skip to content

Python

Obstruo exposes an OpenAI-compatible API, so any Python library that talks to OpenAI works with Obstruo out of the box. This page covers the official openai SDK and raw httpx.

Prerequisites

  • An ObstruoKey and endpoint URL - see Quick Start
  • A Logical Model configured in your project

openai-python SDK

Install the SDK if you haven't already:

pip install openai

Replace your existing client instantiation:

import openai

client = openai.OpenAI(
    api_key="your-obstruo-key",
    base_url="https://api.obstruo.ai/your-org/v1",
)

Everything else stays the same - completions, streaming, embeddings, tool calls:

response = client.chat.completions.create(
    model="obstruo-chat",
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Summarise this contract: ..."},
    ],
)
print(response.choices[0].message.content)
with client.chat.completions.stream(
    model="obstruo-chat",
    messages=[{"role": "user", "content": "Tell me a story."}],
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)
response = client.embeddings.create(
    model="obstruo-embedding",
    input="The quick brown fox",
)
vector = response.data[0].embedding
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "parameters": {
                "type": "object",
                "properties": {"city": {"type": "string"}},
                "required": ["city"],
            },
        },
    }
]

response = client.chat.completions.create(
    model="obstruo-chat",
    messages=[{"role": "user", "content": "What's the weather in Warsaw?"}],
    tools=tools,
)

Async client

Use AsyncOpenAI for async code - the interface is identical:

import asyncio
import openai

client = openai.AsyncOpenAI(
    api_key="your-obstruo-key",
    base_url="https://api.obstruo.ai/your-org/v1",
)

async def main():
    response = await client.chat.completions.create(
        model="obstruo-chat",
        messages=[{"role": "user", "content": "Hello!"}],
    )
    print(response.choices[0].message.content)

asyncio.run(main())

Environment variables

Store credentials in environment variables rather than hardcoding them:

export OBSTRUO_API_KEY="your-obstruo-key"
export OBSTRUO_BASE_URL="https://api.obstruo.ai/your-org/v1"
import os
import openai

client = openai.OpenAI(
    api_key=os.environ["OBSTRUO_API_KEY"],
    base_url=os.environ["OBSTRUO_BASE_URL"],
)

Reading gateway metadata

Obstruo attaches metadata to every response. The location differs between streaming and non-streaming.

Non-streaming

The obstruo key is present in the response body:

response = client.chat.completions.create(
    model="obstruo-chat",
    messages=[{"role": "user", "content": "Hello!"}],
)

# standard OpenAI field
print(response.choices[0].message.content)

# redaction summary
redaction = response.model_extra.get("obstruo", {}).get("redaction", {})
print(redaction.get("total_entities"))  # 0 = no PII found
print(redaction.get("by_category"))     # {"EMAIL_ADDRESS": 1, ...}

# routing info
routing = response.model_extra.get("obstruo", {}).get("routing", {})
print(routing.get("resolved_model"))    # "gpt-4o-mini"
print(routing.get("provider_type"))     # "OpenAI"

Streaming

For streaming responses, metadata is available in the HTTP response headers:

stream = client.chat.completions.create(
    model="obstruo-chat",
    messages=[{"role": "user", "content": "Hello!"}],
    stream=True,
)
pii_state = stream.response.headers.get("x-obstruo-pii-state")
# "no-pii" | "redacted" | "disabled"
for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)

Raw HTTP with httpx

If you prefer to call the API directly without the SDK:

import httpx

client = httpx.Client(
    base_url="https://api.obstruo.ai/your-org/v1",
    headers={"Authorization": "Bearer your-obstruo-key"},
)

response = client.post("/chat/completions", json={
    "model": "obstruo-chat",
    "messages": [{"role": "user", "content": "Hello!"}],
})
response.raise_for_status()
print(response.json()["choices"][0]["message"]["content"])

Next steps