AgentForge

Validation

Automatic input and output validation for tools using Zod schemas.

How Validation Works

AgentForge validates tool inputs and outputs automatically:

  1. Input validation — before execute() is called, the LLM's input is validated against the input schema
  2. Output validation — after execute() returns, the result is validated against the output schema
  3. Error handling — validation errors are returned to the LLM as ToolResultMessage with isError: true
const tool = defineTool({
  name: 'create-user',
  description: 'Create a new user',
  input: z.object({
    email: z.string().email(),
    name: z.string().min(1),
    age: z.number().int().min(0).max(150),
  }),
  output: z.object({
    id: z.string().uuid(),
    created: z.boolean(),
  }),
  execute: async (input) => {
    // Input is already validated — email is valid, name is non-empty, age is reasonable
    const id = crypto.randomUUID();
    return { id, created: true };
  },
});

Validation Errors

When the LLM sends invalid input, AgentForge:

  1. Catches the Zod validation error
  2. Formats it as a clear error message
  3. Returns it to the LLM as a tool error
  4. The LLM can retry with corrected input

The agent doesn't crash — it self-corrects.

Schema to JSON Schema

AgentForge converts Zod schemas to JSON Schema for the LLM's tool definition. This happens automatically via zod-to-json-schema:

// This Zod schema:
z.object({
  query: z.string().describe('Search query'),
  limit: z.number().optional().default(10),
})

// Becomes this JSON Schema (sent to the LLM):
{
  "type": "object",
  "properties": {
    "query": { "type": "string", "description": "Search query" },
    "limit": { "type": "number", "default": 10 }
  },
  "required": ["query"]
}

Complex Schemas

Zod supports complex validation that maps to JSON Schema:

const input = z.object({
  filters: z.array(z.object({
    field: z.string(),
    operator: z.enum(['eq', 'gt', 'lt', 'contains']),
    value: z.union([z.string(), z.number()]),
  })),
  sort: z.object({
    field: z.string(),
    direction: z.enum(['asc', 'desc']),
  }).optional(),
});

Next Steps

  • Retry — automatic retry with backoff
  • Serialization — how tool results are serialized