# Agent definition reference

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

`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.

:::note{title="Version"}
Needs `@trayai/helix-sdk` and `@trayai/helix-cli` newer than 1.6.0.
:::

## defineTool

```typescript
// @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;
}
```

| Field | Required | Rules |
|---|---|---|
| `name` | Yes | Matches `^[a-z][a-z0-9_]{0,63}$`. Unique within any agent that lists it |
| `description` | Yes | Non-empty. Read by the model |
| `input` | Yes | A Zod schema. Validated before every call, from an agent or directly |
| `needsApproval` | No | `true` pauses every agent call; a predicate pauses when it returns `true` for the validated input. Ignored on direct calls |
| `handler` | Yes | Runs 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:

```typescript
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

```typescript
// @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;
  };
}
```

| Field | Required | Default | Rules |
|---|---|---|---|
| `name` | Yes | | Matches `^[a-z][a-z0-9-]{0,63}$`. The name callers pass to `ctx.agent()` |
| `description` | Yes | | Non-empty. Shown by `helix agent list`; the description of the `agent_<name>` tool when another agent delegates here |
| `model` | Yes | | Model id for the provider behind `auth` |
| `auth` | Yes | | Alias present in both `authentications` and `aiProviders` |
| `fallbacks` | No | `[]` | Tried in order when the current model throws. Never used after an abort |
| `instructions` | Exactly one of the two | | System prompt, inline |
| `instructionsFile` | Exactly one of the two | | Path relative to the agent file. Resolved when the agent is first used |
| `tools` | No | `[]` | `defineTool` values. Duplicate names throw |
| `agents` | No | `[]` | Agent names. Checked at first run; cycles are allowed. Delegates may not hold `needsApproval` tools |
| `memory.scope` | No | `'project'` | `'user'` keys sessions by the `userId` on the execution's `ctx` and makes `sessions()` available |
| `memory.maxSessionMessages` | No | `200` | Positive 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.ttl` | No | none | Positive integer of seconds. Opt-in idle retention; omitted, sessions do not expire |
| `limits.maxIterations` | No | `25` | Model steps per call |
| `limits.maxToolCalls` | No | `50` | Tool 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 |
|---|---|
| Directory | `functions/_agents/`, any depth of subdirectory |
| Export | `export default defineAgent({ ... })` |
| Discovery | `helix 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` export | Skipped, with a warning naming the file |
| Registration | By `name`, not file name. Two agents with the same `name` fail the deploy. Under `helix dev`, one silently replaces the other |
| Maximum | 20 agent files per project |

Files under `functions/_agents/` are never HTTP routes.

## totalToolCallsIs

```typescript
// @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:

```typescript
agentSessions?:
  | { store: 'managed' }
  | { store: 'dynamodb'; auth: string; table: string; region: string }
```

| Form | Meaning |
|---|---|
| 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](/documentation/guides/agent-session-storage/).

## Related exports

| Export | Kind |
|---|---|
| `defineTool`, `defineAgent`, `totalToolCallsIs` | Functions |
| `isToolDefinition`, `isAgentDefinition` | Type guards for the two definition shapes |
| `DefineToolConfig`, `HelixTool`, `AgentDefinitionConfig`, `AgentDefinition` | Definition types |
| `AgentCallOptions`, `AgentResult`, `AgentStreamResult`, `AgentApprovalDecision`, `AgentPendingApproval`, `HelixAgent` | Call types, see [`ctx.agent()`](/documentation/reference/context/agent/) |
| `AgentSession`, `AgentSessionPage`, `AgentSessionPageOptions`, `AgentSessionsList`, `AgentSessionSummary` | Session types |
| `stepCountIs`, `hasToolCall`, `convertToModelMessages`, `ModelMessage`, `UIMessage`, `ToolSet`, `StopCondition` | AI SDK helpers and types re-exported for use with agents |

## Example

```typescript
// 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](/documentation/guides/agent-tools/) and [defining agents](/documentation/guides/defining-agents/).

---

Canonical: https://helix.tray.ai/documentation/reference/agents/
Any link on this page is available as markdown by appending .md to its URL.
Full corpus: https://helix.tray.ai/documentation/llms-full.txt