Skip to main content

Codex

The Codex harness adapter connects HarnessAgent to the Codex app-server. The adapter runs a bridge inside the sandbox and streams Codex thread events back to the host over a sandbox-exposed WebSocket.

Note

Harness packages are experimental. Expect breaking changes between releases as this early API gets further refined.

Setup

pnpm add @ai-sdk/harness @ai-sdk/harness-codex @ai-sdk/sandbox-vercel
npm install @ai-sdk/harness @ai-sdk/harness-codex @ai-sdk/sandbox-vercel
yarn add @ai-sdk/harness @ai-sdk/harness-codex @ai-sdk/sandbox-vercel
bun add @ai-sdk/harness @ai-sdk/harness-codex @ai-sdk/sandbox-vercel

The adapter bootstraps the Codex bridge dependencies inside the sandbox when the first session starts.

Import

import { codex, createCodex } from '@ai-sdk/harness-codex';

codex is equivalent to createCodex() with its default configuration.

Basic Usage

import { HarnessAgent } from '@ai-sdk/harness/agent';
import { codex } from '@ai-sdk/harness-codex';
import { createVercelNetworkSandboxSession } from '@ai-sdk/sandbox-vercel';

const agent = new HarnessAgent({
  harness: codex,
  model: 'gpt-5.6-luna',
});

const sandboxSession = await createVercelNetworkSandboxSession({
  runtime: 'node24',
  ports: [4000],
  template: await agent.getSandboxTemplate(),
});
const session = await agent.createSession({ sandboxSession });

let exitCode = 0;
try {
  const result = await agent.stream({
    session,
    prompt: 'Check the test failures and fix the production code.',
  });

  for await (const part of result.stream) {
    if (part.type === 'text-delta') {
      process.stdout.write(part.text);
    }
  }
} catch (err) {
  exitCode = 1;
  console.error(err);
} finally {
  await session.destroy();
  await sandboxSession.destroy();
  process.exit(exitCode);
}

To use this agent, ensure environment variables include VERCEL_OIDC_TOKEN for Vercel Sandbox, and one of the variables listed under authentication for Codex.

Adapter Settings

Use createCodex() to configure the runtime:

const harness = createCodex({
  reasoningEffort: 'high',
  webSearch: true,
  codexConfig: {
    model_verbosity: 'low',
  },
});

Settings:

  • auth: authentication mode (auto, direct, or ai-gateway) or an isolated authentication environment.
  • credentialForwarding: optional synchronous or asynchronous callback that customizes each credential immediately before the harness adapter forwards it into a sandbox process. It receives the credential value that would otherwise be forwarded (either the real credential or a masked value) and the environment variable name used to expose it. This callback only controls the value forwarded into the sandbox process. It does not restrict which credentials the harness adapter can discover, read, or otherwise access in the host process.
  • codexConfig: additional native Codex configuration. Values pass through as provided, so use the snake_case keys from Codex's config.toml reference. The adapter's managed values take precedence over conflicting entries.
  • mcpServers: MCP server definitions keyed by server name.
  • reasoningEffort: low, medium, high, xhigh, or max.
  • webSearch: allow live web search.
  • port: bridge port override.
  • startupTimeoutMs: maximum time to wait for the bridge to start.
  • reconnect: reconnect timing after an established bridge WebSocket connection drops. maxElapsedMs controls the total retry window, including connection establishment and backoff delays, and defaults to 30 seconds. initialDelayMs defaults to 50 milliseconds, and maxDelayMs defaults to 2 seconds. These retries use exponential backoff and are separate from startupTimeoutMs. They cannot recover when the sandbox, bridge process, or bridge endpoint is permanently unavailable.
  • mintBridgeToken: synchronous function that receives the sandbox id and returns the bridge authentication token. By default, the adapter generates a random 32-byte token. Custom implementations must return a suitably secret token.

Built-in Tool Filtering

Codex supports activeTools and inactiveTools for bash, webSearch, apply_patch, and view_image. Host tools are filtered before they are sent to Codex. Native Codex configuration disables bash, view_image, and webSearch individually. When bash, apply_patch, and view_image are all inactive, the adapter disables Codex environments and explicitly disables bash and view_image. When apply_patch is inactive but bash or view_image remains active, the adapter installs a Codex PreToolUse hook that denies patch execution. Before starting each turn, the adapter checks that Codex loaded and trusted the hook and fails the turn if it did not. Including webSearch in activeTools does not enable it on its own; set webSearch: true on createCodex() to allow live search.

const agent = new HarnessAgent({
  harness: createCodex(),
  sandbox: createVercelSandbox({ runtime: 'node24', ports: [4000] }),
  inactiveTools: ['apply_patch'],
});

Structured Output

Codex supports schema-backed HarnessAgent structured output. The adapter passes the JSON Schema through the Codex app-server's turn/start outputSchema parameter.

Authentication

The auth setting selects how credentials are resolved from the host environment:

  • auto (default): use AI Gateway credentials when available, then fall back to direct OpenAI credentials.
  • direct: use OpenAI credentials.
  • ai-gateway: use AI Gateway credentials.

When the sandbox supports additive request transformations, the bridge receives placeholders and the adapter injects credentials into matching outbound requests. Sandboxes without that capability retain direct credential forwarding.

Supported environment variables:

  • VERCEL_OIDC_TOKEN
  • AI_GATEWAY_API_KEY
  • AI_GATEWAY_BASE_URL
  • OPENAI_API_KEY
  • CODEX_API_KEY
  • OPENAI_BASE_URL
  • OPENAI_ORGANIZATION
  • OPENAI_PROJECT

If no applicable credential environment variable is set, the adapter attempts to resolve a native subscription from the host system unless AI Gateway authentication is selected.

Select a specific authentication mode when you do not want automatic detection:

const directHarness = createCodex({ auth: 'direct' });
const gatewayHarness = createCodex({ auth: 'ai-gateway' });

Pass an authentication environment to use programmatically resolved credentials without reading process.env:

const harness = createCodex({
  auth: { OPENAI_API_KEY: await resolveOpenAIToken() },
});

The supplied record replaces the host environment for authentication discovery. Only recognized authentication variables are forwarded.

For OpenAI-compatible endpoints, select direct and set OPENAI_BASE_URL.

Sandbox

Codex requires a network sandbox with at least one exposed port, e.g. @ai-sdk/sandbox-vercel:

const sandboxSession = await createVercelNetworkSandboxSession({
  runtime: 'node24',
  ports: [4000],
  template: await agent.getSandboxTemplate(),
});

Built-in Tools

The adapter exposes these Codex built-ins through agent.tools:

  • bash and webSearch use the common cross-harness tool names.
  • apply_patch accepts Codex's freeform patch string.
  • view_image accepts a local image path, with optional detail and environment_id fields.

Codex file changes may also appear as dynamic fileChange tool parts because some Codex file mutations do not originate from a visible model-callable tool.

Known Limitations

Codex does not currently support built-in tool approval requests. Use permissionMode: 'allow-all' with this adapter. Host-executed AI SDK tool approvals still work.

When the app-server must cold-resume a thread, Codex does not provide raw events for apply_patch and view_image, so those tool calls and results cannot be surfaced for that resumed thread.