PAIPAI

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.

Learn more

On this page