VerdifaX

Integrating OpenAI

Same shape as the Claude integration. One helper, one call after the model response.

Install

pip install verdifax openai

Basic pattern

from openai import OpenAI
import verdifax

client = OpenAI()  # picks up OPENAI_API_KEY

resp = client.chat.completions.create(
    model="gpt-4o",
    messages=[
        {"role": "user", "content": "Classify this support ticket..."}
    ],
)
output = resp.choices[0].message.content

receipt = verdifax.attest_openai_response(
    prompt="Classify this support ticket...",
    response=output,
    program_id="a" * 64,
    route_id="openai-classify-v1",
    registry_record_hash="b" * 64,
)

print(receipt.manifest_hash)

Streaming

If you stream tokens, attest the assembled response after the stream completes:

chunks = []
stream = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": prompt}],
    stream=True,
)
for event in stream:
    if event.choices[0].delta.content:
        chunks.append(event.choices[0].delta.content)
output = "".join(chunks)

receipt = verdifax.attest_openai_response(
    prompt=prompt,
    response=output,
    program_id="a" * 64,
    route_id="openai-stream-v1",
    registry_record_hash="b" * 64,
)

Function calling / tool use

Tool calls produce structured outputs, not free text. Attest the canonical JSON of the tool call:

import json

resp = client.chat.completions.create(
    model="gpt-4o",
    tools=[...],
    messages=[...],
)
tool_call = resp.choices[0].message.tool_calls[0]
canonical = json.dumps({
    "name": tool_call.function.name,
    "arguments": json.loads(tool_call.function.arguments),
}, sort_keys=True)

receipt = verdifax.attest(
    payload=canonical,
    program_id="a" * 64,
    route_id="openai-tools-v1",
    registry_record_hash="b" * 64,
)

The sort_keys=True is important — it canonicalizes the JSON so identical tool calls always seal to the same hash.

Continue