# Codex Agent - Documentation

> For the complete documentation index, see [llms.txt](/llms.txt). Markdown is available with `Accept: text/markdown` and `.md` URL variants.

Source: /docs/guides/sandbox-coding-agent-codex

# Codex Agent

Copy pageCopy page

Copy pageCopy page

Codex is OpenAI’s coding agent. On Novita Sandbox, the `codex` template gives you a ready-to-use, isolated environment where Codex can read and edit code, run commands, and complete multi-step engineering tasks autonomously — without directly modifying files on your local machine.
Typical use cases:

- Autonomous coding tasks — hand Codex a prompt (e.g. “add error handling to all API endpoints”) and let it implement changes end to end.

- Working on real repositories — clone a Git repo into the sandbox and have Codex refactor, fix bugs, or add features.

- Safe, unattended automation — run the agent fully automatically inside an isolated sandbox, so file and command actions never affect your own environment.

- Multi-step workflows — start a session to plan, then resume it to carry out each step.

The `codex` template comes with Codex pre-installed, so you can spin up a sandbox and drive Codex in just a few lines. The examples below use the SDK’s unified `Novita` client, create a sandbox from the `codex` template, run the `codex` CLI through `commands.run`, stream its output, then kill the sandbox.

##

[​](#quick-start)

Quick start

`codex exec "<prompt>"`: the `exec` subcommand runs Codex non-interactively — it processes the prompt, prints the result, and exits, instead of opening an interactive session. This is what makes it scriptable inside a sandbox.

`--full-auto`: runs Codex fully autonomously, automatically approving the file and command actions it would otherwise prompt for. Convenient in an isolated sandbox, but use it only in trusted, sandboxed environments. `--skip-git-repo-check` lets Codex run outside a Git repository (by default it expects to run inside one).

Python

```
import os

from novita_sandbox import Novita

def main() -> None:
novita = Novita(api_key=os.environ["NOVITA_API_KEY"])

sandbox = novita.sandbox.create(
"codex",
timeout=3600,
envs={"CODEX_API_KEY": os.environ["CODEX_API_KEY"]},
)
print("Sandbox created:", sandbox.sandbox_id)

try:
execution = sandbox.commands.run(
'codex exec --full-auto --skip-git-repo-check "Hello"',
on_stdout=lambda data: print(data, end=""),
on_stderr=lambda data: print(data, end=""),
timeout=0,
)
print(execution)
finally:
sandbox.kill()
print("Sandbox killed")

if __name__ == "__main__":
main()
```

##

[​](#custom-codex-configuration)

Custom Codex configuration

To make Codex use a custom LLM (custom API token, base URL, or model), write the credentials to `~/.codex/auth.json` and the provider settings to `~/.codex/config.toml` after creating the sandbox and before running `codex`.

Python

```
import os

from novita_sandbox import Novita

def main() -> None:
novita = Novita(api_key=os.environ["NOVITA_API_KEY"])
sandbox = novita.sandbox.create("codex", timeout=3600)
print("Sandbox created:", sandbox.sandbox_id)

try:
sandbox.files.write(
"~/.codex/auth.json",
"""{
"OPENAI_API_KEY": ""
}""",
)
sandbox.files.write(
"~/.codex/config.toml",
"""model_provider = "custom"
model = ""
model_reasoning_effort = "high"
disable_response_storage = true
[model_providers]
[model_providers.custom]
name = "custom"
wire_api = "responses"
requires_openai_auth = true
base_url = ""
""",
)

execution = sandbox.commands.run(
'codex exec --full-auto --skip-git-repo-check "Hello"',
on_stdout=lambda data: print(data, end=""),
on_stderr=lambda data: print(data, end=""),
timeout=0,
)
print(execution)
finally:
sandbox.kill()
print("Sandbox killed")

if __name__ == "__main__":
main()
```

##

[​](#work-on-a-cloned-repository)

Work on a cloned repository

A common workflow is to clone a Git repository into the sandbox and let Codex work on it. Use `sandbox.git.clone` to check out the repo (with credentials for private repos), then run `codex` from inside the cloned directory.

Python

JavaScript & TypeScript

```
import os

from novita_sandbox import Novita

novita = Novita(api_key=os.environ["NOVITA_API_KEY"])
sandbox = novita.sandbox.create("codex", timeout=3600)

try:
sandbox.git.clone(
"https://github.com/your-org/your-repo.git",
path="/home/user/repo",
username="x-access-token",
password=os.environ["GITHUB_TOKEN"],
depth=1,
)

result = sandbox.commands.run(
'codex exec --full-auto --skip-git-repo-check "Add error handling to all API endpoints"',
cwd="/home/user/repo",
on_stdout=lambda data: print(data, end=""),
timeout=0,
)
print(result)
finally:
sandbox.kill()
```

```
import { Novita } from 'novita-sandbox'

const novita = new Novita({ apiKey: process.env.NOVITA_API_KEY })
const sandbox = await novita.sandbox.create('codex', { timeoutMs: 3_600_000 })

try {
await sandbox.git.clone('https://github.com/your-org/your-repo.git', {
path: '/home/user/repo',
username: 'x-access-token',
password: process.env.GITHUB_TOKEN,
depth: 1,
})

const result = await sandbox.commands.run(
'codex exec --full-auto --skip-git-repo-check "Add error handling to all API endpoints"',
{
cwd: '/home/user/repo',
onStdout: (data) => process.stdout.write(data),
timeoutMs: 0,
}
)
console.log(result)
} finally {
await sandbox.kill()
}
```

##

[​](#resume-a-session)

Resume a session

Codex can continue a previous session, so you can run a multi-step workflow across several invocations. Start a session with `--json` to capture the `thread_id` from the first event (`thread.started`), then pass it to `codex exec resume <thread_id>` to continue where you left off.

Python

JavaScript & TypeScript

```
import json
import os

from novita_sandbox import Novita

def main() -> None:
novita = Novita(api_key=os.environ["NOVITA_API_KEY"])

sandbox = novita.sandbox.create(
"codex",
timeout=3600,
envs={"CODEX_API_KEY": os.environ["CODEX_API_KEY"]},
)
print("Sandbox created:", sandbox.sandbox_id)

try:
# Start a new session with JSON output to capture the thread ID.
initial = sandbox.commands.run(
'codex exec --full-auto --skip-git-repo-check --json "Create plan.md with a 3-step plan for a TODO CLI app"',
timeout=0,
)
# The first --json event is thread.started.
thread_id = json.loads(initial.stdout.strip().splitlines()[0])["thread_id"]
print("Thread ID:", thread_id)

# Resume the session with a follow-up task.
follow_up = sandbox.commands.run(
f'codex exec resume {thread_id} --full-auto --skip-git-repo-check "Now implement step 1 of the plan"',
on_stdout=lambda data: print(data, end=""),
timeout=0,
)
print(follow_up)
finally:
sandbox.kill()
print("Sandbox killed")

if __name__ == "__main__":
main()
```

```
import { Novita } from 'novita-sandbox'

const novita = new Novita({ apiKey: process.env.NOVITA_API_KEY })

const sandbox = await novita.sandbox.create('codex', {
timeoutMs: 3_600_000,
envs: { CODEX_API_KEY: process.env.CODEX_API_KEY },
})
console.log('Sandbox created:', sandbox.sandboxId)

try {
// Start a new session with JSON output to capture the thread ID.
const initial = await sandbox.commands.run(
'codex exec --full-auto --skip-git-repo-check --json "Create plan.md with a 3-step plan for a TODO CLI app"',
{ timeoutMs: 0 }
)
// The first --json event is thread.started.
const threadId = JSON.parse(initial.stdout.trim().split('\n')[0]).thread_id
console.log('Thread ID:', threadId)

// Resume the session with a follow-up task.
const followUp = await sandbox.commands.run(
`codex exec resume ${threadId} --full-auto --skip-git-repo-check "Now implement step 1 of the plan"`,
{
onStdout: (data) => process.stdout.write(data),
timeoutMs: 0,
}
)
console.log(followUp)
} finally {
await sandbox.kill()
console.log('Sandbox killed')
}
```

Last modified on August 6, 2026

[OpenVPN](/docs/guides/sandbox-vpn-openvpn)[Claude Code Agent](/docs/guides/sandbox-coding-agent-claude-code)
