Skip to main content

axio-transport-codex

PyPI Python License: MIT

ChatGPT OAuth transport for axio using the OpenAI Responses API.

Authenticates via the same OAuth2 PKCE flow used by the ChatGPT desktop client - no API key purchase required; your ChatGPT subscription covers usage. Implements the OpenAI Responses API (not the legacy chat completions endpoint).

Features

  • No API key purchase - authenticates with your ChatGPT account via OAuth2 PKCE
  • Responses API - uses OpenAI's newer Responses endpoint (/backend-api/codex/responses)
  • Automatic token refresh - access tokens are silently refreshed before expiry; callers notified via on_auth_refresh
  • Full streaming - incremental text, reasoning, and tool-call events via SSE
  • Tool calling - works with all axio tool handlers; parallel tool calls enabled
  • Retry logic - automatic backoff on 429 and 5xx responses; honours Retry-After header
  • aiohttp-based - non-blocking I/O throughout

Installation

pip install axio-transport-codex

With the TUI settings screen (ChatGPT sign-in dialog):

pip install "axio-transport-codex[tui]"

Authentication

CodexTransport authenticates with ChatGPT using OAuth2 PKCE. The transport stores an access token (api_key), a refresh token, and an expiry timestamp. It refreshes the access token automatically when it is within 30 seconds of expiry.

Running the OAuth flow

Use run_oauth_flow() from axio_transport_codex.oauth to obtain tokens for the first time. It opens a browser window for ChatGPT sign-in and waits for the callback on http://localhost:1455/auth/callback.

import asyncio
from axio_transport_codex.oauth import run_oauth_flow
from axio_transport_codex import CodexTransport


async def main() -> None:
    tokens = await run_oauth_flow()
    # tokens = {
    #   "access_token": "...",
    #   "refresh_token": "...",
    #   "expires_at": "1234567890",   # Unix timestamp as string
    #   "account_id": "...",
    # }

    transport = CodexTransport(
        api_key=tokens["access_token"],
        refresh_token=tokens["refresh_token"],
        expires_at=tokens["expires_at"],
        account_id=tokens["account_id"],
    )

Persisting tokens across sessions

Pass an on_auth_refresh callback to receive updated credentials whenever the access token is refreshed. Save the returned dict to disk or a secrets store and restore it on the next run.

import json, pathlib, aiohttp
from axio_transport_codex import CodexTransport

CRED_FILE = pathlib.Path("~/.config/axio/codex.json").expanduser()


async def save_tokens(tokens: dict[str, str]) -> None:
    CRED_FILE.parent.mkdir(parents=True, exist_ok=True)
    CRED_FILE.write_text(json.dumps(tokens))


async def main() -> None:
    creds = json.loads(CRED_FILE.read_text()) if CRED_FILE.exists() else {}

    async with aiohttp.ClientSession() as session:
        transport = CodexTransport(
            api_key=creds.get("api_key", ""),
            refresh_token=creds.get("refresh_token", ""),
            expires_at=creds.get("expires_at", ""),
            account_id=creds.get("account_id", ""),
            session=session,
            on_auth_refresh=save_tokens,
        )
        # use transport with an Agent ...

Refreshing tokens manually

from axio_transport_codex.oauth import refresh_access_token

tokens = await refresh_access_token(refresh_token="...")
# tokens = {"access_token": ..., "refresh_token": ..., "expires_at": ..., "account_id": ...}

Usage

import asyncio
import aiohttp
from axio.agent import Agent
from axio.context import MemoryContextStore
from axio.events import TextDelta
from axio_transport_codex import CodexTransport, CODEX_MODELS


async def main() -> None:
    async with aiohttp.ClientSession() as session:
        transport = CodexTransport(
            api_key="<your-chatgpt-access-token>",
            refresh_token="<your-refresh-token>",
            expires_at="<unix-timestamp-string>",
            account_id="<your-account-id>",
            model=CODEX_MODELS["gpt-4.1"],
            session=session,
        )
        agent = Agent(system="You are a helpful assistant.", tools=[], transport=transport)
        ctx = MemoryContextStore()
        async for event in agent.run_stream("Explain the Rust borrow checker.", ctx):
            if isinstance(event, TextDelta):
                print(event.delta, end="", flush=True)
        print()


asyncio.run(main())

The session parameter is required for streaming. Create an aiohttp.ClientSession in an async context and pass it to the transport.

Configuration reference

CodexTransport is a dataclass with the following fields:

Field Type Default Description
name str "ChatGPT (Codex)" Display name (used by TUI)
api_key str "" ChatGPT OAuth access token
refresh_token str "" OAuth refresh token for silent renewal
expires_at str "" Access token expiry as a Unix timestamp string
account_id str "" ChatGPT account/organisation ID (sent as ChatGPT-Account-ID header)
base_url str "https://chatgpt.com/backend-api/codex" API base URL
model ModelSpec CODEX_MODELS["gpt-4.1"] Active model
models ModelRegistry all CODEX_MODELS Available models
session aiohttp.ClientSession | None None HTTP session (required for streaming)
on_auth_refresh Callable[[dict[str, str]], Awaitable[None]] | None None Callback invoked with fresh credentials after token refresh
max_retries int 10 Maximum retry attempts on 429 / 5xx
retry_base_delay float 5.0 Base delay in seconds for exponential backoff

Models

Model ID Context Max output Capabilities
gpt-4.1 1,047,576 32,768 text, vision, tool use
gpt-4.1-mini 1,047,576 32,768 text, vision, tool use
gpt-4.1-nano 1,047,576 32,768 text, tool use
gpt-4o 128,000 16,384 text, vision, tool use
gpt-4o-mini 128,000 16,384 text, vision, tool use
o4-mini 200,000 100,000 text, reasoning, tool use
o3 200,000 100,000 text, reasoning, tool use
o3-mini 200,000 100,000 text, reasoning, tool use

The default model is gpt-4.1.

fetch_models()

await transport.fetch_models() queries the Codex /models endpoint for the list of models your account has access to. If the request fails or the account is not configured, it falls back to the built-in CODEX_MODELS registry. Models not found in the built-in registry are added with basic text and tool_use capabilities.

session and api_key must be set before calling fetch_models().

Plugin registration

When installed, this package registers itself via entry points so axio-tui discovers it automatically:

[project.entry-points."axio.transport"]
codex = "axio_transport_codex:CodexTransport"

[project.entry-points."axio.transport.settings"]
codex = "axio_transport_codex.tui:CodexSettingsScreen"

Part of the axio ecosystem

axio · axio-transport-openai · axio-transport-anthropic · axio-tui

License

MIT

Metadata

Release files for axio-transport-codex 0.11.3

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-transport-codex 0.11.3
File Size Uploaded
axio_transport_codex-0.11.3.tar.gz 88.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for axio-transport-codex 0.11.3
File Interpreter ABI Platform
axio_transport_codex-0.11.3-py3-none-any.whl Python 3 none any Details

Total release size: 102.5 kB

Release files / axio_transport_codex-0.11.3.tar.gz

Download URL axio_transport_codex-0.11.3.tar.gz
Size 88.5 kB
Tags Source
SHA-256 checksum
How to use checksums
7be9ec90d3cde1ac127d52db271b7ddeb5e7bb776117881b2030545324fe4230
BLAKE2b-256 checksum
How to use checksums
593b3bb8237139cc74ab224787ee5bc77ce90960ceeedfe4893b9a466403d3d9
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 Sep 17, 2026.

Transparency log

Release files / axio_transport_codex-0.11.3-py3-none-any.whl

Download URL axio_transport_codex-0.11.3-py3-none-any.whl
Size 14.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
aeb438b59de8c128833f8856ebca0fcf36568540e01eff017bd679553b67bda8
BLAKE2b-256 checksum
How to use checksums
136911075b2a22cba3120cf8f3511ce444c7d724c319c0a3740a1f085143a591
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 Sep 17, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.11.3 This release

2 release files

0.11.2

2 release files

0.11.1

2 release files

0.11.0

2 release files

0.10.1

2 release files

0.10.0

2 release files

0.9.9

2 release files

0.9.8

2 release files

0.9.7

2 release files

0.9.6

2 release files

0.9.5

2 release files

0.9.4

2 release files

0.9.2

2 release files

0.9.1

2 release files

0.9.0

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.2

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.5

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.0

2 release files

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