ADR-0010: Zod v4 for schema validation
ADR-0010: Zod v4 for schema validation
Section titled “ADR-0010: Zod v4 for schema validation”Status: Accepted Date: 2026-04-20
Context
Section titled “Context”Core types are compile-time only. Every byte that crosses the boundary into our runtime — agent configs loaded from disk, tool inputs produced by LLMs, delegated tasks sent between agents — is just a string or Record<string, unknown> until something validates it. Without a validator, ADR-0006’s security guarantee is aspirational: a TypeScript readonly modifier is erased by the time the code runs.
We need a validation library. Three serious candidates exist: Zod, Valibot, and ArkType. They do the same job; the trade-offs differ.
Decision
Section titled “Decision”Use Zod 4.3.6 as the validation library, pinned to that exact version. Schemas live in the separate @agent-platform/schemas package (see ADR-0011).
Consequences
Section titled “Consequences”- Ecosystem and maturity. Zod is the most battle-tested of the three candidates. At trust boundaries, conservative is the right default — we want the library to have had its bugs found by other teams before ours.
- JSON Schema export. Zod 4 has
z.toJSONSchemabuilt in. This matters because tool definitions must advertise JSON Schemas to LLMs for function-calling. Having the conversion built in avoids a second dependency or a hand-maintained schema layer. - Bundle size. ~30KB gzipped. A non-issue on Node.js; manageable on Cloudflare Workers within their size limits. If the runtime platform turns out to be tight on size, the schema shapes translate nearly 1:1 to Valibot — this is not a one-way door.
- Strict-mode ergonomics. Zod’s
.strict()rejects unknown object keys, which is the mechanism that makesDelegatedContextSchemaan ADR-0006 enforcement point. No custom validator code needed. - Tight TypeScript inference.
z.inferplays well with our strict compiler settings, includingexactOptionalPropertyTypesandreadonly. - Pinned version.
save-exact=truein.npmrcmeans an upgrade is a conscious decision, not a side effect. Zod 4 is stable but the minor cadence is brisk.
Alternatives considered
Section titled “Alternatives considered”- Valibot. ~3KB gzipped, modular by design. Smaller community; JSON Schema export is a separate plugin with less breadth. Right choice if bundle size dominates (e.g., edge Workers with many schemas). Not our bottleneck yet.
- ArkType. Fastest parser in the category, uses TypeScript-like syntax for schemas. Smallest community of the three; ecosystem tooling (editor plugins, error formatters) less developed. Would reconsider in a year.
- Hand-rolled type guards. No schema declaration, no JSON Schema export, no composition. Verbose, error-prone at scale, and requires us to maintain a separate “here’s how to check an AgentDefinition” file that will inevitably drift from the types.
Migration posture
Section titled “Migration posture”If we later want to switch to Valibot (bundle size) or ArkType (perf), the Assert<Equals<z.infer<typeof S>, CoreType>> checks would detect drift during migration, and individual schema files are small. Budget: roughly a day of focused work per ~10 schemas. This is not a decision we’re stuck with.