Skip to content
Helix Docs

Agent definition reference

Exact signatures for defineTool and defineAgent, every option with its default, where agent files live, and the agentSessions config key.

For developers Updated Oct 20, 2026
View as Markdown

defineTool and defineAgent from @trayai/helix-sdk declare the tools an agent may call and the agent itself. An agent file lives under functions/_agents/ and default-exports its definition; tools live wherever you keep shared code. This page gives exact signatures, every option with its default, and the helix.config.ts key that selects where sessions are stored.

defineTool

// @trayai/helix-sdk
function defineTool<TSchema extends ZodType>(config: DefineToolConfig<TSchema>): HelixTool<TSchema>

interface DefineToolConfig<TSchema extends ZodType> {
  name: string;
  description: string;
  input: TSchema;
  needsApproval?: boolean | ((input: z.infer<TSchema>) => boolean | Promise<boolean>);
  handler: (ctx: PlatformContext & { input: z.infer<TSchema> }) => Promise<unknown> | unknown;
}
FieldRequiredRules
nameYesMatches ^[a-z][a-z0-9_]{0,63}$. Unique within any agent that lists it
descriptionYesNon-empty. Read by the model
inputYesA Zod schema. Validated before every call, from an agent or directly
needsApprovalNotrue pauses every agent call; a predicate pauses when it returns true for the validated input. Ignored on direct calls
handlerYesRuns with the caller’s ctx; ctx.input is the parsed input

A bad name, empty description, non-Zod input, or missing handler throws from defineTool itself, at module load.

HelixTool

The return value is callable and carries its definition:

interface HelixTool<TSchema extends ZodType> {
  (input: z.infer<TSchema>): Promise<unknown>;   // validate, then run with getContext()
  readonly name: string;
  readonly description: string;
  readonly inputSchema: TSchema;
  readonly needsApproval?: DefineToolConfig<TSchema>['needsApproval'];
  readonly execute: (input: unknown, ctx: PlatformContext) => Promise<unknown>;
}

PlatformContext is the SDK’s name for the ctx a function receives, exported from @trayai/helix-sdk. Its userId and headers are optional, since a tool can run from a schedule.

A direct call outside a function execution throws, because there is no ctx to run with. Invalid input throws SdkError.inputValidationFailed naming the failing fields. Inside an agent loop a thrown handler error becomes a tool error result the model can read; on a direct call it propagates.

defineAgent

// @trayai/helix-sdk
function defineAgent(config: AgentDefinitionConfig): AgentDefinition

interface AgentDefinitionConfig {
  name: string;
  description: string;
  model: string;
  auth: string;
  fallbacks?: Array<{ model: string; auth: string }>;
  instructions?: string;
  instructionsFile?: string;
  tools?: HelixTool[];
  agents?: string[];
  memory?: {
    scope?: 'project' | 'user';
    maxSessionMessages?: number;
    ttl?: number;
  };
  limits?: {
    maxIterations?: number;
    maxToolCalls?: number;
  };
}
FieldRequiredDefaultRules
nameYesMatches ^[a-z][a-z0-9-]{0,63}$. The name callers pass to ctx.agent()
descriptionYesNon-empty. Shown by helix agent list; the description of the agent_<name> tool when another agent delegates here
modelYesModel id for the provider behind auth
authYesAlias present in both authentications and aiProviders
fallbacksNo[]Tried in order when the current model throws. Never used after an abort
instructionsExactly one of the twoSystem prompt, inline
instructionsFileExactly one of the twoPath relative to the agent file. Resolved when the agent is first used
toolsNo[]defineTool values. Duplicate names throw
agentsNo[]Agent names. Checked at first run; cycles are allowed. Delegates may not hold needsApproval tools
memory.scopeNo'project''user' keys sessions by the userId on the execution’s ctx and makes sessions() available
memory.maxSessionMessagesNo200Positive integer. Cap on the messages sent to the model per turn. The window always starts on a user message, and a turn longer than the cap is sent whole. Storage is not limited
memory.ttlNononePositive integer of seconds. Opt-in idle retention; omitted, sessions do not expire
limits.maxIterationsNo25Model steps per call
limits.maxToolCallsNo50Tool executions per call

Validation runs when the file loads. The error names the agent and the failing field.

Delegation

Each name under agents becomes a tool named agent_ plus the name with hyphens replaced by underscores, taking { prompt: string }. The delegate runs its own loop in its own new session and returns its final text. Delegation depth is capped at three; beyond that the tool returns { error: 'delegation_depth_exceeded' } to the calling model.

Where agent files live

Rule
Directoryfunctions/_agents/, any depth of subdirectory
Exportexport default defineAgent({ ... })
Discoveryhelix dev and the deploy build import every file in the directory. Adding or removing a file needs a dev server restart
Files without a default defineAgent exportSkipped, with a warning naming the file
RegistrationBy name, not file name. Two agents with the same name fail the deploy. Under helix dev, one silently replaces the other
Maximum20 agent files per project

Files under functions/_agents/ are never HTTP routes.

totalToolCallsIs

// @trayai/helix-sdk
function totalToolCallsIs(max: number): StopCondition<ToolSet>

A stop condition that ends a run once max tool executions have happened across all steps. Pair it with the AI SDK’s stepCountIs in stopWhen.

Config: agentSessions

Selects where sessions are stored. Applies to every agent in the project:

agentSessions?:
  | { store: 'managed' }
  | { store: 'dynamodb'; auth: string; table: string; region: string }
FormMeaning
Omitted or { store: 'managed' }The platform stores sessions in deployed executions; helix dev keeps them in memory
{ store: 'dynamodb', ... }A DynamoDB table you own, in dev and in production. auth is an authentication alias holding an AWS credential; table and region name the table

With the DynamoDB store, agent.sessions() is unsupported and a single message is capped at 400 KB. Table layout and permissions are in bring your own session storage.

ExportKind
defineTool, defineAgent, totalToolCallsIsFunctions
isToolDefinition, isAgentDefinitionType guards for the two definition shapes
DefineToolConfig, HelixTool, AgentDefinitionConfig, AgentDefinitionDefinition types
AgentCallOptions, AgentResult, AgentStreamResult, AgentApprovalDecision, AgentPendingApproval, HelixAgentCall types, see ctx.agent()
AgentSession, AgentSessionPage, AgentSessionPageOptions, AgentSessionsList, AgentSessionSummarySession types
stepCountIs, hasToolCall, convertToModelMessages, ModelMessage, UIMessage, ToolSet, StopConditionAI SDK helpers and types re-exported for use with agents

Example

// functions/_agents/billing-agent.ts
import { defineAgent } from '@trayai/helix-sdk';
import lookupInvoice from '../_shared/tools/lookup-invoice';
import applyCredit from '../_shared/tools/apply-credit';

export default defineAgent({
  name: 'billing-agent',
  description: 'Answers invoice questions and applies account credits.',
  model: 'claude-sonnet-4-5',
  auth: 'anthropicKey',
  fallbacks: [{ model: 'gpt-4o', auth: 'openaiKey' }],
  instructionsFile: './billing-agent.md',
  tools: [lookupInvoice, applyCredit],
  memory: { scope: 'user', maxSessionMessages: 80 },
  limits: { maxIterations: 12 },
});

Usage is covered in defining tools and defining agents.

Loading search…

Jump to a section

tab to move · esc to close