defineAgent()
Server-side agent: model, identity, instructions, tools, commands.
defineAgent describes what the model may do. It does not serve HTTP, open a database, or render a UI. Put the result in createPai().
import { defineAgent } from "@pai/core";
import { openai } from "@ai-sdk/openai";
import { z } from "zod";
export const assistantAgent = defineAgent({
name: "assistant",
model: openai("gpt-4.1-mini"),
identity: z.object({
userId: z.string(),
workspaceId: z.string(),
}),
instructions: "Help with this workspace. Prefer tools over guessing.",
tools: { searchDocs },
});The registry key (main) is set later in createPai({ agents: { main: assistantAgent } }). name is a human label.
Import
import { defineAgent } from "@pai/core";Signature
function defineAgent<TConfig extends AgentConfig>(
config: TConfig,
): AgentDefinition<InferRegisteredAgentContract<TConfig>>;Parameters
config: AgentConfig
name: string
Human label for the agent.
model: LanguageModel | ModelSelection | ((ctx) => model)
Any AI SDK language model. See AI SDK models.
instructions: string | ((ctx) => string | Promise<string>)
System prompt. The function form sees identity and runtimeContext.
identity?: z.ZodType
Trusted caller schema. Set this whenever threads are isolated by workspace or user. See Identity.
tools?: Record<string, ToolDefinition | ToolRegistration>
Server tools. See defineTool().
tool: ToolDefinition
When wrapping for enabled, mapContext, or onOutput.
enabled?: boolean | ((ctx) => boolean | Promise<boolean>)
Whether the model is offered the tool. Availability, not authorization.
Defaults to true.
mapContext?: (ctx) => toolContext
Project runtimeContext into the tool's contextSchema.
onOutput?: (ctx) => void | Promise<void>
Observe this tool's validated output. Receives output and input,
typed from the tool, plus tool.name, call.toolCallId,
runtimeContext, identity, clientData, threadId, and signal.
Runs once per successful call. Throwing fails the run.
commands?: Record<string, CommandDefinition>
UI/server operations. expose: "client" is on defineCommand(), not a registration wrapper.
runtimeContext?: (input) => context | Promise<context>
Load DB handles and permissions. Tools read ctx.context, not identity.
clientData?: z.ZodType
Untrusted per-request extras (open document). Never derive a partition from it.
maxSteps?: number
Cap tool/model loops per run. The default guards against a run that will not end; set a lower cap only when the agent should stop sooner.
Defaults to 100.
lifecycle?: AgentLifecycle
Run hooks. See composeLifecycle().
runMetadata?: { private?: z.ZodRawShape; public?: z.ZodRawShape }
Zod schemas for per-run metadata.
private?: z.ZodRawShape
Server-only.
public?: z.ZodRawShape
Client-readable.
threadMetadata?: { private?, public? }
messageMetadata?: { private?, public? }
version?: string
threadTitles?: boolean | ThreadTitleConfig
reasoningSummary?: boolean | ReasoningSummaryConfig
providerTools?: ToolSet
Provider-native AI SDK tools with durable schemas.
trigger?: { renderForModel?: boolean }
How application-triggered messages are prepared for the model.
Returns
A AgentDefinition.
Pass this to createPai({ agents }). Use InferAgentContract<typeof agent>
for a single-agent client type; prefer InferPaiContract<typeof pai> for apps.