# Prompts API Reference

Complete API reference for defining and configuring prompts

## Overview

Prompts define the instructions and configuration for LLM interactions in Standard Agents. Each prompt specifies system instructions, model configuration, tools, input validation, and context options.

- Key Features

  - **File-based**: Defined in `agents/prompts/` directory
  - **Auto-discovered**: No manual registration required
  - **Type-safe**: Full TypeScript support with Zod validation
  - **Composable**: Prompts can be exposed as tools for other prompts
  - **Hot-reloadable**: Changes trigger HMR in development

## Quick Start

The examples use the purpose-named configurations in [Example model choices](/docs/core-concepts/models#example-model-choices).

Create a new prompt in `agents/prompts/`:

```typescript agents/prompts/customer_support.ts
import { definePrompt } from '@standardagents/spec';

export default definePrompt({
  name: 'customer_support',
  toolDescription: 'Handle customer support inquiries',
  prompt: `You are a helpful customer support agent.
Always be polite and try to resolve issues quickly.`,
  model: 'conversational',
  includeChat: true,
});
```

Reference it in an agent:

```typescript agents/agents/support_agent.ts
import { defineAgent } from '@standardagents/spec';

export default defineAgent({
  name: 'support_agent',
  sideA: {
    prompt: 'customer_support',  // References the prompt above
  },
  sideB: { human: true },
});
```

## Configuration Options

- name (string), required

  Unique identifier for this prompt. Use snake_case.

  ```typescript
  name: 'customer_support'
  ```

* toolDescription (string), required

  Description shown when prompt is exposed as a tool. Always required for potential tool use.

  ```typescript
  toolDescription: 'Search for information and provide relevant results'
  ```

- prompt (string | StructuredPrompt), required

  The system instructions sent to the LLM. Supports template variables using `{{variableName}}` syntax.

  ```typescript
  prompt: `You are helping {{userName}} with their request.
  Current date: {{currentDate}}
  Customer tier: {{customerTier}}`
  ```

* model (string), required

  Name of the model configuration to use. Must be defined in `agents/models/`.

  ```typescript
  model: 'conversational'
  ```

> **Note:**
>
> Every prompt is callable as a tool.
> The deprecated `exposeAsTool` field has no effect.

- includeChat (boolean), default: false

  Include full chat history in LLM context.

  ```typescript
  includeChat: true
  ```

* includePastTools (boolean), default: false

  Include earlier tool calls and their results in context, including calls from
  the current turn. Set this explicitly on each prompt with tools. Use `true`
  when a later step needs a result. With `false`, a tool loop can repeat calls
  until a step limit stops it.

  ```typescript
  includePastTools: true
  ```

- parallelToolCalls (boolean)

  Allow the model to return multiple tool calls. An explicit value controls the provider option. An omitted value uses the provider default. Local tools execute sequentially in returned order.

  ```typescript
  parallelToolCalls: false
  ```

* toolChoice ('auto' | 'none' | 'required'), default: 'auto'

  Tool calling strategy:

  - `'auto'`: LLM decides whether to use tools
  - `'none'`: Disable tool calling
  - `'required'`: Force the LLM to call at least one tool

  ```typescript
  toolChoice: 'required'
  ```

- requiredSchema (ZodSchema)

  Zod schema for input validation when called as a tool. The side A prompt
  schema also defines creation arguments when its agent runs as a subagent.

  ```typescript
  requiredSchema: z.object({
    userId: z.string().describe('The user ID to look up'),
    includeHistory: z.boolean().optional().describe('Include transaction history'),
  })
  ```

* tools ((string | SubpromptConfig | PromptToolConfig)\[]), default: \[]

  Available callable names, subprompt settings, and static tool options.

  ```typescript
  includePastTools: true,
  tools: [
    'search_knowledge_base',
    { name: 'create_ticket', includeErrors: true },
  ]
  ```

An exposed agent referenced in `tools` performs a handoff in the current thread.
Persistent child relationships belong in an owning agent side's `subagents` array.
Subagent relationship configuration in a prompt tool entry is a definition-time error.

- hooks (string\[])

  Hook IDs to run when this prompt is active. References hooks by their unique `id` property from `agents/hooks/`. A non-empty array selects the parent base set. An omitted or empty array uses the agent's hooks. Required child hooks run before or after that base set according to their stage.

  ```typescript
  hooks: ['limit_to_20_messages', 'log_tool_calls']
  ```

* reasoning (ReasoningConfig)

  Extended thinking configuration for models that support it.

  ```typescript
  reasoning: {
    level: 100,
    maxTokens: 10000,
  }
  ```

- env (Record\<string, string>)

  Default environment values for this prompt. Thread and agent values override
  them. They override user-account and instance values.

* variables (VariableDefinition\[])

  Environment variable declarations for this prompt. Each declaration sets
  `name`, `type`, `required`, and `description`. `scoped` is optional.

- providerOptions (Record\<string, unknown>)

  Provider options for this prompt. These override model-level options.

* historyLimit (number)

  A positive integer that bounds loaded top-level history when `includeChat`
  is enabled. The window advances in blocks of this size. It contains at least
  this many messages and fewer than twice this many when enough history exists.
  Tools, hooks, and `execution.messageHistory` see this window. Unset loads all
  eligible history. Stored messages remain intact.

- recentImageThreshold (number), default: 10

  A positive integer that sets how many recent messages retain image content.

## Tools in Prompts

Tools are callable capabilities exposed to LLMs. They can be:

- Functions

  Custom code defined in `agents/tools/`

* Prompts

  Other prompts exposed as tools (sub-prompts)

- Agents

  Entire agents exposed as tools (handoffs)

### Adding Tools

```typescript
definePrompt({
  name: 'support_prompt',
  includePastTools: true,
  tools: [
    'search_knowledge_base',                    // Simple reference
    { name: 'create_ticket' },                  // Object form
    { name: 'sub_prompt', includeErrors: true }, // With options
  ],
  // ...
});
```

### SubpromptConfig options

- name (string), required

  Name of the tool

* includeTextResponse (boolean), default: true

  Include text response from sub-prompt execution

- includeToolCalls (boolean), default: true

  Include tool call details from sub-prompt

* includeErrors (boolean), default: true

  Include error details from sub-prompt

- initUserMessageProperty (string)

  Property from tool arguments to use as initial user message

* initAttachmentsProperty (string)

  Argument property with an attachment path or an array of attachment paths.

### PromptToolConfig options

```typescript
{
  name: 'web_search',
  env: { SEARCH_CONTEXT: 'documentation' },
  options: { searchContextSize: 'high' },
}
```

`env` scopes environment values to the invocation.
`options` contains static tool options.
The deprecated `tenvs` alias remains available for environment values.
The admin `GET /api/prompts/:name` response retains `tools[].options` unchanged.
Prompt list and detail responses include the model display name in `model_name`.
Their `model_provider` field contains a provider name for icon lookup.

## Input Validation

Define input validation with Zod schemas:

```typescript
import { definePrompt } from '@standardagents/spec';
import { z } from 'zod';

export default definePrompt({
  name: 'user_lookup',
  toolDescription: 'Look up user information',
  prompt: 'You help find user information...',
  model: 'fast-response',
  requiredSchema: z.object({
    userId: z.string().describe('The user ID to look up'),
    includeHistory: z.boolean().optional().describe('Include transaction history'),
  }),
});
```

### Supported Zod Types

Prompt schemas require Zod 4 (`zod@^4.0.0`). Zod 3 schemas are unsupported.

### Complete list of supported types

| Zod Type       | Example                            | Notes          |
| -------------- | ---------------------------------- | -------------- |
| `z.string()`   | `z.string().min(1)`                | Text values    |
| `z.number()`   | `z.number().positive()`            | Numeric values |
| `z.boolean()`  | `z.boolean()`                      | True/false     |
| `z.null()`     | `z.null()`                         | Null value     |
| `z.literal()`  | `z.literal('active')`              | Exact value    |
| `z.enum()`     | `z.enum(['a', 'b'])`               | One of values  |
| `z.array()`    | `z.array(z.string())`              | Arrays         |
| `z.object()`   | `z.object({...})`                  | Objects        |
| `z.record()`   | `z.record(z.string(), z.string())` | Dynamic keys   |
| `z.union()`    | `z.union([...])`                   | Multiple types |
| `z.optional()` | `z.string().optional()`            | Optional field |
| `z.nullable()` | `z.string().nullable()`            | Can be null    |
| `z.default()`  | `z.number().default(10)`           | Default value  |

**Note:** The default recursive schema type depth is 7 levels.

## Extended Thinking

Configure extended thinking for models that support it:

```typescript
definePrompt({
  name: 'complex_analysis',
  toolDescription: 'Analyze a complex problem with extended reasoning',
  prompt: 'You analyze complex problems...',
  model: 'tool-reasoning',
  reasoning: {
    level: 100,          // 0 to 100
    maxTokens: 10000,    // Maximum reasoning tokens
    exclude: false,      // Include reasoning in response
    include: true,       // Send earlier reasoning back on later requests (default)
  },
});
```

### Reasoning Options

- level (number)

  A prompt can set `reasoning.level` from 0 to 100. An unset level uses the model's default. Level 0 requests the least reasoning. A provider disables reasoning when the model supports that setting. Otherwise, it selects the lowest native setting. Each provider maps the level to the nearest option the model declares.

  A prompt's `reasoning.level` replaces a native effort value in `providerOptions`. Other `providerOptions` keys remain. Without a level, `providerOptions` apply as provided. Native effort values in a model's `providerOptions` remain valid.

  Saved prompt input with `reasoning.effort` fails validation. A published package prompt with `reasoning.effort` loads with a warning. The runtime ignores that field.

* maxTokens (number)

  Maximum tokens for reasoning (Anthropic, Google, Qwen)

- exclude (boolean), default: false

  Use reasoning internally but exclude from response

* include (boolean), default: true

  Send the stored reasoning of earlier assistant messages back to the model on later requests. Set `false` to stop sending it. The reasoning stays in the message record either way.

## Exposing Prompts as Tools

Every prompt is callable as a tool:

```typescript
// agents/prompts/code_reviewer.ts
definePrompt({
  name: 'code_reviewer',
  toolDescription: 'Review code for bugs and improvements',
  prompt: `You are an expert code reviewer.
Analyze the provided code for:
- Bugs and potential issues
- Performance improvements
- Best practices violations`,
  model: 'code-generation',
  requiredSchema: z.object({
    code: z.string().describe('Code to review'),
    language: z.string().describe('Programming language'),
  }),
});
```

Use in another prompt:

```typescript
// agents/prompts/developer_assistant.ts
definePrompt({
  name: 'developer_assistant',
  toolDescription: 'Help developers with coding tasks',
  prompt: 'You are a helpful coding assistant...',
  model: 'code-generation',
  tools: ['code_reviewer'],  // Use the prompt tool
});
```

### Sub-Prompt Execution Flow

When an LLM calls a prompt tool:

1. **Tool call received**: Parent prompt receives tool call with arguments
2. **Validation**: Arguments validated against `requiredSchema`
3. **Sub-prompt execution**: New execution context created
4. **Message hierarchy**: Messages stored with `parent_id` and `depth`
5. **Result rollup**: Sub-prompt response returned as tool result
6. **Parent continues**: Parent LLM receives result and continues

## Examples

### Basic Conversation

```typescript
import { definePrompt } from '@standardagents/spec';

export default definePrompt({
  name: 'assistant',
  toolDescription: 'General assistant for conversations',
  prompt: `You are a helpful assistant.
Provide clear, accurate, and friendly responses.`,
  model: 'conversational',
  includeChat: true,
});
```

### Customer Support with Tools

```typescript
import { definePrompt } from '@standardagents/spec';
import { z } from 'zod';

export default definePrompt({
  name: 'customer_support',
  toolDescription: 'Handle customer support inquiries',
  prompt: `You are a customer support agent for Acme Corp.

Your responsibilities:
- Answer questions about products and services
- Help resolve issues on first contact
- Create support tickets when needed
- Escalate to specialists for complex issues

Always be professional and empathetic.`,
  model: 'conversational',
  includeChat: true,
  includePastTools: true,
  tools: [
    'search_knowledge_base',
    'lookup_customer',
    { name: 'create_ticket', includeErrors: true },
  ],
});
```

### Data Analysis with Reasoning

```typescript
import { definePrompt } from '@standardagents/spec';
import { z } from 'zod';

export default definePrompt({
  name: 'data_analyst',
  toolDescription: 'Analyze data and generate insights',
  prompt: `You are a data analyst expert.
Analyze the provided data and return actionable insights.
Use statistical analysis when appropriate.`,
  model: 'tool-reasoning',
  reasoning: {
    level: 66,
    exclude: false,
  },
  requiredSchema: z.object({
    data: z.string().describe('Data to analyze (JSON format)'),
    question: z.string().describe('Analysis question'),
    format: z.enum(['summary', 'detailed', 'json']).default('summary'),
  }),
  includePastTools: true,
  tools: [
    'calculate_statistics',
    'generate_chart',
  ],
});
```

### Orchestrator

```typescript
import { definePrompt } from '@standardagents/spec';

export default definePrompt({
  name: 'orchestrator',
  toolDescription: 'Coordinate complex multi-step tasks',
  prompt: `You are a task orchestrator.
Break down complex requests into steps and coordinate execution.
Use specialized prompts for specific tasks.`,
  model: 'tool-reasoning',
  includeChat: true,
  includePastTools: true,
  tools: [
    'data_analyst',      // Sub-prompt
    'code_reviewer',     // Sub-prompt
    'research_agent',    // Agent tool
    'search_web',        // Function tool
  ],
});
```

## Type Definitions

### Canonical prompt types

Import the current types from the package:

```typescript
import type {
  PromptDefinition,
  PromptToolConfig,
  SubpromptConfig,
  PromptInput,
} from '@standardagents/spec';
```

A prompt's `tools` array accepts callable names, `SubpromptConfig`, and `PromptToolConfig`.
`SubpromptConfig` controls result filters and initial message mappings.
`PromptToolConfig` supplies scoped environment values and static options.

### ReasoningConfig

```typescript
interface ReasoningConfig {
  /** Reasoning level from 0 to 100 */
  level?: number;

  /** Maximum tokens for reasoning */
  maxTokens?: number;

  /** Use reasoning internally but exclude from response */
  exclude?: boolean;

  /** Send earlier reasoning back on later requests (default true) */
  include?: boolean;
}
```

### PromptInput Type Helper

Extract the input type from a prompt definition:

```typescript
import type { PromptInput } from '@standardagents/spec';
import myPrompt from './my_prompt';

type MyPromptInput = PromptInput<typeof myPrompt>;
// { userId: string; options?: { format: 'json' | 'text' } }
```

## Best Practices

### Write Clear System Prompts

```typescript
// Good - clear structure and expectations
definePrompt({
  name: 'support_agent',
  prompt: `You are a customer support agent for Acme Corp.

## Your Role
- Answer questions about products and services
- Help resolve issues on first contact
- Create tickets for complex issues

## Guidelines
- Be professional and empathetic
- Ask clarifying questions when needed
- Never share internal information

## Available Tools
Use these tools to help customers:
- search_knowledge_base: Find product information
- create_ticket: Create support tickets`,
  // ...
});

// Avoid - vague instructions
definePrompt({
  name: 'support_agent',
  prompt: 'Help customers.',
  // ...
});
```

### Use Descriptive Tool Descriptions

```typescript
// Good - specific and actionable
definePrompt({
  name: 'search_prompt',
  toolDescription: 'Search the knowledge base for product information, FAQs, and troubleshooting guides. Returns relevant articles.',
  // ...
});

// Avoid - too vague
definePrompt({
  name: 'search_prompt',
  toolDescription: 'Search stuff',
  // ...
});
```

### Validate Inputs with Zod

```typescript
// Good - detailed schema with descriptions
requiredSchema: z.object({
  customerId: z.string().min(1).describe('Customer ID from CRM'),
  issue: z.string().min(10).describe('Description of the issue'),
  priority: z.enum(['low', 'medium', 'high']).default('medium'),
}).strict()

// Avoid - no validation
requiredSchema: z.object({
  data: z.any(),
})
```

### Enable includeChat for Conversations

```typescript
// For conversational prompts
definePrompt({
  name: 'chat_assistant',
  includeChat: true,  // Needed for context
  // ...
});

// For single-shot tasks
definePrompt({
  name: 'code_formatter',
  includeChat: false,  // No history needed
  // ...
});
```

## File Structure

```
agents/
└── prompts/
    ├── customer_support.ts   # export default definePrompt({...})
    ├── data_analyst.ts       # export default definePrompt({...})
    └── orchestrator.ts       # export default definePrompt({...})
```

**Requirements:**

- One prompt per file
- Default export required
- Use snake_case for file names

## Related Documentation

- [Models](/docs/api-reference/models)

  Define model configurations

* [Tools](/docs/api-reference/tools)

  Create custom function tools

- [Agents](/docs/api-reference/agents)

  Configure agents that use prompts

* [Hooks](/docs/api-reference/hooks)

  Intercept execution at various points
