You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit b1cbf62
Browse filesBrowse the repository at this point in the historyBrowse files
## Why
The Python SDK currently exposes sandbox selection differently depending
on where it is used: thread lifecycle methods accept `SandboxMode`,
while turns accept the lower-level `SandboxPolicy` shape. For the common
case of choosing an access level, that leaks app-server wire details
into otherwise straightforward SDK usage.
This makes the common path explicit and discoverable: callers choose a
named sandbox preset once, using the same keyword on threads and turns.
The preset name `workspace_write` also makes the granted capability
clear at the callsite.
## What changed
- Added a root-level `Sandbox` enum with documented 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.
- Documented that omitting `sandbox=` delegates to app-server's
configured default, while explicit turn overrides remain sticky for
subsequent turns.
- Updated sync and async thread lifecycle and turn APIs to consistently
accept `sandbox=Sandbox...`, translating to the existing app-server
thread and turn representations internally.
- Updated the public API artifact generator so regenerated SDK wrappers
retain the friendly enum shape.
- Replaced low-level policy construction in Python docs, examples, and
the walkthrough notebook with the preset API.
- Added focused coverage for root exports, method signatures,
preset-to-wire mapping, and rejection of raw string sandbox inputs.
## API impact
High-level turn calls now use `sandbox=` instead of `sandbox_policy=`:
```python
from openai_codex import Codex, Sandbox
with Codex() as codex:
thread = codex.thread_start(sandbox=Sandbox.workspace_write)
result = thread.run("Review the diff only.", sandbox=Sandbox.read_only)
```
`thread_start(...)` already defaults to `ApprovalMode.auto_review`, so
normal writable usage is concise:
```python
with Codex() as codex:
thread = codex.thread_start(sandbox=Sandbox.workspace_write)
thread.run("Update the files in this workspace.")
```
With that combination, edits inside `cwd` and configured writable roots
run within the workspace-write sandbox. Operations that require
approval, such as edits outside those roots, are routed through auto
review. When `sandbox=` is omitted, app-server resolves its configured
default. A sandbox supplied to `run(...)` or `turn(...)` applies to that
turn and subsequent turns.
## Test coverage
- `sdk/python/tests/test_public_api_signatures.py` covers the public
export and parameter names, including the default approval mode.
- `sdk/python/tests/test_public_api_runtime_behavior.py` covers preset
mappings to the existing wire types and raw string rejection.
review = thread.run("Review the diff only.", sandbox=Sandbox.read_only)
52
+
```
53
+
54
+
Available presets:
55
+
56
+
-`Sandbox.read_only`: read files without allowing writes.
57
+
-`Sandbox.workspace_write`: the normal default for projects with a recorded trust decision; read files and write inside the workspace and configured writable roots.
58
+
-`Sandbox.full_access`: run without filesystem access restrictions.
59
+
60
+
When `sandbox=` is omitted, app-server uses its configured default. A sandbox
61
+
passed to `run(...)` or `turn(...)` applies to that turn and subsequent turns
result = thread.run("Review the diff only.", sandbox=Sandbox.read_only)
196
+
```
197
+
198
+
Presets:
199
+
200
+
-`Sandbox.read_only`: read files without allowing writes.
201
+
-`Sandbox.workspace_write`: the normal default for projects with a recorded trust decision; read files and write inside the workspace and configured writable roots.
202
+
-`Sandbox.full_access`: run without filesystem access restrictions.
203
+
204
+
When `sandbox=` is omitted, app-server uses its configured default. A sandbox
205
+
passed to `run(...)` or `turn(...)` applies to that turn and subsequent turns.
result = thread.run("Review only.", sandbox=Sandbox.read_only)
61
+
```
62
+
63
+
The presets are:
64
+
65
+
-`Sandbox.read_only`: read files without allowing writes.
66
+
-`Sandbox.workspace_write`: the normal default for projects with a recorded trust decision; read files and write inside the workspace and configured writable roots.
67
+
-`Sandbox.full_access`: run without filesystem access restrictions.
68
+
69
+
When `sandbox=` is omitted, app-server uses its configured default. A turn
70
+
sandbox override applies to that turn and subsequent turns.
52
71
53
72
## Why only `thread_start(...)` and `thread_resume(...)`?
review = thread.run("Review the diff only.", sandbox=Sandbox.read_only)
94
+
```
95
+
96
+
Available presets:
97
+
98
+
-`Sandbox.read_only`: read files without allowing writes.
99
+
-`Sandbox.workspace_write`: the normal default for projects with a recorded trust decision; read files and write inside the workspace and configured writable roots.
100
+
-`Sandbox.full_access`: run without filesystem access restrictions.
101
+
102
+
When `sandbox=` is omitted, app-server uses its configured default. A turn
103
+
override also becomes the sandbox for subsequent turns on that thread.
104
+
105
+
## 5) Continue the same thread (multi-turn)
80
106
81
107
```python
82
108
from openai_codex import Codex
@@ -91,7 +117,7 @@ with Codex() as codex:
91
117
print("second:", second.final_response)
92
118
```
93
119
94
-
## 5) Async parity
120
+
## 6) Async parity
95
121
96
122
Use `async with AsyncCodex()` as the normal async entrypoint. `AsyncCodex`
97
123
initializes lazily, and context entry makes startup/shutdown explicit.
@@ -111,7 +137,7 @@ async def main() -> None:
111
137
asyncio.run(main())
112
138
```
113
139
114
-
## 6) Resume an existing thread
140
+
## 7) Resume an existing thread
115
141
116
142
```python
117
143
from openai_codex import Codex
@@ -124,7 +150,7 @@ with Codex() as codex:
124
150
print(result.final_response)
125
151
```
126
152
127
-
## 7) Public app-server types
153
+
## 8) Public app-server types
128
154
129
155
The convenience wrappers live at the package root. Public app-server value and
130
156
event types live under:
@@ -133,7 +159,7 @@ event types live under:
133
159
from openai_codex.types import ThreadReadResponse, Turn, TurnStatus
134
160
```
135
161
136
-
## 8) Next stops
162
+
## 9) Next stops
137
163
138
164
- API surface and signatures: `docs/api-reference.md`
0 commit comments