This is PR 2 of the Python SDK PyPI publishing split. [PR 1](https://github.com/openai/codex/pull/18862) refreshed the generated SDK bindings; this PR makes the runtime package itself publishable, and PR 3 will wire the SDK package/version pinning to this runtime package. ## Summary - Rename the runtime distribution to `openai-codex-cli-bin` while keeping the import package as `codex_cli_bin`. - Make the runtime package wheel-only and build `py3-none-<platform>` wheels instead of interpreter-specific wheels. - Add `stage-runtime --codex-version` and `--platform-tag` so release staging can produce the platform wheel matrix from Codex release tags. - Add focused artifact workflow tests for version normalization, platform tag injection, and runtime wheel metadata. ## Why Rename There is already an unofficial PyPI package, [`codex-bin`](https://pypi.org/project/codex-bin/), distributing OpenAI Codex binaries. Publishing the official SDK runtime dependency as `openai-codex-cli-bin` makes the ownership clear, avoids confusing the SDK-pinned runtime wheel with that unowned wrapper, and keeps the import package unchanged as `codex_cli_bin`. ## Tests - `uv run --extra dev pytest tests/test_artifact_workflow_and_binaries.py` -> 21 passed - `uv run --extra dev python scripts/update_sdk_artifacts.py stage-runtime /tmp/codex-python-pr2-rebased/runtime-stage /tmp/codex-python-pr2-rebased/codex --codex-version rust-v0.116.0-alpha.1 --platform-tag macosx_11_0_arm64` - `uv run --with build --extra dev python -m build --wheel /tmp/codex-python-pr2-rebased/runtime-stage` - `uv run --with twine --extra dev twine check /tmp/codex-python-pr2-rebased/runtime-stage/dist/openai_codex_cli_bin-0.116.0a1-py3-none-macosx_11_0_arm64.whl` ## Note - Full `uv run --extra dev pytest` currently fails because regenerating from schemas already on `main` adds new DeviceKey Python types. I left that generated catch-up out of this runtime-only PR.
3.4 KiB
FAQ
Thread vs turn
- A
Threadis conversation state. - A
Turnis one model execution inside that thread. - Multi-turn chat means multiple turns on the same
Thread.
run() vs stream()
TurnHandle.run()/AsyncTurnHandle.run()is the easiest path. It consumes events until completion and returns the canonical generated app-serverTurnmodel.TurnHandle.stream()/AsyncTurnHandle.stream()yields raw notifications (Notification) so you can react event-by-event.
Choose run() for most apps. Choose stream() for progress UIs, custom timeout logic, or custom parsing.
Sync vs async clients
Codexis the sync public API.AsyncCodexis an async replica of the same public API shape.- Prefer
async with AsyncCodex()for async code. It is the standard path for explicit startup/shutdown, andAsyncCodexinitializes lazily on context entry or first awaited API use.
If your app is not already async, stay with Codex.
Public kwargs are snake_case
Public API keyword names are snake_case. The SDK still maps them to wire camelCase under the hood.
If you are migrating older code, update these names:
approvalPolicy->approval_policybaseInstructions->base_instructionsdeveloperInstructions->developer_instructionsmodelProvider->model_providermodelProviders->model_providerssortKey->sort_keysourceKinds->source_kindsoutputSchema->output_schemasandboxPolicy->sandbox_policy
Why only thread_start(...) and thread_resume(...)?
The public API keeps only explicit lifecycle calls:
thread_start(...)to create new threadsthread_resume(thread_id, ...)to continue existing threads
This avoids duplicate ways to do the same operation and keeps behavior explicit.
Why does constructor fail?
Codex() is eager: it starts transport and calls initialize in __init__.
Common causes:
- published runtime package (
openai-codex-cli-bin) is not installed - local
codex_binoverride points to a missing file - local auth/session is missing
- incompatible/old app-server
Maintainers stage releases by building the SDK once and the runtime once per
platform with the same pinned runtime version. Publish openai-codex-cli-bin as
platform wheels only; do not publish an sdist:
cd sdk/python
python scripts/update_sdk_artifacts.py generate-types
python scripts/update_sdk_artifacts.py \
stage-sdk \
/tmp/codex-python-release/codex-app-server-sdk \
--runtime-version 1.2.3
python scripts/update_sdk_artifacts.py \
stage-runtime \
/tmp/codex-python-release/openai-codex-cli-bin \
/path/to/codex \
--runtime-version 1.2.3
Why does a turn "hang"?
A turn is complete only when turn/completed arrives for that turn ID.
run()waits for this automatically.- With
stream(), keep consuming notifications until completion.
How do I retry safely?
Use retry_on_overload(...) for transient overload failures (ServerBusyError).
Do not blindly retry all errors. For InvalidParamsError or MethodNotFoundError, fix inputs/version compatibility instead.
Common pitfalls
- Starting a new thread for every prompt when you wanted continuity.
- Forgetting to
close()(or not using context managers). - Assuming
run()returns extra SDK-only fields instead of the generatedTurnmodel. - Mixing SDK input classes with raw dicts incorrectly.