Skip to main content

OpenAI adapter for governing tool execution with BIGHUB.

Project description

bighub-openai - Production-Safe OpenAI Agents

bighub-openai makes OpenAI tool-calling agents production-safe.

Where it fits:

OpenAI Responses API  ->  bighub-openai  ->  BIGHUB Control Plane  ->  execute / block / approve

bighub-openai depends on both bighub and the official openai Python SDK. It targets the Responses API (client.responses.create) and requires openai>=2.0.0,<3.0.0.

Before any registered tool executes, the adapter:

  • Validates the action against BIGHUB policies
  • Enforces execution boundaries
  • Blocks or escalates risky decisions
  • Ingests governed execution into Future Memory for pattern learning
  • Sets store=false by default so tool-call data is not persisted on OpenAI servers

Decision enforcement outcomes:

  • allowed -> execute tool
  • blocked -> do not execute tool
  • requires_approval -> do not execute tool; adapter output status is approval_required

Install

pip install bighub-openai

Requires Python 3.9+. Recommended: use a dedicated virtual environment to avoid dependency conflicts with other packages that pin different openai versions.

Quickstart (5 lines)

from bighub_openai import GuardedOpenAI

def refund_payment(order_id: str, amount: float) -> dict:
    return {"ok": True, "order_id": order_id, "amount": amount}

guard = GuardedOpenAI(
    openai_api_key="sk-...",
    bighub_api_key="bhk_...",
    actor="AI_AGENT_001",
    domain="payments",
)

guard.tool("refund_payment", refund_payment, value_from_args=lambda a: a["amount"])

response = guard.run(
    messages=[
        {"role": "user", "content": "Refund order ord_123 for 199.99"},
    ],
    model="gpt-4.1",
)

print(response)

Async quickstart

from bighub_openai import AsyncGuardedOpenAI

guard = AsyncGuardedOpenAI(
    openai_api_key="sk-...",
    bighub_api_key="bhk_...",
    actor="AI_AGENT_001",
    domain="payments",
)

guard.tool(...) auto-generates a strict JSON schema from your Python function signature. Provide parameters_schema=... only when you need custom schema constraints.

run(...) returns a structured payload with both model output and governance execution events:

{
  "llm_response": {...},
  "execution": {
    "events": [...],
    "last": {
      "tool": "refund_payment",
      "status": "executed" | "blocked" | "approval_required",
      "decision": {...}
    }
  }
}

run_stream(...) yields structured stream events mapped from the Responses API streaming protocol:

Adapter event type Responses API event Description
llm_delta response.output_text.delta Incremental text token
llm_text_done response.output_text.done Complete text segment
output_item_added response.output_item.added New output item started
function_call_args_delta response.function_call_arguments.delta Streaming function args
function_call_args_done response.function_call_arguments.done Complete function args
refusal_delta response.refusal.delta Model refusal chunk
response_done response.completed Response finished
response_failed response.failed Response error
execution_event (adapter) Governed tool decision/execution result
final_response (adapter) Final payload, same shape as run(...)

Example:

for event in guard.run_stream(
    messages=[{"role": "user", "content": "Refund order ord_123 for 199.99"}],
    model="gpt-4.1",
):
    if event["type"] == "llm_delta":
        print(event["delta"], end="")
    elif event["type"] == "execution_event":
        print("\n[tool]", event["event"]["tool"], event["event"]["status"])
    elif event["type"] == "final_response":
        print("\nDone:", event["response"]["output_text"])

Async example:

async for event in guard.run_stream(
    messages=[{"role": "user", "content": "Refund order ord_123 for 199.99"}],
    model="gpt-4.1",
):
    if event["type"] == "llm_delta":
        print(event["delta"], end="")
    elif event["type"] == "execution_event":
        print("\n[tool]", event["event"]["tool"], event["event"]["status"])
    elif event["type"] == "final_response":
        print("\nDone:", event["response"]["output_text"])

Decision modes

  • decision_mode="submit" (default) -> calls client.actions.submit(...)
  • decision_mode="submit_v2" -> calls client.actions.submit_v2(...)

You can set it globally on GuardedOpenAI(...) or per tool in register_tool(..., decision_mode="submit_v2").

Audit hook

Use on_decision to forward structured events to your observability stack:

guard = GuardedOpenAI(..., on_decision=lambda event: print(event))

Event payload contract includes stable identifiers:

  • trace_id (run correlation id)
  • request_id (BIGHUB validation id when available)
  • event_id (adapter event id)

Silent mode

When you want to evaluate governance without executing tools:

decision = guard.check_tool("refund_payment", {"order_id": "ord_123", "amount": 199.0})

Approval loop helper

Use HITL helpers when a tool decision returns requires_approval:

  • run_with_approval(...) runs, captures pending approval, and can resume with a callback
  • resume_after_approval(...) resolves one approval request then resumes tool execution

Approval callbacks should run server-side (not in the client) to avoid exposing approval credentials.

Example:

result = guard.run_with_approval(
    messages=[{"role": "user", "content": "Refund order ord_123 for 5000"}],
    model="gpt-4.1",
    on_approval_required=lambda ctx: {
        "resolution": "approved",
        "comment": "approved by on-call",
    },
)

print(result["approval_loop"])

Async example:

result = await guard.run_with_approval(
    messages=[{"role": "user", "content": "Refund order ord_123 for 5000"}],
    model="gpt-4.1",
    on_approval_required=lambda ctx: {
        "resolution": "approved",
        "comment": "approved by on-call",
    },
)

print(result["approval_loop"])

Future memory ingest

By default, GuardedOpenAI ingests governed execution events to BIGHUB future memory:

guard = GuardedOpenAI(..., memory_enabled=True, memory_source="openai_adapter")

The adapter ingests memory in best-effort mode:

  • short timeout (memory_ingest_timeout_ms, default 300)
  • exceptions are swallowed
  • governance execution path is never blocked by telemetry

Each event includes idempotency/versioning metadata for stable analytics:

  • event_id (dedupe key)
  • seq (position within run)
  • schema_version (current: 1)
  • source_version (for example bighub-openai@0.2.x)

This powers pattern learning and context endpoints such as client.actions.memory_context(...).

Fail Modes

  • fail_mode="closed" (default): if policy check fails, tool execution is blocked.
  • fail_mode="open": if policy check fails unexpectedly, tool execution proceeds.

Provider resilience knobs

GuardedOpenAI and AsyncGuardedOpenAI expose provider resilience settings:

  • provider_timeout_seconds
  • provider_max_retries
  • provider_retry_backoff_seconds
  • provider_retry_max_backoff_seconds
  • provider_retry_jitter_seconds
  • provider_circuit_breaker_failures (set >0 to enable)
  • provider_circuit_breaker_reset_seconds

Retries only trigger on transient OpenAI errors (APIConnectionError, APITimeoutError, RateLimitError). Non-retryable errors (e.g. BadRequestError, AuthenticationError) fail immediately.

Example:

guard = GuardedOpenAI(
    openai_api_key="sk-...",
    bighub_api_key="bhk_...",
    actor="AI_AGENT_001",
    domain="payments",
    provider_timeout_seconds=20,
    provider_max_retries=3,
    provider_retry_backoff_seconds=0.2,
    provider_retry_max_backoff_seconds=2.0,
    provider_retry_jitter_seconds=0.15,
    provider_circuit_breaker_failures=5,
    provider_circuit_breaker_reset_seconds=30,
)

Responses API compatibility

This adapter is built specifically for the OpenAI Responses API (client.responses.create). Key design choices:

  • Tool schema: Uses flat {type: "function", name, parameters, strict} format (not the nested {type: "function", function: {...}} from Chat Completions).
  • Multi-turn context: Uses previous_response_id for efficient multi-turn loops. Reasoning items from prior turns are preserved automatically by the API.
  • store: false: Set by default on all provider calls. Override via extra_create_args={"store": True} if you need statefulness.
  • Output parsing: Handles response.output_text natively and falls back to response.output[].content[].text extraction for edge cases.
  • Function calls: Parses function_call items from response.output[] and ignores reasoning, message, and other item types safely.
  • function_call_output: Returns results as {type: "function_call_output", call_id, output} per the Responses API specification.

Notes

  • This adapter is intentionally provider-specific.
  • Core policy and transport behavior remain in the bighub SDK.
  • Compatible with openai>=2.0.0,<3.0.0 (Responses API).

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

bighub_openai-0.2.0.tar.gz (20.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

bighub_openai-0.2.0-py3-none-any.whl (14.6 kB view details)

Uploaded Python 3

File details

Details for the file bighub_openai-0.2.0.tar.gz.

File metadata

  • Download URL: bighub_openai-0.2.0.tar.gz
  • Upload date:
  • Size: 20.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.0

File hashes

Hashes for bighub_openai-0.2.0.tar.gz
Algorithm Hash digest
SHA256 f4e97a37efd1d867804fe02f24e667a428ee17a778cb6e61e1892a5f7d1381d3
MD5 3dee1fe285b9e384208ab46372acf0ba
BLAKE2b-256 5535dedfb5e5dd5684143e1767bb7f9ffa56c9009c0af692e3d2f5de8c63bec6

See more details on using hashes here.

File details

Details for the file bighub_openai-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: bighub_openai-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 14.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.0

File hashes

Hashes for bighub_openai-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8185e1c73e428806f708fb1245b4e6f5e8bdadbdffca245c5f5b84df82d5933e
MD5 52f07875932e12db580381480fa4e03b
BLAKE2b-256 67be5379ab95def73c9ad8d0c3ae8e89dfa175cd4aed412c650038b4059b9df4

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page