PAIPAI

defineCommand()

Typed server function on a thread. The model never calls this.

A command is a typed server function on a thread. Use it when the UI should do something deterministic: rename, rate a response, reset a sandbox.

The model does not call commands. Tools are for the model. Commands are for your UI.

The command name is the key in defineAgent({ commands }), not a field on defineCommand.

export const rateResponse = defineCommand({
  expose: "client",
  input: z.object({
    runId: z.string(),
    rating: z.enum(["up", "down"]),
  }),
  run: async (ctx) => ({ ok: true }),
});

Import

import { defineCommand } from "@pai/core";

Signature

function defineCommand<TInput extends z.ZodType, TOutput = unknown>(
  config: CommandConfig<TInput, ..., TOutput, ...>,
): CommandDefinition<...>;

Parameters

config: CommandConfig

input: z.ZodType

Runtime validator for untrusted input.

run: (ctx: CommandExecutionContext) => MaybePromise<TOutput>

Server implementation.

expose?: "client"

Omit for server-only. "client" → thread.commands.name(input).

thread?: "ensure" | "existing"

"ensure" may create the thread.

Defaults to existing.

capabilities?: CapabilityMap

runMetadata?: RunMetadataSchemas

CommandExecutionContext

input: z.output<TInput>

thread: RuntimeThread

Current thread facade (no nested .commands).

agentId: string

createPai registry id, or the agent's name with no registry.

identity: { identity: unknown; clientData: unknown }

Narrow identity against your agent schema. Commands do not receive runtimeContext.

capabilities: CapabilityFacades

files: ScopedFiles

signal: AbortSignal

Returns

A CommandDefinition.

Register as defineAgent({ commands: { rateResponse } }). The map key is the command name.

Learn more

On this page