codex-sdk-py 0.0.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,423 @@
1
+ Metadata-Version: 2.4
2
+ Name: codex-sdk-py
3
+ Version: 0.0.3
4
+ Summary: Python SDK for the OpenAI Codex agent
5
+ Project-URL: Homepage, https://github.com/nogataka/codex-sdk-python
6
+ Project-URL: Documentation, https://github.com/nogataka/codex-sdk-python#readme
7
+ Project-URL: Repository, https://github.com/nogataka/codex-sdk-python
8
+ Project-URL: Issues, https://github.com/nogataka/codex-sdk-python/issues
9
+ Author-email: OpenAI <support@openai.com>
10
+ License-Expression: Apache-2.0
11
+ Keywords: agent,ai,codex,openai,sdk
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: Apache Software License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Typing :: Typed
22
+ Requires-Python: >=3.10
23
+ Provides-Extra: dev
24
+ Requires-Dist: mypy>=1.8; extra == 'dev'
25
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
26
+ Requires-Dist: pytest-cov>=4.0; extra == 'dev'
27
+ Requires-Dist: pytest>=8.0; extra == 'dev'
28
+ Requires-Dist: ruff>=0.2; extra == 'dev'
29
+ Description-Content-Type: text/markdown
30
+
31
+ # Codex SDK for Python
32
+
33
+ Embed the Codex agent in your workflows and apps.
34
+
35
+ The Python SDK wraps the bundled `codex` binary. It spawns the CLI and exchanges JSONL events over stdin/stdout.
36
+
37
+ ## Installation
38
+
39
+ ```bash
40
+ pip install codex-sdk-py
41
+ ```
42
+
43
+ Requires Python 3.10+.
44
+
45
+ ## Quickstart
46
+
47
+ ```python
48
+ import asyncio
49
+ from codex_sdk import Codex
50
+
51
+ async def main():
52
+ codex = Codex()
53
+ thread = codex.start_thread()
54
+ turn = await thread.run("Diagnose the test failure and propose a fix")
55
+
56
+ print(turn.final_response)
57
+ print(turn.items)
58
+
59
+ asyncio.run(main())
60
+ ```
61
+
62
+ Call `run()` repeatedly on the same `Thread` instance to continue that conversation.
63
+
64
+ ```python
65
+ next_turn = await thread.run("Implement the fix")
66
+ ```
67
+
68
+ ### Streaming responses
69
+
70
+ `run()` buffers events until the turn finishes. To react to intermediate progress—tool calls, streaming responses, and file change notifications—use `run_streamed()` instead, which returns an async generator of structured events.
71
+
72
+ ```python
73
+ async def stream_example():
74
+ codex = Codex()
75
+ thread = codex.start_thread()
76
+
77
+ streamed = await thread.run_streamed("Diagnose the test failure and propose a fix")
78
+
79
+ async for event in streamed.events:
80
+ match event.get("type"):
81
+ case "item.completed":
82
+ print("item", event.get("item"))
83
+ case "turn.completed":
84
+ print("usage", event.get("usage"))
85
+ ```
86
+
87
+ ### Structured output
88
+
89
+ The Codex agent can produce a JSON response that conforms to a specified schema. The schema can be provided for each turn as a plain JSON object.
90
+
91
+ ```python
92
+ schema = {
93
+ "type": "object",
94
+ "properties": {
95
+ "summary": {"type": "string"},
96
+ "status": {"type": "string", "enum": ["ok", "action_required"]},
97
+ },
98
+ "required": ["summary", "status"],
99
+ "additionalProperties": False,
100
+ }
101
+
102
+ turn = await thread.run("Summarize repository status", {"output_schema": schema})
103
+ print(turn.final_response)
104
+ ```
105
+
106
+ You can also create a JSON schema from a [Pydantic model](https://docs.pydantic.dev/) using `model_json_schema()`.
107
+
108
+ ```python
109
+ from pydantic import BaseModel
110
+ from typing import Literal
111
+
112
+ class StatusResponse(BaseModel):
113
+ summary: str
114
+ status: Literal["ok", "action_required"]
115
+
116
+ turn = await thread.run(
117
+ "Summarize repository status",
118
+ {"output_schema": StatusResponse.model_json_schema()}
119
+ )
120
+ print(turn.final_response)
121
+ ```
122
+
123
+ ### Attaching images
124
+
125
+ Provide structured input entries when you need to include images alongside text. Text entries are concatenated into the final prompt while image entries are passed to the Codex CLI via `--image`.
126
+
127
+ ```python
128
+ turn = await thread.run([
129
+ {"type": "text", "text": "Describe these screenshots"},
130
+ {"type": "local_image", "path": "./ui.png"},
131
+ {"type": "local_image", "path": "./diagram.jpg"},
132
+ ])
133
+ ```
134
+
135
+ ### Resuming an existing thread
136
+
137
+ Threads are persisted in `~/.codex/sessions`. If you lose the in-memory `Thread` object, reconstruct it with `resume_thread()` and keep going.
138
+
139
+ ```python
140
+ import os
141
+
142
+ saved_thread_id = os.environ["CODEX_THREAD_ID"]
143
+ thread = codex.resume_thread(saved_thread_id)
144
+ await thread.run("Implement the fix")
145
+ ```
146
+
147
+ ### Working directory controls
148
+
149
+ Codex runs in the current working directory by default. To avoid unrecoverable errors, Codex requires the working directory to be a Git repository. You can skip the Git repository check by passing the `skip_git_repo_check` option when creating a thread.
150
+
151
+ ```python
152
+ thread = codex.start_thread({
153
+ "working_directory": "/path/to/project",
154
+ "skip_git_repo_check": True,
155
+ })
156
+ ```
157
+
158
+ ### Sandbox modes
159
+
160
+ Control how the agent interacts with your filesystem using `sandbox_mode`.
161
+
162
+ ```python
163
+ from codex_sdk import Codex, SandboxMode
164
+
165
+ thread = codex.start_thread({
166
+ "sandbox_mode": SandboxMode.WORKSPACE_WRITE,
167
+ })
168
+ ```
169
+
170
+ Available modes:
171
+ - `SandboxMode.READ_ONLY` - Agent can only read files
172
+ - `SandboxMode.WORKSPACE_WRITE` - Agent can read/write in the workspace
173
+ - `SandboxMode.DANGER_FULL_ACCESS` - Full filesystem access (use with caution)
174
+
175
+ ### Approval policies
176
+
177
+ Control when the agent requires approval for actions.
178
+
179
+ ```python
180
+ from codex_sdk import Codex, ApprovalMode
181
+
182
+ thread = codex.start_thread({
183
+ "approval_policy": ApprovalMode.ON_FAILURE,
184
+ })
185
+ ```
186
+
187
+ Available modes:
188
+ - `ApprovalMode.NEVER` - Never require approval
189
+ - `ApprovalMode.ON_REQUEST` - Approve on explicit request
190
+ - `ApprovalMode.ON_FAILURE` - Approve after failures
191
+ - `ApprovalMode.UNTRUSTED` - Always require approval
192
+
193
+ ### Cancelling a turn
194
+
195
+ Use `asyncio.Event` to cancel an ongoing turn (equivalent to `AbortSignal` in TypeScript).
196
+
197
+ ```python
198
+ import asyncio
199
+
200
+ async def cancellable_example():
201
+ codex = Codex()
202
+ thread = codex.start_thread()
203
+
204
+ cancel_event = asyncio.Event()
205
+
206
+ async def cancel_after_delay():
207
+ await asyncio.sleep(5)
208
+ cancel_event.set()
209
+
210
+ # Start cancellation timer
211
+ asyncio.create_task(cancel_after_delay())
212
+
213
+ try:
214
+ turn = await thread.run(
215
+ "Long running task",
216
+ {"cancel_event": cancel_event}
217
+ )
218
+ except asyncio.CancelledError:
219
+ print("Turn was cancelled")
220
+ ```
221
+
222
+ ### Controlling the Codex CLI environment
223
+
224
+ By default, the Codex CLI inherits the Python process environment. Provide the optional `env` parameter when instantiating the `Codex` client to fully control which variables the CLI receives—useful for sandboxed hosts.
225
+
226
+ ```python
227
+ codex = Codex({
228
+ "env": {
229
+ "PATH": "/usr/local/bin",
230
+ },
231
+ })
232
+ ```
233
+
234
+ The SDK still injects its required variables (such as `OPENAI_BASE_URL` and `CODEX_API_KEY`) on top of the environment you provide.
235
+
236
+ ### Passing `--config` overrides
237
+
238
+ Use the `config` option to provide additional Codex CLI configuration overrides. The SDK accepts a dict, flattens it into dotted paths, and serializes values as TOML literals before passing them as repeated `--config key=value` flags.
239
+
240
+ ```python
241
+ codex = Codex({
242
+ "config": {
243
+ "show_raw_agent_reasoning": True,
244
+ "sandbox_workspace_write": {"network_access": True},
245
+ },
246
+ })
247
+ ```
248
+
249
+ Thread options still take precedence for overlapping settings because they are emitted after these global overrides.
250
+
251
+ ## API Reference
252
+
253
+ ### Classes
254
+
255
+ #### `Codex`
256
+ Main entry point for the SDK.
257
+
258
+ ```python
259
+ codex = Codex(options: CodexOptions | None = None)
260
+ ```
261
+
262
+ Methods:
263
+ - `start_thread(options: ThreadOptions | None = None) -> Thread` - Start a new conversation
264
+ - `resume_thread(thread_id: str, options: ThreadOptions | None = None) -> Thread` - Resume an existing conversation
265
+
266
+ #### `Thread`
267
+ Represents a conversation with the agent.
268
+
269
+ Properties:
270
+ - `id: str | None` - Thread ID (populated after first turn)
271
+
272
+ Methods:
273
+ - `async run(input: Input, turn_options: TurnOptions | None = None) -> Turn` - Execute a turn and return results
274
+ - `async run_streamed(input: Input, turn_options: TurnOptions | None = None) -> StreamedTurn` - Execute a turn with streaming events
275
+
276
+ #### `Turn`
277
+ Result of a completed turn.
278
+
279
+ ```python
280
+ @dataclass
281
+ class Turn:
282
+ items: list[ThreadItem] # All items produced during the turn
283
+ final_response: str # The agent's final response text
284
+ usage: Usage | None # Token usage statistics
285
+ ```
286
+
287
+ #### `StreamedTurn`
288
+ Result of a streamed turn.
289
+
290
+ ```python
291
+ @dataclass
292
+ class StreamedTurn:
293
+ events: AsyncGenerator[ThreadEvent, None] # Async generator of events
294
+ ```
295
+
296
+ ### Types
297
+
298
+ #### Input Types
299
+ - `Input = str | list[UserInput]` - User input (string or structured)
300
+ - `TextUserInput` - Text input: `{"type": "text", "text": "..."}`
301
+ - `ImageUserInput` - Image input: `{"type": "local_image", "path": "..."}`
302
+
303
+ #### Event Types
304
+ - `ThreadStartedEvent` - Thread started
305
+ - `TurnStartedEvent` - Turn started
306
+ - `TurnCompletedEvent` - Turn completed (includes usage)
307
+ - `TurnFailedEvent` - Turn failed (includes error)
308
+ - `ItemStartedEvent` - Item started
309
+ - `ItemUpdatedEvent` - Item updated
310
+ - `ItemCompletedEvent` - Item completed
311
+ - `ThreadErrorEvent` - Unrecoverable error
312
+
313
+ #### Item Types
314
+ - `AgentMessageItem` - Agent's response text
315
+ - `ReasoningItem` - Agent's reasoning summary
316
+ - `CommandExecutionItem` - Shell command execution
317
+ - `FileChangeItem` - File modifications
318
+ - `McpToolCallItem` - MCP tool invocation
319
+ - `WebSearchItem` - Web search query
320
+ - `TodoListItem` - Agent's task list
321
+ - `ErrorItem` - Non-fatal error
322
+
323
+ ### Enums
324
+
325
+ ```python
326
+ class SandboxMode(StrEnum):
327
+ READ_ONLY = "read-only"
328
+ WORKSPACE_WRITE = "workspace-write"
329
+ DANGER_FULL_ACCESS = "danger-full-access"
330
+
331
+ class ApprovalMode(StrEnum):
332
+ NEVER = "never"
333
+ ON_REQUEST = "on-request"
334
+ ON_FAILURE = "on-failure"
335
+ UNTRUSTED = "untrusted"
336
+
337
+ class ModelReasoningEffort(StrEnum):
338
+ MINIMAL = "minimal"
339
+ LOW = "low"
340
+ MEDIUM = "medium"
341
+ HIGH = "high"
342
+ XHIGH = "xhigh"
343
+
344
+ class WebSearchMode(StrEnum):
345
+ DISABLED = "disabled"
346
+ CACHED = "cached"
347
+ LIVE = "live"
348
+ ```
349
+
350
+ ## Development
351
+
352
+ ### Setup
353
+
354
+ ```bash
355
+ # Clone the repository
356
+ git clone https://github.com/openai/codex.git
357
+ cd codex/sdk/python
358
+
359
+ # Install development dependencies
360
+ pip install -e ".[dev]"
361
+ ```
362
+
363
+ ### Running tests
364
+
365
+ ```bash
366
+ pytest tests/ -v
367
+ ```
368
+
369
+ ### Linting and formatting
370
+
371
+ ```bash
372
+ # Lint
373
+ ruff check codex_sdk/
374
+
375
+ # Format
376
+ ruff format codex_sdk/
377
+
378
+ # Type check
379
+ mypy codex_sdk/
380
+ ```
381
+
382
+ ## Release Process
383
+
384
+ Releases are automated via GitHub Actions.
385
+
386
+ ### Creating a release
387
+
388
+ 1. Update the version in `codex_sdk/__init__.py`:
389
+ ```python
390
+ __version__ = "0.1.0"
391
+ ```
392
+
393
+ 2. Commit the version change:
394
+ ```bash
395
+ git add codex_sdk/__init__.py
396
+ git commit -m "Bump version to 0.1.0"
397
+ ```
398
+
399
+ 3. Create and push a tag:
400
+ ```bash
401
+ git tag v0.1.0
402
+ git push origin main --tags
403
+ ```
404
+
405
+ 4. GitHub Actions will automatically:
406
+ - Build the package
407
+ - Publish to PyPI
408
+ - Create a GitHub Release
409
+
410
+ ### Required secrets
411
+
412
+ Set the following secrets in your GitHub repository:
413
+
414
+ - `PYPI_TOKEN`: Your PyPI API token for publishing packages
415
+
416
+ To create a PyPI token:
417
+ 1. Go to https://pypi.org/manage/account/token/
418
+ 2. Create a new token with "Upload packages" scope
419
+ 3. Add it to your GitHub repository secrets
420
+
421
+ ## License
422
+
423
+ Apache-2.0
@@ -0,0 +1,14 @@
1
+ codex_sdk/__init__.py,sha256=ITfGEiUSUFTwh-QP2m2pAnyxw-BYBreucm161frNI80,2442
2
+ codex_sdk/codex.py,sha256=ZTfzyP0Af_mp_6tYk-nRm0hEXjFUnRJUrpIC0RXPaAs,2148
3
+ codex_sdk/codex_options.py,sha256=j6VXVLqXFgfzgfi59uZFXadGSa_Quv3PMhHcY5FXkPs,1174
4
+ codex_sdk/events.py,sha256=fThiDLn3F2osyOYy6X9NYDAlkhpDXBaBdX7j4lvF0nc,2453
5
+ codex_sdk/exec.py,sha256=_LvstngtTbZcDfFdJ778TKrDvgndM1W7BJvYCFZFsAQ,13279
6
+ codex_sdk/items.py,sha256=6Vdw_4_IhZWcimfFlH-NCvOZ8dj6T-ktQdPYb0oiVyk,4206
7
+ codex_sdk/output_schema_file.py,sha256=YbMsIVJ6DE8a7XqMWYXZRVqRFhfPQ-bhu2mGI0zrOkk,1950
8
+ codex_sdk/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
+ codex_sdk/thread.py,sha256=njoS-ku6JXM_1jKMddaqk_4bFrj0z-hPGhVV4UYt0o8,7695
10
+ codex_sdk/thread_options.py,sha256=gCfUS-CPcVK1mAgOPRMYW2tsf3F-vpaN6JF93pp8UqA,1742
11
+ codex_sdk/turn_options.py,sha256=iGfg4Tlq5U9whxIOtuqmErRkrmwJXEfOa-fqcTFwoas,535
12
+ codex_sdk_py-0.0.3.dist-info/METADATA,sha256=9rsofZr1TfaSDdLF0XEs-hIenm9txWb3KYhORtHxaEI,11311
13
+ codex_sdk_py-0.0.3.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
14
+ codex_sdk_py-0.0.3.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.28.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any