Schema Libraries
Choose from built-in, Zod, Valibot, or ArkType for validation
Agentuity uses the StandardSchema interface for validation, which means you can use any compatible library.
Choosing a Library
| Library | Syntax | Best For |
|---|---|---|
@agentuity/schema | s.object({ name: s.string() }) | Zero dependencies, basic validation |
| Zod | z.object({ name: z.string() }) | AI SDK integration (.describe() support) |
| Valibot | v.object({ name: v.string() }) | Smallest bundle size |
| ArkType | type({ name: 'string' }) | TypeScript-native syntax, fast runtime |
Recommendation: Start with @agentuity/schema for simple cases. Use other libraries depending on your needs. For example, Zod is recommended when working with generateObject() (its .describe() helps guide LLM output).
Using @agentuity/schema
The built-in schema library provides simple validation with zero external dependencies.
Basic Schema
import { createAgent, type AgentContext } from '@agentuity/runtime';
import { s } from '@agentuity/schema';
const agent = createAgent('UserProcessor', {
schema: {
input: s.object({
email: s.string(),
age: s.number(),
role: s.string(),
}),
output: s.object({
success: s.boolean(),
userId: s.string(),
}),
},
handler: async (ctx: AgentContext, input) => {
ctx.logger.info('Processing user', { email: input.email });
return {
success: true,
userId: crypto.randomUUID(),
};
},
});
export default agent;Common Patterns
import { s } from '@agentuity/schema';
// Primitives
s.string() // Any string
s.number() // Any number
s.boolean() // Boolean
s.null() // Null value
// Objects and arrays
s.object({ name: s.string() }) // Object shape
s.array(s.string()) // Array of strings
// Optional and nullable
s.optional(s.string()) // string | undefined
s.nullable(s.string()) // string | null
// Unions and literals
s.union(s.string(), s.number()) // string | number
s.literal('active') // Exact valueWhen to Use
Use @agentuity/schema for simple validation needs. For advanced features like email validation, string length constraints, or complex transformations, consider Zod or Valibot.
Using Valibot
Installation
bun add valibotBasic Schema
import { createAgent, type AgentContext } from '@agentuity/runtime';
import * as v from 'valibot';
const InputSchema = v.object({
email: v.pipe(v.string(), v.email()),
age: v.pipe(v.number(), v.minValue(0), v.maxValue(120)),
role: v.picklist(['admin', 'user', 'guest']),
});
const OutputSchema = v.object({
success: v.boolean(),
userId: v.string(),
});
const agent = createAgent('UserProcessor', {
schema: {
input: InputSchema,
output: OutputSchema,
},
handler: async (ctx: AgentContext, input) => {
ctx.logger.info('Processing user', { email: input.email, role: input.role });
return {
success: true,
userId: crypto.randomUUID(),
};
},
});
export default agent;Common Patterns
import * as v from 'valibot';
// Strings
v.string() // Any string
v.pipe(v.string(), v.minLength(5)) // Minimum length
v.pipe(v.string(), v.maxLength(100)) // Maximum length
v.pipe(v.string(), v.email()) // Email format
v.pipe(v.string(), v.url()) // URL format
// Numbers
v.number() // Any number
v.pipe(v.number(), v.minValue(0)) // Minimum value
v.pipe(v.number(), v.maxValue(100)) // Maximum value
v.pipe(v.number(), v.integer()) // Integer only
// Arrays and objects
v.array(v.string()) // Array of strings
v.object({ name: v.string() }) // Object shape
// Optional and nullable
v.optional(v.string()) // string | undefined
v.nullable(v.string()) // string | null
v.nullish(v.string()) // string | null | undefined
// Enums
v.picklist(['a', 'b', 'c']) // One of these values
v.literal('exact') // Exact value
// Defaults
v.optional(v.string(), 'default') // With default valueUsing ArkType
Installation
bun add arktypeBasic Schema
import { createAgent, type AgentContext } from '@agentuity/runtime';
import { type } from 'arktype';
const InputSchema = type({
email: 'string.email',
age: 'number>=0&<=120',
role: '"admin"|"user"|"guest"',
});
const OutputSchema = type({
success: 'boolean',
userId: 'string',
});
const agent = createAgent('UserProcessor', {
schema: {
input: InputSchema,
output: OutputSchema,
},
handler: async (ctx: AgentContext, input) => {
ctx.logger.info('Processing user', { email: input.email, role: input.role });
return {
success: true,
userId: crypto.randomUUID(),
};
},
});
export default agent;Common Patterns
import { type } from 'arktype';
// Strings
type('string') // Any string
type('string>5') // Minimum length (greater than 5 chars)
type('string<100') // Maximum length
type('string.email') // Email format
type('string.url') // URL format
// Numbers
type('number') // Any number
type('number>0') // Greater than 0
type('number<=100') // Less than or equal to 100
type('integer') // Integer only
type('number>=0&<=120') // Range (0 to 120)
// Arrays and objects
type('string[]') // Array of strings
type({ name: 'string' }) // Object shape
// Optional and union
type('string?') // string | undefined
type('string|null') // string | null
// Enums and literals
type('"a"|"b"|"c"') // One of these values
type('"exact"') // Exact value
// Nested objects
type({
user: {
name: 'string',
email: 'string.email',
},
tags: 'string[]?',
})Migrating Between Libraries
Schemas are interchangeable in createAgent(). The same agent structure works with any StandardSchema library:
// With @agentuity/schema (built-in)
import { s } from '@agentuity/schema';
const schema = { input: s.object({ name: s.string() }) };
// With Zod
import { z } from 'zod';
const schema = { input: z.object({ name: z.string() }) };
// With Valibot
import * as v from 'valibot';
const schema = { input: v.object({ name: v.string() }) };
// With ArkType
import { type } from 'arktype';
const schema = { input: type({ name: 'string' }) };
// All work the same way in createAgent()
createAgent('MyAgent', { schema, handler: async (ctx, input) => { ... } });Next Steps
- Creating Agents: Full guide to agent creation with Zod examples
- Using the AI SDK: Add LLM capabilities to your agents
Need Help?
Join our Community for assistance or just to hang with other humans building agents.
Send us an email at hi@agentuity.com if you'd like to get in touch.
Please Follow us on
If you haven't already, please Signup for your free account now and start building your first agent!