Skip to main content

axio-responses

PyPI Python License: MIT

The OpenAI Responses API as axio speaks it: request items in, StreamEvents out.

Both halves live here rather than in a transport because two transports speak this API — the public /v1/responses endpoint and the ChatGPT backend Codex uses. It opens no connection and has no HTTP client dependency.

Installation

pip install axio-responses

Usage

Building the request

from axio.blocks import TextBlock
from axio.messages import Message
from axio_responses import convert_messages, convert_tools

messages, system, tools = [Message(role="user", content=[TextBlock(text="hi")])], "be brief", []

instructions, items = convert_messages(messages, system)
payload = {
    "model": "gpt-5.6",
    "instructions": instructions,
    "input": items,
    "stream": True,
    "tools": convert_tools(tools),
}
assert payload["instructions"] == "be brief"

convert_messages returns the system prompt separately, because this API takes it as instructions rather than as a message. Tool calls and their outputs become function_call and function_call_output items beside the messages, not blocks inside them.

Reading the stream

Responses is an axio_sse.Reader: one @on(...) method per event, dispatching on the payload's own type. Its class body names only the events it interprets. The API publishes one event family per tool it can run, so that set grows with the tools and not with the protocol; everything else is forwarded through unmatched() rather than dropped.

from collections.abc import AsyncIterator

import aiohttp
from axio.events import StreamEvent
from axio_responses import Responses


async def stream(resp: aiohttp.ClientResponse) -> AsyncIterator[StreamEvent]:
    turn = Responses(status=resp.status, request_id=resp.headers.get("x-request-id"))
    async for made in turn.over(resp.content.iter_any(), until="[DONE]"):
        yield made
    yield turn.finished()

Events axio has no type for — the API's own hosted tools, its audio, its bookkeeping — travel as ProviderEvent under the provider's own name rather than being dropped.

Errors and recovery

ResponsesAPIError extends axio.exceptions.StreamError. It preserves code, param, the actual HTTP status, request_id, and body. HTTP failures also retain raw_body; SSE failures retain event_type. A stream error can have HTTP status 200. Missing fields remain None. Bodies such as {"detail": "..."}, lists, and plain text retain their original shape. Diagnostic text is not used as an error code.

recovery distinguishes quota, authentication, permission, invalid requests, temporary failures, and unknown failures. retryable describes the provider failure only. A caller must also enforce an attempt limit and prevent replay after emitting events. Subscription quota errors are not retryable. Authentication errors do not, by themselves, prove token revocation.

ResponsesInterruptedError means no terminal event arrived, including after a refusal delta. Known response.incomplete reasons still produce their existing IterationEnd stop reasons. An unknown incomplete reason raises ResponsesIncompleteError with the original event body. AgentStream collectors preserve these exception types and fields.

from axio_responses import Recovery, ResponsesAPIError

error = ResponsesAPIError.from_http(
    '{"error":{"code":"subscription_sharing_usage_limit_exceeded","param":"model"}}',
    status=429,
    headers={"x-request-id": "req-example"},
)
assert error.recovery is Recovery.quota
assert not error.retryable
assert error.param == "model"
assert error.request_id == "req-example"

Holding it against the schema

from axio_responses import Responses

PUBLISHED_EVENTS = {"response.output_text.delta", "response.completed", "response.refusal.delta"}

# Every name the reader claims is one the schema publishes. A typo is a handler that never runs.
assert Responses.names() >= PUBLISHED_EVENTS

names() answers what the reader claims, so a test can hold it against the union OpenAI publishes. The check is <=, not ==: the reader deliberately names fewer events than the API sends. Reading with strict=True raises UnknownEvent on a name it does not claim, which is how a test fails on the day OpenAI adds one.

License

MIT

Metadata

Release files for axio-responses 0.12.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for axio-responses 0.12.1
File Size Uploaded Provenance Actions
axio_responses-0.12.1.tar.gz 22.5 kB With provenance Details for axio_responses-0.12.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for axio-responses 0.12.1
File Interpreter ABI Platform Actions
axio_responses-0.12.1-py3-none-any.whl Python 3 none any Details for axio_responses-0.12.1-py3-none-any.whl

Total release size: 37.0 kB

Release files / axio_responses-0.12.1.tar.gz

Download URL axio_responses-0.12.1.tar.gz
Size 22.5 kB
Tags Source
SHA-256 checksum
How to use checksums
38ecc520610f656668100cbee21b94f5cd04d217ccf54fb1024b5e36c53d68a7
BLAKE2b-256 checksum
How to use checksums
8d87e6dd57676bc1cd8dab8b33b174983dbaed68d5921b8557226e6b7fb434dd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.

Transparency log

Release files / axio_responses-0.12.1-py3-none-any.whl

Download URL axio_responses-0.12.1-py3-none-any.whl
Size 14.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8576b5195f08ab2cd046a8dc94e4e10d6adc50b249b7a3bfb153df1c76783ce3
BLAKE2b-256 checksum
How to use checksums
10107674fa0d4e8505ac3149088bf1fe5d627f00b75fa8ffbab337eac1c19da4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.

Transparency log

Security for axio-responses 0.12.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for axio_responses-0.12.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 17, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page