SecureOpenAI
Drop-in replacement for the OpenAI Python SDK. Change one import, keep all your code. Every request gets cryptographic signing, policy enforcement, and audit logging automatically.
Quick Start
from openai import OpenAI
client = OpenAI()
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": "Hello"}]
)from macaw_adapters.openai import SecureOpenAI
client = SecureOpenAI(app_name="my-app")
response = client.chat.completions.create(
model="gpt-4", # Policy may override
messages=[{"role": "user", "content": "Hello"}]
)When to Use Each Path
SecureOpenAI supports three usage patterns depending on your identity requirements:
| Scenario | Path | Example |
|---|---|---|
| Simple app, no user distinction | Direct on service | client.chat.completions.create() |
| Multi-user, per-user policies | bind_to_user | service.bind_to_user(user) |
| A2A communication, explicit control | invoke_tool | user.invoke_tool("tool:xxx/generate") |
Constructor
client = SecureOpenAI(
api_key="sk-...", # or OPENAI_API_KEY env var
app_name="my-app", # Application name for MACAW registration
intent_policy={...}, # Optional: MAPL policy declaration
jwt_token=None, # Optional: enables user mode with this identity
user_name=None # Optional: username for user mode registration
)| Parameter | Type | Description |
|---|---|---|
| api_key | str | OpenAI API key (or use OPENAI_API_KEY env var) |
| app_name | str | Application name for MACAW registration |
| intent_policy | dict | Optional MAPL policy declaration |
| jwt_token | str | If provided, enables user mode with this identity |
| user_name | str | Optional username for user mode registration |
MACAW-Protected Methods
These methods are routed through MACAW PEP for policy enforcement, audit logging, and authenticated prompts:
# Chat completions (identical to OpenAI)
client.chat.completions.create(model, messages, tools?, stream=False, ...)
# Text completions
client.completions.create(model, prompt, ...)
# Embeddings
client.embeddings.create(model, input, ...)Streaming Support
Set stream=True for real-time token streaming. Policy enforcement happens before the first chunk is returned — blocked requests never start streaming.
Pass-through APIs
These APIs are passed directly to the underlying OpenAI client without MACAW interception. Use for ancillary operations that don't require policy enforcement:
| Property | Description |
|---|---|
| client.models | List and retrieve available models |
| client.images | DALL-E image generation and editing |
| client.audio | Whisper transcription and TTS |
| client.files | File upload/download for fine-tuning |
| client.fine_tuning | Fine-tuning job management |
| client.moderations | Content moderation checks |
| client.batches | Batch API for async processing |
| client.beta | Assistants, threads, vector stores |
Full API Coverage: SecureOpenAI provides complete access to the OpenAI API. Only one import needed — no need to import both openai and SecureOpenAI.
Multi-User: bind_to_user()
For multi-user SaaS apps where different users need different permissions. The user's JWT identity flows through for policy evaluation, enabling per-user access control.
from macaw_adapters.openai import SecureOpenAI
from macaw_client import MACAWClient
# Create service (once, shared)
service = SecureOpenAI(app_name="my-service")
# Create user agent with JWT identity
user = MACAWClient(
user_name="alice",
iam_token=jwt_token,
agent_type="user"
)
user.register()
# Bind user to service -> returns BoundSecureOpenAI
user_client = service.bind_to_user(user)
# Same API, but with user's identity for policy enforcement
response = user_client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": "Hello"}]
)
# Cleanup when done
user_client.unbind()Why bind_to_user?
Without bind_to_user(), all users share the service's identity. With it, each user's JWT flows through, enabling policies like: Alice = GPT-3.5 only, max 500 tokens; Bob = GPT-4, max 2000 tokens.
Streaming Responses
Set stream=True for real-time token streaming. Policy enforcement happens before the first chunk is returned — blocked requests never start streaming.
# Streaming response - works identically to OpenAI
response = client.chat.completions.create(
model="gpt-3.5-turbo",
messages=[{"role": "user", "content": "Write a poem"}],
stream=True # Returns iterator
)
# Iterate over streaming chunks
for chunk in response:
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)Streaming Security
Policy checks (model, max_tokens, etc.) are validated before streaming begins. Each chunk is logged for audit compliance. The underlying invoke_tool(stream=True) handles this automatically.
A2A: invoke_tool()
For agent-to-agent (A2A) systems or when you need explicit control over tool routing. Returns raw dict instead of SDK types.
# Service registers tools
service = SecureOpenAI(app_name="openai-service")
# User agent calls invoke_tool directly
result = user.invoke_tool(
tool_name="tool:openai-service/generate", # MAPL name
parameters={
"model": "gpt-3.5-turbo",
"messages": [{"role": "user", "content": "Hello"}]
},
target_agent=service.server_id
)
# Result is raw dict (not ChatCompletion)
content = result["choices"][0]["message"]["content"]MAPL Tool Names
SecureOpenAI registers tools using MAPL-compliant resource names for policy matching:
| Tool Name | Method | Prompts Field |
|---|---|---|
| tool:<app>/generate | chat.completions.create | messages |
| tool:<app>/complete | completions.create | prompt |
| tool:<app>/embed | embeddings.create | input |
Use these tool names in your MAPL policies to control access. For example,tool:my-app/generate matches chat completions from an app named "my-app".
Policy Integration
Policies can control every aspect of OpenAI requests:
{
"constraints": {
"parameters": {
"tool:my-app/generate": {
"model": {
"allowed_values": ["gpt-3.5-turbo", "gpt-4"]
},
"max_tokens": {
"type": "integer",
"max": 2000
},
"temperature": {
"type": "number",
"range": [0.0, 1.0]
}
}
}
}
}Policy Enforcement Behavior
- • Model downgrade: Request for gpt-4 may be changed to gpt-3.5-turbo if policy restricts
- • Token reduction: max_tokens=4000 reduced to 2000 if policy limit is lower
- • Denial: Request blocked if no policy allows the operation
Examples
from macaw_adapters.openai import SecureOpenAI
client = SecureOpenAI(app_name="chat-app")
# Stream responses with user-specific policy
stream = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": "Write a poem"}],
stream=True
)
for chunk in stream:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="")tools = [{
"type": "function",
"function": {
"name": "get_weather",
"parameters": {...}
}
}]
# Tool calls are logged and policy-checked
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": "What's the weather?"}],
tools=tools
)
# Tool call recorded in audit log
tool_calls = response.choices[0].message.tool_callsOfficial API Reference
SecureOpenAI maintains API compatibility with the official OpenAI Python SDK:
SDK Compatibility: openai-python ≥1.0.0 • Tested with v1.x API