Skip to content
Development
Agent

codex

Research notes on OpenAI Codex's configuration, credential discovery, and runtime behavior based on agent-jj implementation.

From plugin
sandbox-agent
1.5k4 skills4 agents2 commands1 MCP

How it fires

How this agent gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.

Context preview

The summary Claude sees to decide when to auto-load this agent.

Research notes on OpenAI Codex's configuration, credential discovery, and runtime behavior based on agent-jj implementation.

Agent definition

codex.md

Codex Research

Research notes on OpenAI Codex's configuration, credential discovery, and runtime behavior based on agent-jj implementation.

Overview

  • **Provider**: OpenAI
  • **Execution Method (this repo)**: Codex App Server (JSON-RPC over stdio)
  • **Execution Method (alternatives)**: SDK (`@openai/codex-sdk`) or CLI binary
  • **Session Persistence**: Thread ID (string)
  • **Import**: Dynamic import to avoid bundling issues
  • **Binary Location**: `~/.nvm/versions/node/current/bin/codex` (npm global install)

SDK Architecture

**The SDK wraps a bundled binary** - it does NOT make direct API calls.

  • The TypeScript SDK includes a pre-compiled Codex binary
  • When you use the SDK, it spawns this binary as a child process
  • Communication happens via stdin/stdout using JSONL (JSON Lines) format
  • The binary itself handles the actual communication with OpenAI's backend services

Sources: [Codex SDK docs](https://developers.openai.com/codex/sdk/), [GitHub](https://github.com/openai/codex)

CLI Usage (Alternative to App Server / SDK)

You can use the `codex` binary directly instead of the SDK:

Interactive Mode

codex "your prompt here"
codex --model o3 "your prompt"

Non-Interactive Mode (`codex exec`)

codex exec "your prompt here"
codex exec --json "your prompt"  # JSONL output
codex exec -m o3 "your prompt"
codex exec --dangerously-bypass-approvals-and-sandbox "prompt"
codex exec resume --last  # Resume previous session

Key CLI Flags

| Flag | Description | |------|-------------| | `--json` | Print events to stdout as JSONL | | `-m, --model MODEL` | Model to use | | `-s, --sandbox MODE` | `read-only`, `workspace-write`, `danger-full-access` | | `--full-auto` | Auto-approve with workspace-write sandbox | | `--dangerously-bypass-approvals-and-sandbox` | Skip all prompts (dangerous) | | `-C, --cd DIR` | Working directory | | `-o, --output-last-message FILE` | Write final response to file | | `--output-schema FILE` | JSON Schema for structured output |

Session Management

codex resume          # Pick from previous sessions
codex resume --last   # Resume most recent
codex fork --last     # Fork most recent session

Credential Discovery

Priority Order

1. User-configured credentials (from `credentials` array) 2. Environment variable: `CODEX_API_KEY` 3. Environment variable: `OPENAI_API_KEY` 4. Bootstrap extraction from config files

Config File Location

| Path | Description | |------|-------------| | `~/.codex/auth.json` | Primary auth config |

Auth File Structure

// API Key authentication
{
  "OPENAI_API_KEY": "sk-..."
}

// OAuth authentication
{
  "tokens": {
    "access_token": "..."
  }
}

SDK Usage

Client Initialization

import { Codex } from "@openai/codex-sdk";

// With API key
const codex = new Codex({ apiKey: "sk-..." });

// Without API key (uses default auth)
const codex = new Codex();

Dynamic import is used to avoid bundling the SDK:

const { Codex } = await import("@openai/codex-sdk");

Thread Management

// Start new thread
const thread = codex.startThread();

// Resume existing thread
const thread = codex.resumeThread(threadId);

Running Prompts

const { events } = await thread.runStreamed(prompt);

for await (const event of events) {
  // Process events
}

App Server Protocol (JSON-RPC)

Codex App Server uses JSON-RPC 2.0 over JSONL/stdin/stdout (no port required).

Key Requests

  • `initialize` → returns server info
  • `thread/start` → starts a new thread
  • `turn/start` → sends user input for a thread

Event Notifications (examples)

{ "method": "thread/started", "params": { "thread": { "id": "thread_abc123" } } }
{ "method": "item/completed", "params": { "item": { "type": "agentMessage", "text": "..." } } }
{ "method": "turn/completed", "params": { "threadId": "thread_abc123", "turn": { "items": [] } } }

Approval Requests (server → client)

The server can send JSON-RPC requests (with `id`) for approvals:

  • `item/commandExecution/requestApproval`
  • `item/fileChange/requestApproval`

These require JSON-RPC responses with a decision payload.

App Server WebSocket Transport (Experimental)

Codex app-server also supports an experimental WebSocket transport:

codex app-server --listen ws://127.0.0.1:4500

Transport constraints

  • Listen URL must be `ws://IP:PORT` (not `localhost`, not `http://...`)
  • One JSON-RPC message per WebSocket text frame
  • Incoming: text frame JSON is parsed as a JSON-RPC message
  • Outgoing: JSON-RPC messages are serialized and sent as text frames
  • Ping/Pong is handled; binary frames are ignored

Connection lifecycle

  • Each accepted socket becomes a distinct connection with its own session state
  • Every connection must send `initialize` first
  • Sending non-`initialize` requests before init returns `"Not initialized"`
  • Sending `initialize` twice on the same connection returns `"Already initialized"`
  • Broadcast notifications are only sent to initialized connections

Operational notes

  • WebSocket mode is currently marked experimental/unsupported upstream
  • It is a raw WS server (no built-in TLS/auth); keep it on loopback or place it behind your own secure proxy/tunnel

Upstream implementation references (openai/codex `main`, commit `03adb5db`)

  • `codex-rs/app-server/src/transport.rs`
  • `codex-rs/app-server/src/message_processor.rs`
  • `codex-rs/app-server/README.md`

Response Schema

// CodexRunResultSchema
type CodexRunResult = string | {
  result?: string;
  output?: string;
  message?: string;
  // ...additional fields via passthrough
};

Content is extracted in priority order: `result` > `output` > `message`

Thread ID Retrieval

Thread ID can be obtained from multiple sources:

1. `thread.started` event's `thread_id` property 2. Thread object's `id` getter (after first turn) 3. Thread object's `

Read more
Ships withsandbox-agent

Run Coding Agents in Sandboxes. Control Them Over HTTP. Supports Claude Code, Codex, OpenCode, and Amp.

Get the whole plugin
Stats
1,528
Stars
119
Forks
Maintained
Maintenance
TypeScript
Language
Apache-2.0
License
1mo ago
Last commit
6mo ago
Created

Repo: rivet-dev/sandbox-agent