Skip to content

CodexAgent output schema is empty when using Zod 4 (zod-to-json-schema v3 incompatibility) #82

@enitrat

Description

@enitrat

Bug

When using CodexAgent with an outputSchema (a Zod 4 object), the generated JSON schema sent to OpenAI is empty — just {"$schema": "..."} with no type or properties. OpenAI rejects this:

"Invalid schema for response_format 'codex_output_schema':
 schema must be a JSON Schema of 'type: "object"', got 'type: "None"'."

Root cause

src/agents/cli.ts uses zod-to-json-schema v3 to convert the Zod schema:

const { zodToJsonSchema } = await import("zod-to-json-schema");
const jsonSchema = zodToJsonSchema(params.options.outputSchema);

zod-to-json-schema v3 was written for Zod 3's internal _def structure. Zod 4 changed its internals, so the library silently falls through every type check and produces a bare { $schema: "..." } object. The package is officially deprecated in favor of Zod 4's native .toJSONSchema().

Minimal Reproducible Example

mkdir zod4-mre && cd zod4-mre
npm init -y
npm install zod@4 zod-to-json-schema@3

mre.mjs

import { z } from "zod";
import { zodToJsonSchema } from "zod-to-json-schema";

const OutputSchema = z.object({
  name: z.string(),
  age: z.number(),
});

// Bug: produces empty schema
console.log("zod-to-json-schema v3:");
console.log(JSON.stringify(zodToJsonSchema(OutputSchema), null, 2));

// Fix: Zod 4 built-in method
console.log("\nZod 4 .toJSONSchema():");
console.log(JSON.stringify(OutputSchema.toJSONSchema(), null, 2));
node mre.mjs

Output:

zod-to-json-schema v3:
{
  "$schema": "http://json-schema.org/draft-07/schema#"
}

Zod 4 .toJSONSchema():
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "name": { "type": "string" },
    "age": { "type": "number" }
  },
  "required": ["name", "age"],
  "additionalProperties": false
}

Tested with zod 4.3.6 + zod-to-json-schema 3.25.1.

Related

PR #77 addresses this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions