Cordium documentation · Latest

Codex

This example drives OpenAI Codex from your own program via the Cordium SDKs to implement features in a TypeScript web application. For each task, the program starts an ephemeral Workspace from a pre-built Template in which the repository is already cloned and its dependencies are already installed, runs codex exec inside it, runs the test suite, collects the resulting diff and Codex's summary, and deletes the Workspace. This orchestration pattern is the building block of internal coding-agent platforms, evaluation harnesses and "best-of-N" setups (read a parallel version here).

As in all the AI examples, the OpenAI API key never enters the Workspace. Codex is configured with a custom model provider that points to an Octelium LLM Service, which injects the key on a per-request basis (read more here).

The Octelium Service

A Cluster administrator stores the OpenAI API key as an Octelium Secret and exposes the OpenAI API as an LLM Service:

octeliumctl create secret openai-api-key
kind: Service metadata: name: openai spec: mode: LLM config: upstream: url: https://api.openai.com llm: protocol: OPENAI auth: bearer: fromSecret: openai-api-key

The Users who run the program must be allowed to access the openai Service by a Policy.

The Template

The codex Template of the storefront Space clones the repository with a read-only token, installs Codex, configures its model provider and installs the npm dependencies. Since these are ON_CREATE tasks, they run once in the Template's pre-build and every Workspace starts with everything ready:

spec: image: registry: url: node:24-bookworm repository: url: https://github.com/acme-corp/storefront cloneOptions: branch: main authentication: http: username: x-access-token password: fromSecret: github-read-token.storefront.cordium runtime: envVars: # A placeholder. Octelium injects the real API key and never forwards this one. - key: OPENAI_API_KEY value: injected-by-octelium - key: CI value: "true" tasks: - name: install-codex type: ON_CREATE runAsRoot: true onFailure: ON_FAILURE_ABORT run: npm install -g @openai/codex - name: configure-codex type: ON_CREATE workingDir: /workspace onFailure: ON_FAILURE_ABORT run: | mkdir -p "$HOME/.codex" cat > "$HOME/.codex/config.toml" <<'EOF' model_provider = "octelium" [model_providers.octelium] name = "OpenAI via Octelium" base_url = "http://openai/v1" env_key = "OPENAI_API_KEY" wire_api = "responses" EOF - name: install-dependencies type: ON_CREATE workingDir: /workspace/repo onFailure: ON_FAILURE_ABORT run: npm ci limit: cpu: millicores: 4000 memory: megabytes: 8192 storage: megabytes: 20000

Create and pre-build the Template:

cordium create secret github-read-token.storefront.cordium --from-env GITHUB_READ_TOKEN cordium create template codex.storefront.cordium --file codex.yaml cordium build codex.storefront.cordium
note

The read-only token is used by the Workspace's git credential helper, which means that it is readable inside the Workspace. Use a fine-grained token restricted to the Contents: read permission of the repository. To keep even that token out of the Workspace, clone the repository through an Octelium HTTP Service in a POST_START task instead, as shown in the Claude Code example.

The Orchestrator

The following Python program uses the Cordium SDK to run one Codex task and return its result. It runs with your own identity, or with a WORKLOAD User's identity in automation (read more about authenticating the SDKs here):

import sys from dataclasses import dataclass from cordium import Cordium, shell_quote @dataclass class Result: workspace: str codex_exit_code: int tests_passed: bool summary: str diff: str def run_task(client: Cordium, task: str) -> Result: workspace = client.workspaces.run( template="codex.storefront.cordium", ephemeral=True, display_name=f"Codex: {task[:40]}", timeout=600, ) try: codex = workspace.exec( "codex exec --sandbox danger-full-access " f"--output-last-message /tmp/summary.md {shell_quote(task)} < /dev/null", cwd="/workspace/repo", timeout=3600, ) tests = workspace.exec("npm test", cwd="/workspace/repo", timeout=1200) diff = workspace.exec("git add -A && git diff --cached", cwd="/workspace/repo", check=True) summary = workspace.files.read_text("/tmp/summary.md") if codex.exit_code == 0 else "" return Result(workspace.name, codex.exit_code, tests.exit_code == 0, summary, diff.stdout) finally: workspace.delete() if __name__ == "__main__": with Cordium() as client: result = run_task(client, sys.argv[1]) print(result.summary) print(f"Tests passed: {result.tests_passed}") with open("codex.patch", "w") as f: f.write(result.diff)
export OCTELIUM_DOMAIN=<DOMAIN> python run_codex.py "Add a 'Sort by price' option to the product list page, with unit tests" git apply codex.patch

Here are a few notes about this program:

  • workspaces.run() creates and starts the Workspace, and waits until it is RUNNING. Since the Template is pre-built, this typically takes a few seconds.

  • codex exec runs non-interactively, streams its progress to stderr and writes its final message to /tmp/summary.md. --sandbox danger-full-access disables Codex's own sandbox, which is meant for developer machines; the Workspace is the sandbox here. Its standard input is redirected from /dev/null since exec sessions do not signal the end of the standard input.

  • exec returns the exit code instead of raising, unless check=True is passed. Every exec session counts as activity, so the Workspace is not stopped by the inactivity timeout while Codex is working.

  • The Workspace is always deleted, even if any step fails. To debug a failed run, skip the deletion and open a terminal in it from the web portal.

The equivalent flow is also available via the CLI, for example from a shell script:

cordium create ws --template codex.storefront.cordium --ephemeral --start cordium exec --no-stdin -w /workspace/repo <WORKSPACE> -- \ sh -c 'codex exec --sandbox danger-full-access "Add a Sort by price option" < /dev/null' cordium exec --no-stdin -w /workspace/repo <WORKSPACE> -- sh -c 'git add -A && git diff --cached' > codex.patch cordium delete ws <WORKSPACE>