# How the OpenAI Codex Plugin Handles Structured Output Parsing from Codex Responses

> Learn how the OpenAI Codex plugin handles structured output parsing from Codex responses. Discover the parseStructuredOutput helper for safe JSON parsing and error handling.

- Repository: [OpenAI/codex-plugin-cc](https://github.com/openai/codex-plugin-cc)
- Tags: how-to-guide
- Published: 2026-08-05

---

**The OpenAI Codex plugin parses structured output from Codex responses using a dedicated `parseStructuredOutput` helper in `plugins/codex/scripts/lib/codex.mjs`, which safely wraps `JSON.parse()` with fallback handling for empty responses and malformed JSON.**

When integrating OpenAI Codex into code-review and task-handling workflows, the `codex-plugin-cc` repository must reliably extract machine-readable data from the model's raw string output. This article examines how the plugin transforms Codex responses into structured payloads, where this parsing occurs in the codebase, and why this design ensures robust downstream processing.

## The `parseStructuredOutput` Parsing Logic

Located in [`plugins/codex/scripts/lib/codex.mjs`](https://github.com/openai/codex-plugin-cc/blob/main/plugins/codex/scripts/lib/codex.mjs#L1188-L1205), the `parseStructuredOutput` function serves as the single entry point for structured output parsing.

### Function Signature and Behavior

```javascript
export function parseStructuredOutput(rawOutput, fallback = {}) {
  if (!rawOutput) {
    return {
      parsed: null,
      parseError: fallback.failureMessage ?? "Codex did not return a final structured message.",
      rawOutput: rawOutput ?? "",
      ...fallback
    };
  }

  try {
    return {
      parsed: JSON.parse(rawOutput),
      parseError: null,
      rawOutput,
      ...fallback
    };
  } catch (error) {
    return {
      parsed: null,
      parseError: error.message,
      rawOutput,
      ...fallback
    };
  }
}

```

The function implements a three-branch strategy:

- **Empty input guard**: Returns a default payload with `parsed: null` and a configurable error message when `rawOutput` is falsy
- **Successful parse**: Returns the parsed JSON object with `parseError: null`
- **Malformed JSON**: Catches `JSON.parse()` exceptions and surfaces the error message in `parseError`

The `fallback` object is spread into every return path, ensuring callers receive a consistent shape that always includes their contextual metadata—typically `status` and `failureMessage` fields from the Codex turn result.

## Where Structured Output Parsing Is Invoked

The parsing function is called immediately after a Codex turn completes, as implemented in [`plugins/codex/scripts/codex-companion.mjs`](https://github.com/openai/codex-plugin-cc/blob/main/plugins/codex/scripts/codex-companion.mjs#L418-L425):

```javascript
const result = await runAppServerTurn(...);
const parsed = parseStructuredOutput(result.finalMessage, {
  status: result.status,
  failureMessage: result.error?.message ?? result.stderr
});

```

This integration pattern demonstrates how structured output parsing bridges the raw model response and downstream rendering utilities. The resulting `parsed` object carries four essential properties:

| Property | Description |
|----------|-------------|
| `parsed` | The deserialized JSON object, or `null` if parsing failed |
| `parseError` | Error description string, or `null` on success |
| `rawOutput` | Original string from Codex for debugging or display |
| Fallback fields | Contextual metadata merged from the second argument |

The payload is then passed to `renderReviewResult` or `renderTaskResult` in [`plugins/codex/scripts/lib/render.mjs`](https://github.com/openai/codex-plugin-cc/blob/main/plugins/codex/scripts/lib/render.mjs), which produces human-readable output for the user interface.

## Practical Code Examples

### Stand-Alone Parser Usage

```javascript
import { parseStructuredOutput } from "./plugins/codex/scripts/lib/codex.mjs";

const raw = '{"summary":"All good","details":{"files":3}}';
const result = parseStructuredOutput(raw, { status: "success" });

console.log(result.parsed);      // { summary: 'All good', details: { files: 3 } }
console.log(result.parseError);  // null

```

### Handling Malformed Output

```javascript
import { parseStructuredOutput } from "./plugins/codex/scripts/lib/codex.mjs";

const raw = 'Not a JSON string';
const result = parseStructuredOutput(raw, {
  status: "error",
  failureMessage: "Bad output"
});

console.log(result.parsed);      // null
console.log(result.parseError);  // "Unexpected token N in JSON at position 0"

```

### Integration Within a Codex Turn

```javascript
const turn = await runAppServerTurn(workspaceRoot, { /* options */ });

const payload = parseStructuredOutput(turn.finalMessage, {
  status: turn.status,
  failureMessage: turn.error?.message ?? turn.stderr
});

if (payload.parseError) {
  console.error("Failed to parse structured output:", payload.parseError);
  // Surface raw output to user for manual inspection
}

```

## Architectural Design Benefits

The structured output parsing system in `codex-plugin-cc` follows three core principles:

- **Defensive programming**: The plugin never throws on malformed Codex responses. All error conditions are captured in `parseError`, preventing cascading failures in review and task pipelines.
- **Contract stability**: Downstream code receives a predictable object shape regardless of parsing success or failure. This eliminates null-check branching scattered through rendering and logging utilities.
- **Modularity**: Isolating parsing logic in `codex.mjs` allows independent testing and future extension—such as supporting alternative serialization formats like YAML or MessagePack—without touching networking or UI layers.

## Summary

- The **primary parsing function** `parseStructuredOutput` lives in `plugins/codex/scripts/lib/codex.mjs` (lines 1188-1205)
- It wraps `JSON.parse()` with **empty-input handling**, **exception catching**, and **fallback field merging**
- Invocation occurs in `codex-companion.mjs` (lines 418-425) immediately after `runAppServerTurn` completes
- Output flows to rendering utilities in `render.mjs` via a **uniform contract** with `parsed`, `parseError`, and `rawOutput` fields
- The design ensures **graceful degradation** when Codex returns malformed or empty structured output

## Frequently Asked Questions

### What happens if Codex returns an empty response?

The `parseStructuredOutput` function detects falsy `rawOutput` values and returns a payload with `parsed: null` and a configurable error message. By default, this message reads "Codex did not return a final structured message" unless overridden via `fallback.failureMessage`.

### Can the parser handle non-JSON formats?

No. The current implementation strictly uses `JSON.parse()` as implemented in `codex.mjs`. Supporting additional formats would require extending `parseStructuredOutput` with format detection or adding a new parser module while preserving the same return contract.

### Where is the parsed output consumed in the plugin?

The parsed payload is consumed by rendering utilities in `plugins/codex/scripts/lib/render.mjs`, specifically `renderReviewResult` and `renderTaskResult` functions. These utilities transform the structured data into human-readable terminal output for code reviews and task completions.

### How does this parsing approach affect testability?

Isolating parsing logic in a pure function makes unit testing straightforward. The `parseStructuredOutput` function has no side effects and depends only on its arguments, allowing comprehensive coverage of success paths, JSON syntax errors, and empty input conditions without mocking network or file system dependencies.