## Why `openai-codex` needs a beta release lifecycle without requiring beta releases of its pinned runtime package. Previously, SDK staging rewrote its runtime dependency to the SDK version, which made an SDK-only beta impossible. ## What changed - Set the initial SDK beta version to `0.1.0b1` and pin it to published stable `openai-codex-cli-bin==0.132.0`. - Decoupled SDK release staging from runtime versioning so it preserves the reviewed exact runtime pin. - Added a `python-v*` tag workflow that builds and publishes only `openai-codex` through PyPI trusted publishing. - Removed the Beta classifier from runtime package metadata for future runtime publications. - Regenerated protocol-derived SDK models from the selected stable runtime package. `0.132.0` is the newest stable runtime admitted by the checked-in dependency date fence and retains the Linux wheel family currently used by SDK CI. ## Release setup Before pushing `python-v0.1.0b1`, configure PyPI trusted publishing for the `openai-codex` project with workflow `python-sdk-release.yml`, environment `pypi`, and job `publish-python-sdk`. ## Validation - `uv run --frozen --extra dev ruff check src/openai_codex scripts examples tests` - Parsed `.github/workflows/python-sdk-release.yml` with PyYAML. - Built staged release artifacts locally: `openai_codex-0.1.0b1-py3-none-any.whl` and `openai_codex-0.1.0b1.tar.gz`. - Verified wheel metadata pins `openai-codex-cli-bin==0.132.0`. - Tests are deferred to online CI for this PR.
4.2 KiB
OpenAI Codex Python SDK (Experimental)
Experimental Python SDK for codex app-server JSON-RPC v2 over stdio, with a small default surface optimized for real scripts and apps.
The generated wire-model layer is sourced from the pinned openai-codex-cli-bin
runtime package and exposed as Pydantic models with snake_case Python fields
that serialize back to the protocol's camelCase wire format.
The package root exports the ergonomic client API; public Codex protocol value and
event types live in openai_codex.types.
Install
cd sdk/python
uv sync
source .venv/bin/activate
Published SDK builds pin an exact compatible openai-codex-cli-bin runtime
dependency. Pass CodexConfig(codex_bin=...) only
when you intentionally want to run against a specific local app-server binary.
Quickstart
from openai_codex import Codex, Sandbox
with Codex() as codex:
# Call login_api_key(...) first when this Codex session is not
# already authenticated.
thread = codex.thread_start(model="gpt-5", sandbox=Sandbox.workspace_write)
result = thread.run("Say hello in one sentence.")
print(result.final_response)
print(len(result.items))
thread.run(...) and thread.turn(...).run() return TurnResult. Its
final_response is None when the turn completes without a final-answer or
phase-less assistant message item.
Sandbox
Use the same enum when creating a thread or changing its sandbox for a turn:
from openai_codex import Codex, Sandbox
with Codex() as codex:
thread = codex.thread_start(sandbox=Sandbox.workspace_write)
thread.run("Make the requested change.")
review = thread.run("Review the diff only.", sandbox=Sandbox.read_only)
Available presets:
Sandbox.read_only: read files without allowing writes.Sandbox.workspace_write: the normal default for projects with a recorded trust decision; read files and write inside the workspace and configured writable roots.Sandbox.full_access: run without filesystem access restrictions.
When sandbox= is omitted, Codex uses its configured default. A sandbox
passed to run(...) or turn(...) applies to that turn and subsequent turns
on the thread.
Login
Use the auth helper that matches your app:
from openai_codex import Codex
with Codex() as codex:
codex.login_api_key("sk-...")
account = codex.account()
print(account.account)
Interactive ChatGPT login returns a handle. Open the provided URL or device-code page, then wait for the matching completion event:
with Codex() as codex:
login = codex.login_chatgpt()
print(login.auth_url)
completed = login.wait()
print(completed.success)
Use login_chatgpt_device_code() for device-code auth, handle.cancel() to
stop an in-progress interactive login, and logout() to clear the active
Codex account session.
Docs map
- Golden path tutorial:
docs/getting-started.md - API reference (signatures + behavior):
docs/api-reference.md - Common decisions and pitfalls:
docs/faq.md - Runnable examples index:
examples/README.md - Jupyter walkthrough notebook:
notebooks/sdk_walkthrough.ipynb
Examples
Start here:
cd sdk/python
python examples/01_quickstart_constructor/sync.py
python examples/01_quickstart_constructor/async.py
Runtime
Published SDK builds are pinned to an exact openai-codex-cli-bin package
version, and that runtime package carries the platform-specific binary for the
target wheel. SDK beta releases are versioned independently of runtime releases.
Compatibility and versioning
- Package:
openai-codex - Runtime package:
openai-codex-cli-bin - Python:
>=3.10 - Target protocol: Codex
app-serverJSON-RPC v2 - Versioning rule: SDK releases pin one exact compatible Codex runtime version
Notes
Codex()is eager and performs startup +initializein the constructor.- Use context managers (
with Codex() as codex:) to ensure shutdown. - Plain strings are accepted anywhere a turn input is accepted; they are
shorthand for
TextInput(...). - Prefer
thread.run("...")for the common case. Usethread.turn(...)when you need streaming, steering, or interrupt control. - For transient overload, use
retry_on_overloadfrom the package root.