The official Codex SDKs give a programmatic interface for running tasks from TypeScript/JavaScript and Python. They are needed where the codex exec shell commands are no longer enough: when you must hold a thread, continue the conversation across several turns and embed the final result into a service. If exec is the agent as a link of a pipeline, the SDK is the agent as an embedded library controlled by your code: it creates a thread, leads it and consumes the result programmatically.
The key concepts of the SDK are the thread and the turn. A thread is a conversation that lives between calls; a turn is one step within it. This model is needed precisely for multi-step work: you start a task, get the result, continue the same thread with the next request, preserving context. A one-off exec does not give this - it finishes and forgets; the SDK, on the contrary, lets you build a service where the agent leads coherent work across several calls, like a real dialogue.
It helps to see the TypeScript integration in full once. Below are installing the package and minimal code: create a client, start a thread, run a request to inspect the repository without edits. The result comes into the code as a value that can be parsed and used further. This is the point of the SDK: the agent is embedded in your process, and you work with its output as with an ordinary result of an async call rather than parsing text from stdout.
The Python integration is arranged symmetrically but with an explicit sandbox model. Below are installing the package and code via a context manager: create a client, start a thread with sandbox=Sandbox.read_only, run. Note read_only right in the thread start - it is the same boundary discipline as in the CLI but expressed in code. The SDK does not cancel the sandbox and permissions: they are set programmatically, and setting them narrowly here is as important as in interactive work.
Boundaries in the SDK are set explicitly, because there is no one to confirm on the fly. As in exec, a programmatic run is non-interactive: the sandbox, permissions and approval mode are defined in code before the run, not along the way. Read-only for an exploratory task, narrow access for an editing one - this is expressed by the thread-start parameters. The temptation to "give the SDK full access so it does not get in the way" is as dangerous here as disabling the sandbox in the CLI: a programmatic interface does not remove responsibility for boundaries.
Handling the result in the SDK is code, not reading by eye, and this is its strength. The final result comes as a value the service can check, parse by schema, save, pass on. Structured output is especially apt here: the service needs data of a defined shape, not free text. This is exactly why the SDK is chosen when the agent is embedded into a product: the output becomes part of the program, worked with like any other result of a call to an external system.
The point of the SDK is to turn the agent into a controllable component of a service with explicit boundaries and machine output. The thread and turn give continuity, the sandbox and permissions control, structured output a consumable result. This is the top level of the same ladder that starts with interactive work and passes through exec: from a conversation to a pipeline and further to an embedded component. And at each step one principle applies - boundaries are set consciously, and the result is checked rather than taken on faith.
The typical failures around the SDK are predictable. Taking the SDK where a one-off exec would suffice and complicating without need. Giving the thread full access instead of a narrow sandbox in the start parameters. Parsing free text instead of structured output when embedding the result into a service. And forgetting that a programmatic run is non-interactive, relying on approval on the fly. Take the SDK for multi-step embedded work, set the sandbox and permissions in code, use structured output and check the result programmatically.
// npm install @openai/codex-sdk
import { Codex } from "@openai/codex-sdk";
const codex = new Codex();
const thread = codex.startThread();
const result = await thread.run(
"Inspect the repository and return the three highest-risk modules. Do not edit files."
);
// result - a value for the service: check, parse by schema, save# pip install openai-codex
# from openai_codex import Codex, Sandbox
# with Codex() as codex:
# thread = codex.thread_start(sandbox=Sandbox.read_only)
# result = thread.run("Inspect the repository and return the highest-risk modules.")
# sandbox=read_only right in the thread start - boundaries are set in code, before the run