@standardagents/agentbuilder-template 0.21.1 → 0.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,14 +1,16 @@
1
- declare const ROOT_AGENTS_MD = "# Standard Agents\n\nThis project uses Standard Agents - a framework for building AI agents on Cloudflare Workers.\n\n## Architecture Overview\n\nStandard Agents uses a **composition model** where four core components work together:\n\n```\nModel \u2192 Prompt \u2192 Agent \u2192 Thread\n \u2502 \u2502 \u2502 \u2502\n \u2502 \u2502 \u2502 \u2514\u2500 Conversation instance (Durable Object)\n \u2502 \u2502 \u2514\u2500 Orchestrates conversation flow\n \u2502 \u2514\u2500 System instructions + tools\n \u2514\u2500 LLM provider configuration\n```\n\n**Models** define which LLM to use (provider, model ID, pricing, fallbacks).\n**Prompts** define what the LLM should do (system instructions, available tools).\n**Agents** orchestrate conversations (which prompt, stop conditions, turn limits).\n**Threads** are individual conversation instances with persistent storage.\n\n## How Components Compose\n\n### Basic Flow\n1. User creates a thread with an agent\n2. Agent uses its configured prompt\n3. Prompt specifies the model and tools\n4. LLM responds, potentially calling tools\n5. Tools execute and return results\n6. Loop continues until stop condition\n\n### Sub-Prompts (Prompts as Tools)\nPrompts can call other prompts as tools. This enables:\n- **Specialized reasoning**: A main prompt delegates to expert sub-prompts\n- **Structured outputs**: Sub-prompt validates and formats data\n- **Context isolation**: Sub-prompt gets fresh context without full history\n\n```typescript\n// Main prompt can call 'data_extractor' as a tool\ndefinePrompt({\n name: 'main_assistant',\n tools: ['data_extractor'], // Another prompt exposed as tool\n // ...\n});\n```\n\n### Agent Handoffs (Agents as Tools)\nAgents can delegate to other agents entirely:\n- **Specialization**: Route to domain-specific agents\n- **Escalation**: Hand off to more capable agents\n- **Workflows**: Chain agents for multi-step processes\n\n```typescript\ndefineAgent({\n name: 'triage_agent',\n exposeAsTool: true,\n toolDescription: 'Hand off to triage for initial assessment',\n // ...\n});\n```\n\n## File Structure\n\n```\nAGENTS.md # Project guidance for AI coding tools\nCLAUDE.md -> AGENTS.md # Compatibility symlink\nvite.config.ts # Uses builder(); Cloudflare config is generated\ntsconfig.json # Includes agents and generated .agents types\nagents/\n\u251C\u2500\u2500 agents/ # Agent definitions (defineAgent)\n\u2502 \u251C\u2500\u2500 AGENTS.md\n\u2502 \u2514\u2500\u2500 CLAUDE.md -> AGENTS.md\n\u251C\u2500\u2500 prompts/ # Prompt definitions (definePrompt)\n\u2502 \u251C\u2500\u2500 AGENTS.md\n\u2502 \u2514\u2500\u2500 CLAUDE.md -> AGENTS.md\n\u251C\u2500\u2500 models/ # Model configurations (defineModel)\n\u2502 \u251C\u2500\u2500 AGENTS.md\n\u2502 \u2514\u2500\u2500 CLAUDE.md -> AGENTS.md\n\u251C\u2500\u2500 tools/ # Custom tools (defineTool)\n\u2502 \u251C\u2500\u2500 AGENTS.md\n\u2502 \u2514\u2500\u2500 CLAUDE.md -> AGENTS.md\n\u251C\u2500\u2500 hooks/ # Lifecycle hooks (defineHook)\n\u2502 \u251C\u2500\u2500 AGENTS.md\n\u2502 \u2514\u2500\u2500 CLAUDE.md -> AGENTS.md\n\u2514\u2500\u2500 api/ # Thread API endpoints (defineThreadEndpoint)\n \u251C\u2500\u2500 AGENTS.md\n \u2514\u2500\u2500 CLAUDE.md -> AGENTS.md\n```\n\nThe `builder()` Vite plugin generates the Worker entry, Durable Object bindings, Cloudflare Vite plugin configuration, and local `.agents/` support files at build time. Agent files are **auto-discovered** at runtime. No manual registration needed.\n\n## ThreadState\n\n`ThreadState` is the state object available in tools and hooks:\n\n```typescript\ninterface ThreadState {\n // Identity (readonly)\n threadId: string; // Thread identifier\n agentId: string; // Agent identifier\n userId: string | null; // User identifier (if set)\n createdAt: number; // Creation timestamp\n children: SubagentRegistryEntry[]; // Resumable child registry\n terminated: number | null; // Soft-termination timestamp\n arguments: Record<string, unknown>; // Invocation or subagent creation args\n context: Record<string, unknown>; // Current-execution scratch data\n\n // Methods\n getMessages(options?): Promise<MessagesResult>; // Get conversation history\n injectMessage(input): Promise<Message>; // Add message to thread\n queueMessage(input): Promise<void>; // Queue message for next step\n loadModel(name): Promise<ModelConfig>; // Load model definition\n loadPrompt(name): Promise<PromptConfig>; // Load prompt definition\n loadAgent(name): Promise<AgentConfig>; // Load agent definition\n env(propertyName): Promise<string>; // Resolve env value for this thread\n setEnv(propertyName, value): Promise<void>; // Set thread env + propagate to active descendants\n getValue<T = unknown>(key: string): Promise<T | null>; // Read durable per-thread JSON value\n setValue(key: string, value: unknown): Promise<void>; // Write durable value; null/undefined deletes\n notifyParent(content): Promise<void>; // Queue a silent message to the parent when one exists\n setStatus(status): Promise<void>; // Update this child in the parent registry; no-op without a parent\n stopSession(options?): Promise<void>; // Terminally stop the current agent session\n getChildThread(referenceId): Promise<ThreadState | null>; // Resolve child thread\n getParentThread(): Promise<ThreadState | null>; // Resolve parent thread\n terminate(): Promise<void>; // Soft-terminate thread\n runCode(source, options?): CodeExecution; // Run JS/TS in a fresh Dynamic Worker sandbox\n}\n```\n\n`state.arguments` is read-only thread invocation data. Resumable `subagent_create.arguments` persists with the child thread, is visible to both child sides, and is also available as prompt variables. Use `state.context` only for mutable scratch data during the current execution; it is not durable storage.\n\n`runCode` has no implicit access to thread state, filesystem, network, timers, or host globals. Bridge only the exact capabilities needed through `imports` or `globals`; use `modules` for local relative ES modules; use `execute` to select the export and args to run. `modules` keys are graph-root relative paths; entry-source imports resolve from `filename` when supplied, including `../` parent paths that stay inside the supplied graph. TypeScript input is accepted by default and erased before evaluation. In thread endpoints, `runCode` is forwarded into the thread Durable Object; pass plain transferable options there and keep function-backed bridges in tools or in-thread execution contexts.\n\n## Subagents\n\n`dual_ai` agents can be used as subagents from prompt tool configs:\n\n- Each subagent runs in its own thread (`DurableThread`)\n- Parent/child linkage is tracked in thread metadata\n- Resumable children are visible in `state.children`\n- Parent threads create/message resumable children via built-ins (`subagent_create`, `subagent_message`)\n- `subagent_create.arguments` is validated from the receiving child side's prompt schema and persists as `ThreadState.arguments` plus prompt variables for the life of the child thread\n- Child completion results are queued back to the parent when `parentCommunication` is `implicit`\n- Explicit relationships can stay idle until code calls `state.notifyParent()` or `state.setStatus()`; use `state.stopSession({ result, notifyParent, status })` when a tool should also terminally end the child session\n\nAccess in tools:\n```typescript\nexport default defineTool('...', schema, async (state, args) => {\n const threadId = state.threadId;\n const creationArgs = state.arguments;\n const { messages } = await state.getMessages();\n const count = (await state.getValue<number>('invocation_count')) ?? 0;\n await state.setValue('invocation_count', count + 1);\n // ...\n});\n```\n\nAccess in hooks:\n```typescript\nexport default defineHook({\n hook: 'before_create_message',\n id: 'my_hook',\n execute: async (state, message) => {\n console.log(`Thread: ${state.threadId}, Agent: ${state.agentId}`);\n return message;\n }\n});\n```\n\n## Quick Reference\n\n| Function | Purpose | Directory |\n|----------|---------|-----------|\n| `defineModel()` | Configure LLM provider | `agents/models/` |\n| `definePrompt()` | System instructions + tools | `agents/prompts/` |\n| `defineAgent()` | Conversation orchestration | `agents/agents/` |\n| `defineTool()` | Custom tool functions | `agents/tools/` |\n| `defineHook()` | Lifecycle interception | `agents/hooks/` |\n| `defineThreadEndpoint()` | Custom API routes | `agents/api/` |\n\n## Runtime Utilities\n\nImport from `@standardagents/builder`:\n\n```typescript\nimport {\n queueTool, // Queue another tool for execution\n injectMessage, // Add message without triggering execution\n getMessages, // Retrieve message history\n emitThreadEvent, // Send custom WebSocket events\n} from '@standardagents/builder';\n```\n\n## Documentation\n\nFull documentation: https://docs.standardagentbuilder.com\n\n- [Architecture Overview](https://docs.standardagentbuilder.com/introduction/architecture)\n- [Models](https://docs.standardagentbuilder.com/core-concepts/models)\n- [Prompts](https://docs.standardagentbuilder.com/core-concepts/prompts)\n- [Agents](https://docs.standardagentbuilder.com/core-concepts/agents)\n- [Tools](https://docs.standardagentbuilder.com/core-concepts/tools)\n- [Hooks](https://docs.standardagentbuilder.com/core-concepts/hooks)\n- [ThreadState](https://docs.standardagentbuilder.com/core-concepts/flowstate)\n- [Thread API](https://docs.standardagentbuilder.com/core-concepts/api)\n";
1
+ declare const ROOT_AGENTS_MD = "# Standard Agents\n\nThis project uses Standard Agents - a framework for building AI agents on Cloudflare Workers.\n\n## Architecture Overview\n\nStandard Agents uses a **composition model** where four core components work together:\n\n```\nModel \u2192 Prompt \u2192 Agent \u2192 Thread\n \u2502 \u2502 \u2502 \u2502\n \u2502 \u2502 \u2502 \u2514\u2500 Conversation instance (Durable Object)\n \u2502 \u2502 \u2514\u2500 Orchestrates conversation flow\n \u2502 \u2514\u2500 System instructions + tools\n \u2514\u2500 LLM provider configuration\n```\n\n**Models** define which LLM to use (provider, model ID, pricing, fallbacks).\n**Prompts** define what the LLM should do (system instructions, available tools).\n**Agents** orchestrate conversations (which prompt, stop conditions, turn limits).\n**Threads** are individual conversation instances with persistent storage.\n\n## How Components Compose\n\n### Basic Flow\n1. User creates a thread with an agent\n2. Agent uses its configured prompt\n3. Prompt specifies the model and tools\n4. LLM responds, potentially calling tools\n5. Tools execute and return results\n6. Loop continues until stop condition\n\n### Sub-Prompts (Prompts as Tools)\nPrompts can call other prompts as tools. This enables:\n- **Specialized reasoning**: A main prompt delegates to expert sub-prompts\n- **Structured outputs**: Sub-prompt validates and formats data\n- **Context isolation**: Sub-prompt gets fresh context without full history\n\n```typescript\n// Main prompt can call 'data_extractor' as a tool\ndefinePrompt({\n name: 'main_assistant',\n tools: ['data_extractor'], // Another prompt exposed as tool\n // ...\n});\n```\n\n### Agent Handoffs (Agents as Tools)\nAgents can delegate to other agents entirely:\n- **Specialization**: Route to domain-specific agents\n- **Escalation**: Hand off to more capable agents\n- **Workflows**: Chain agents for multi-step processes\n\n```typescript\ndefineAgent({\n name: 'triage_agent',\n exposeAsTool: true,\n toolDescription: 'Hand off to triage for initial assessment',\n // ...\n});\n```\n\n## File Structure\n\n```\nAGENTS.md # Project guidance for AI coding tools\nCLAUDE.md -> AGENTS.md # Compatibility symlink\nvite.config.ts # Uses builder(); Cloudflare config is generated\ntsconfig.json # Includes agents and generated .agents types\nagents/\n\u251C\u2500\u2500 agents/ # Agent definitions (defineAgent)\n\u2502 \u251C\u2500\u2500 AGENTS.md\n\u2502 \u2514\u2500\u2500 CLAUDE.md -> AGENTS.md\n\u251C\u2500\u2500 prompts/ # Prompt definitions (definePrompt)\n\u2502 \u251C\u2500\u2500 AGENTS.md\n\u2502 \u2514\u2500\u2500 CLAUDE.md -> AGENTS.md\n\u251C\u2500\u2500 models/ # Model configurations (defineModel)\n\u2502 \u251C\u2500\u2500 AGENTS.md\n\u2502 \u2514\u2500\u2500 CLAUDE.md -> AGENTS.md\n\u251C\u2500\u2500 providers/ # Provider definitions (defineProvider)\n\u2502 \u251C\u2500\u2500 AGENTS.md\n\u2502 \u2514\u2500\u2500 CLAUDE.md -> AGENTS.md\n\u251C\u2500\u2500 tools/ # Custom tools (defineTool)\n\u2502 \u251C\u2500\u2500 AGENTS.md\n\u2502 \u2514\u2500\u2500 CLAUDE.md -> AGENTS.md\n\u251C\u2500\u2500 hooks/ # Lifecycle hooks (defineHook)\n\u2502 \u251C\u2500\u2500 AGENTS.md\n\u2502 \u2514\u2500\u2500 CLAUDE.md -> AGENTS.md\n\u2514\u2500\u2500 api/ # Thread API endpoints (defineThreadEndpoint)\n \u251C\u2500\u2500 AGENTS.md\n \u2514\u2500\u2500 CLAUDE.md -> AGENTS.md\n```\n\nThe `builder()` Vite plugin generates the Worker entry, Durable Object bindings, Cloudflare Vite plugin configuration, and local `.agents/` support files at build time. Agent files are **auto-discovered** at runtime. No manual registration needed.\n\n## ThreadState\n\n`ThreadState` is the state object available in tools and hooks:\n\n```typescript\ninterface ThreadState {\n // Identity (readonly)\n threadId: string; // Thread identifier\n agentId: string; // Agent identifier\n userId: string | null; // User identifier (if set)\n createdAt: number; // Creation timestamp\n children: SubagentRegistryEntry[]; // Resumable child registry\n terminated: number | null; // Soft-termination timestamp\n arguments: Record<string, unknown>; // Invocation or subagent creation args\n context: Record<string, unknown>; // Current-execution scratch data\n\n // Methods\n getMessages(options?): Promise<MessagesResult>; // Get conversation history\n injectMessage(input): Promise<Message>; // Add message to thread\n queueMessage(input): Promise<void>; // Queue message for next step\n loadModel(name): Promise<ModelConfig>; // Load model definition\n loadPrompt(name): Promise<PromptConfig>; // Load prompt definition\n loadAgent(name): Promise<AgentConfig>; // Load agent definition\n env(propertyName): Promise<string>; // Resolve env value for this thread\n setEnv(propertyName, value): Promise<void>; // Set thread env + propagate to active descendants\n getValue<T = unknown>(key: string): Promise<T | null>; // Read durable per-thread JSON value\n setValue(key: string, value: unknown): Promise<void>; // Write durable value; null/undefined deletes\n notifyParent(content): Promise<void>; // Queue a silent message to the parent when one exists\n setStatus(status): Promise<void>; // Update this child in the parent registry; no-op without a parent\n stopSession(options?): Promise<void>; // Terminally stop the current agent session\n getChildThread(referenceId): Promise<ThreadState | null>; // Resolve child thread\n getParentThread(): Promise<ThreadState | null>; // Resolve parent thread\n terminate(): Promise<void>; // Soft-terminate thread\n runCode(source, options?): CodeExecution; // Run JS/TS in a fresh Dynamic Worker sandbox\n}\n```\n\n`state.arguments` is read-only thread invocation data. Resumable `subagent_create.arguments` persists with the child thread, is visible to both child sides, and is also available as prompt variables. Use `state.context` only for mutable scratch data during the current execution; it is not durable storage.\n\n`runCode` has no implicit access to thread state, filesystem, network, timers, or host globals. Bridge only the exact capabilities needed through `imports` or `globals`; use `modules` for local relative ES modules; use `execute` to select the export and args to run. `modules` keys are graph-root relative paths; entry-source imports resolve from `filename` when supplied, including `../` parent paths that stay inside the supplied graph. TypeScript input is accepted by default and erased before evaluation. In thread endpoints, `runCode` is forwarded into the thread Durable Object; pass plain transferable options there and keep function-backed bridges in tools or in-thread execution contexts.\n\n## Subagents\n\n`dual_ai` agents can be used as subagents from prompt tool configs:\n\n- Each subagent runs in its own thread (`DurableThread`)\n- Parent/child linkage is tracked in thread metadata\n- Resumable children are visible in `state.children`\n- Parent threads create/message resumable children via built-ins (`subagent_create`, `subagent_message`)\n- `subagent_create.arguments` is validated from the receiving child side's prompt schema and persists as `ThreadState.arguments` plus prompt variables for the life of the child thread\n- Child completion results are queued back to the parent when `parentCommunication` is `implicit`\n- Explicit relationships can stay idle until code calls `state.notifyParent()` or `state.setStatus()`; use `state.stopSession({ result, notifyParent, status })` when a tool should also terminally end the child session\n\nAccess in tools:\n```typescript\nexport default defineTool('...', schema, async (state, args) => {\n const threadId = state.threadId;\n const creationArgs = state.arguments;\n const { messages } = await state.getMessages();\n const count = (await state.getValue<number>('invocation_count')) ?? 0;\n await state.setValue('invocation_count', count + 1);\n // ...\n});\n```\n\nAccess in hooks:\n```typescript\nexport default defineHook({\n hook: 'before_create_message',\n id: 'my_hook',\n execute: async (state, message) => {\n console.log(`Thread: ${state.threadId}, Agent: ${state.agentId}`);\n return message;\n }\n});\n```\n\n## Quick Reference\n\n| Function | Purpose | Directory |\n|----------|---------|-----------|\n| `defineModel()` | Configure LLM provider | `agents/models/` |\n| `defineProvider()` | Custom provider endpoints and overrides | `agents/providers/` |\n| `definePrompt()` | System instructions + tools | `agents/prompts/` |\n| `defineAgent()` | Conversation orchestration | `agents/agents/` |\n| `defineTool()` | Custom tool functions | `agents/tools/` |\n| `defineHook()` | Lifecycle interception | `agents/hooks/` |\n| `defineThreadEndpoint()` | Custom API routes | `agents/api/` |\n\n## Runtime Utilities\n\nImport from `@standardagents/builder`:\n\n```typescript\nimport {\n queueTool, // Queue another tool for execution\n injectMessage, // Add message without triggering execution\n getMessages, // Retrieve message history\n emitThreadEvent, // Send custom WebSocket events\n} from '@standardagents/builder';\n```\n\n## Documentation\n\nFull documentation: https://docs.standardagentbuilder.com\n\n- [Architecture Overview](https://docs.standardagentbuilder.com/introduction/architecture)\n- [Models](https://docs.standardagentbuilder.com/core-concepts/models)\n- [Prompts](https://docs.standardagentbuilder.com/core-concepts/prompts)\n- [Agents](https://docs.standardagentbuilder.com/core-concepts/agents)\n- [Tools](https://docs.standardagentbuilder.com/core-concepts/tools)\n- [Hooks](https://docs.standardagentbuilder.com/core-concepts/hooks)\n- [ThreadState](https://docs.standardagentbuilder.com/core-concepts/flowstate)\n- [Thread API](https://docs.standardagentbuilder.com/core-concepts/api)\n";
2
2
 
3
- declare const MODELS_AGENTS_MD = "# Model Definitions\n\nModels define which LLM provider and model to use for prompts.\n\n## Properties\n\n| Property | Type | Required | Description |\n|----------|------|----------|-------------|\n| `name` | `string` | Yes | Unique identifier for this model configuration |\n| `provider` | `'openai' \\| 'anthropic' \\| 'openrouter' \\| 'google' \\| 'cerebras' \\| 'groq' \\| 'xai'` | Yes | LLM provider |\n| `model` | `string` | Yes | Model ID sent to provider API |\n| `fallbacks` | `string[]` | No | Fallback model names to try if primary fails |\n| `inputPrice` | `number` | No | Cost per 1M input tokens (USD) |\n| `outputPrice` | `number` | No | Cost per 1M output tokens (USD) |\n| `cachedPrice` | `number` | No | Cost per 1M cached input tokens |\n| `includedProviders` | `string[]` | No | Provider prefixes for OpenRouter routing |\n| `providerTools` | `string[]` | No | Provider-built-in tool names to make available for prompts using this model |\n\n## Example\n\n```typescript\nimport { defineModel } from '@standardagents/builder';\n\nexport default defineModel({\n name: 'default',\n provider: 'openrouter',\n model: 'google/gemini-3-flash-preview',\n fallbacks: ['fast', 'cheap-heavy'],\n});\n```\n\n## Provider Tools\n\nProviders can expose built-in tools such as search, file search, code execution,\nor provider-specific tools through their `getTools()` implementation. Enable the\nprovider tool names on the model with `providerTools`; prompts can then include\nthose tools like normal tool names. Provider tools execute on the upstream\nprovider, not in AgentBuilder, and successful calls are logged as provider tool\nentries.\n\nOpenRouter exposes `web_search`, `web_fetch`, `datetime`, and `image_generation`\nas provider-executed server tools. Configure optional OpenRouter parameters with\n`providerOptions.serverTools` on the model.\n\n## Recommended Models (OpenRouter)\n\n| Use Case | Model ID | Description |\n|----------|----------|-------------|\n| Fast/Cheap | `z-ai/glm-4.5-air` | Quick responses, low cost |\n| Mid-tier | `google/gemini-3-flash-preview` | Good balance of speed and quality |\n| Cheap Heavy | `nvidia/nemotron-3-ultra-550b-a55b` | Frontier open reasoning and orchestration, still affordable |\n| Heavy | `google/gemini-3-pro-preview` | Most capable, for complex tasks |\n\n**\u26A0\uFE0F Google Models**: When using Google models (`google/gemini-*`), you must enable `reasoning` in your prompt configuration or tool calls will fail. See the prompts AGENTS.md for details.\n\n## Provider API Keys\n\nSet these environment variables in `.dev.vars` (local) or Cloudflare secrets (production):\n\n| Provider | Environment Variable |\n|----------|---------------------|\n| Cloudflare Workers AI | `CLOUDFLARE_API_TOKEN` + `CLOUDFLARE_ACCOUNT_ID` |\n| Cerebras | `CEREBRAS_API_KEY` |\n| Groq | `GROQ_API_KEY` |\n| OpenAI | `OPENAI_API_KEY` |\n| Anthropic | `ANTHROPIC_API_KEY` |\n| OpenRouter | `OPENROUTER_API_KEY` |\n| Google | `GOOGLE_API_KEY` |\n| xAI | `XAI_API_KEY` |\n\nIf `STANDARD_AGENTS_API_KEY` is present and a provider-specific key is not set,\nfirst-party Standard Agents providers route through the hosted Standard Agents\nrouter. Setting a provider-specific key always uses that provider directly.\n\n## Fallback Strategy\n\nWhen a model fails, fallbacks are tried in order:\n1. Primary model (2 attempts)\n2. First fallback (2 attempts)\n3. Second fallback (2 attempts)\n4. ...and so on\n\nRetries occur on: network errors, rate limits (429), server errors (5xx), auth errors (401).\n\n## OpenRouter Configuration\n\nFor OpenRouter, use the full model path:\n\n```typescript\nexport default defineModel({\n name: 'heavy',\n provider: 'openrouter',\n model: 'google/gemini-3-pro-preview',\n includedProviders: ['google'], // Prefer Google's servers\n});\n```\n\n## Best Practices\n\n- **Name by use case**, not model ID (e.g., `fast`, `default`, `heavy`)\n- **Configure fallbacks** for production reliability\n- **Set pricing** for cost tracking in logs when your provider or runtime does not supply it automatically\n- **Cerebras note:** documented Cerebras models have built-in fallback pricing for request logs, but custom/private Cerebras models should still set `inputPrice` and `outputPrice`\n- **Use environment variables** for API keys, never hardcode\n\n## Documentation\n\nFull reference: https://docs.standardagentbuilder.com/api-reference/define/model\n";
3
+ declare const MODELS_AGENTS_MD = "# Model Definitions\n\nModels define which LLM provider and model to use for prompts.\n\n## Properties\n\n| Property | Type | Required | Description |\n|----------|------|----------|-------------|\n| `name` | `string` | Yes | Unique identifier for this model configuration |\n| `provider` | `ProviderFactory` | Yes | Imported provider factory such as `openrouter`, `openai`, or a local provider from `agents/providers` |\n| `model` | `string` | Yes | Model ID sent to provider API |\n| `fallbacks` | `string[]` | No | Fallback model names to try if primary fails |\n| `inputPrice` | `number` | No | Cost per 1M input tokens (USD) |\n| `outputPrice` | `number` | No | Cost per 1M output tokens (USD) |\n| `cachedPrice` | `number` | No | Cost per 1M cached input tokens |\n| `includedProviders` | `string[]` | No | Provider prefixes for OpenRouter routing |\n| `providerTools` | `string[]` | No | Provider-built-in tool names to make available for prompts using this model |\n\n## Example\n\n```typescript\nimport { defineModel } from '@standardagents/builder';\nimport { openrouter } from '@standardagents/openrouter';\n\nexport default defineModel({\n name: 'default',\n provider: openrouter,\n model: 'google/gemini-3-flash-preview',\n fallbacks: ['fast', 'cheap-heavy'],\n});\n```\n\n## Provider Tools\n\nProviders can expose built-in tools such as search, file search, code execution,\nor provider-specific tools through their `getTools()` implementation. Enable the\nprovider tool names on the model with `providerTools`; prompts can then include\nthose tools like normal tool names. Provider tools execute on the upstream\nprovider, not in AgentBuilder, and successful calls are logged as provider tool\nentries.\n\nOpenRouter exposes `web_search`, `web_fetch`, `datetime`, and `image_generation`\nas provider-executed server tools. Configure optional OpenRouter parameters with\n`providerOptions.serverTools` on the model.\n\n## Recommended Models (OpenRouter)\n\n| Use Case | Model ID | Description |\n|----------|----------|-------------|\n| Fast/Cheap | `z-ai/glm-4.5-air` | Quick responses, low cost |\n| Mid-tier | `google/gemini-3-flash-preview` | Good balance of speed and quality |\n| Cheap Heavy | `nvidia/nemotron-3-ultra-550b-a55b` | Frontier open reasoning and orchestration, still affordable |\n| Heavy | `google/gemini-3-pro-preview` | Most capable, for complex tasks |\n\n**\u26A0\uFE0F Google Models**: When using Google models (`google/gemini-*`), you must enable `reasoning` in your prompt configuration or tool calls will fail. See the prompts AGENTS.md for details.\n\n## Provider API Keys\n\nSet these environment variables in `.dev.vars` (local) or Cloudflare secrets (production):\n\n| Provider | Environment Variable |\n|----------|---------------------|\n| Cloudflare Workers AI | `CLOUDFLARE_API_TOKEN` + `CLOUDFLARE_ACCOUNT_ID` |\n| Cerebras | `CEREBRAS_API_KEY` |\n| Groq | `GROQ_API_KEY` |\n| OpenAI | `OPENAI_API_KEY` |\n| Anthropic | `ANTHROPIC_API_KEY` |\n| OpenRouter | `OPENROUTER_API_KEY` |\n| Baseten Model APIs | `BASETEN_API_KEY` |\n| Google | `GOOGLE_API_KEY` |\n| xAI | `XAI_API_KEY` |\n\nIf `STANDARD_AGENTS_API_KEY` is present and a provider-specific key is not set,\nfirst-party Standard Agents providers route through the hosted Standard Agents\nrouter. Setting a provider-specific key always uses that provider directly.\n\n## User-Defined Providers\n\nCreate `agents/providers/<name>.ts` when a provider is compatible with an existing\nprovider package but needs its own API key, endpoint, icon, model list, pricing, or\nother provider behavior.\n\n```typescript\n// agents/providers/darkbloom.ts\nimport { defineProvider, providerEnv } from '@standardagents/builder';\nimport { openai } from '@standardagents/openai';\n\nexport default defineProvider({\n name: 'darkbloom',\n label: 'Darkbloom',\n baseProvider: openai,\n config: {\n apiKey: providerEnv('DARKBLOOM_API_KEY', { valueType: 'secret' }),\n baseUrl: providerEnv('DARKBLOOM_BASE_URL', {\n valueType: 'url',\n default: 'https://api.darkbloom.dev/v1',\n }),\n },\n});\n```\n\n```typescript\n// agents/models/darkbloom_chat.ts\nimport { defineModel } from '@standardagents/builder';\nimport darkbloom from '../providers/darkbloom';\n\nexport default defineModel({\n name: 'darkbloom_chat',\n provider: darkbloom,\n model: 'darkbloom-chat',\n});\n```\n\nProvider `overrides` can replace behavior such as `getModels`, `getIcon`,\n`getTools`, pricing/capability lookup, `generate`, or `stream`. Call `next()`\ninside an override to compose with the base provider; return your own value to\nreplace it.\n\n## Fallback Strategy\n\nWhen a model fails, fallbacks are tried in order:\n1. Primary model (2 attempts)\n2. First fallback (2 attempts)\n3. Second fallback (2 attempts)\n4. ...and so on\n\nRetries occur on: network errors, rate limits (429), server errors (5xx), auth errors (401).\n\n## OpenRouter Configuration\n\nFor OpenRouter, use the full model path:\n\n```typescript\nimport { defineModel } from '@standardagents/builder';\nimport { openrouter } from '@standardagents/openrouter';\n\nexport default defineModel({\n name: 'heavy',\n provider: openrouter,\n model: 'google/gemini-3-pro-preview',\n includedProviders: ['google'], // Prefer Google's servers\n});\n```\n\n## Best Practices\n\n- **Name by use case**, not model ID (e.g., `fast`, `default`, `heavy`)\n- **Configure fallbacks** for production reliability\n- **Set pricing** for cost tracking in logs when your provider or runtime does not supply it automatically\n- **Cerebras note:** documented Cerebras models attach provider-owned `usage.cost` values for request logs, but custom/private Cerebras models should still set `inputPrice` and `outputPrice`\n- **Use environment variables** for API keys, never hardcode\n\n## Documentation\n\nFull reference: https://docs.standardagentbuilder.com/api-reference/define/model\n";
4
4
 
5
- declare const PROMPTS_AGENTS_MD = "# Prompt Definitions\n\nPrompts define system instructions, model selection, and available tools for LLM interactions.\n\n## Properties\n\n| Property | Type | Required | Description |\n|----------|------|----------|-------------|\n| `name` | `string` | Yes | Unique identifier for this prompt |\n| `toolDescription` | `string` | Yes | Description shown when used as a tool |\n| `prompt` | `string \\| StructuredPrompt` | Yes | System instructions |\n| `model` | `string` | Yes | Model name to use (references `agents/models/`) |\n| `tools` | `(string \\| ToolConfig \\| SubagentToolConfig)[]` | No | Available tools (include ai_human agent names for handoffs and dual_ai subagent configs) |\n| `includeChat` | `boolean` | No | Include full conversation history |\n| `includePastTools` | `boolean` | No | Include previous tool results |\n| `parallelToolCalls` | `boolean` | No | Allow multiple concurrent tool calls |\n| `toolChoice` | `'auto' \\| 'none' \\| 'required'` | No | Tool calling strategy |\n| `requiredSchema` | `z.ZodObject` | No | Input validation when called as tool |\n| `variables` | `VariableDefinition[]` | No | Variable declarations (`name`, `type`, `required`, `scoped`, `description`) |\n| `env` | `Record<string, string>` | No | Prompt-level default values for variables |\n| `hooks` | `string[]` | No | Hook IDs to run for this prompt (overrides agent hooks) |\n| `reasoning` | `ReasoningConfig` | No | Extended thinking configuration |\n\n## Basic Example\n\n```typescript\nimport { definePrompt } from '@standardagents/builder';\n\nexport default definePrompt({\n name: 'customer_support',\n toolDescription: 'Handle customer support inquiries',\n model: 'default',\n prompt: `You are a helpful customer support agent.\nAlways be polite and professional.\nIf you cannot help, escalate to a human.`,\n tools: ['search_knowledge_base', 'create_ticket'],\n includeChat: true,\n});\n```\n\n## Structured Prompts\n\nInclude other prompts for reusable instruction blocks:\n\n```typescript\nexport default definePrompt({\n name: 'main_assistant',\n toolDescription: 'Primary assistant',\n model: 'default',\n prompt: [\n { type: 'text', content: 'You are a helpful assistant.\\n\\n' },\n { type: 'include', prompt: 'common_rules' }, // Includes another prompt\n { type: 'env', property: 'ASSISTANT_TONE' }, // Inject variable value\n { type: 'text', content: '\\n\\nBe concise.' },\n ],\n});\n```\n\n`type: 'env'` inserts a resolved thread variable value. Use this only for non-secret values that are safe to expose to the LLM.\n\nThe sandboxed coding prompt declares `HTTP_HOST` as a text variable. Its URL helper uses that value as the origin for files exposed from the thread `public/` directory and endpoints exposed from the thread `api/` directory. Public URLs should usually omit extensions; extensionless public paths resolve `.html`, then `.js`, then `.ts`, then matching `index` files in the same order. Browser pages should reference only public files, `api/` endpoints, or absolute external URLs, using relative asset URLs like `./app` and `./api/todos`; private `src/` files are not served directly. Public `.ts` files are transformed to browser JavaScript and are not server endpoints. Server-side endpoints live under the thread filesystem `api/` directory, and the `api/` directory name stays in the public URL: `api/todo.ts` is `/api/threads/{threadId}/api/todo`, while `api/todo.ts` is not `/api/threads/{threadId}/todo` or `/api/threads/{threadId}/todos`. Endpoint files default-export a function that accepts `Request` and returns `Response` or `Promise<Response>`. Endpoint code can import `fetch`, `fs`, and `storage`, and can import private helpers with relative paths such as `../src/todo.ts`. When the coding agent creates a site, page, or endpoint, it should call `get_public_url` with the created file path and use the returned URL.\n\nSandboxed code and `api/` endpoints can persist small JSON-serializable runtime data through `import { storage } from \"storage\"`. Use `storage.get`, `storage.set`, `storage.delete`, and `storage.has` with stable logical keys. Do not expose, mention, or depend on internal storage key prefixes.\n\nThe sandboxed coding prompt includes `delete_file` for removing files or empty directories from the thread filesystem. Use it to clean up obsolete implementation files, stale public assets, and abandoned endpoint routes after the replacement is working.\n\n## Tool Configuration\n\nTools can be simple names or detailed configs:\n\n```typescript\ntools: [\n 'simple_tool', // Just the tool name\n {\n name: 'complex_tool',\n includeTextResponse: true, // Include sub-prompt text in result\n includeToolCalls: false, // Exclude sub-prompt tool calls\n includeErrors: true, // Include error details\n initUserMessageProperty: 'query', // Use this arg as initial message\n },\n],\n```\n\nProvider-built-in tools use the same `tools` list once the selected model enables\nthem with `providerTools`. AgentBuilder passes them to the provider and records\nprovider-reported calls in request logs; it does not execute those tools locally.\nGenerated prompt files may store these selections as `provider:<toolName>` to\ndistinguish provider tools from local tools with the same name.\n\n### Subagent Tool Configuration\n\nUse `SubagentToolConfig` when the tool is a `dual_ai` agent:\n\n```typescript\ntools: [\n // Blocking, non-resumable (default)\n { name: 'data_processor_agent' },\n\n // Non-blocking, resumable with a single instance\n {\n name: 'browser_agent',\n blocking: false,\n immediate: {\n nameEnv: 'BROWSER_AGENT_NAME',\n descriptionEnv: 'BROWSER_AGENT_DESCRIPTION',\n scopedEnv: ['BROWSER_AGENT_API_KEY'],\n },\n optional: 'ENABLE_BROWSER_AGENT',\n initAgentNameProperty: 'name',\n resumable: {\n receives_messages: 'side_a',\n maxInstances: 1,\n parentCommunication: 'explicit',\n },\n },\n]\n```\n\nWhen prompt-configured resumable dual_ai subagents exist, the runtime auto-injects:\n- `subagent_create` for spawning new child instances\n- `subagent_message` for messaging active resumable instances\n\n`subagent_create` requires a non-empty `name` for human-friendly child thread labels.\nAgentBuilder stores that argument as a `name:<value>` thread tag.\n`subagent_create.arguments` is shaped by the prompt schema on the child side selected by `resumable.receives_messages`.\nAgentBuilder persists those initial arguments with the child thread, exposes them as `ThreadState.arguments` and prompt variables, and keeps them visible to both child sides for later resumptions.\n\nSet `immediate: true` to run a tool automatically when the prompt activates.\nUse `immediate: { nameEnv, descriptionEnv, scopedEnv }` when you want safe per-instance bootstrap hints while keeping copied scoped env runtime-only.\nSet `optional: 'ENV_NAME'` to enable a subagent branch only when env resolves to `true`, `1`, or `yes`.\nSet `resumable.parentCommunication: 'explicit'` when the child should stay quiet until its own tools or hooks call `state.notifyParent()`, `state.setStatus()`, or `state.stopSession({ result, notifyParent, status })`.\nIf required scoped vars are missing, the runtime returns `error_code: \"subagent_env_required\"` with a temporary `GET/POST /api/threads/:threadId/variables/:requestId` endpoint in `error_data.endpoint`.\n\n## Input Validation\n\nValidate inputs when prompt is called as a tool:\n\n```typescript\nimport { z } from 'zod';\n\nexport default definePrompt({\n name: 'data_extractor',\n toolDescription: 'Extract structured data from text',\n model: 'default',\n prompt: 'Extract the requested data from the input.',\n requiredSchema: z.object({\n text: z.string().describe('Text to extract from'),\n fields: z.array(z.string()).describe('Fields to extract'),\n }),\n});\n```\n\n## Extended Thinking (Reasoning)\n\nEnable for complex reasoning tasks:\n\n```typescript\nexport default definePrompt({\n name: 'code_reviewer',\n toolDescription: 'Review code for issues',\n model: 'heavy',\n prompt: 'Review the code thoroughly...',\n reasoning: {\n effort: 'high', // 'low' | 'medium' | 'high'\n maxTokens: 16000, // Max thinking tokens\n exclude: true, // Don't include thinking in response\n },\n});\n```\n\n**\u26A0\uFE0F Google Models Require Reasoning**: When using Google models (`google/gemini-*`) via OpenRouter, you **must** include `reasoning` configuration or tool calls will fail. At minimum:\n\n```typescript\nreasoning: {\n effort: 'low', // Can be 'low', 'medium', or 'high'\n},\n```\n\n## Hooks\n\nAttach lifecycle hooks to a prompt:\n\n```typescript\nexport default definePrompt({\n name: 'customer_support',\n toolDescription: 'Handle customer support',\n model: 'default',\n prompt: 'You are a support agent...',\n hooks: ['limit_to_20', 'redact_pii'], // Hook IDs from agents/hooks/\n});\n```\n\nPrompt hooks take precedence over agent hooks. See `agents/hooks/AGENTS.md` for details.\n\n## Best Practices\n\n- **Write clear instructions** - Structure with headers and bullet points\n- **Describe tools thoroughly** - LLMs decide based on descriptions\n- **Validate inputs with Zod** - Catch errors early\n- **Use `includeChat`** for conversational context\n- **Name by purpose**, not model (e.g., `support_agent` not `gpt4_prompt`)\n\n## Documentation\n\nFull reference: https://docs.standardagentbuilder.com/api-reference/define/prompt\n";
5
+ declare const PROVIDERS_AGENTS_MD = "# Provider Definitions\n\nProvider definitions create named provider factories that wrap a base provider\npackage with connection config and optional method overrides.\n\nUse `defineProvider()` and export the result as the default export:\n\n```typescript\nimport { defineProvider, providerEnv, providerValue } from '@standardagents/builder';\nimport { openai } from '@standardagents/openai';\n\nexport default defineProvider({\n name: 'my_openai_compatible_provider',\n label: 'My OpenAI-compatible Provider',\n baseProvider: openai,\n config: {\n apiKey: providerEnv('MY_PROVIDER_API_KEY', {\n valueType: 'secret',\n required: true,\n description: 'Provider API key.',\n }),\n baseUrl: providerValue('https://api.example.com/v1'),\n },\n});\n```\n\nModels can then import the provider definition and use it like any other provider\nfactory:\n\n```typescript\nimport { defineModel } from '@standardagents/builder';\nimport myProvider from '../providers/my_openai_compatible_provider';\n\nexport default defineModel({\n name: 'custom_fast',\n provider: myProvider,\n model: 'gpt-4o-mini',\n});\n```\n\nProvider `overrides` can replace behavior such as `getModels`, `getIcon`,\n`getTools`, pricing/capability lookup, `generate`, or `stream`. Call `next()`\ninside an override to compose with the base provider; return your own value to\nreplace it.\n\nKeep credentials in secret env values. Do not hardcode API keys in provider\ndefinition files.\n";
6
+
7
+ declare const PROMPTS_AGENTS_MD = "# Prompt Definitions\n\nPrompts define system instructions, model selection, and available tools for LLM interactions.\n\n## Properties\n\n| Property | Type | Required | Description |\n|----------|------|----------|-------------|\n| `name` | `string` | Yes | Unique identifier for this prompt |\n| `toolDescription` | `string` | Yes | Description shown when used as a tool |\n| `prompt` | `string \\| StructuredPrompt` | Yes | System instructions |\n| `model` | `string` | Yes | Model name to use (references `agents/models/`) |\n| `tools` | `(string \\| ToolConfig \\| SubagentToolConfig)[]` | No | Available tools (include ai_human agent names for handoffs and dual_ai subagent configs) |\n| `includeChat` | `boolean` | No | Include full conversation history |\n| `includePastTools` | `boolean` | No | Include previous tool results |\n| `parallelToolCalls` | `boolean` | No | Allow multiple concurrent tool calls |\n| `toolChoice` | `'auto' \\| 'none' \\| 'required'` | No | Tool calling strategy |\n| `requiredSchema` | `z.ZodObject` | No | Input validation when called as tool |\n| `variables` | `VariableDefinition[]` | No | Variable declarations (`name`, `type`, `required`, `scoped`, `description`) |\n| `env` | `Record<string, string>` | No | Prompt-level default values for variables |\n| `hooks` | `string[]` | No | Hook IDs to run for this prompt (overrides agent hooks) |\n| `reasoning` | `ReasoningConfig` | No | Extended thinking configuration |\n\n## Basic Example\n\n```typescript\nimport { definePrompt } from '@standardagents/builder';\n\nexport default definePrompt({\n name: 'customer_support',\n toolDescription: 'Handle customer support inquiries',\n model: 'default',\n prompt: `You are a helpful customer support agent.\nAlways be polite and professional.\nIf you cannot help, escalate to a human.`,\n tools: ['search_knowledge_base', 'create_ticket'],\n includeChat: true,\n});\n```\n\n## Structured Prompts\n\nInclude other prompts for reusable instruction blocks:\n\n```typescript\nexport default definePrompt({\n name: 'main_assistant',\n toolDescription: 'Primary assistant',\n model: 'default',\n prompt: [\n { type: 'text', content: 'You are a helpful assistant.\\n\\n' },\n { type: 'include', prompt: 'common_rules' }, // Includes another prompt\n { type: 'env', property: 'ASSISTANT_TONE' }, // Inject variable value\n { type: 'text', content: '\\n\\nBe concise.' },\n ],\n});\n```\n\n`type: 'env'` inserts a resolved thread variable value. Use this only for non-secret values that are safe to expose to the LLM.\n\nThe sandboxed coding prompt declares `HTTP_HOST` as a text variable and injects its resolved value with a structured `{ type: 'env', property: 'HTTP_HOST' }` prompt part. Its URL helper uses that value as the origin for files exposed from the thread `public/` directory and endpoints exposed from the thread `api/` directory. Public URLs should usually omit extensions; extensionless public paths resolve `.html`, then `.js`, then `.ts`, then matching `index` files in the same order. Browser pages should reference only public files, `api/` endpoints, or absolute external URLs, using relative asset URLs like `./app` and `./api/todos`; private `src/` files are not served directly. Public `.ts` files are transformed to browser JavaScript and are not server endpoints. Server-side endpoints live under the thread filesystem `api/` directory, and the `api/` directory name stays in the public URL: `api/todo.ts` is `/api/threads/{threadId}/api/todo`, while `api/todo.ts` is not `/api/threads/{threadId}/todo` or `/api/threads/{threadId}/todos`. Endpoint files default-export a function that accepts `Request` and returns `Response` or `Promise<Response>`. Endpoint code can import `fetch`, `fs`, and `storage`, and can import private helpers with relative paths such as `../src/todo.ts`. When the coding agent creates a site, page, or endpoint, it should call `get_public_url` with the created file path and use the returned URL.\n\nThe sandboxed coding prompt includes `set_goal` (write the whole goal: a short `summary`, a `description` that is the user's objective in their own words captured verbatim, plus ordered steps) and `update_goal_step` (flip one step's status as you start/finish it), and should check work incrementally, checking steps off as it goes and finishing with a summary once every step is done. `coding_validate_typescript` is only an early signal; for real verification, call helper exports with `coding_run`, get public URLs for pages or endpoints, then probe those URLs from `coding_run` using `import { fetch } from \"fetch\"`. Side-effecting endpoint checks should use disposable data and clean up through the endpoint, storage, or file cleanup path when practical. The prompt also includes `fetch_url` for reading known external public http(s) pages; use the `coding_run` fetch bridge for custom methods, headers, request bodies, or thread endpoint checks.\n\nSandboxed code and `api/` endpoints can persist small JSON-serializable runtime data through `import { storage } from \"storage\"`. Use `storage.get`, `storage.set`, `storage.delete`, and `storage.has` with stable logical keys. Do not expose, mention, or depend on internal storage key prefixes.\n\nThe sandboxed coding prompt includes `delete_file` for removing files or empty directories from the thread filesystem. Use it to clean up obsolete implementation files, stale public assets, and abandoned endpoint routes after the replacement is working.\n\n## Tool Configuration\n\nTools can be simple names or detailed configs:\n\n```typescript\ntools: [\n 'simple_tool', // Just the tool name\n {\n name: 'complex_tool',\n includeTextResponse: true, // Include sub-prompt text in result\n includeToolCalls: false, // Exclude sub-prompt tool calls\n includeErrors: true, // Include error details\n initUserMessageProperty: 'query', // Use this arg as initial message\n },\n],\n```\n\nProvider-built-in tools use the same `tools` list once the selected model enables\nthem with `providerTools`. AgentBuilder passes them to the provider and records\nprovider-reported calls in request logs; it does not execute those tools locally.\nGenerated prompt files may store these selections as `provider:<toolName>` to\ndistinguish provider tools from local tools with the same name.\n\n### Subagent Tool Configuration\n\nUse `SubagentToolConfig` when the tool is a `dual_ai` agent:\n\n```typescript\ntools: [\n // Blocking, non-resumable (default)\n { name: 'data_processor_agent' },\n\n // Non-blocking, resumable with a single instance\n {\n name: 'browser_agent',\n blocking: false,\n immediate: {\n nameEnv: 'BROWSER_AGENT_NAME',\n descriptionEnv: 'BROWSER_AGENT_DESCRIPTION',\n scopedEnv: ['BROWSER_AGENT_API_KEY'],\n },\n optional: 'ENABLE_BROWSER_AGENT',\n initAgentNameProperty: 'name',\n resumable: {\n receives_messages: 'side_a',\n maxInstances: 1,\n parentCommunication: 'explicit',\n },\n },\n]\n```\n\nWhen prompt-configured resumable dual_ai subagents exist, the runtime auto-injects:\n- `subagent_create` for spawning new child instances\n- `subagent_message` for messaging active resumable instances\n\n`subagent_create` requires a non-empty `name` for human-friendly child thread labels.\nAgentBuilder stores that argument as a `name:<value>` thread tag.\n`subagent_create.arguments` is shaped by the prompt schema on the child side selected by `resumable.receives_messages`.\nAgentBuilder persists those initial arguments with the child thread, exposes them as `ThreadState.arguments` and prompt variables, and keeps them visible to both child sides for later resumptions.\n\nSet `immediate: true` to run a tool automatically when the prompt activates.\nUse `immediate: { nameEnv, descriptionEnv, scopedEnv }` when you want safe per-instance bootstrap hints while keeping copied scoped env runtime-only.\nSet `optional: 'ENV_NAME'` to enable a subagent branch only when env resolves to `true`, `1`, or `yes`.\nSet `resumable.parentCommunication: 'explicit'` when the child should stay quiet until its own tools or hooks call `state.notifyParent()`, `state.setStatus()`, or `state.stopSession({ result, notifyParent, status })`.\nSet top-level `parentCommunication: 'explicit'` on a NON-resumable subagent when its completion should not be auto-queued to the parent (so it never wakes the parent) \u2014 for background children that deliver results through another channel, e.g. the parent's thread KV. `resumable.parentCommunication` takes precedence when both are set.\nSet `hidden: true` to keep a subagent relationship declared and spawnable by runtime code (`state.invokeTool()`/`queueTool()` from hooks) while excluding its tool from every LLM request \u2014 the model can never call it (for infrastructure children like a background compaction agent).\nIf required scoped vars are missing, the runtime returns `error_code: \"subagent_env_required\"` with a temporary `GET/POST /api/threads/:threadId/variables/:requestId` endpoint in `error_data.endpoint`.\n\n## Input Validation\n\nValidate inputs when prompt is called as a tool:\n\n```typescript\nimport { z } from 'zod';\n\nexport default definePrompt({\n name: 'data_extractor',\n toolDescription: 'Extract structured data from text',\n model: 'default',\n prompt: 'Extract the requested data from the input.',\n requiredSchema: z.object({\n text: z.string().describe('Text to extract from'),\n fields: z.array(z.string()).describe('Fields to extract'),\n }),\n});\n```\n\n## Extended Thinking (Reasoning)\n\nEnable for complex reasoning tasks:\n\n```typescript\nexport default definePrompt({\n name: 'code_reviewer',\n toolDescription: 'Review code for issues',\n model: 'heavy',\n prompt: 'Review the code thoroughly...',\n reasoning: {\n effort: 'high', // 'low' | 'medium' | 'high'\n maxTokens: 16000, // Max thinking tokens\n exclude: true, // Don't include thinking in response\n },\n});\n```\n\n**\u26A0\uFE0F Google Models Require Reasoning**: When using Google models (`google/gemini-*`) via OpenRouter, you **must** include `reasoning` configuration or tool calls will fail. At minimum:\n\n```typescript\nreasoning: {\n effort: 'low', // Can be 'low', 'medium', or 'high'\n},\n```\n\n## Hooks\n\nAttach lifecycle hooks to a prompt:\n\n```typescript\nexport default definePrompt({\n name: 'customer_support',\n toolDescription: 'Handle customer support',\n model: 'default',\n prompt: 'You are a support agent...',\n hooks: ['limit_to_20', 'redact_pii'], // Hook IDs from agents/hooks/\n});\n```\n\nPrompt hooks take precedence over agent hooks. See `agents/hooks/AGENTS.md` for details.\n\n## Best Practices\n\n- **Write clear instructions** - Structure with headers and bullet points\n- **Describe tools thoroughly** - LLMs decide based on descriptions\n- **Validate inputs with Zod** - Catch errors early\n- **Use `includeChat`** for conversational context\n- **Name by purpose**, not model (e.g., `support_agent` not `gpt4_prompt`)\n\n## Documentation\n\nFull reference: https://docs.standardagentbuilder.com/api-reference/define/prompt\n";
6
8
 
7
9
  declare const AGENT_DEFINITIONS_AGENTS_MD = "# Agent Definitions\n\nAgents orchestrate conversations by defining prompts, stop conditions, and turn limits.\n\n## Agent Properties\n\n| Property | Type | Required | Description |\n|----------|------|----------|-------------|\n| `name` | `string` | Yes | Unique identifier for this agent |\n| `type` | `'ai_human' \\| 'dual_ai'` | No | Conversation type (default: `ai_human`) |\n| `sideA` | `SideConfig` | Yes | Configuration for side A (AI in ai_human) |\n| `sideB` | `SideConfig` | No | Configuration for side B (required for dual_ai) |\n| `maxSessionTurns` | `number` | No | Max total turns across both sides |\n| `exposeAsTool` | `boolean` | No | Allow other prompts to hand off to this agent |\n| `toolDescription` | `string` | No | Description when used as tool (required if exposeAsTool) |\n| `env` | `Record<string, string>` | No | Agent-level default variable values |\n| `hooks` | `string[]` | No | Hook IDs to run for this agent (fallback if prompt has no hooks) |\n| `tags` | `string[]` | No | Tags for categorization and filtering |\n\n## Side Configuration\n\n| Property | Type | Required | Description |\n|----------|------|----------|-------------|\n| `label` | `string` | No | Display name for this side |\n| `prompt` | `string` | Yes | Prompt name to use (references `agents/prompts/`) |\n| `stopOnResponse` | `boolean` | No | Stop turn when LLM returns text (default: true) |\n| `stopTool` | `string` | No | Tool that stops this side's turn |\n| `stopToolResponseProperty` | `string` | No | Property to extract from stop tool result |\n| `maxSteps` | `number` | No | Maximum step budget for this side |\n| `sessionStop` | `string \\| SessionToolBinding` | No | Terminal success lifecycle binding |\n| `sessionFail` | `string \\| SessionToolBinding` | No | Terminal failure lifecycle binding |\n| `sessionStatus` | `string \\| SessionToolBinding` | No | Non-terminal status lifecycle binding |\n| `manualStopCondition` | `boolean` | No | Enable custom stop handling via hooks |\n\n## Basic Example (AI-Human)\n\n```typescript\nimport { defineAgent } from '@standardagents/builder';\n\nexport default defineAgent({\n name: 'support_agent',\n type: 'ai_human',\n sideA: {\n label: 'Support',\n prompt: 'customer_support',\n stopOnResponse: true,\n sessionStop: 'close_ticket',\n maxSteps: 50,\n },\n tags: ['support', 'tier-1'],\n});\n```\n\n## Dual-AI Example\n\nTwo AI agents conversing (e.g., debate, iterative refinement):\n\n```typescript\nexport default defineAgent({\n name: 'code_review_debate',\n type: 'dual_ai',\n maxSessionTurns: 20,\n sideA: {\n label: 'Reviewer',\n prompt: 'code_reviewer',\n stopOnResponse: true,\n },\n sideB: {\n label: 'Developer',\n prompt: 'code_defender',\n stopOnResponse: true,\n },\n});\n```\n\n## Dual-AI Subagent Pattern\n\nWhen a `dual_ai` agent is used as a subagent tool, a common split is:\n- **sideA**: performs work (tools, data gathering, execution)\n- **sideB**: reflection, verification, and quality checks\n\n```typescript\nexport default defineAgent({\n name: 'research_subagent',\n type: 'dual_ai',\n exposeAsTool: true,\n toolDescription: 'Researches and validates findings autonomously',\n maxSessionTurns: 16,\n sideA: {\n label: 'Worker',\n prompt: 'research_worker',\n sessionStatus: 'set_subagent_status',\n sessionFail: 'fail_research_subagent',\n sessionStop: 'finish_subagent',\n },\n sideB: {\n label: 'Reviewer',\n prompt: 'research_reviewer',\n stopOnResponse: true,\n },\n});\n```\n\n## Agent Handoffs\n\nExpose an agent for handoffs from other prompts:\n\n```typescript\nexport default defineAgent({\n name: 'escalation_agent',\n type: 'ai_human',\n exposeAsTool: true,\n toolDescription: 'Escalate to senior support for complex issues',\n sideA: {\n prompt: 'senior_support',\n },\n});\n```\n\nOther prompts can then include the agent name in their `tools` array to enable handoffs.\n\n## Stop Conditions (Priority Order)\n\n1. **sessionFail** - Ends entire conversation with a terminal failure\n2. **sessionStop** - Ends entire conversation successfully\n3. **stopTool** - Ends current side's turn\n4. **maxSteps** - Ends side execution when the safety budget is reached\n5. **stopOnResponse** - Ends turn when LLM returns text\n6. **maxSessionTurns** - Ends conversation (hard limit: 250)\n\n## Hooks\n\nAttach lifecycle hooks at the agent level:\n\n```typescript\nexport default defineAgent({\n name: 'support_agent',\n type: 'ai_human',\n hooks: ['log_all_messages', 'sanitize_results'],\n sideA: {\n prompt: 'customer_support',\n },\n});\n```\n\nAgent hooks run as a fallback when the active prompt has no hooks defined. Prompt hooks always take precedence. See `agents/hooks/AGENTS.md` for details.\n\n## Naming Convention\n\nAgent names **must** end with the `_agent` suffix (e.g., `support_agent`, `research_agent`).\nThis convention is enforced by the builder UI and makes agents easily identifiable in logs and code.\n\n## Best Practices\n\n- **Use descriptive names** (`customer_support_agent` not `agent1`)\n- **Always use the _agent suffix** - names like `support_agent`, `research_agent`\n- **Always set maxSteps or maxSessionTurns** as safety limits\n- **Match stop conditions to use case** - chat apps use stopOnResponse, workflows use stopTool\n- **Use labels** for clarity in logs and UI\n- **Organize with tags** for filtering\n\n## Documentation\n\nFull reference: https://docs.standardagentbuilder.com/api-reference/define/agent\n";
8
10
 
9
- declare const TOOLS_AGENTS_MD = "# Custom Tools\n\nTools extend agent capabilities beyond text generation. They allow LLMs to fetch data, perform calculations, execute side effects, and chain to other prompts or agents.\n\n## Function Signature\n\n```typescript\ndefineTool({\n description: string, // What the tool does (shown to LLM)\n args?: z.ZodObject, // Input validation schema (optional)\n execute: (state, args) => ToolResult, // Implementation\n variables?: VariableDefinition[], // Declared variables (optional)\n})\n```\n\n## Basic Example\n\n```typescript\nimport { defineTool } from '@standardagents/builder';\nimport { z } from 'zod';\n\nexport default defineTool({\n description: 'Search the knowledge base for articles matching a query',\n args: z.object({\n query: z.string().describe('Search query'),\n limit: z.number().optional().default(10).describe('Max results'),\n }),\n execute: async (state, args) => {\n const results = await searchKB(args.query, args.limit);\n return {\n status: 'success',\n result: JSON.stringify(results),\n };\n },\n});\n```\n\n## Argument Schemas\n\nTool args must be a top-level `z.object(...)`. Prefer explicit, bounded schemas made from strings, numbers, booleans, nulls, literals, enums, arrays, objects, optionals, nullables, and defaults. Avoid provider-visible recursive or open-ended schemas such as `z.unknown()`, `z.any()`, and `z.object({}).catchall(...)`; strict tool providers can reject the generated JSON Schema. If a tool needs arbitrary JSON input, accept it as a JSON string and parse it inside `execute`.\n\n## ToolResult Interface\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `status` | `'success' \\| 'error'` | Whether the tool succeeded |\n| `result` | `string` | Tool output (required for success) |\n| `error` | `string` | Error message (for error status) |\n| `error_code` | `string` | Machine-readable error code |\n| `error_data` | `Record<string, unknown>` | Structured error payload |\n| `attachments` | `ToolAttachment[]` | Files to attach (images, etc.) |\n\n## ThreadState Access\n\nThe `state` parameter provides access to:\n\n```typescript\nexecute: async (state, args) => {\n // Thread information\n const threadId = state.thread.id;\n const thread = state.thread.instance;\n const creationArgs = state.arguments; // Invocation or subagent creation args\n\n // Configuration\n const agentName = state.agent.name;\n const modelName = state.model.name;\n\n // Message history\n const messages = state.messages;\n\n // Thread variable resolution\n const apiKey = await state.env('GOOGLE_API_KEY');\n await state.setEnv('LAST_TOOL_RUN_AT', new Date().toISOString());\n\n // Durable per-thread JSON values\n const runCount = (await state.getValue<number>('run_count')) ?? 0;\n await state.setValue('run_count', runCount + 1);\n\n // Sandboxed JS/TS execution with explicit bridge capabilities\n const run = state.runCode('export async function main(path) { return await read(path) }', {\n execute: { fn: 'main', args: ['/notes.txt'] },\n globals: {\n read: async (path: string) => {\n const data = await state.readFile(path);\n return data ? new TextDecoder().decode(data) : null;\n },\n },\n });\n const codeResult = await run;\n\n // Parent state (for sub-prompts)\n const root = state.rootState;\n}\n```\n\nUse `state.runCode()` instead of `eval` or `new Function` for model- or user-authored JavaScript/TypeScript. The sandbox starts with no ambient host capabilities; provide imports/globals explicitly, use `modules` for local relative ES modules, use `execute` to select an export and pass args, use `report` for streamed observations, and call `run.terminate(reason)` from your own timeout budget when needed. `modules` keys are graph-root relative paths; entry-source imports resolve from `options.filename` when supplied. Relative module imports may use `./` and `../` as long as they resolve within the supplied module graph. In thread endpoints, `runCode` is forwarded into the thread Durable Object; pass plain transferable option values there, and do function-backed bridges from tools or in-thread execution contexts.\n\n## Tool Without Arguments\n\n```typescript\nexport default defineTool({\n description: 'Get current server time',\n execute: async (state) => {\n return {\n status: 'success',\n result: new Date().toISOString(),\n };\n },\n});\n```\n\n## Error Handling\n\nReturn errors gracefully instead of throwing:\n\n```typescript\nexport default defineTool({\n description: 'Fetch user data',\n args: z.object({ userId: z.string() }),\n execute: async (state, args) => {\n try {\n const user = await fetchUser(args.userId);\n return { status: 'success', result: JSON.stringify(user) };\n } catch (error) {\n return {\n status: 'error',\n error: `Failed to fetch user: ${error.message}`,\n };\n }\n },\n});\n```\n\n## Queueing Additional Tools\n\nQueue another tool to run after the current one:\n\n```typescript\nimport { queueTool } from '@standardagents/builder';\n\nexport default defineTool({\n description: 'Create order and send confirmation',\n args: z.object({ items: z.array(z.string()) }),\n execute: async (state, args) => {\n const order = await createOrder(args.items);\n\n // Queue email tool to run next\n queueTool(state, 'send_confirmation_email', {\n orderId: order.id,\n email: state.thread.metadata.userEmail,\n });\n\n return { status: 'success', result: JSON.stringify(order) };\n },\n});\n```\n\n## Injecting Messages\n\nAdd messages without triggering re-execution:\n\n```typescript\nimport { injectMessage } from '@standardagents/builder';\n\nexport default defineTool({\n description: 'Log audit event',\n args: z.object({ event: z.string() }),\n execute: async (state, args) => {\n await injectMessage(state, {\n role: 'system',\n content: `[AUDIT] ${args.event}`,\n });\n return { status: 'success', result: 'Logged' };\n },\n});\n```\n\n## Stopping Sessions\n\n`state.execution.stop()` stops the current execution loop. To terminally end the active agent session, including blocking subagent runs that expect a session boundary, use `state.stopSession()`:\n\n```typescript\nawait state.stopSession({\n result: 'Waiting for clarification',\n notifyParent: 'Please clarify the request',\n status: 'waiting for clarification',\n});\n```\n\n`notifyParent` queues a silent message to the parent when one exists; `status` is ignored without a parent registry entry. Omit `notifyParent` and `status` when stopping should not send a parent message or update child status.\n\n## Variables and Env\n\nTools can declare variable requirements with `variables`, including `required` and `description` metadata:\n\n```typescript\nexport default defineTool({\n description: 'Search uploaded documents',\n args: z.object({ query: z.string() }),\n execute: async (state, args) => {\n const vectorStoreId = await state.env('VECTOR_STORE_ID');\n const results = await searchVectorStore(vectorStoreId, args.query);\n return { status: 'success', result: JSON.stringify(results) };\n },\n variables: [\n {\n name: 'VECTOR_STORE_ID',\n type: 'text',\n required: true,\n scoped: false,\n description: 'OpenAI Vector Store ID',\n },\n ],\n});\n```\n\nUse `scoped: true` for per-instance values that should not inherit from parent thread env (for example per-account OAuth tokens on subagents).\n\n## Returning Attachments\n\nTools can return file attachments (e.g., generated images):\n\n```typescript\nexport default defineTool({\n description: 'Generate a chart from data',\n args: z.object({ data: z.array(z.number()) }),\n execute: async (state, args) => {\n const chartImage = await generateChart(args.data);\n return {\n status: 'success',\n result: 'Chart generated successfully',\n attachments: [{\n name: 'chart.png',\n mimeType: 'image/png',\n data: chartImage.base64,\n width: 800,\n height: 600,\n }],\n };\n },\n});\n```\n\n## Best Practices\n\n- **Write clear descriptions** - LLMs decide tool usage based on descriptions\n- **Describe all parameters** with `.describe()` in Zod schemas\n- **Handle errors gracefully** - return error status, don't throw\n- **Use snake_case** for file names (`search_knowledge_base.ts`)\n- **Keep tools focused** - one task per tool\n- **Use `state.rootState`** when queueing from sub-prompts\n\n## Supported Zod Types\n\n- Primitives: `string`, `number`, `boolean`, `null`\n- Enums: `z.enum(['a', 'b', 'c'])`\n- Arrays: `z.array(z.string())`\n- Objects: `z.object({ ... })`\n- Optional: `z.string().optional()`\n- Default: `z.number().default(10)`\n- Nullable: `z.string().nullable()`\n\n## Documentation\n\nFull reference: https://docs.standardagentbuilder.com/api-reference/define/tool\n";
11
+ declare const TOOLS_AGENTS_MD = "# Custom Tools\n\nTools extend agent capabilities beyond text generation. They allow LLMs to fetch data, perform calculations, execute side effects, and chain to other prompts or agents.\n\n## Function Signature\n\n```typescript\ndefineTool({\n description: string, // What the tool does (shown to LLM)\n args?: z.ZodObject, // Input validation schema (optional)\n execute: (state, args) => ToolResult, // Implementation\n variables?: VariableDefinition[], // Declared variables (optional)\n progressArgument?: string, // Arg holding a short progress label, e.g. \"writing index.html\"\n})\n```\n\n## Basic Example\n\n```typescript\nimport { defineTool } from '@standardagents/builder';\nimport { z } from 'zod';\n\nexport default defineTool({\n description: 'Search the knowledge base for articles matching a query',\n args: z.object({\n query: z.string().describe('Search query'),\n limit: z.number().optional().default(10).describe('Max results'),\n }),\n execute: async (state, args) => {\n const results = await searchKB(args.query, args.limit);\n return {\n status: 'success',\n result: JSON.stringify(results),\n };\n },\n});\n```\n\n## Argument Schemas\n\nTool args must be a top-level `z.object(...)`. Prefer explicit, bounded schemas made from strings, numbers, booleans, nulls, literals, enums, arrays, objects, optionals, nullables, and defaults. Avoid provider-visible recursive or open-ended schemas such as `z.unknown()`, `z.any()`, and `z.object({}).catchall(...)`; strict tool providers can reject the generated JSON Schema. If a tool needs arbitrary JSON input, accept it as a JSON string and parse it inside `execute`.\n\n## ToolResult Interface\n\n| Property | Type | Description |\n|----------|------|-------------|\n| `status` | `'success' \\| 'error'` | Whether the tool succeeded |\n| `result` | `string` | Tool output (required for success) |\n| `error` | `string` | Error message (for error status) |\n| `error_code` | `string` | Machine-readable error code |\n| `error_data` | `Record<string, unknown>` | Structured error payload |\n| `attachments` | `ToolAttachment[]` | Files to attach (images, etc.) |\n\n## ThreadState Access\n\nThe `state` parameter provides access to:\n\n```typescript\nexecute: async (state, args) => {\n // Thread information\n const threadId = state.thread.id;\n const thread = state.thread.instance;\n const creationArgs = state.arguments; // Invocation or subagent creation args\n\n // Configuration\n const agentName = state.agent.name;\n const modelName = state.model.name;\n\n // Message history\n const messages = state.messages;\n\n // Thread variable resolution\n const apiKey = await state.env('GOOGLE_API_KEY');\n await state.setEnv('LAST_TOOL_RUN_AT', new Date().toISOString());\n\n // Durable per-thread JSON values\n const runCount = (await state.getValue<number>('run_count')) ?? 0;\n await state.setValue('run_count', runCount + 1);\n\n // The thread's user profile (identity only, never credentials) \u2014 for\n // per-user personalization or entitlement checks. Null when user-less.\n const user = await state.user();\n\n // Instance-GLOBAL Agent Skills library (agentskills.io SKILL.md format).\n // Skills install once and are visible to every thread; load a skill's body\n // only when it's applicable (progressive disclosure).\n const skills = await state.skills.list();\n const skill = await state.skills.get('pdf-processing');\n const script = await state.skills.readFile('pdf-processing', 'scripts/extract.py');\n\n // Sandboxed JS/TS execution with explicit bridge capabilities\n const run = state.runCode('export async function main(path) { return await read(path) }', {\n execute: { fn: 'main', args: ['/notes.txt'] },\n globals: {\n read: async (path: string) => {\n const data = await state.readFile(path);\n return data ? new TextDecoder().decode(data) : null;\n },\n },\n });\n const codeResult = await run;\n\n // Parent state (for sub-prompts)\n const root = state.rootState;\n}\n```\n\nUse `state.runCode()` instead of `eval` or `new Function` for model- or user-authored JavaScript/TypeScript. The sandbox starts with no ambient host capabilities; provide imports/globals explicitly, use `modules` for local relative ES modules, use `execute` to select an export and pass args, use `report` for streamed observations, and call `run.terminate(reason)` from your own timeout budget when needed. `modules` keys are graph-root relative paths; entry-source imports resolve from `options.filename` when supplied. Relative module imports may use `./` and `../` as long as they resolve within the supplied module graph. In thread endpoints, `runCode` is forwarded into the thread Durable Object; pass plain transferable option values there, and do function-backed bridges from tools or in-thread execution contexts.\n\nSandboxed coding code must not use ambient network globals. For HTTP inside `coding_run`, import `{ fetch }` from `\"fetch\"`; the bridge supports `fetch(url, init)` with methods, headers, and bodies, and returns a Response-like object with `text()`, `json()`, `arrayBuffer()`, and `headers.get()`. The sandboxed coding prompt includes `fetch_url` for reading known external public http(s) pages as Markdown. Use the `coding_run` fetch bridge instead for custom methods, headers, request bodies, or checks against thread public file/API endpoint URLs returned by `get_public_url`.\n\nSandboxed coding agents should verify runtime behavior as they work. `coding_validate_typescript` is useful but incomplete; call helper exports with `coding_run`, probe pages and endpoints with `coding_run` plus the fetch bridge, inspect status/body, and clean up disposable side-effecting test data when practical.\n\n## Tool Without Arguments\n\n```typescript\nexport default defineTool({\n description: 'Get current server time',\n execute: async (state) => {\n return {\n status: 'success',\n result: new Date().toISOString(),\n };\n },\n});\n```\n\n## Error Handling\n\nReturn errors gracefully instead of throwing:\n\n```typescript\nexport default defineTool({\n description: 'Fetch user data',\n args: z.object({ userId: z.string() }),\n execute: async (state, args) => {\n try {\n const user = await fetchUser(args.userId);\n return { status: 'success', result: JSON.stringify(user) };\n } catch (error) {\n return {\n status: 'error',\n error: `Failed to fetch user: ${error.message}`,\n };\n }\n },\n});\n```\n\n## Queueing Additional Tools\n\nQueue another tool to run after the current one:\n\n```typescript\nimport { queueTool } from '@standardagents/builder';\n\nexport default defineTool({\n description: 'Create order and send confirmation',\n args: z.object({ items: z.array(z.string()) }),\n execute: async (state, args) => {\n const order = await createOrder(args.items);\n\n // Queue email tool to run next\n queueTool(state, 'send_confirmation_email', {\n orderId: order.id,\n email: state.thread.metadata.userEmail,\n });\n\n return { status: 'success', result: JSON.stringify(order) };\n },\n});\n```\n\n## Injecting Messages\n\nAdd messages without triggering re-execution:\n\n```typescript\nimport { injectMessage } from '@standardagents/builder';\n\nexport default defineTool({\n description: 'Log audit event',\n args: z.object({ event: z.string() }),\n execute: async (state, args) => {\n await injectMessage(state, {\n role: 'system',\n content: `[AUDIT] ${args.event}`,\n });\n return { status: 'success', result: 'Logged' };\n },\n});\n```\n\n## Stopping Sessions\n\n`state.execution.stop()` stops the current execution loop. To terminally end the active agent session, including blocking subagent runs that expect a session boundary, use `state.stopSession()`:\n\n```typescript\nawait state.stopSession({\n result: 'Waiting for clarification',\n notifyParent: 'Please clarify the request',\n status: 'waiting for clarification',\n});\n```\n\n`notifyParent` queues a silent message to the parent when one exists; `status` is ignored without a parent registry entry. Omit `notifyParent` and `status` when stopping should not send a parent message or update child status.\n\n## Variables and Env\n\nTools can declare variable requirements with `variables`, including `required` and `description` metadata:\n\n```typescript\nexport default defineTool({\n description: 'Search uploaded documents',\n args: z.object({ query: z.string() }),\n execute: async (state, args) => {\n const vectorStoreId = await state.env('VECTOR_STORE_ID');\n const results = await searchVectorStore(vectorStoreId, args.query);\n return { status: 'success', result: JSON.stringify(results) };\n },\n variables: [\n {\n name: 'VECTOR_STORE_ID',\n type: 'text',\n required: true,\n scoped: false,\n description: 'OpenAI Vector Store ID',\n },\n ],\n});\n```\n\nUse `scoped: true` for per-instance values that should not inherit from parent thread env (for example per-account OAuth tokens on subagents).\n\n## Returning Attachments\n\nTools can return file attachments (e.g., generated images):\n\n```typescript\nexport default defineTool({\n description: 'Generate a chart from data',\n args: z.object({ data: z.array(z.number()) }),\n execute: async (state, args) => {\n const chartImage = await generateChart(args.data);\n return {\n status: 'success',\n result: 'Chart generated successfully',\n attachments: [{\n name: 'chart.png',\n mimeType: 'image/png',\n data: chartImage.base64,\n width: 800,\n height: 600,\n }],\n };\n },\n});\n```\n\n## Best Practices\n\n- **Write clear descriptions** - LLMs decide tool usage based on descriptions\n- **Describe all parameters** with `.describe()` in Zod schemas\n- **Handle errors gracefully** - return error status, don't throw\n- **Use snake_case** for file names (`search_knowledge_base.ts`)\n- **Keep tools focused** - one task per tool\n- **Use `state.rootState`** when queueing from sub-prompts\n\n## Supported Zod Types\n\n- Primitives: `string`, `number`, `boolean`, `null`\n- Enums: `z.enum(['a', 'b', 'c'])`\n- Arrays: `z.array(z.string())`\n- Objects: `z.object({ ... })`\n- Optional: `z.string().optional()`\n- Default: `z.number().default(10)`\n- Nullable: `z.string().nullable()`\n\n## Documentation\n\nFull reference: https://docs.standardagentbuilder.com/api-reference/define/tool\n";
10
12
 
11
- declare const HOOKS_AGENTS_MD = "# Lifecycle Hooks\n\nHooks intercept and modify agent execution at specific lifecycle points.\n\n## Available Hooks\n\n| Hook | Signature | Purpose |\n|------|-----------|---------|\n| `after_thread_created` | `(state: ThreadState) => void` | Initialize a newly created thread before execution |\n| `after_subagent_created` | `(state: ThreadState, childState: ThreadState) => void` | Run parent-side logic after a child thread is created |\n| `after_system_message` | `(state: ThreadState, systemMessage: string) => string \\| null \\| undefined` | Modify the rendered system message for a request |\n| `filter_messages` | `(state: ThreadState, messages: Message[]) => Message[]` | Filter raw messages before LLM context |\n| `prefilter_llm_history` | `(state: ThreadState, messages: LLMMessage[]) => LLMMessage[]` | Modify chat completion messages before LLM |\n| `before_create_message` | `(state: ThreadState, message: Message) => Message` | Modify message before database insert |\n| `after_create_message` | `(state: ThreadState, message: Message) => void` | Run logic after message created |\n| `before_update_message` | `(state: ThreadState, id: string, updates: Record) => Record` | Modify updates before message update |\n| `after_update_message` | `(state: ThreadState, message: Message) => void` | Run logic after message updated |\n| `before_store_tool_result` | `(state: ThreadState, toolCall: HookToolCall, result: HookToolResult) => HookToolResult` | Modify tool result before storage |\n| `after_tool_call_success` | `(state: ThreadState, toolCall: HookToolCall, result: HookToolResult) => HookToolResult \\| null` | Process successful tool execution |\n| `after_tool_call_failure` | `(state: ThreadState, toolCall: HookToolCall, result: HookToolResult) => HookToolResult \\| null` | Process failed tool execution |\n\nAll hooks receive `ThreadState` as their first parameter, providing access to thread identity, message history, resource loading, durable per-thread values via `getValue` / `setValue`, and sandboxed JS/TS execution via `runCode`.\n\n## Creating a Hook\n\nEach hook file exports a default `defineHook` call with three properties:\n\n```typescript\nimport { defineHook } from '@standardagents/builder';\n\nexport default defineHook({\n hook: 'filter_messages', // Hook type\n id: 'limit_recent_messages', // Unique ID (snake_case)\n execute: async (state, messages) => {\n return messages.slice(-20);\n }\n});\n```\n\n## Hook Scoping\n\nHooks are scoped to **prompts** or **agents** via their ID:\n\n```typescript\n// In a prompt definition\ndefinePrompt({\n name: 'customer_support',\n hooks: ['limit_recent_messages', 'redact_pii'],\n // ...\n});\n\n// In an agent definition\ndefineAgent({\n name: 'support_agent',\n hooks: ['log_all_messages'],\n // ...\n});\n```\n\n- **Prompt hooks** take precedence over agent hooks\n- If a prompt defines hooks, only those run (agent hooks are skipped)\n- If no prompt hooks are defined, agent hooks run as fallback\n- Hooks are filtered by type at runtime\n\n## File Naming\n\nHook files can use **any name** \u2014 the hook type and ID are defined inside the file:\n\n```\nagents/hooks/\n\u251C\u2500\u2500 my_filter.ts # Could contain any hook type\n\u251C\u2500\u2500 redact_sensitive_data.ts\n\u251C\u2500\u2500 log_tool_usage.ts\n\u2514\u2500\u2500 add_metadata.ts\n```\n\n## Examples\n\n### Filter Messages (Limit Context)\n\n```typescript\nimport { defineHook } from '@standardagents/builder';\n\nexport default defineHook({\n hook: 'filter_messages',\n id: 'limit_to_20',\n execute: async (state, messages) => {\n return messages.slice(-20);\n }\n});\n```\n\n### Prefilter LLM History (Redact Content)\n\n```typescript\nimport { defineHook } from '@standardagents/builder';\n\nexport default defineHook({\n hook: 'prefilter_llm_history',\n id: 'redact_pii',\n execute: async (state, messages) => {\n return messages.map(msg => ({\n ...msg,\n content: typeof msg.content === 'string'\n ? msg.content.replace(/\\b\\d{4}-\\d{4}-\\d{4}-\\d{4}\\b/g, '[REDACTED]')\n : msg.content,\n }));\n }\n});\n```\n\n### Before Create Message (Add Metadata)\n\n```typescript\nimport { defineHook } from '@standardagents/builder';\n\nexport default defineHook({\n hook: 'before_create_message',\n id: 'add_version_metadata',\n execute: async (state, message) => {\n if (message.role === 'user' && message.content) {\n return { ...message, content: `[v1.0] ${message.content}` };\n }\n return message;\n }\n});\n```\n\n### Before Store Tool Result (Sanitize)\n\n```typescript\nimport { defineHook } from '@standardagents/builder';\n\nexport default defineHook({\n hook: 'before_store_tool_result',\n id: 'sanitize_results',\n execute: async (state, toolCall, toolResult) => {\n // toolCall: { id, type: 'function', function: { name, arguments } }\n // toolResult: { status, result?, error?, stack?, attachments? }\n if (toolResult.result) {\n return { ...toolResult, result: toolResult.result.replace(/secret/gi, '[REDACTED]') };\n }\n return toolResult;\n }\n});\n```\n\n### After Tool Call Success (Logging)\n\n```typescript\nimport { defineHook } from '@standardagents/builder';\n\nexport default defineHook({\n hook: 'after_tool_call_success',\n id: 'log_tool_success',\n execute: async (state, toolCall, result) => {\n console.log(`Tool ${toolCall.function.name} succeeded`);\n return null; // Return null to use original result\n }\n});\n```\n\n### After Tool Call Failure (Recovery)\n\n```typescript\nimport { defineHook } from '@standardagents/builder';\n\nexport default defineHook({\n hook: 'after_tool_call_failure',\n id: 'weather_fallback',\n execute: async (state, toolCall, result) => {\n if (toolCall.function.name === 'fetch_weather') {\n return {\n status: 'success',\n result: JSON.stringify({ temp: 'unavailable', fallback: true }),\n };\n }\n return null; // Use original error for other tools\n }\n});\n```\n\n## Hook Categories\n\n**Transformation hooks** (return modified data):\n- `after_system_message` (return replacement string, or null/undefined for no change)\n- `filter_messages`\n- `prefilter_llm_history`\n- `before_create_message`\n- `before_update_message`\n- `before_store_tool_result`\n- `after_tool_call_success` (return modified result or null)\n- `after_tool_call_failure` (return modified result or null)\n\n**Event hooks** (side effects only):\n- `after_thread_created`\n- `after_subagent_created`\n- `after_create_message`\n- `after_update_message`\n\n## Best Practices\n\n- **Keep hooks fast** - target <100ms execution\n- **Wrap in try-catch** - hooks continue on error (original data preserved)\n- **Use unique IDs** - hook IDs must be snake_case and unique across the project\n- **Scope appropriately** - assign hooks to prompts or agents that need them\n- **Document purpose** with clear comments\n- **Use for cross-cutting concerns** - logging, redaction, enrichment\n\n## Documentation\n\nFull reference: https://docs.standardagentbuilder.com/api-reference/define/hook\n";
13
+ declare const HOOKS_AGENTS_MD = "# Lifecycle Hooks\n\nHooks intercept and modify agent execution at specific lifecycle points.\n\n## Available Hooks\n\n| Hook | Signature | Purpose |\n|------|-----------|---------|\n| `after_thread_created` | `(state: ThreadState) => void` | Initialize a newly created thread before execution |\n| `after_subagent_created` | `(state: ThreadState, childState: ThreadState) => void` | Run parent-side logic after a child thread is created |\n| `after_system_message` | `(state: ThreadState, systemMessage: string) => string \\| null \\| undefined` | Modify the rendered system message for a request |\n| `filter_messages` | `(state: ThreadState, messages: Message[]) => Message[]` | Filter raw messages before LLM context |\n| `prefilter_llm_history` | `(state: ThreadState, messages: LLMMessage[]) => LLMMessage[]` | Modify chat completion messages before LLM |\n| `before_create_message` | `(state: ThreadState, message: Message) => Message` | Modify message before database insert |\n| `after_create_message` | `(state: ThreadState, message: Message) => void` | Run logic after message created |\n| `before_update_message` | `(state: ThreadState, id: string, updates: Record) => Record` | Modify updates before message update |\n| `after_update_message` | `(state: ThreadState, message: Message) => void` | Run logic after message updated |\n| `before_store_tool_result` | `(state: ThreadState, toolCall: HookToolCall, result: HookToolResult) => HookToolResult` | Modify tool result before storage |\n| `after_tool_call_success` | `(state: ThreadState, toolCall: HookToolCall, result: HookToolResult) => HookToolResult \\| null` | Process successful tool execution |\n| `after_tool_call_failure` | `(state: ThreadState, toolCall: HookToolCall, result: HookToolResult) => HookToolResult \\| null` | Process failed tool execution |\n| `tool_call_started` | `(state: ThreadState, toolCall: HookToolCall, progress?: string) => void` | Observe a tool call when it starts streaming (before it runs) |\n| `tool_call_done` | `(state: ThreadState, toolCall: HookToolCall, result: HookToolResult) => void` | Observe a tool call after it finishes (success or failure) |\n\nAll hooks receive `ThreadState` as their first parameter, providing access to thread identity, message history, resource loading, durable per-thread values via `getValue` / `setValue`, and sandboxed JS/TS execution via `runCode`.\n\n## Creating a Hook\n\nEach hook file exports a default `defineHook` call with three properties:\n\n```typescript\nimport { defineHook } from '@standardagents/builder';\n\nexport default defineHook({\n hook: 'filter_messages', // Hook type\n id: 'limit_recent_messages', // Unique ID (snake_case)\n execute: async (state, messages) => {\n return messages.slice(-20);\n }\n});\n```\n\n## Hook Scoping\n\nHooks are scoped to **prompts** or **agents** via their ID:\n\n```typescript\n// In a prompt definition\ndefinePrompt({\n name: 'customer_support',\n hooks: ['limit_recent_messages', 'redact_pii'],\n // ...\n});\n\n// In an agent definition\ndefineAgent({\n name: 'support_agent',\n hooks: ['log_all_messages'],\n // ...\n});\n```\n\n- **Prompt hooks** take precedence over agent hooks\n- If a prompt defines hooks, only those run (agent hooks are skipped)\n- If no prompt hooks are defined, agent hooks run as fallback\n- Hooks are filtered by type at runtime\n\n## File Naming\n\nHook files can use **any name** \u2014 the hook type and ID are defined inside the file:\n\n```\nagents/hooks/\n\u251C\u2500\u2500 my_filter.ts # Could contain any hook type\n\u251C\u2500\u2500 redact_sensitive_data.ts\n\u251C\u2500\u2500 log_tool_usage.ts\n\u2514\u2500\u2500 add_metadata.ts\n```\n\n## Examples\n\n### Filter Messages (Limit Context)\n\n```typescript\nimport { defineHook } from '@standardagents/builder';\n\nexport default defineHook({\n hook: 'filter_messages',\n id: 'limit_to_20',\n execute: async (state, messages) => {\n return messages.slice(-20);\n }\n});\n```\n\n### Prefilter LLM History (Redact Content)\n\n```typescript\nimport { defineHook } from '@standardagents/builder';\n\nexport default defineHook({\n hook: 'prefilter_llm_history',\n id: 'redact_pii',\n execute: async (state, messages) => {\n return messages.map(msg => ({\n ...msg,\n content: typeof msg.content === 'string'\n ? msg.content.replace(/\\b\\d{4}-\\d{4}-\\d{4}-\\d{4}\\b/g, '[REDACTED]')\n : msg.content,\n }));\n }\n});\n```\n\n### Before Create Message (Add Metadata)\n\n```typescript\nimport { defineHook } from '@standardagents/builder';\n\nexport default defineHook({\n hook: 'before_create_message',\n id: 'add_version_metadata',\n execute: async (state, message) => {\n if (message.role === 'user' && message.content) {\n return { ...message, content: `[v1.0] ${message.content}` };\n }\n return message;\n }\n});\n```\n\n### Before Store Tool Result (Sanitize)\n\n```typescript\nimport { defineHook } from '@standardagents/builder';\n\nexport default defineHook({\n hook: 'before_store_tool_result',\n id: 'sanitize_results',\n execute: async (state, toolCall, toolResult) => {\n // toolCall: { id, type: 'function', function: { name, arguments } }\n // toolResult: { status, result?, error?, stack?, attachments? }\n if (toolResult.result) {\n return { ...toolResult, result: toolResult.result.replace(/secret/gi, '[REDACTED]') };\n }\n return toolResult;\n }\n});\n```\n\n### After Tool Call Success (Logging)\n\n```typescript\nimport { defineHook } from '@standardagents/builder';\n\nexport default defineHook({\n hook: 'after_tool_call_success',\n id: 'log_tool_success',\n execute: async (state, toolCall, result) => {\n console.log(`Tool ${toolCall.function.name} succeeded`);\n return null; // Return null to use original result\n }\n});\n```\n\n### After Tool Call Failure (Recovery)\n\n```typescript\nimport { defineHook } from '@standardagents/builder';\n\nexport default defineHook({\n hook: 'after_tool_call_failure',\n id: 'weather_fallback',\n execute: async (state, toolCall, result) => {\n if (toolCall.function.name === 'fetch_weather') {\n return {\n status: 'success',\n result: JSON.stringify({ temp: 'unavailable', fallback: true }),\n };\n }\n return null; // Use original error for other tools\n }\n});\n```\n\n## Hook Categories\n\n**Transformation hooks** (return modified data):\n- `after_system_message` (return replacement string, or null/undefined for no change)\n- `filter_messages`\n- `prefilter_llm_history`\n- `before_create_message`\n- `before_update_message`\n- `before_store_tool_result`\n- `after_tool_call_success` (return modified result or null)\n- `after_tool_call_failure` (return modified result or null)\n\n**Event hooks** (side effects only):\n- `after_thread_created`\n- `after_subagent_created`\n- `after_create_message`\n- `after_update_message`\n\n## Best Practices\n\n- **Keep hooks fast** - target <100ms execution\n- **Wrap in try-catch** - hooks continue on error (original data preserved)\n- **Use unique IDs** - hook IDs must be snake_case and unique across the project\n- **Scope appropriately** - assign hooks to prompts or agents that need them\n- **Document purpose** with clear comments\n- **Use for cross-cutting concerns** - logging, redaction, enrichment\n\n## Documentation\n\nFull reference: https://docs.standardagentbuilder.com/api-reference/define/hook\n";
12
14
 
13
15
  declare const API_AGENTS_MD = "# Thread-Specific API Endpoints\n\nDefine custom API endpoints that operate on specific threads with access to the thread's ThreadState.\n\n## File-Based Routing\n\n| File Pattern | HTTP Method | Route |\n|--------------|-------------|-------|\n| `name.ts` | GET | `/api/threads/:threadId/name` |\n| `name.get.ts` | GET | `/api/threads/:threadId/name` |\n| `name.post.ts` | POST | `/api/threads/:threadId/name` |\n| `name.put.ts` | PUT | `/api/threads/:threadId/name` |\n| `name.delete.ts` | DELETE | `/api/threads/:threadId/name` |\n| `index.ts` | GET | `/api/threads/:threadId` |\n| `nested/route.ts` | GET | `/api/threads/:threadId/nested/route` |\n| `items/[id].ts` | GET | `/api/threads/:threadId/items/:id` |\n| `files/[*].ts` | GET | `/api/threads/:threadId/files/*` |\n\nFiles without a method suffix default to GET. Method suffixes are case-insensitive and support `.get.ts`, `.post.ts`, `.put.ts`, `.patch.ts`, and `.delete.ts`.\n\nDynamic segments use `[name]` and are passed to the handler as `params.name`. Catch-all segments use `[*]` and are passed as `params['*']`; the catch-all value may contain `/` for nested paths. Static routes match before dynamic routes, and dynamic routes match before catch-all routes.\n\n## Basic Example\n\n```typescript\n// agents/api/status.get.ts -> GET /api/threads/:threadId/status\nimport { defineThreadEndpoint } from '@standardagents/spec';\n\nexport default defineThreadEndpoint(async (req, state, params) => {\n const { messages, total } = await state.getMessages();\n return Response.json({\n threadId: state.threadId,\n messageCount: total,\n status: 'active',\n params,\n });\n});\n```\n\n## Handler Parameters\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| `req` | `Request` | The incoming HTTP request |\n| `state` | `ThreadState` | Thread state with messages, identity, `arguments`, file system, `runCode`, etc. |\n| `params` | `Record<string, string>` | Route parameters captured from `[name]` and `[*]` path segments |\n\nNote: `state.execution` is always `null` in endpoints since the thread is at rest. `state.runCode()` is available from endpoints and is forwarded into the thread runtime; pass plain transferable option values there, and do function-backed sandbox bridges from tools or in-thread execution contexts.\n\n## ThreadState Methods\n\nAccess thread data through the state object:\n\n```typescript\nimport { defineThreadEndpoint } from '@standardagents/spec';\n\nexport default defineThreadEndpoint(async (req, state) => {\n // Thread identity\n console.log('Thread ID:', state.threadId);\n console.log('Agent ID:', state.agentId);\n console.log('User ID:', state.userId);\n console.log('Arguments:', state.arguments);\n\n // Message operations\n const { messages, total, hasMore } = await state.getMessages({\n limit: 100,\n offset: 0,\n order: 'desc',\n });\n\n // Thread env (thread scope + active descendants)\n const approvalGate = await state.env('TOPDOWN_APPROVAL_GATE');\n await state.setEnv('TOPDOWN_APPROVAL_GATE', approvalGate || 'open');\n\n // Durable per-thread JSON values\n const exports = (await state.getValue<number>('export_count')) ?? 0;\n await state.setValue('export_count', exports + 1);\n\n // File system operations\n const files = await state.findFiles('**/*.json');\n const data = await state.readFile('/data/config.json');\n\n // Resource loading\n const agent = await state.loadAgent('my-agent');\n const prompt = await state.loadPrompt('my-prompt');\n\n return Response.json({ messages, total });\n});\n```\n\n## POST with Request Body\n\n```typescript\n// agents/api/export.post.ts -> POST /api/threads/:threadId/export\nimport { defineThreadEndpoint } from '@standardagents/spec';\n\nexport default defineThreadEndpoint(async (req, state) => {\n const body = await req.json();\n const { format = 'json' } = body;\n\n const { messages } = await state.getMessages();\n\n if (format === 'csv') {\n const csv = messages.map(m => `${m.role},${m.content}`).join('\\n');\n return new Response(csv, {\n headers: { 'Content-Type': 'text/csv' },\n });\n }\n\n return Response.json(messages);\n});\n```\n\n## Nested Routes\n\nCreate directories for nested routes:\n\n```\nagents/api/\n\u251C\u2500\u2500 status.get.ts -> GET /api/threads/:threadId/status\n\u251C\u2500\u2500 export.post.ts -> POST /api/threads/:threadId/export\n\u2514\u2500\u2500 messages/\n \u251C\u2500\u2500 count.ts -> GET /api/threads/:threadId/messages/count\n \u251C\u2500\u2500 [id].ts -> GET /api/threads/:threadId/messages/:id\n \u2514\u2500\u2500 [*].ts -> GET /api/threads/:threadId/messages/*\n```\n\n## Error Handling\n\n```typescript\nimport { defineThreadEndpoint } from '@standardagents/spec';\n\nexport default defineThreadEndpoint(async (req, state) => {\n try {\n const data = await riskyOperation();\n return Response.json(data);\n } catch (error) {\n return Response.json({ error: error.message }, { status: 500 });\n }\n});\n```\n\n## File System Operations\n\n```typescript\nimport { defineThreadEndpoint } from '@standardagents/spec';\n\nexport default defineThreadEndpoint(async (req, state) => {\n // Read files\n const content = await state.readFile('/data/file.txt');\n\n // Write files\n await state.writeFile('/output/result.json', JSON.stringify(data), 'application/json');\n\n // List directory\n const { entries } = await state.readdirFile('/data');\n\n // Move or rename files and directories (does not overwrite an existing destination)\n await state.moveFile('/data/file.txt', '/archive/file.txt');\n await state.renameFile('/output/result.json', 'final.json');\n\n // Search files\n const matches = await state.grepFiles('pattern');\n const paths = await state.findFiles('**/*.ts');\n\n return Response.json({ success: true });\n});\n```\n\n## Best Practices\n\n- **Keep handlers fast** - endpoints are in the request path\n- **Paginate large queries** - use limit/offset for messages\n- **Validate input data** - check request body before processing\n- **Use descriptive file names** - `export.post.ts` not `ep1.ts`\n- **Return proper status codes** - 200, 400, 404, 500\n- **Import from spec** - use `@standardagents/spec` for `defineThreadEndpoint`\n\n## Documentation\n\nFull reference: https://docs.standardagentbuilder.com/core-concepts/api\n";
14
16
 
@@ -51,7 +53,7 @@ declare const FIRST_PARTY_PROVIDER_PACKAGES: readonly ["@standardagents/anthropi
51
53
  */
52
54
  declare const APPROVED_DEPENDENCY_BUILD_SCRIPTS: readonly ["@google/genai", "@openrouter/sdk", "esbuild", "protobufjs", "sharp", "workerd"];
53
55
  declare const DEFAULT_TEMPLATE_VERSIONS: TemplateVersions;
54
- declare const AGENTBUILDER_TEMPLATE_VERSION = "0.21.1";
56
+ declare const AGENTBUILDER_TEMPLATE_VERSION = "0.22.0";
55
57
  declare function packageNameFromProjectName(projectName: string): string;
56
58
  declare function renderPackageJson(options: AgentBuilderProjectTemplateOptions): string;
57
59
  declare function renderViteConfig(): string;
@@ -62,4 +64,4 @@ declare function renderTemplateMetadata(options: AgentBuilderProjectTemplateOpti
62
64
  declare function renderAgentBuilderSupportFiles(options: AgentBuilderProjectTemplateOptions): TemplateFile[];
63
65
  declare function renderAgentBuilderProject(options: AgentBuilderProjectTemplateOptions): TemplateFile[];
64
66
 
65
- export { AGENTBUILDER_TEMPLATE_VERSION, AGENT_DEFINITIONS_AGENTS_MD as AGENTS_CLAUDE_MD, AGENT_DEFINITIONS_AGENTS_MD, API_AGENTS_MD, API_AGENTS_MD as API_CLAUDE_MD, APPROVED_DEPENDENCY_BUILD_SCRIPTS, type AgentBuilderProjectTemplateOptions, DEFAULT_TEMPLATE_VERSIONS, FIRST_PARTY_PROVIDER_PACKAGES, HOOKS_AGENTS_MD, HOOKS_AGENTS_MD as HOOKS_CLAUDE_MD, MODELS_AGENTS_MD, MODELS_AGENTS_MD as MODELS_CLAUDE_MD, PROMPTS_AGENTS_MD, PROMPTS_AGENTS_MD as PROMPTS_CLAUDE_MD, type PackageManager, ROOT_AGENTS_MD, ROOT_AGENTS_MD as ROOT_CLAUDE_MD, TOOLS_AGENTS_MD, TOOLS_AGENTS_MD as TOOLS_CLAUDE_MD, type TemplateFile, type TemplateVersions, packageNameFromProjectName, renderAgentBuilderProject, renderAgentBuilderSupportFiles, renderDevVarsExample, renderGitignore, renderPackageJson, renderTemplateMetadata, renderTsConfig, renderViteConfig };
67
+ export { AGENTBUILDER_TEMPLATE_VERSION, AGENT_DEFINITIONS_AGENTS_MD as AGENTS_CLAUDE_MD, AGENT_DEFINITIONS_AGENTS_MD, API_AGENTS_MD, API_AGENTS_MD as API_CLAUDE_MD, APPROVED_DEPENDENCY_BUILD_SCRIPTS, type AgentBuilderProjectTemplateOptions, DEFAULT_TEMPLATE_VERSIONS, FIRST_PARTY_PROVIDER_PACKAGES, HOOKS_AGENTS_MD, HOOKS_AGENTS_MD as HOOKS_CLAUDE_MD, MODELS_AGENTS_MD, MODELS_AGENTS_MD as MODELS_CLAUDE_MD, PROMPTS_AGENTS_MD, PROMPTS_AGENTS_MD as PROMPTS_CLAUDE_MD, PROVIDERS_AGENTS_MD, PROVIDERS_AGENTS_MD as PROVIDERS_CLAUDE_MD, type PackageManager, ROOT_AGENTS_MD, ROOT_AGENTS_MD as ROOT_CLAUDE_MD, TOOLS_AGENTS_MD, TOOLS_AGENTS_MD as TOOLS_CLAUDE_MD, type TemplateFile, type TemplateVersions, packageNameFromProjectName, renderAgentBuilderProject, renderAgentBuilderSupportFiles, renderDevVarsExample, renderGitignore, renderPackageJson, renderTemplateMetadata, renderTsConfig, renderViteConfig };
package/dist/index.js CHANGED
@@ -78,6 +78,9 @@ agents/
78
78
  \u251C\u2500\u2500 models/ # Model configurations (defineModel)
79
79
  \u2502 \u251C\u2500\u2500 AGENTS.md
80
80
  \u2502 \u2514\u2500\u2500 CLAUDE.md -> AGENTS.md
81
+ \u251C\u2500\u2500 providers/ # Provider definitions (defineProvider)
82
+ \u2502 \u251C\u2500\u2500 AGENTS.md
83
+ \u2502 \u2514\u2500\u2500 CLAUDE.md -> AGENTS.md
81
84
  \u251C\u2500\u2500 tools/ # Custom tools (defineTool)
82
85
  \u2502 \u251C\u2500\u2500 AGENTS.md
83
86
  \u2502 \u2514\u2500\u2500 CLAUDE.md -> AGENTS.md
@@ -173,6 +176,7 @@ export default defineHook({
173
176
  | Function | Purpose | Directory |
174
177
  |----------|---------|-----------|
175
178
  | \`defineModel()\` | Configure LLM provider | \`agents/models/\` |
179
+ | \`defineProvider()\` | Custom provider endpoints and overrides | \`agents/providers/\` |
176
180
  | \`definePrompt()\` | System instructions + tools | \`agents/prompts/\` |
177
181
  | \`defineAgent()\` | Conversation orchestration | \`agents/agents/\` |
178
182
  | \`defineTool()\` | Custom tool functions | \`agents/tools/\` |
@@ -216,7 +220,7 @@ Models define which LLM provider and model to use for prompts.
216
220
  | Property | Type | Required | Description |
217
221
  |----------|------|----------|-------------|
218
222
  | \`name\` | \`string\` | Yes | Unique identifier for this model configuration |
219
- | \`provider\` | \`'openai' \\| 'anthropic' \\| 'openrouter' \\| 'google' \\| 'cerebras' \\| 'groq' \\| 'xai'\` | Yes | LLM provider |
223
+ | \`provider\` | \`ProviderFactory\` | Yes | Imported provider factory such as \`openrouter\`, \`openai\`, or a local provider from \`agents/providers\` |
220
224
  | \`model\` | \`string\` | Yes | Model ID sent to provider API |
221
225
  | \`fallbacks\` | \`string[]\` | No | Fallback model names to try if primary fails |
222
226
  | \`inputPrice\` | \`number\` | No | Cost per 1M input tokens (USD) |
@@ -229,10 +233,11 @@ Models define which LLM provider and model to use for prompts.
229
233
 
230
234
  \`\`\`typescript
231
235
  import { defineModel } from '@standardagents/builder';
236
+ import { openrouter } from '@standardagents/openrouter';
232
237
 
233
238
  export default defineModel({
234
239
  name: 'default',
235
- provider: 'openrouter',
240
+ provider: openrouter,
236
241
  model: 'google/gemini-3-flash-preview',
237
242
  fallbacks: ['fast', 'cheap-heavy'],
238
243
  });
@@ -274,6 +279,7 @@ Set these environment variables in \`.dev.vars\` (local) or Cloudflare secrets (
274
279
  | OpenAI | \`OPENAI_API_KEY\` |
275
280
  | Anthropic | \`ANTHROPIC_API_KEY\` |
276
281
  | OpenRouter | \`OPENROUTER_API_KEY\` |
282
+ | Baseten Model APIs | \`BASETEN_API_KEY\` |
277
283
  | Google | \`GOOGLE_API_KEY\` |
278
284
  | xAI | \`XAI_API_KEY\` |
279
285
 
@@ -281,6 +287,48 @@ If \`STANDARD_AGENTS_API_KEY\` is present and a provider-specific key is not set
281
287
  first-party Standard Agents providers route through the hosted Standard Agents
282
288
  router. Setting a provider-specific key always uses that provider directly.
283
289
 
290
+ ## User-Defined Providers
291
+
292
+ Create \`agents/providers/<name>.ts\` when a provider is compatible with an existing
293
+ provider package but needs its own API key, endpoint, icon, model list, pricing, or
294
+ other provider behavior.
295
+
296
+ \`\`\`typescript
297
+ // agents/providers/darkbloom.ts
298
+ import { defineProvider, providerEnv } from '@standardagents/builder';
299
+ import { openai } from '@standardagents/openai';
300
+
301
+ export default defineProvider({
302
+ name: 'darkbloom',
303
+ label: 'Darkbloom',
304
+ baseProvider: openai,
305
+ config: {
306
+ apiKey: providerEnv('DARKBLOOM_API_KEY', { valueType: 'secret' }),
307
+ baseUrl: providerEnv('DARKBLOOM_BASE_URL', {
308
+ valueType: 'url',
309
+ default: 'https://api.darkbloom.dev/v1',
310
+ }),
311
+ },
312
+ });
313
+ \`\`\`
314
+
315
+ \`\`\`typescript
316
+ // agents/models/darkbloom_chat.ts
317
+ import { defineModel } from '@standardagents/builder';
318
+ import darkbloom from '../providers/darkbloom';
319
+
320
+ export default defineModel({
321
+ name: 'darkbloom_chat',
322
+ provider: darkbloom,
323
+ model: 'darkbloom-chat',
324
+ });
325
+ \`\`\`
326
+
327
+ Provider \`overrides\` can replace behavior such as \`getModels\`, \`getIcon\`,
328
+ \`getTools\`, pricing/capability lookup, \`generate\`, or \`stream\`. Call \`next()\`
329
+ inside an override to compose with the base provider; return your own value to
330
+ replace it.
331
+
284
332
  ## Fallback Strategy
285
333
 
286
334
  When a model fails, fallbacks are tried in order:
@@ -296,9 +344,12 @@ Retries occur on: network errors, rate limits (429), server errors (5xx), auth e
296
344
  For OpenRouter, use the full model path:
297
345
 
298
346
  \`\`\`typescript
347
+ import { defineModel } from '@standardagents/builder';
348
+ import { openrouter } from '@standardagents/openrouter';
349
+
299
350
  export default defineModel({
300
351
  name: 'heavy',
301
- provider: 'openrouter',
352
+ provider: openrouter,
302
353
  model: 'google/gemini-3-pro-preview',
303
354
  includedProviders: ['google'], // Prefer Google's servers
304
355
  });
@@ -309,7 +360,7 @@ export default defineModel({
309
360
  - **Name by use case**, not model ID (e.g., \`fast\`, \`default\`, \`heavy\`)
310
361
  - **Configure fallbacks** for production reliability
311
362
  - **Set pricing** for cost tracking in logs when your provider or runtime does not supply it automatically
312
- - **Cerebras note:** documented Cerebras models have built-in fallback pricing for request logs, but custom/private Cerebras models should still set \`inputPrice\` and \`outputPrice\`
363
+ - **Cerebras note:** documented Cerebras models attach provider-owned \`usage.cost\` values for request logs, but custom/private Cerebras models should still set \`inputPrice\` and \`outputPrice\`
313
364
  - **Use environment variables** for API keys, never hardcode
314
365
 
315
366
  ## Documentation
@@ -317,6 +368,56 @@ export default defineModel({
317
368
  Full reference: https://docs.standardagentbuilder.com/api-reference/define/model
318
369
  `;
319
370
 
371
+ // src/docs/providers.ts
372
+ var PROVIDERS_AGENTS_MD = `# Provider Definitions
373
+
374
+ Provider definitions create named provider factories that wrap a base provider
375
+ package with connection config and optional method overrides.
376
+
377
+ Use \`defineProvider()\` and export the result as the default export:
378
+
379
+ \`\`\`typescript
380
+ import { defineProvider, providerEnv, providerValue } from '@standardagents/builder';
381
+ import { openai } from '@standardagents/openai';
382
+
383
+ export default defineProvider({
384
+ name: 'my_openai_compatible_provider',
385
+ label: 'My OpenAI-compatible Provider',
386
+ baseProvider: openai,
387
+ config: {
388
+ apiKey: providerEnv('MY_PROVIDER_API_KEY', {
389
+ valueType: 'secret',
390
+ required: true,
391
+ description: 'Provider API key.',
392
+ }),
393
+ baseUrl: providerValue('https://api.example.com/v1'),
394
+ },
395
+ });
396
+ \`\`\`
397
+
398
+ Models can then import the provider definition and use it like any other provider
399
+ factory:
400
+
401
+ \`\`\`typescript
402
+ import { defineModel } from '@standardagents/builder';
403
+ import myProvider from '../providers/my_openai_compatible_provider';
404
+
405
+ export default defineModel({
406
+ name: 'custom_fast',
407
+ provider: myProvider,
408
+ model: 'gpt-4o-mini',
409
+ });
410
+ \`\`\`
411
+
412
+ Provider \`overrides\` can replace behavior such as \`getModels\`, \`getIcon\`,
413
+ \`getTools\`, pricing/capability lookup, \`generate\`, or \`stream\`. Call \`next()\`
414
+ inside an override to compose with the base provider; return your own value to
415
+ replace it.
416
+
417
+ Keep credentials in secret env values. Do not hardcode API keys in provider
418
+ definition files.
419
+ `;
420
+
320
421
  // src/docs/prompts.ts
321
422
  var PROMPTS_AGENTS_MD = `# Prompt Definitions
322
423
 
@@ -378,7 +479,9 @@ export default definePrompt({
378
479
 
379
480
  \`type: 'env'\` inserts a resolved thread variable value. Use this only for non-secret values that are safe to expose to the LLM.
380
481
 
381
- The sandboxed coding prompt declares \`HTTP_HOST\` as a text variable. Its URL helper uses that value as the origin for files exposed from the thread \`public/\` directory and endpoints exposed from the thread \`api/\` directory. Public URLs should usually omit extensions; extensionless public paths resolve \`.html\`, then \`.js\`, then \`.ts\`, then matching \`index\` files in the same order. Browser pages should reference only public files, \`api/\` endpoints, or absolute external URLs, using relative asset URLs like \`./app\` and \`./api/todos\`; private \`src/\` files are not served directly. Public \`.ts\` files are transformed to browser JavaScript and are not server endpoints. Server-side endpoints live under the thread filesystem \`api/\` directory, and the \`api/\` directory name stays in the public URL: \`api/todo.ts\` is \`/api/threads/{threadId}/api/todo\`, while \`api/todo.ts\` is not \`/api/threads/{threadId}/todo\` or \`/api/threads/{threadId}/todos\`. Endpoint files default-export a function that accepts \`Request\` and returns \`Response\` or \`Promise<Response>\`. Endpoint code can import \`fetch\`, \`fs\`, and \`storage\`, and can import private helpers with relative paths such as \`../src/todo.ts\`. When the coding agent creates a site, page, or endpoint, it should call \`get_public_url\` with the created file path and use the returned URL.
482
+ The sandboxed coding prompt declares \`HTTP_HOST\` as a text variable and injects its resolved value with a structured \`{ type: 'env', property: 'HTTP_HOST' }\` prompt part. Its URL helper uses that value as the origin for files exposed from the thread \`public/\` directory and endpoints exposed from the thread \`api/\` directory. Public URLs should usually omit extensions; extensionless public paths resolve \`.html\`, then \`.js\`, then \`.ts\`, then matching \`index\` files in the same order. Browser pages should reference only public files, \`api/\` endpoints, or absolute external URLs, using relative asset URLs like \`./app\` and \`./api/todos\`; private \`src/\` files are not served directly. Public \`.ts\` files are transformed to browser JavaScript and are not server endpoints. Server-side endpoints live under the thread filesystem \`api/\` directory, and the \`api/\` directory name stays in the public URL: \`api/todo.ts\` is \`/api/threads/{threadId}/api/todo\`, while \`api/todo.ts\` is not \`/api/threads/{threadId}/todo\` or \`/api/threads/{threadId}/todos\`. Endpoint files default-export a function that accepts \`Request\` and returns \`Response\` or \`Promise<Response>\`. Endpoint code can import \`fetch\`, \`fs\`, and \`storage\`, and can import private helpers with relative paths such as \`../src/todo.ts\`. When the coding agent creates a site, page, or endpoint, it should call \`get_public_url\` with the created file path and use the returned URL.
483
+
484
+ The sandboxed coding prompt includes \`set_goal\` (write the whole goal: a short \`summary\`, a \`description\` that is the user's objective in their own words captured verbatim, plus ordered steps) and \`update_goal_step\` (flip one step's status as you start/finish it), and should check work incrementally, checking steps off as it goes and finishing with a summary once every step is done. \`coding_validate_typescript\` is only an early signal; for real verification, call helper exports with \`coding_run\`, get public URLs for pages or endpoints, then probe those URLs from \`coding_run\` using \`import { fetch } from "fetch"\`. Side-effecting endpoint checks should use disposable data and clean up through the endpoint, storage, or file cleanup path when practical. The prompt also includes \`fetch_url\` for reading known external public http(s) pages; use the \`coding_run\` fetch bridge for custom methods, headers, request bodies, or thread endpoint checks.
382
485
 
383
486
  Sandboxed code and \`api/\` endpoints can persist small JSON-serializable runtime data through \`import { storage } from "storage"\`. Use \`storage.get\`, \`storage.set\`, \`storage.delete\`, and \`storage.has\` with stable logical keys. Do not expose, mention, or depend on internal storage key prefixes.
384
487
 
@@ -449,6 +552,8 @@ Set \`immediate: true\` to run a tool automatically when the prompt activates.
449
552
  Use \`immediate: { nameEnv, descriptionEnv, scopedEnv }\` when you want safe per-instance bootstrap hints while keeping copied scoped env runtime-only.
450
553
  Set \`optional: 'ENV_NAME'\` to enable a subagent branch only when env resolves to \`true\`, \`1\`, or \`yes\`.
451
554
  Set \`resumable.parentCommunication: 'explicit'\` when the child should stay quiet until its own tools or hooks call \`state.notifyParent()\`, \`state.setStatus()\`, or \`state.stopSession({ result, notifyParent, status })\`.
555
+ Set top-level \`parentCommunication: 'explicit'\` on a NON-resumable subagent when its completion should not be auto-queued to the parent (so it never wakes the parent) \u2014 for background children that deliver results through another channel, e.g. the parent's thread KV. \`resumable.parentCommunication\` takes precedence when both are set.
556
+ Set \`hidden: true\` to keep a subagent relationship declared and spawnable by runtime code (\`state.invokeTool()\`/\`queueTool()\` from hooks) while excluding its tool from every LLM request \u2014 the model can never call it (for infrastructure children like a background compaction agent).
452
557
  If required scoped vars are missing, the runtime returns \`error_code: "subagent_env_required"\` with a temporary \`GET/POST /api/threads/:threadId/variables/:requestId\` endpoint in \`error_data.endpoint\`.
453
558
 
454
559
  ## Input Validation
@@ -705,6 +810,7 @@ defineTool({
705
810
  args?: z.ZodObject, // Input validation schema (optional)
706
811
  execute: (state, args) => ToolResult, // Implementation
707
812
  variables?: VariableDefinition[], // Declared variables (optional)
813
+ progressArgument?: string, // Arg holding a short progress label, e.g. "writing index.html"
708
814
  })
709
815
  \`\`\`
710
816
 
@@ -771,6 +877,17 @@ execute: async (state, args) => {
771
877
  const runCount = (await state.getValue<number>('run_count')) ?? 0;
772
878
  await state.setValue('run_count', runCount + 1);
773
879
 
880
+ // The thread's user profile (identity only, never credentials) \u2014 for
881
+ // per-user personalization or entitlement checks. Null when user-less.
882
+ const user = await state.user();
883
+
884
+ // Instance-GLOBAL Agent Skills library (agentskills.io SKILL.md format).
885
+ // Skills install once and are visible to every thread; load a skill's body
886
+ // only when it's applicable (progressive disclosure).
887
+ const skills = await state.skills.list();
888
+ const skill = await state.skills.get('pdf-processing');
889
+ const script = await state.skills.readFile('pdf-processing', 'scripts/extract.py');
890
+
774
891
  // Sandboxed JS/TS execution with explicit bridge capabilities
775
892
  const run = state.runCode('export async function main(path) { return await read(path) }', {
776
893
  execute: { fn: 'main', args: ['/notes.txt'] },
@@ -790,6 +907,10 @@ execute: async (state, args) => {
790
907
 
791
908
  Use \`state.runCode()\` instead of \`eval\` or \`new Function\` for model- or user-authored JavaScript/TypeScript. The sandbox starts with no ambient host capabilities; provide imports/globals explicitly, use \`modules\` for local relative ES modules, use \`execute\` to select an export and pass args, use \`report\` for streamed observations, and call \`run.terminate(reason)\` from your own timeout budget when needed. \`modules\` keys are graph-root relative paths; entry-source imports resolve from \`options.filename\` when supplied. Relative module imports may use \`./\` and \`../\` as long as they resolve within the supplied module graph. In thread endpoints, \`runCode\` is forwarded into the thread Durable Object; pass plain transferable option values there, and do function-backed bridges from tools or in-thread execution contexts.
792
909
 
910
+ Sandboxed coding code must not use ambient network globals. For HTTP inside \`coding_run\`, import \`{ fetch }\` from \`"fetch"\`; the bridge supports \`fetch(url, init)\` with methods, headers, and bodies, and returns a Response-like object with \`text()\`, \`json()\`, \`arrayBuffer()\`, and \`headers.get()\`. The sandboxed coding prompt includes \`fetch_url\` for reading known external public http(s) pages as Markdown. Use the \`coding_run\` fetch bridge instead for custom methods, headers, request bodies, or checks against thread public file/API endpoint URLs returned by \`get_public_url\`.
911
+
912
+ Sandboxed coding agents should verify runtime behavior as they work. \`coding_validate_typescript\` is useful but incomplete; call helper exports with \`coding_run\`, probe pages and endpoints with \`coding_run\` plus the fetch bridge, inspect status/body, and clean up disposable side-effecting test data when practical.
913
+
793
914
  ## Tool Without Arguments
794
915
 
795
916
  \`\`\`typescript
@@ -981,6 +1102,8 @@ Hooks intercept and modify agent execution at specific lifecycle points.
981
1102
  | \`before_store_tool_result\` | \`(state: ThreadState, toolCall: HookToolCall, result: HookToolResult) => HookToolResult\` | Modify tool result before storage |
982
1103
  | \`after_tool_call_success\` | \`(state: ThreadState, toolCall: HookToolCall, result: HookToolResult) => HookToolResult \\| null\` | Process successful tool execution |
983
1104
  | \`after_tool_call_failure\` | \`(state: ThreadState, toolCall: HookToolCall, result: HookToolResult) => HookToolResult \\| null\` | Process failed tool execution |
1105
+ | \`tool_call_started\` | \`(state: ThreadState, toolCall: HookToolCall, progress?: string) => void\` | Observe a tool call when it starts streaming (before it runs) |
1106
+ | \`tool_call_done\` | \`(state: ThreadState, toolCall: HookToolCall, result: HookToolResult) => void\` | Observe a tool call after it finishes (success or failure) |
984
1107
 
985
1108
  All hooks receive \`ThreadState\` as their first parameter, providing access to thread identity, message history, resource loading, durable per-thread values via \`getValue\` / \`setValue\`, and sandboxed JS/TS execution via \`runCode\`.
986
1109
 
@@ -1385,7 +1508,7 @@ var DEFAULT_TEMPLATE_VERSIONS = {
1385
1508
  typescript: "latest",
1386
1509
  zod: "latest"
1387
1510
  };
1388
- var AGENTBUILDER_TEMPLATE_VERSION = "0.21.1";
1511
+ var AGENTBUILDER_TEMPLATE_VERSION = "0.22.0";
1389
1512
  function ensureTrailingNewline(value) {
1390
1513
  return value.endsWith("\n") ? value : `${value}
1391
1514
  `;
@@ -1548,6 +1671,8 @@ function renderAgentBuilderProject(options) {
1548
1671
  symlink("agents/prompts/CLAUDE.md", "AGENTS.md", "Add Claude prompt docs symlink"),
1549
1672
  file("agents/models/AGENTS.md", MODELS_AGENTS_MD, "Add model docs"),
1550
1673
  symlink("agents/models/CLAUDE.md", "AGENTS.md", "Add Claude model docs symlink"),
1674
+ file("agents/providers/AGENTS.md", PROVIDERS_AGENTS_MD, "Add provider docs"),
1675
+ symlink("agents/providers/CLAUDE.md", "AGENTS.md", "Add Claude provider docs symlink"),
1551
1676
  file("agents/tools/AGENTS.md", TOOLS_AGENTS_MD, "Add tool docs"),
1552
1677
  symlink("agents/tools/CLAUDE.md", "AGENTS.md", "Add Claude tool docs symlink"),
1553
1678
  file("agents/hooks/AGENTS.md", HOOKS_AGENTS_MD, "Add hook docs"),
@@ -1575,6 +1700,8 @@ export {
1575
1700
  MODELS_AGENTS_MD as MODELS_CLAUDE_MD,
1576
1701
  PROMPTS_AGENTS_MD,
1577
1702
  PROMPTS_AGENTS_MD as PROMPTS_CLAUDE_MD,
1703
+ PROVIDERS_AGENTS_MD,
1704
+ PROVIDERS_AGENTS_MD as PROVIDERS_CLAUDE_MD,
1578
1705
  ROOT_AGENTS_MD,
1579
1706
  ROOT_AGENTS_MD as ROOT_CLAUDE_MD,
1580
1707
  TOOLS_AGENTS_MD,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/docs/root.ts","../src/docs/models.ts","../src/docs/prompts.ts","../src/docs/agents.ts","../src/docs/tools.ts","../src/docs/hooks.ts","../src/docs/api.ts","../src/index.ts"],"sourcesContent":["export const ROOT_AGENTS_MD = `# Standard Agents\n\nThis project uses Standard Agents - a framework for building AI agents on Cloudflare Workers.\n\n## Architecture Overview\n\nStandard Agents uses a **composition model** where four core components work together:\n\n\\`\\`\\`\nModel → Prompt → Agent → Thread\n │ │ │ │\n │ │ │ └─ Conversation instance (Durable Object)\n │ │ └─ Orchestrates conversation flow\n │ └─ System instructions + tools\n └─ LLM provider configuration\n\\`\\`\\`\n\n**Models** define which LLM to use (provider, model ID, pricing, fallbacks).\n**Prompts** define what the LLM should do (system instructions, available tools).\n**Agents** orchestrate conversations (which prompt, stop conditions, turn limits).\n**Threads** are individual conversation instances with persistent storage.\n\n## How Components Compose\n\n### Basic Flow\n1. User creates a thread with an agent\n2. Agent uses its configured prompt\n3. Prompt specifies the model and tools\n4. LLM responds, potentially calling tools\n5. Tools execute and return results\n6. Loop continues until stop condition\n\n### Sub-Prompts (Prompts as Tools)\nPrompts can call other prompts as tools. This enables:\n- **Specialized reasoning**: A main prompt delegates to expert sub-prompts\n- **Structured outputs**: Sub-prompt validates and formats data\n- **Context isolation**: Sub-prompt gets fresh context without full history\n\n\\`\\`\\`typescript\n// Main prompt can call 'data_extractor' as a tool\ndefinePrompt({\n name: 'main_assistant',\n tools: ['data_extractor'], // Another prompt exposed as tool\n // ...\n});\n\\`\\`\\`\n\n### Agent Handoffs (Agents as Tools)\nAgents can delegate to other agents entirely:\n- **Specialization**: Route to domain-specific agents\n- **Escalation**: Hand off to more capable agents\n- **Workflows**: Chain agents for multi-step processes\n\n\\`\\`\\`typescript\ndefineAgent({\n name: 'triage_agent',\n exposeAsTool: true,\n toolDescription: 'Hand off to triage for initial assessment',\n // ...\n});\n\\`\\`\\`\n\n## File Structure\n\n\\`\\`\\`\nAGENTS.md # Project guidance for AI coding tools\nCLAUDE.md -> AGENTS.md # Compatibility symlink\nvite.config.ts # Uses builder(); Cloudflare config is generated\ntsconfig.json # Includes agents and generated .agents types\nagents/\n├── agents/ # Agent definitions (defineAgent)\n│ ├── AGENTS.md\n│ └── CLAUDE.md -> AGENTS.md\n├── prompts/ # Prompt definitions (definePrompt)\n│ ├── AGENTS.md\n│ └── CLAUDE.md -> AGENTS.md\n├── models/ # Model configurations (defineModel)\n│ ├── AGENTS.md\n│ └── CLAUDE.md -> AGENTS.md\n├── tools/ # Custom tools (defineTool)\n│ ├── AGENTS.md\n│ └── CLAUDE.md -> AGENTS.md\n├── hooks/ # Lifecycle hooks (defineHook)\n│ ├── AGENTS.md\n│ └── CLAUDE.md -> AGENTS.md\n└── api/ # Thread API endpoints (defineThreadEndpoint)\n ├── AGENTS.md\n └── CLAUDE.md -> AGENTS.md\n\\`\\`\\`\n\nThe \\`builder()\\` Vite plugin generates the Worker entry, Durable Object bindings, Cloudflare Vite plugin configuration, and local \\`.agents/\\` support files at build time. Agent files are **auto-discovered** at runtime. No manual registration needed.\n\n## ThreadState\n\n\\`ThreadState\\` is the state object available in tools and hooks:\n\n\\`\\`\\`typescript\ninterface ThreadState {\n // Identity (readonly)\n threadId: string; // Thread identifier\n agentId: string; // Agent identifier\n userId: string | null; // User identifier (if set)\n createdAt: number; // Creation timestamp\n children: SubagentRegistryEntry[]; // Resumable child registry\n terminated: number | null; // Soft-termination timestamp\n arguments: Record<string, unknown>; // Invocation or subagent creation args\n context: Record<string, unknown>; // Current-execution scratch data\n\n // Methods\n getMessages(options?): Promise<MessagesResult>; // Get conversation history\n injectMessage(input): Promise<Message>; // Add message to thread\n queueMessage(input): Promise<void>; // Queue message for next step\n loadModel(name): Promise<ModelConfig>; // Load model definition\n loadPrompt(name): Promise<PromptConfig>; // Load prompt definition\n loadAgent(name): Promise<AgentConfig>; // Load agent definition\n env(propertyName): Promise<string>; // Resolve env value for this thread\n setEnv(propertyName, value): Promise<void>; // Set thread env + propagate to active descendants\n getValue<T = unknown>(key: string): Promise<T | null>; // Read durable per-thread JSON value\n setValue(key: string, value: unknown): Promise<void>; // Write durable value; null/undefined deletes\n notifyParent(content): Promise<void>; // Queue a silent message to the parent when one exists\n setStatus(status): Promise<void>; // Update this child in the parent registry; no-op without a parent\n stopSession(options?): Promise<void>; // Terminally stop the current agent session\n getChildThread(referenceId): Promise<ThreadState | null>; // Resolve child thread\n getParentThread(): Promise<ThreadState | null>; // Resolve parent thread\n terminate(): Promise<void>; // Soft-terminate thread\n runCode(source, options?): CodeExecution; // Run JS/TS in a fresh Dynamic Worker sandbox\n}\n\\`\\`\\`\n\n\\`state.arguments\\` is read-only thread invocation data. Resumable \\`subagent_create.arguments\\` persists with the child thread, is visible to both child sides, and is also available as prompt variables. Use \\`state.context\\` only for mutable scratch data during the current execution; it is not durable storage.\n\n\\`runCode\\` has no implicit access to thread state, filesystem, network, timers, or host globals. Bridge only the exact capabilities needed through \\`imports\\` or \\`globals\\`; use \\`modules\\` for local relative ES modules; use \\`execute\\` to select the export and args to run. \\`modules\\` keys are graph-root relative paths; entry-source imports resolve from \\`filename\\` when supplied, including \\`../\\` parent paths that stay inside the supplied graph. TypeScript input is accepted by default and erased before evaluation. In thread endpoints, \\`runCode\\` is forwarded into the thread Durable Object; pass plain transferable options there and keep function-backed bridges in tools or in-thread execution contexts.\n\n## Subagents\n\n\\`dual_ai\\` agents can be used as subagents from prompt tool configs:\n\n- Each subagent runs in its own thread (\\`DurableThread\\`)\n- Parent/child linkage is tracked in thread metadata\n- Resumable children are visible in \\`state.children\\`\n- Parent threads create/message resumable children via built-ins (\\`subagent_create\\`, \\`subagent_message\\`)\n- \\`subagent_create.arguments\\` is validated from the receiving child side's prompt schema and persists as \\`ThreadState.arguments\\` plus prompt variables for the life of the child thread\n- Child completion results are queued back to the parent when \\`parentCommunication\\` is \\`implicit\\`\n- Explicit relationships can stay idle until code calls \\`state.notifyParent()\\` or \\`state.setStatus()\\`; use \\`state.stopSession({ result, notifyParent, status })\\` when a tool should also terminally end the child session\n\nAccess in tools:\n\\`\\`\\`typescript\nexport default defineTool('...', schema, async (state, args) => {\n const threadId = state.threadId;\n const creationArgs = state.arguments;\n const { messages } = await state.getMessages();\n const count = (await state.getValue<number>('invocation_count')) ?? 0;\n await state.setValue('invocation_count', count + 1);\n // ...\n});\n\\`\\`\\`\n\nAccess in hooks:\n\\`\\`\\`typescript\nexport default defineHook({\n hook: 'before_create_message',\n id: 'my_hook',\n execute: async (state, message) => {\n console.log(\\`Thread: \\${state.threadId}, Agent: \\${state.agentId}\\`);\n return message;\n }\n});\n\\`\\`\\`\n\n## Quick Reference\n\n| Function | Purpose | Directory |\n|----------|---------|-----------|\n| \\`defineModel()\\` | Configure LLM provider | \\`agents/models/\\` |\n| \\`definePrompt()\\` | System instructions + tools | \\`agents/prompts/\\` |\n| \\`defineAgent()\\` | Conversation orchestration | \\`agents/agents/\\` |\n| \\`defineTool()\\` | Custom tool functions | \\`agents/tools/\\` |\n| \\`defineHook()\\` | Lifecycle interception | \\`agents/hooks/\\` |\n| \\`defineThreadEndpoint()\\` | Custom API routes | \\`agents/api/\\` |\n\n## Runtime Utilities\n\nImport from \\`@standardagents/builder\\`:\n\n\\`\\`\\`typescript\nimport {\n queueTool, // Queue another tool for execution\n injectMessage, // Add message without triggering execution\n getMessages, // Retrieve message history\n emitThreadEvent, // Send custom WebSocket events\n} from '@standardagents/builder';\n\\`\\`\\`\n\n## Documentation\n\nFull documentation: https://docs.standardagentbuilder.com\n\n- [Architecture Overview](https://docs.standardagentbuilder.com/introduction/architecture)\n- [Models](https://docs.standardagentbuilder.com/core-concepts/models)\n- [Prompts](https://docs.standardagentbuilder.com/core-concepts/prompts)\n- [Agents](https://docs.standardagentbuilder.com/core-concepts/agents)\n- [Tools](https://docs.standardagentbuilder.com/core-concepts/tools)\n- [Hooks](https://docs.standardagentbuilder.com/core-concepts/hooks)\n- [ThreadState](https://docs.standardagentbuilder.com/core-concepts/flowstate)\n- [Thread API](https://docs.standardagentbuilder.com/core-concepts/api)\n`;\n\nexport const ROOT_CLAUDE_MD = ROOT_AGENTS_MD;\n","export const MODELS_AGENTS_MD = `# Model Definitions\n\nModels define which LLM provider and model to use for prompts.\n\n## Properties\n\n| Property | Type | Required | Description |\n|----------|------|----------|-------------|\n| \\`name\\` | \\`string\\` | Yes | Unique identifier for this model configuration |\n| \\`provider\\` | \\`'openai' \\\\| 'anthropic' \\\\| 'openrouter' \\\\| 'google' \\\\| 'cerebras' \\\\| 'groq' \\\\| 'xai'\\` | Yes | LLM provider |\n| \\`model\\` | \\`string\\` | Yes | Model ID sent to provider API |\n| \\`fallbacks\\` | \\`string[]\\` | No | Fallback model names to try if primary fails |\n| \\`inputPrice\\` | \\`number\\` | No | Cost per 1M input tokens (USD) |\n| \\`outputPrice\\` | \\`number\\` | No | Cost per 1M output tokens (USD) |\n| \\`cachedPrice\\` | \\`number\\` | No | Cost per 1M cached input tokens |\n| \\`includedProviders\\` | \\`string[]\\` | No | Provider prefixes for OpenRouter routing |\n| \\`providerTools\\` | \\`string[]\\` | No | Provider-built-in tool names to make available for prompts using this model |\n\n## Example\n\n\\`\\`\\`typescript\nimport { defineModel } from '@standardagents/builder';\n\nexport default defineModel({\n name: 'default',\n provider: 'openrouter',\n model: 'google/gemini-3-flash-preview',\n fallbacks: ['fast', 'cheap-heavy'],\n});\n\\`\\`\\`\n\n## Provider Tools\n\nProviders can expose built-in tools such as search, file search, code execution,\nor provider-specific tools through their \\`getTools()\\` implementation. Enable the\nprovider tool names on the model with \\`providerTools\\`; prompts can then include\nthose tools like normal tool names. Provider tools execute on the upstream\nprovider, not in AgentBuilder, and successful calls are logged as provider tool\nentries.\n\nOpenRouter exposes \\`web_search\\`, \\`web_fetch\\`, \\`datetime\\`, and \\`image_generation\\`\nas provider-executed server tools. Configure optional OpenRouter parameters with\n\\`providerOptions.serverTools\\` on the model.\n\n## Recommended Models (OpenRouter)\n\n| Use Case | Model ID | Description |\n|----------|----------|-------------|\n| Fast/Cheap | \\`z-ai/glm-4.5-air\\` | Quick responses, low cost |\n| Mid-tier | \\`google/gemini-3-flash-preview\\` | Good balance of speed and quality |\n| Cheap Heavy | \\`nvidia/nemotron-3-ultra-550b-a55b\\` | Frontier open reasoning and orchestration, still affordable |\n| Heavy | \\`google/gemini-3-pro-preview\\` | Most capable, for complex tasks |\n\n**⚠️ Google Models**: When using Google models (\\`google/gemini-*\\`), you must enable \\`reasoning\\` in your prompt configuration or tool calls will fail. See the prompts AGENTS.md for details.\n\n## Provider API Keys\n\nSet these environment variables in \\`.dev.vars\\` (local) or Cloudflare secrets (production):\n\n| Provider | Environment Variable |\n|----------|---------------------|\n| Cloudflare Workers AI | \\`CLOUDFLARE_API_TOKEN\\` + \\`CLOUDFLARE_ACCOUNT_ID\\` |\n| Cerebras | \\`CEREBRAS_API_KEY\\` |\n| Groq | \\`GROQ_API_KEY\\` |\n| OpenAI | \\`OPENAI_API_KEY\\` |\n| Anthropic | \\`ANTHROPIC_API_KEY\\` |\n| OpenRouter | \\`OPENROUTER_API_KEY\\` |\n| Google | \\`GOOGLE_API_KEY\\` |\n| xAI | \\`XAI_API_KEY\\` |\n\nIf \\`STANDARD_AGENTS_API_KEY\\` is present and a provider-specific key is not set,\nfirst-party Standard Agents providers route through the hosted Standard Agents\nrouter. Setting a provider-specific key always uses that provider directly.\n\n## Fallback Strategy\n\nWhen a model fails, fallbacks are tried in order:\n1. Primary model (2 attempts)\n2. First fallback (2 attempts)\n3. Second fallback (2 attempts)\n4. ...and so on\n\nRetries occur on: network errors, rate limits (429), server errors (5xx), auth errors (401).\n\n## OpenRouter Configuration\n\nFor OpenRouter, use the full model path:\n\n\\`\\`\\`typescript\nexport default defineModel({\n name: 'heavy',\n provider: 'openrouter',\n model: 'google/gemini-3-pro-preview',\n includedProviders: ['google'], // Prefer Google's servers\n});\n\\`\\`\\`\n\n## Best Practices\n\n- **Name by use case**, not model ID (e.g., \\`fast\\`, \\`default\\`, \\`heavy\\`)\n- **Configure fallbacks** for production reliability\n- **Set pricing** for cost tracking in logs when your provider or runtime does not supply it automatically\n- **Cerebras note:** documented Cerebras models have built-in fallback pricing for request logs, but custom/private Cerebras models should still set \\`inputPrice\\` and \\`outputPrice\\`\n- **Use environment variables** for API keys, never hardcode\n\n## Documentation\n\nFull reference: https://docs.standardagentbuilder.com/api-reference/define/model\n`;\n\nexport const MODELS_CLAUDE_MD = MODELS_AGENTS_MD;\n","export const PROMPTS_AGENTS_MD = `# Prompt Definitions\n\nPrompts define system instructions, model selection, and available tools for LLM interactions.\n\n## Properties\n\n| Property | Type | Required | Description |\n|----------|------|----------|-------------|\n| \\`name\\` | \\`string\\` | Yes | Unique identifier for this prompt |\n| \\`toolDescription\\` | \\`string\\` | Yes | Description shown when used as a tool |\n| \\`prompt\\` | \\`string \\\\| StructuredPrompt\\` | Yes | System instructions |\n| \\`model\\` | \\`string\\` | Yes | Model name to use (references \\`agents/models/\\`) |\n| \\`tools\\` | \\`(string \\\\| ToolConfig \\\\| SubagentToolConfig)[]\\` | No | Available tools (include ai_human agent names for handoffs and dual_ai subagent configs) |\n| \\`includeChat\\` | \\`boolean\\` | No | Include full conversation history |\n| \\`includePastTools\\` | \\`boolean\\` | No | Include previous tool results |\n| \\`parallelToolCalls\\` | \\`boolean\\` | No | Allow multiple concurrent tool calls |\n| \\`toolChoice\\` | \\`'auto' \\\\| 'none' \\\\| 'required'\\` | No | Tool calling strategy |\n| \\`requiredSchema\\` | \\`z.ZodObject\\` | No | Input validation when called as tool |\n| \\`variables\\` | \\`VariableDefinition[]\\` | No | Variable declarations (\\`name\\`, \\`type\\`, \\`required\\`, \\`scoped\\`, \\`description\\`) |\n| \\`env\\` | \\`Record<string, string>\\` | No | Prompt-level default values for variables |\n| \\`hooks\\` | \\`string[]\\` | No | Hook IDs to run for this prompt (overrides agent hooks) |\n| \\`reasoning\\` | \\`ReasoningConfig\\` | No | Extended thinking configuration |\n\n## Basic Example\n\n\\`\\`\\`typescript\nimport { definePrompt } from '@standardagents/builder';\n\nexport default definePrompt({\n name: 'customer_support',\n toolDescription: 'Handle customer support inquiries',\n model: 'default',\n prompt: \\`You are a helpful customer support agent.\nAlways be polite and professional.\nIf you cannot help, escalate to a human.\\`,\n tools: ['search_knowledge_base', 'create_ticket'],\n includeChat: true,\n});\n\\`\\`\\`\n\n## Structured Prompts\n\nInclude other prompts for reusable instruction blocks:\n\n\\`\\`\\`typescript\nexport default definePrompt({\n name: 'main_assistant',\n toolDescription: 'Primary assistant',\n model: 'default',\n prompt: [\n { type: 'text', content: 'You are a helpful assistant.\\\\n\\\\n' },\n { type: 'include', prompt: 'common_rules' }, // Includes another prompt\n { type: 'env', property: 'ASSISTANT_TONE' }, // Inject variable value\n { type: 'text', content: '\\\\n\\\\nBe concise.' },\n ],\n});\n\\`\\`\\`\n\n\\`type: 'env'\\` inserts a resolved thread variable value. Use this only for non-secret values that are safe to expose to the LLM.\n\nThe sandboxed coding prompt declares \\`HTTP_HOST\\` as a text variable. Its URL helper uses that value as the origin for files exposed from the thread \\`public/\\` directory and endpoints exposed from the thread \\`api/\\` directory. Public URLs should usually omit extensions; extensionless public paths resolve \\`.html\\`, then \\`.js\\`, then \\`.ts\\`, then matching \\`index\\` files in the same order. Browser pages should reference only public files, \\`api/\\` endpoints, or absolute external URLs, using relative asset URLs like \\`./app\\` and \\`./api/todos\\`; private \\`src/\\` files are not served directly. Public \\`.ts\\` files are transformed to browser JavaScript and are not server endpoints. Server-side endpoints live under the thread filesystem \\`api/\\` directory, and the \\`api/\\` directory name stays in the public URL: \\`api/todo.ts\\` is \\`/api/threads/{threadId}/api/todo\\`, while \\`api/todo.ts\\` is not \\`/api/threads/{threadId}/todo\\` or \\`/api/threads/{threadId}/todos\\`. Endpoint files default-export a function that accepts \\`Request\\` and returns \\`Response\\` or \\`Promise<Response>\\`. Endpoint code can import \\`fetch\\`, \\`fs\\`, and \\`storage\\`, and can import private helpers with relative paths such as \\`../src/todo.ts\\`. When the coding agent creates a site, page, or endpoint, it should call \\`get_public_url\\` with the created file path and use the returned URL.\n\nSandboxed code and \\`api/\\` endpoints can persist small JSON-serializable runtime data through \\`import { storage } from \"storage\"\\`. Use \\`storage.get\\`, \\`storage.set\\`, \\`storage.delete\\`, and \\`storage.has\\` with stable logical keys. Do not expose, mention, or depend on internal storage key prefixes.\n\nThe sandboxed coding prompt includes \\`delete_file\\` for removing files or empty directories from the thread filesystem. Use it to clean up obsolete implementation files, stale public assets, and abandoned endpoint routes after the replacement is working.\n\n## Tool Configuration\n\nTools can be simple names or detailed configs:\n\n\\`\\`\\`typescript\ntools: [\n 'simple_tool', // Just the tool name\n {\n name: 'complex_tool',\n includeTextResponse: true, // Include sub-prompt text in result\n includeToolCalls: false, // Exclude sub-prompt tool calls\n includeErrors: true, // Include error details\n initUserMessageProperty: 'query', // Use this arg as initial message\n },\n],\n\\`\\`\\`\n\nProvider-built-in tools use the same \\`tools\\` list once the selected model enables\nthem with \\`providerTools\\`. AgentBuilder passes them to the provider and records\nprovider-reported calls in request logs; it does not execute those tools locally.\nGenerated prompt files may store these selections as \\`provider:<toolName>\\` to\ndistinguish provider tools from local tools with the same name.\n\n### Subagent Tool Configuration\n\nUse \\`SubagentToolConfig\\` when the tool is a \\`dual_ai\\` agent:\n\n\\`\\`\\`typescript\ntools: [\n // Blocking, non-resumable (default)\n { name: 'data_processor_agent' },\n\n // Non-blocking, resumable with a single instance\n {\n name: 'browser_agent',\n blocking: false,\n immediate: {\n nameEnv: 'BROWSER_AGENT_NAME',\n descriptionEnv: 'BROWSER_AGENT_DESCRIPTION',\n scopedEnv: ['BROWSER_AGENT_API_KEY'],\n },\n optional: 'ENABLE_BROWSER_AGENT',\n initAgentNameProperty: 'name',\n resumable: {\n receives_messages: 'side_a',\n maxInstances: 1,\n parentCommunication: 'explicit',\n },\n },\n]\n\\`\\`\\`\n\nWhen prompt-configured resumable dual_ai subagents exist, the runtime auto-injects:\n- \\`subagent_create\\` for spawning new child instances\n- \\`subagent_message\\` for messaging active resumable instances\n\n\\`subagent_create\\` requires a non-empty \\`name\\` for human-friendly child thread labels.\nAgentBuilder stores that argument as a \\`name:<value>\\` thread tag.\n\\`subagent_create.arguments\\` is shaped by the prompt schema on the child side selected by \\`resumable.receives_messages\\`.\nAgentBuilder persists those initial arguments with the child thread, exposes them as \\`ThreadState.arguments\\` and prompt variables, and keeps them visible to both child sides for later resumptions.\n\nSet \\`immediate: true\\` to run a tool automatically when the prompt activates.\nUse \\`immediate: { nameEnv, descriptionEnv, scopedEnv }\\` when you want safe per-instance bootstrap hints while keeping copied scoped env runtime-only.\nSet \\`optional: 'ENV_NAME'\\` to enable a subagent branch only when env resolves to \\`true\\`, \\`1\\`, or \\`yes\\`.\nSet \\`resumable.parentCommunication: 'explicit'\\` when the child should stay quiet until its own tools or hooks call \\`state.notifyParent()\\`, \\`state.setStatus()\\`, or \\`state.stopSession({ result, notifyParent, status })\\`.\nIf required scoped vars are missing, the runtime returns \\`error_code: \"subagent_env_required\"\\` with a temporary \\`GET/POST /api/threads/:threadId/variables/:requestId\\` endpoint in \\`error_data.endpoint\\`.\n\n## Input Validation\n\nValidate inputs when prompt is called as a tool:\n\n\\`\\`\\`typescript\nimport { z } from 'zod';\n\nexport default definePrompt({\n name: 'data_extractor',\n toolDescription: 'Extract structured data from text',\n model: 'default',\n prompt: 'Extract the requested data from the input.',\n requiredSchema: z.object({\n text: z.string().describe('Text to extract from'),\n fields: z.array(z.string()).describe('Fields to extract'),\n }),\n});\n\\`\\`\\`\n\n## Extended Thinking (Reasoning)\n\nEnable for complex reasoning tasks:\n\n\\`\\`\\`typescript\nexport default definePrompt({\n name: 'code_reviewer',\n toolDescription: 'Review code for issues',\n model: 'heavy',\n prompt: 'Review the code thoroughly...',\n reasoning: {\n effort: 'high', // 'low' | 'medium' | 'high'\n maxTokens: 16000, // Max thinking tokens\n exclude: true, // Don't include thinking in response\n },\n});\n\\`\\`\\`\n\n**⚠️ Google Models Require Reasoning**: When using Google models (\\`google/gemini-*\\`) via OpenRouter, you **must** include \\`reasoning\\` configuration or tool calls will fail. At minimum:\n\n\\`\\`\\`typescript\nreasoning: {\n effort: 'low', // Can be 'low', 'medium', or 'high'\n},\n\\`\\`\\`\n\n## Hooks\n\nAttach lifecycle hooks to a prompt:\n\n\\`\\`\\`typescript\nexport default definePrompt({\n name: 'customer_support',\n toolDescription: 'Handle customer support',\n model: 'default',\n prompt: 'You are a support agent...',\n hooks: ['limit_to_20', 'redact_pii'], // Hook IDs from agents/hooks/\n});\n\\`\\`\\`\n\nPrompt hooks take precedence over agent hooks. See \\`agents/hooks/AGENTS.md\\` for details.\n\n## Best Practices\n\n- **Write clear instructions** - Structure with headers and bullet points\n- **Describe tools thoroughly** - LLMs decide based on descriptions\n- **Validate inputs with Zod** - Catch errors early\n- **Use \\`includeChat\\`** for conversational context\n- **Name by purpose**, not model (e.g., \\`support_agent\\` not \\`gpt4_prompt\\`)\n\n## Documentation\n\nFull reference: https://docs.standardagentbuilder.com/api-reference/define/prompt\n`;\n\nexport const PROMPTS_CLAUDE_MD = PROMPTS_AGENTS_MD;\n","export const AGENT_DEFINITIONS_AGENTS_MD = `# Agent Definitions\n\nAgents orchestrate conversations by defining prompts, stop conditions, and turn limits.\n\n## Agent Properties\n\n| Property | Type | Required | Description |\n|----------|------|----------|-------------|\n| \\`name\\` | \\`string\\` | Yes | Unique identifier for this agent |\n| \\`type\\` | \\`'ai_human' \\\\| 'dual_ai'\\` | No | Conversation type (default: \\`ai_human\\`) |\n| \\`sideA\\` | \\`SideConfig\\` | Yes | Configuration for side A (AI in ai_human) |\n| \\`sideB\\` | \\`SideConfig\\` | No | Configuration for side B (required for dual_ai) |\n| \\`maxSessionTurns\\` | \\`number\\` | No | Max total turns across both sides |\n| \\`exposeAsTool\\` | \\`boolean\\` | No | Allow other prompts to hand off to this agent |\n| \\`toolDescription\\` | \\`string\\` | No | Description when used as tool (required if exposeAsTool) |\n| \\`env\\` | \\`Record<string, string>\\` | No | Agent-level default variable values |\n| \\`hooks\\` | \\`string[]\\` | No | Hook IDs to run for this agent (fallback if prompt has no hooks) |\n| \\`tags\\` | \\`string[]\\` | No | Tags for categorization and filtering |\n\n## Side Configuration\n\n| Property | Type | Required | Description |\n|----------|------|----------|-------------|\n| \\`label\\` | \\`string\\` | No | Display name for this side |\n| \\`prompt\\` | \\`string\\` | Yes | Prompt name to use (references \\`agents/prompts/\\`) |\n| \\`stopOnResponse\\` | \\`boolean\\` | No | Stop turn when LLM returns text (default: true) |\n| \\`stopTool\\` | \\`string\\` | No | Tool that stops this side's turn |\n| \\`stopToolResponseProperty\\` | \\`string\\` | No | Property to extract from stop tool result |\n| \\`maxSteps\\` | \\`number\\` | No | Maximum step budget for this side |\n| \\`sessionStop\\` | \\`string \\\\| SessionToolBinding\\` | No | Terminal success lifecycle binding |\n| \\`sessionFail\\` | \\`string \\\\| SessionToolBinding\\` | No | Terminal failure lifecycle binding |\n| \\`sessionStatus\\` | \\`string \\\\| SessionToolBinding\\` | No | Non-terminal status lifecycle binding |\n| \\`manualStopCondition\\` | \\`boolean\\` | No | Enable custom stop handling via hooks |\n\n## Basic Example (AI-Human)\n\n\\`\\`\\`typescript\nimport { defineAgent } from '@standardagents/builder';\n\nexport default defineAgent({\n name: 'support_agent',\n type: 'ai_human',\n sideA: {\n label: 'Support',\n prompt: 'customer_support',\n stopOnResponse: true,\n sessionStop: 'close_ticket',\n maxSteps: 50,\n },\n tags: ['support', 'tier-1'],\n});\n\\`\\`\\`\n\n## Dual-AI Example\n\nTwo AI agents conversing (e.g., debate, iterative refinement):\n\n\\`\\`\\`typescript\nexport default defineAgent({\n name: 'code_review_debate',\n type: 'dual_ai',\n maxSessionTurns: 20,\n sideA: {\n label: 'Reviewer',\n prompt: 'code_reviewer',\n stopOnResponse: true,\n },\n sideB: {\n label: 'Developer',\n prompt: 'code_defender',\n stopOnResponse: true,\n },\n});\n\\`\\`\\`\n\n## Dual-AI Subagent Pattern\n\nWhen a \\`dual_ai\\` agent is used as a subagent tool, a common split is:\n- **sideA**: performs work (tools, data gathering, execution)\n- **sideB**: reflection, verification, and quality checks\n\n\\`\\`\\`typescript\nexport default defineAgent({\n name: 'research_subagent',\n type: 'dual_ai',\n exposeAsTool: true,\n toolDescription: 'Researches and validates findings autonomously',\n maxSessionTurns: 16,\n sideA: {\n label: 'Worker',\n prompt: 'research_worker',\n sessionStatus: 'set_subagent_status',\n sessionFail: 'fail_research_subagent',\n sessionStop: 'finish_subagent',\n },\n sideB: {\n label: 'Reviewer',\n prompt: 'research_reviewer',\n stopOnResponse: true,\n },\n});\n\\`\\`\\`\n\n## Agent Handoffs\n\nExpose an agent for handoffs from other prompts:\n\n\\`\\`\\`typescript\nexport default defineAgent({\n name: 'escalation_agent',\n type: 'ai_human',\n exposeAsTool: true,\n toolDescription: 'Escalate to senior support for complex issues',\n sideA: {\n prompt: 'senior_support',\n },\n});\n\\`\\`\\`\n\nOther prompts can then include the agent name in their \\`tools\\` array to enable handoffs.\n\n## Stop Conditions (Priority Order)\n\n1. **sessionFail** - Ends entire conversation with a terminal failure\n2. **sessionStop** - Ends entire conversation successfully\n3. **stopTool** - Ends current side's turn\n4. **maxSteps** - Ends side execution when the safety budget is reached\n5. **stopOnResponse** - Ends turn when LLM returns text\n6. **maxSessionTurns** - Ends conversation (hard limit: 250)\n\n## Hooks\n\nAttach lifecycle hooks at the agent level:\n\n\\`\\`\\`typescript\nexport default defineAgent({\n name: 'support_agent',\n type: 'ai_human',\n hooks: ['log_all_messages', 'sanitize_results'],\n sideA: {\n prompt: 'customer_support',\n },\n});\n\\`\\`\\`\n\nAgent hooks run as a fallback when the active prompt has no hooks defined. Prompt hooks always take precedence. See \\`agents/hooks/AGENTS.md\\` for details.\n\n## Naming Convention\n\nAgent names **must** end with the \\`_agent\\` suffix (e.g., \\`support_agent\\`, \\`research_agent\\`).\nThis convention is enforced by the builder UI and makes agents easily identifiable in logs and code.\n\n## Best Practices\n\n- **Use descriptive names** (\\`customer_support_agent\\` not \\`agent1\\`)\n- **Always use the _agent suffix** - names like \\`support_agent\\`, \\`research_agent\\`\n- **Always set maxSteps or maxSessionTurns** as safety limits\n- **Match stop conditions to use case** - chat apps use stopOnResponse, workflows use stopTool\n- **Use labels** for clarity in logs and UI\n- **Organize with tags** for filtering\n\n## Documentation\n\nFull reference: https://docs.standardagentbuilder.com/api-reference/define/agent\n`;\n\nexport const AGENTS_CLAUDE_MD = AGENT_DEFINITIONS_AGENTS_MD;\n","export const TOOLS_AGENTS_MD = `# Custom Tools\n\nTools extend agent capabilities beyond text generation. They allow LLMs to fetch data, perform calculations, execute side effects, and chain to other prompts or agents.\n\n## Function Signature\n\n\\`\\`\\`typescript\ndefineTool({\n description: string, // What the tool does (shown to LLM)\n args?: z.ZodObject, // Input validation schema (optional)\n execute: (state, args) => ToolResult, // Implementation\n variables?: VariableDefinition[], // Declared variables (optional)\n})\n\\`\\`\\`\n\n## Basic Example\n\n\\`\\`\\`typescript\nimport { defineTool } from '@standardagents/builder';\nimport { z } from 'zod';\n\nexport default defineTool({\n description: 'Search the knowledge base for articles matching a query',\n args: z.object({\n query: z.string().describe('Search query'),\n limit: z.number().optional().default(10).describe('Max results'),\n }),\n execute: async (state, args) => {\n const results = await searchKB(args.query, args.limit);\n return {\n status: 'success',\n result: JSON.stringify(results),\n };\n },\n});\n\\`\\`\\`\n\n## Argument Schemas\n\nTool args must be a top-level \\`z.object(...)\\`. Prefer explicit, bounded schemas made from strings, numbers, booleans, nulls, literals, enums, arrays, objects, optionals, nullables, and defaults. Avoid provider-visible recursive or open-ended schemas such as \\`z.unknown()\\`, \\`z.any()\\`, and \\`z.object({}).catchall(...)\\`; strict tool providers can reject the generated JSON Schema. If a tool needs arbitrary JSON input, accept it as a JSON string and parse it inside \\`execute\\`.\n\n## ToolResult Interface\n\n| Property | Type | Description |\n|----------|------|-------------|\n| \\`status\\` | \\`'success' \\\\| 'error'\\` | Whether the tool succeeded |\n| \\`result\\` | \\`string\\` | Tool output (required for success) |\n| \\`error\\` | \\`string\\` | Error message (for error status) |\n| \\`error_code\\` | \\`string\\` | Machine-readable error code |\n| \\`error_data\\` | \\`Record<string, unknown>\\` | Structured error payload |\n| \\`attachments\\` | \\`ToolAttachment[]\\` | Files to attach (images, etc.) |\n\n## ThreadState Access\n\nThe \\`state\\` parameter provides access to:\n\n\\`\\`\\`typescript\nexecute: async (state, args) => {\n // Thread information\n const threadId = state.thread.id;\n const thread = state.thread.instance;\n const creationArgs = state.arguments; // Invocation or subagent creation args\n\n // Configuration\n const agentName = state.agent.name;\n const modelName = state.model.name;\n\n // Message history\n const messages = state.messages;\n\n // Thread variable resolution\n const apiKey = await state.env('GOOGLE_API_KEY');\n await state.setEnv('LAST_TOOL_RUN_AT', new Date().toISOString());\n\n // Durable per-thread JSON values\n const runCount = (await state.getValue<number>('run_count')) ?? 0;\n await state.setValue('run_count', runCount + 1);\n\n // Sandboxed JS/TS execution with explicit bridge capabilities\n const run = state.runCode('export async function main(path) { return await read(path) }', {\n execute: { fn: 'main', args: ['/notes.txt'] },\n globals: {\n read: async (path: string) => {\n const data = await state.readFile(path);\n return data ? new TextDecoder().decode(data) : null;\n },\n },\n });\n const codeResult = await run;\n\n // Parent state (for sub-prompts)\n const root = state.rootState;\n}\n\\`\\`\\`\n\nUse \\`state.runCode()\\` instead of \\`eval\\` or \\`new Function\\` for model- or user-authored JavaScript/TypeScript. The sandbox starts with no ambient host capabilities; provide imports/globals explicitly, use \\`modules\\` for local relative ES modules, use \\`execute\\` to select an export and pass args, use \\`report\\` for streamed observations, and call \\`run.terminate(reason)\\` from your own timeout budget when needed. \\`modules\\` keys are graph-root relative paths; entry-source imports resolve from \\`options.filename\\` when supplied. Relative module imports may use \\`./\\` and \\`../\\` as long as they resolve within the supplied module graph. In thread endpoints, \\`runCode\\` is forwarded into the thread Durable Object; pass plain transferable option values there, and do function-backed bridges from tools or in-thread execution contexts.\n\n## Tool Without Arguments\n\n\\`\\`\\`typescript\nexport default defineTool({\n description: 'Get current server time',\n execute: async (state) => {\n return {\n status: 'success',\n result: new Date().toISOString(),\n };\n },\n});\n\\`\\`\\`\n\n## Error Handling\n\nReturn errors gracefully instead of throwing:\n\n\\`\\`\\`typescript\nexport default defineTool({\n description: 'Fetch user data',\n args: z.object({ userId: z.string() }),\n execute: async (state, args) => {\n try {\n const user = await fetchUser(args.userId);\n return { status: 'success', result: JSON.stringify(user) };\n } catch (error) {\n return {\n status: 'error',\n error: \\`Failed to fetch user: \\${error.message}\\`,\n };\n }\n },\n});\n\\`\\`\\`\n\n## Queueing Additional Tools\n\nQueue another tool to run after the current one:\n\n\\`\\`\\`typescript\nimport { queueTool } from '@standardagents/builder';\n\nexport default defineTool({\n description: 'Create order and send confirmation',\n args: z.object({ items: z.array(z.string()) }),\n execute: async (state, args) => {\n const order = await createOrder(args.items);\n\n // Queue email tool to run next\n queueTool(state, 'send_confirmation_email', {\n orderId: order.id,\n email: state.thread.metadata.userEmail,\n });\n\n return { status: 'success', result: JSON.stringify(order) };\n },\n});\n\\`\\`\\`\n\n## Injecting Messages\n\nAdd messages without triggering re-execution:\n\n\\`\\`\\`typescript\nimport { injectMessage } from '@standardagents/builder';\n\nexport default defineTool({\n description: 'Log audit event',\n args: z.object({ event: z.string() }),\n execute: async (state, args) => {\n await injectMessage(state, {\n role: 'system',\n content: \\`[AUDIT] \\${args.event}\\`,\n });\n return { status: 'success', result: 'Logged' };\n },\n});\n\\`\\`\\`\n\n## Stopping Sessions\n\n\\`state.execution.stop()\\` stops the current execution loop. To terminally end the active agent session, including blocking subagent runs that expect a session boundary, use \\`state.stopSession()\\`:\n\n\\`\\`\\`typescript\nawait state.stopSession({\n result: 'Waiting for clarification',\n notifyParent: 'Please clarify the request',\n status: 'waiting for clarification',\n});\n\\`\\`\\`\n\n\\`notifyParent\\` queues a silent message to the parent when one exists; \\`status\\` is ignored without a parent registry entry. Omit \\`notifyParent\\` and \\`status\\` when stopping should not send a parent message or update child status.\n\n## Variables and Env\n\nTools can declare variable requirements with \\`variables\\`, including \\`required\\` and \\`description\\` metadata:\n\n\\`\\`\\`typescript\nexport default defineTool({\n description: 'Search uploaded documents',\n args: z.object({ query: z.string() }),\n execute: async (state, args) => {\n const vectorStoreId = await state.env('VECTOR_STORE_ID');\n const results = await searchVectorStore(vectorStoreId, args.query);\n return { status: 'success', result: JSON.stringify(results) };\n },\n variables: [\n {\n name: 'VECTOR_STORE_ID',\n type: 'text',\n required: true,\n scoped: false,\n description: 'OpenAI Vector Store ID',\n },\n ],\n});\n\\`\\`\\`\n\nUse \\`scoped: true\\` for per-instance values that should not inherit from parent thread env (for example per-account OAuth tokens on subagents).\n\n## Returning Attachments\n\nTools can return file attachments (e.g., generated images):\n\n\\`\\`\\`typescript\nexport default defineTool({\n description: 'Generate a chart from data',\n args: z.object({ data: z.array(z.number()) }),\n execute: async (state, args) => {\n const chartImage = await generateChart(args.data);\n return {\n status: 'success',\n result: 'Chart generated successfully',\n attachments: [{\n name: 'chart.png',\n mimeType: 'image/png',\n data: chartImage.base64,\n width: 800,\n height: 600,\n }],\n };\n },\n});\n\\`\\`\\`\n\n## Best Practices\n\n- **Write clear descriptions** - LLMs decide tool usage based on descriptions\n- **Describe all parameters** with \\`.describe()\\` in Zod schemas\n- **Handle errors gracefully** - return error status, don't throw\n- **Use snake_case** for file names (\\`search_knowledge_base.ts\\`)\n- **Keep tools focused** - one task per tool\n- **Use \\`state.rootState\\`** when queueing from sub-prompts\n\n## Supported Zod Types\n\n- Primitives: \\`string\\`, \\`number\\`, \\`boolean\\`, \\`null\\`\n- Enums: \\`z.enum(['a', 'b', 'c'])\\`\n- Arrays: \\`z.array(z.string())\\`\n- Objects: \\`z.object({ ... })\\`\n- Optional: \\`z.string().optional()\\`\n- Default: \\`z.number().default(10)\\`\n- Nullable: \\`z.string().nullable()\\`\n\n## Documentation\n\nFull reference: https://docs.standardagentbuilder.com/api-reference/define/tool\n`;\n\nexport const TOOLS_CLAUDE_MD = TOOLS_AGENTS_MD;\n","export const HOOKS_AGENTS_MD = `# Lifecycle Hooks\n\nHooks intercept and modify agent execution at specific lifecycle points.\n\n## Available Hooks\n\n| Hook | Signature | Purpose |\n|------|-----------|---------|\n| \\`after_thread_created\\` | \\`(state: ThreadState) => void\\` | Initialize a newly created thread before execution |\n| \\`after_subagent_created\\` | \\`(state: ThreadState, childState: ThreadState) => void\\` | Run parent-side logic after a child thread is created |\n| \\`after_system_message\\` | \\`(state: ThreadState, systemMessage: string) => string \\\\| null \\\\| undefined\\` | Modify the rendered system message for a request |\n| \\`filter_messages\\` | \\`(state: ThreadState, messages: Message[]) => Message[]\\` | Filter raw messages before LLM context |\n| \\`prefilter_llm_history\\` | \\`(state: ThreadState, messages: LLMMessage[]) => LLMMessage[]\\` | Modify chat completion messages before LLM |\n| \\`before_create_message\\` | \\`(state: ThreadState, message: Message) => Message\\` | Modify message before database insert |\n| \\`after_create_message\\` | \\`(state: ThreadState, message: Message) => void\\` | Run logic after message created |\n| \\`before_update_message\\` | \\`(state: ThreadState, id: string, updates: Record) => Record\\` | Modify updates before message update |\n| \\`after_update_message\\` | \\`(state: ThreadState, message: Message) => void\\` | Run logic after message updated |\n| \\`before_store_tool_result\\` | \\`(state: ThreadState, toolCall: HookToolCall, result: HookToolResult) => HookToolResult\\` | Modify tool result before storage |\n| \\`after_tool_call_success\\` | \\`(state: ThreadState, toolCall: HookToolCall, result: HookToolResult) => HookToolResult \\\\| null\\` | Process successful tool execution |\n| \\`after_tool_call_failure\\` | \\`(state: ThreadState, toolCall: HookToolCall, result: HookToolResult) => HookToolResult \\\\| null\\` | Process failed tool execution |\n\nAll hooks receive \\`ThreadState\\` as their first parameter, providing access to thread identity, message history, resource loading, durable per-thread values via \\`getValue\\` / \\`setValue\\`, and sandboxed JS/TS execution via \\`runCode\\`.\n\n## Creating a Hook\n\nEach hook file exports a default \\`defineHook\\` call with three properties:\n\n\\`\\`\\`typescript\nimport { defineHook } from '@standardagents/builder';\n\nexport default defineHook({\n hook: 'filter_messages', // Hook type\n id: 'limit_recent_messages', // Unique ID (snake_case)\n execute: async (state, messages) => {\n return messages.slice(-20);\n }\n});\n\\`\\`\\`\n\n## Hook Scoping\n\nHooks are scoped to **prompts** or **agents** via their ID:\n\n\\`\\`\\`typescript\n// In a prompt definition\ndefinePrompt({\n name: 'customer_support',\n hooks: ['limit_recent_messages', 'redact_pii'],\n // ...\n});\n\n// In an agent definition\ndefineAgent({\n name: 'support_agent',\n hooks: ['log_all_messages'],\n // ...\n});\n\\`\\`\\`\n\n- **Prompt hooks** take precedence over agent hooks\n- If a prompt defines hooks, only those run (agent hooks are skipped)\n- If no prompt hooks are defined, agent hooks run as fallback\n- Hooks are filtered by type at runtime\n\n## File Naming\n\nHook files can use **any name** — the hook type and ID are defined inside the file:\n\n\\`\\`\\`\nagents/hooks/\n├── my_filter.ts # Could contain any hook type\n├── redact_sensitive_data.ts\n├── log_tool_usage.ts\n└── add_metadata.ts\n\\`\\`\\`\n\n## Examples\n\n### Filter Messages (Limit Context)\n\n\\`\\`\\`typescript\nimport { defineHook } from '@standardagents/builder';\n\nexport default defineHook({\n hook: 'filter_messages',\n id: 'limit_to_20',\n execute: async (state, messages) => {\n return messages.slice(-20);\n }\n});\n\\`\\`\\`\n\n### Prefilter LLM History (Redact Content)\n\n\\`\\`\\`typescript\nimport { defineHook } from '@standardagents/builder';\n\nexport default defineHook({\n hook: 'prefilter_llm_history',\n id: 'redact_pii',\n execute: async (state, messages) => {\n return messages.map(msg => ({\n ...msg,\n content: typeof msg.content === 'string'\n ? msg.content.replace(/\\\\b\\\\d{4}-\\\\d{4}-\\\\d{4}-\\\\d{4}\\\\b/g, '[REDACTED]')\n : msg.content,\n }));\n }\n});\n\\`\\`\\`\n\n### Before Create Message (Add Metadata)\n\n\\`\\`\\`typescript\nimport { defineHook } from '@standardagents/builder';\n\nexport default defineHook({\n hook: 'before_create_message',\n id: 'add_version_metadata',\n execute: async (state, message) => {\n if (message.role === 'user' && message.content) {\n return { ...message, content: \\`[v1.0] \\${message.content}\\` };\n }\n return message;\n }\n});\n\\`\\`\\`\n\n### Before Store Tool Result (Sanitize)\n\n\\`\\`\\`typescript\nimport { defineHook } from '@standardagents/builder';\n\nexport default defineHook({\n hook: 'before_store_tool_result',\n id: 'sanitize_results',\n execute: async (state, toolCall, toolResult) => {\n // toolCall: { id, type: 'function', function: { name, arguments } }\n // toolResult: { status, result?, error?, stack?, attachments? }\n if (toolResult.result) {\n return { ...toolResult, result: toolResult.result.replace(/secret/gi, '[REDACTED]') };\n }\n return toolResult;\n }\n});\n\\`\\`\\`\n\n### After Tool Call Success (Logging)\n\n\\`\\`\\`typescript\nimport { defineHook } from '@standardagents/builder';\n\nexport default defineHook({\n hook: 'after_tool_call_success',\n id: 'log_tool_success',\n execute: async (state, toolCall, result) => {\n console.log(\\`Tool \\${toolCall.function.name} succeeded\\`);\n return null; // Return null to use original result\n }\n});\n\\`\\`\\`\n\n### After Tool Call Failure (Recovery)\n\n\\`\\`\\`typescript\nimport { defineHook } from '@standardagents/builder';\n\nexport default defineHook({\n hook: 'after_tool_call_failure',\n id: 'weather_fallback',\n execute: async (state, toolCall, result) => {\n if (toolCall.function.name === 'fetch_weather') {\n return {\n status: 'success',\n result: JSON.stringify({ temp: 'unavailable', fallback: true }),\n };\n }\n return null; // Use original error for other tools\n }\n});\n\\`\\`\\`\n\n## Hook Categories\n\n**Transformation hooks** (return modified data):\n- \\`after_system_message\\` (return replacement string, or null/undefined for no change)\n- \\`filter_messages\\`\n- \\`prefilter_llm_history\\`\n- \\`before_create_message\\`\n- \\`before_update_message\\`\n- \\`before_store_tool_result\\`\n- \\`after_tool_call_success\\` (return modified result or null)\n- \\`after_tool_call_failure\\` (return modified result or null)\n\n**Event hooks** (side effects only):\n- \\`after_thread_created\\`\n- \\`after_subagent_created\\`\n- \\`after_create_message\\`\n- \\`after_update_message\\`\n\n## Best Practices\n\n- **Keep hooks fast** - target <100ms execution\n- **Wrap in try-catch** - hooks continue on error (original data preserved)\n- **Use unique IDs** - hook IDs must be snake_case and unique across the project\n- **Scope appropriately** - assign hooks to prompts or agents that need them\n- **Document purpose** with clear comments\n- **Use for cross-cutting concerns** - logging, redaction, enrichment\n\n## Documentation\n\nFull reference: https://docs.standardagentbuilder.com/api-reference/define/hook\n`;\n\nexport const HOOKS_CLAUDE_MD = HOOKS_AGENTS_MD;\n","export const API_AGENTS_MD = `# Thread-Specific API Endpoints\n\nDefine custom API endpoints that operate on specific threads with access to the thread's ThreadState.\n\n## File-Based Routing\n\n| File Pattern | HTTP Method | Route |\n|--------------|-------------|-------|\n| \\`name.ts\\` | GET | \\`/api/threads/:threadId/name\\` |\n| \\`name.get.ts\\` | GET | \\`/api/threads/:threadId/name\\` |\n| \\`name.post.ts\\` | POST | \\`/api/threads/:threadId/name\\` |\n| \\`name.put.ts\\` | PUT | \\`/api/threads/:threadId/name\\` |\n| \\`name.delete.ts\\` | DELETE | \\`/api/threads/:threadId/name\\` |\n| \\`index.ts\\` | GET | \\`/api/threads/:threadId\\` |\n| \\`nested/route.ts\\` | GET | \\`/api/threads/:threadId/nested/route\\` |\n| \\`items/[id].ts\\` | GET | \\`/api/threads/:threadId/items/:id\\` |\n| \\`files/[*].ts\\` | GET | \\`/api/threads/:threadId/files/*\\` |\n\nFiles without a method suffix default to GET. Method suffixes are case-insensitive and support \\`.get.ts\\`, \\`.post.ts\\`, \\`.put.ts\\`, \\`.patch.ts\\`, and \\`.delete.ts\\`.\n\nDynamic segments use \\`[name]\\` and are passed to the handler as \\`params.name\\`. Catch-all segments use \\`[*]\\` and are passed as \\`params['*']\\`; the catch-all value may contain \\`/\\` for nested paths. Static routes match before dynamic routes, and dynamic routes match before catch-all routes.\n\n## Basic Example\n\n\\`\\`\\`typescript\n// agents/api/status.get.ts -> GET /api/threads/:threadId/status\nimport { defineThreadEndpoint } from '@standardagents/spec';\n\nexport default defineThreadEndpoint(async (req, state, params) => {\n const { messages, total } = await state.getMessages();\n return Response.json({\n threadId: state.threadId,\n messageCount: total,\n status: 'active',\n params,\n });\n});\n\\`\\`\\`\n\n## Handler Parameters\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| \\`req\\` | \\`Request\\` | The incoming HTTP request |\n| \\`state\\` | \\`ThreadState\\` | Thread state with messages, identity, \\`arguments\\`, file system, \\`runCode\\`, etc. |\n| \\`params\\` | \\`Record<string, string>\\` | Route parameters captured from \\`[name]\\` and \\`[*]\\` path segments |\n\nNote: \\`state.execution\\` is always \\`null\\` in endpoints since the thread is at rest. \\`state.runCode()\\` is available from endpoints and is forwarded into the thread runtime; pass plain transferable option values there, and do function-backed sandbox bridges from tools or in-thread execution contexts.\n\n## ThreadState Methods\n\nAccess thread data through the state object:\n\n\\`\\`\\`typescript\nimport { defineThreadEndpoint } from '@standardagents/spec';\n\nexport default defineThreadEndpoint(async (req, state) => {\n // Thread identity\n console.log('Thread ID:', state.threadId);\n console.log('Agent ID:', state.agentId);\n console.log('User ID:', state.userId);\n console.log('Arguments:', state.arguments);\n\n // Message operations\n const { messages, total, hasMore } = await state.getMessages({\n limit: 100,\n offset: 0,\n order: 'desc',\n });\n\n // Thread env (thread scope + active descendants)\n const approvalGate = await state.env('TOPDOWN_APPROVAL_GATE');\n await state.setEnv('TOPDOWN_APPROVAL_GATE', approvalGate || 'open');\n\n // Durable per-thread JSON values\n const exports = (await state.getValue<number>('export_count')) ?? 0;\n await state.setValue('export_count', exports + 1);\n\n // File system operations\n const files = await state.findFiles('**/*.json');\n const data = await state.readFile('/data/config.json');\n\n // Resource loading\n const agent = await state.loadAgent('my-agent');\n const prompt = await state.loadPrompt('my-prompt');\n\n return Response.json({ messages, total });\n});\n\\`\\`\\`\n\n## POST with Request Body\n\n\\`\\`\\`typescript\n// agents/api/export.post.ts -> POST /api/threads/:threadId/export\nimport { defineThreadEndpoint } from '@standardagents/spec';\n\nexport default defineThreadEndpoint(async (req, state) => {\n const body = await req.json();\n const { format = 'json' } = body;\n\n const { messages } = await state.getMessages();\n\n if (format === 'csv') {\n const csv = messages.map(m => \\`\\${m.role},\\${m.content}\\`).join('\\\\n');\n return new Response(csv, {\n headers: { 'Content-Type': 'text/csv' },\n });\n }\n\n return Response.json(messages);\n});\n\\`\\`\\`\n\n## Nested Routes\n\nCreate directories for nested routes:\n\n\\`\\`\\`\nagents/api/\n├── status.get.ts -> GET /api/threads/:threadId/status\n├── export.post.ts -> POST /api/threads/:threadId/export\n└── messages/\n ├── count.ts -> GET /api/threads/:threadId/messages/count\n ├── [id].ts -> GET /api/threads/:threadId/messages/:id\n └── [*].ts -> GET /api/threads/:threadId/messages/*\n\\`\\`\\`\n\n## Error Handling\n\n\\`\\`\\`typescript\nimport { defineThreadEndpoint } from '@standardagents/spec';\n\nexport default defineThreadEndpoint(async (req, state) => {\n try {\n const data = await riskyOperation();\n return Response.json(data);\n } catch (error) {\n return Response.json({ error: error.message }, { status: 500 });\n }\n});\n\\`\\`\\`\n\n## File System Operations\n\n\\`\\`\\`typescript\nimport { defineThreadEndpoint } from '@standardagents/spec';\n\nexport default defineThreadEndpoint(async (req, state) => {\n // Read files\n const content = await state.readFile('/data/file.txt');\n\n // Write files\n await state.writeFile('/output/result.json', JSON.stringify(data), 'application/json');\n\n // List directory\n const { entries } = await state.readdirFile('/data');\n\n // Move or rename files and directories (does not overwrite an existing destination)\n await state.moveFile('/data/file.txt', '/archive/file.txt');\n await state.renameFile('/output/result.json', 'final.json');\n\n // Search files\n const matches = await state.grepFiles('pattern');\n const paths = await state.findFiles('**/*.ts');\n\n return Response.json({ success: true });\n});\n\\`\\`\\`\n\n## Best Practices\n\n- **Keep handlers fast** - endpoints are in the request path\n- **Paginate large queries** - use limit/offset for messages\n- **Validate input data** - check request body before processing\n- **Use descriptive file names** - \\`export.post.ts\\` not \\`ep1.ts\\`\n- **Return proper status codes** - 200, 400, 404, 500\n- **Import from spec** - use \\`@standardagents/spec\\` for \\`defineThreadEndpoint\\`\n\n## Documentation\n\nFull reference: https://docs.standardagentbuilder.com/core-concepts/api\n`;\n\nexport const API_CLAUDE_MD = API_AGENTS_MD;\n","import {\n AGENT_DEFINITIONS_AGENTS_MD,\n API_AGENTS_MD,\n HOOKS_AGENTS_MD,\n MODELS_AGENTS_MD,\n PROMPTS_AGENTS_MD,\n ROOT_AGENTS_MD,\n TOOLS_AGENTS_MD,\n} from './docs/index.js'\n\nexport {\n AGENT_DEFINITIONS_AGENTS_MD,\n AGENT_DEFINITIONS_AGENTS_MD as AGENTS_CLAUDE_MD,\n API_AGENTS_MD,\n API_AGENTS_MD as API_CLAUDE_MD,\n HOOKS_AGENTS_MD,\n HOOKS_AGENTS_MD as HOOKS_CLAUDE_MD,\n MODELS_AGENTS_MD,\n MODELS_AGENTS_MD as MODELS_CLAUDE_MD,\n PROMPTS_AGENTS_MD,\n PROMPTS_AGENTS_MD as PROMPTS_CLAUDE_MD,\n ROOT_AGENTS_MD,\n ROOT_AGENTS_MD as ROOT_CLAUDE_MD,\n TOOLS_AGENTS_MD,\n TOOLS_AGENTS_MD as TOOLS_CLAUDE_MD,\n}\n\nexport type PackageManager = 'pnpm' | 'npm' | 'yarn' | 'bun'\n\nexport interface TemplateFile {\n path: string\n content: string\n message: string\n kind?: 'file' | 'symlink'\n}\n\nexport interface TemplateVersions {\n standardAgents: string\n sip: string\n vite: string\n typescript: string\n zod?: string\n}\n\nexport interface AgentBuilderProjectTemplateOptions {\n projectName: string\n packageManager?: PackageManager | null\n versions?: Partial<TemplateVersions>\n includeTemplateMetadata?: boolean\n templateVersion?: string\n /**\n * Include a working `vite build` script in the rendered package manifest.\n * Only the platform build runner should set this. Local manifests get a\n * guard script instead, because customer projects build and deploy on the\n * Standard Agents platform after a git push — never on the user's machine.\n */\n includeBuildScript?: boolean\n}\n\nexport const FIRST_PARTY_PROVIDER_PACKAGES = [\n '@standardagents/anthropic',\n '@standardagents/cloudflare',\n '@standardagents/cerebras',\n '@standardagents/google',\n '@standardagents/groq',\n '@standardagents/openai',\n '@standardagents/openrouter',\n '@standardagents/xai',\n] as const\n\n/**\n * Dependency packages whose install scripts the generated project approves.\n * pnpm 10 blocks dependency build scripts by default and, under CI (the\n * platform build runner sets CI=true), fails the install outright with\n * ERR_PNPM_IGNORED_BUILDS. These are the script-running packages in the\n * default dependency tree (native binaries and codegen) that the project\n * needs for installs and builds to work.\n */\nexport const APPROVED_DEPENDENCY_BUILD_SCRIPTS = [\n '@google/genai',\n '@openrouter/sdk',\n 'esbuild',\n 'protobufjs',\n 'sharp',\n 'workerd',\n] as const\n\n// Pin first-party @standardagents/* packages to a controlled major range\n// rather than \"latest\". Floating on \"latest\" let the installed builder drift\n// out of sync with the generated provider list (e.g. builder shipped the\n// anthropic provider while a stale template omitted it), breaking the build.\n// Caret on a 0.x version accepts patch releases automatically but holds the\n// minor, so only an intentional \"major\" bump of these packages re-challenges\n// the pin. Bump these together when the platform adopts a new release line.\nexport const DEFAULT_TEMPLATE_VERSIONS: TemplateVersions = {\n standardAgents: '^0.21.0',\n sip: '^1.0.1',\n vite: 'latest',\n typescript: 'latest',\n zod: 'latest',\n}\n\nexport const AGENTBUILDER_TEMPLATE_VERSION = '0.21.1'\n\nfunction ensureTrailingNewline(value: string): string {\n return value.endsWith('\\n') ? value : `${value}\\n`\n}\n\nfunction mergeVersions(versions?: Partial<TemplateVersions>): TemplateVersions {\n return {\n ...DEFAULT_TEMPLATE_VERSIONS,\n ...versions,\n }\n}\n\nexport function packageNameFromProjectName(projectName: string): string {\n const normalized = projectName\n .toLowerCase()\n .replace(/^@[^/]+\\//, '')\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n return normalized || 'agentbuilder-project'\n}\n\nfunction file(path: string, content: string, message: string): TemplateFile {\n return {\n path,\n content: ensureTrailingNewline(content),\n message,\n kind: 'file',\n }\n}\n\nfunction symlink(path: string, target: string, message: string): TemplateFile {\n return {\n path,\n content: target,\n message,\n kind: 'symlink',\n }\n}\n\nexport function renderPackageJson(options: AgentBuilderProjectTemplateOptions): string {\n const versions = mergeVersions(options.versions)\n const standardAgentsVersion = versions.standardAgents\n const dependencies: Record<string, string> = {\n '@standardagents/builder': standardAgentsVersion,\n '@standardagents/spec': standardAgentsVersion,\n '@standardagents/sip': versions.sip,\n zod: versions.zod ?? 'latest',\n }\n\n for (const providerPackage of FIRST_PARTY_PROVIDER_PACKAGES) {\n dependencies[providerPackage] = standardAgentsVersion\n }\n\n return `${JSON.stringify({\n name: packageNameFromProjectName(options.projectName),\n version: '0.0.0',\n private: true,\n type: 'module',\n scripts: {\n dev: 'vite --host 0.0.0.0 --port 5173',\n build: options.includeBuildScript\n ? 'vite build'\n : \"echo 'Standard Agents projects build and deploy on the platform. Push your commit (git push or agents deploy) to trigger a build.' && exit 1\",\n typecheck: 'tsc --noEmit',\n },\n dependencies,\n devDependencies: {\n typescript: versions.typescript,\n vite: versions.vite,\n },\n pnpm: {\n onlyBuiltDependencies: [...APPROVED_DEPENDENCY_BUILD_SCRIPTS],\n },\n }, null, 2)}\\n`\n}\n\nexport function renderViteConfig(): string {\n return `import { defineConfig } from \"vite\"\nimport { builder } from \"@standardagents/builder\"\n\nexport default defineConfig({\n plugins: [builder()],\n})\n`\n}\n\nexport function renderTsConfig(): string {\n return `{\n \"compilerOptions\": {\n \"target\": \"ES2022\",\n \"useDefineForClassFields\": true,\n \"module\": \"ESNext\",\n \"lib\": [\"ES2022\", \"DOM\", \"DOM.Iterable\"],\n \"skipLibCheck\": true,\n \"moduleResolution\": \"Bundler\",\n \"allowImportingTsExtensions\": true,\n \"resolveJsonModule\": true,\n \"isolatedModules\": true,\n \"noEmit\": true,\n \"strict\": true\n },\n \"include\": [\"agents\", \".agents\", \"vite.config.ts\"]\n}\n`\n}\n\nexport function renderGitignore(): string {\n // package.json AND the lockfile are committed: the project owns its\n // @standardagents/* versions and the platform build installs them frozen for\n // byte-exact, reproducible deploys (the build runner uses whichever package\n // manager the committed lockfile implies). Only secrets, dependencies, and\n // local build/dev state are ignored.\n return `node_modules\ndist\n.agents\n.wrangler\n.env\n.dev.vars\n.agentbuilder-dev.log\n`\n}\n\nexport function renderDevVarsExample(): string {\n return `# Standard Agents local development environment\n# Copy to .dev.vars for local-only Worker secrets.\n\n# Local data encryption key. Generate with: openssl rand -hex 32\nENCRYPTION_KEY=\n\n# Optional local admin password for development access.\nSUPER_ADMIN_PASSWORD=password\n\n# Platform connection. The CLI writes real values to .dev.vars for platform-created projects.\nSTANDARD_AGENTS_API_KEY=\nPLATFORM_ENDPOINT=\nSTANDARD_AGENTS_API_URL=\n\n# BYOK provider keys. When set, these keys override Standard Agents hosted routing for that provider.\nCLOUDFLARE_API_TOKEN=\nCLOUDFLARE_ACCOUNT_ID=\nCEREBRAS_API_KEY=\nGOOGLE_API_KEY=\nGROQ_API_KEY=\nOPENAI_API_KEY=\nOPENROUTER_API_KEY=\nANTHROPIC_API_KEY=\nXAI_API_KEY=\n`\n}\n\nexport function renderTemplateMetadata(options: AgentBuilderProjectTemplateOptions): string {\n return `${JSON.stringify({\n generator: '@standardagents/agentbuilder-template',\n template_version: options.templateVersion ?? AGENTBUILDER_TEMPLATE_VERSION,\n project_name: options.projectName,\n }, null, 2)}\\n`\n}\n\nexport function renderAgentBuilderSupportFiles(options: AgentBuilderProjectTemplateOptions): TemplateFile[] {\n return [\n file('package.json', renderPackageJson(options), 'Add local AgentBuilder package manifest'),\n ]\n}\n\nexport function renderAgentBuilderProject(options: AgentBuilderProjectTemplateOptions): TemplateFile[] {\n const files: TemplateFile[] = [\n // The project owns its @standardagents/* versions: the committed manifest is\n // the source of truth the platform build honors (what you test locally is\n // what deploys). It ships a guard `build` script that refuses to build\n // off-platform; the build runner swaps in the real `vite build` at build\n // time. Never set includeBuildScript here — a working local build would let\n // a half-configured checkout deploy from the wrong place.\n file('package.json', renderPackageJson({ ...options, includeBuildScript: false }), 'Add package manifest'),\n // Committed alongside package.json so a freshly cloned repo ignores\n // node_modules, lockfiles, secrets, and local build state without depending\n // on the CLI to generate a .gitignore after clone.\n file('.gitignore', renderGitignore(), 'Add gitignore'),\n file('tsconfig.json', renderTsConfig(), 'Add TypeScript config'),\n file('vite.config.ts', renderViteConfig(), 'Add Vite config'),\n file('agents/agents/AGENTS.md', AGENT_DEFINITIONS_AGENTS_MD, 'Add agent docs'),\n symlink('agents/agents/CLAUDE.md', 'AGENTS.md', 'Add Claude agent docs symlink'),\n file('agents/prompts/AGENTS.md', PROMPTS_AGENTS_MD, 'Add prompt docs'),\n symlink('agents/prompts/CLAUDE.md', 'AGENTS.md', 'Add Claude prompt docs symlink'),\n file('agents/models/AGENTS.md', MODELS_AGENTS_MD, 'Add model docs'),\n symlink('agents/models/CLAUDE.md', 'AGENTS.md', 'Add Claude model docs symlink'),\n file('agents/tools/AGENTS.md', TOOLS_AGENTS_MD, 'Add tool docs'),\n symlink('agents/tools/CLAUDE.md', 'AGENTS.md', 'Add Claude tool docs symlink'),\n file('agents/hooks/AGENTS.md', HOOKS_AGENTS_MD, 'Add hook docs'),\n symlink('agents/hooks/CLAUDE.md', 'AGENTS.md', 'Add Claude hook docs symlink'),\n file('agents/api/AGENTS.md', API_AGENTS_MD, 'Add API docs'),\n symlink('agents/api/CLAUDE.md', 'AGENTS.md', 'Add Claude API docs symlink'),\n ]\n\n if (options.includeTemplateMetadata) {\n files.push(file('.standardagents/template.json', renderTemplateMetadata(options), 'Add Standard Agents template metadata'))\n }\n\n return files\n}\n"],"mappings":";AAAO,IAAM,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAvB,IAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAzB,IAAM,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACA1B,IAAM,8BAA8B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACApC,IAAM,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAxB,IAAM,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAxB,IAAM,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;AC2DtB,IAAM,gCAAgC;AAAA,EAC3C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAUO,IAAM,oCAAoC;AAAA,EAC/C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AASO,IAAM,4BAA8C;AAAA,EACzD,gBAAgB;AAAA,EAChB,KAAK;AAAA,EACL,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,KAAK;AACP;AAEO,IAAM,gCAAgC;AAE7C,SAAS,sBAAsB,OAAuB;AACpD,SAAO,MAAM,SAAS,IAAI,IAAI,QAAQ,GAAG,KAAK;AAAA;AAChD;AAEA,SAAS,cAAc,UAAwD;AAC7E,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAG;AAAA,EACL;AACF;AAEO,SAAS,2BAA2B,aAA6B;AACtE,QAAM,aAAa,YAChB,YAAY,EACZ,QAAQ,aAAa,EAAE,EACvB,QAAQ,eAAe,GAAG,EAC1B,QAAQ,YAAY,EAAE;AACzB,SAAO,cAAc;AACvB;AAEA,SAAS,KAAK,MAAc,SAAiB,SAA+B;AAC1E,SAAO;AAAA,IACL;AAAA,IACA,SAAS,sBAAsB,OAAO;AAAA,IACtC;AAAA,IACA,MAAM;AAAA,EACR;AACF;AAEA,SAAS,QAAQ,MAAc,QAAgB,SAA+B;AAC5E,SAAO;AAAA,IACL;AAAA,IACA,SAAS;AAAA,IACT;AAAA,IACA,MAAM;AAAA,EACR;AACF;AAEO,SAAS,kBAAkB,SAAqD;AACrF,QAAM,WAAW,cAAc,QAAQ,QAAQ;AAC/C,QAAM,wBAAwB,SAAS;AACvC,QAAM,eAAuC;AAAA,IAC3C,2BAA2B;AAAA,IAC3B,wBAAwB;AAAA,IACxB,uBAAuB,SAAS;AAAA,IAChC,KAAK,SAAS,OAAO;AAAA,EACvB;AAEA,aAAW,mBAAmB,+BAA+B;AAC3D,iBAAa,eAAe,IAAI;AAAA,EAClC;AAEA,SAAO,GAAG,KAAK,UAAU;AAAA,IACvB,MAAM,2BAA2B,QAAQ,WAAW;AAAA,IACpD,SAAS;AAAA,IACT,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,MACP,KAAK;AAAA,MACL,OAAO,QAAQ,qBACX,eACA;AAAA,MACJ,WAAW;AAAA,IACb;AAAA,IACA;AAAA,IACA,iBAAiB;AAAA,MACf,YAAY,SAAS;AAAA,MACrB,MAAM,SAAS;AAAA,IACjB;AAAA,IACA,MAAM;AAAA,MACJ,uBAAuB,CAAC,GAAG,iCAAiC;AAAA,IAC9D;AAAA,EACF,GAAG,MAAM,CAAC,CAAC;AAAA;AACb;AAEO,SAAS,mBAA2B;AACzC,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAOT;AAEO,SAAS,iBAAyB;AACvC,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiBT;AAEO,SAAS,kBAA0B;AAMxC,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQT;AAEO,SAAS,uBAA+B;AAC7C,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAyBT;AAEO,SAAS,uBAAuB,SAAqD;AAC1F,SAAO,GAAG,KAAK,UAAU;AAAA,IACvB,WAAW;AAAA,IACX,kBAAkB,QAAQ,mBAAmB;AAAA,IAC7C,cAAc,QAAQ;AAAA,EACxB,GAAG,MAAM,CAAC,CAAC;AAAA;AACb;AAEO,SAAS,+BAA+B,SAA6D;AAC1G,SAAO;AAAA,IACL,KAAK,gBAAgB,kBAAkB,OAAO,GAAG,yCAAyC;AAAA,EAC5F;AACF;AAEO,SAAS,0BAA0B,SAA6D;AACrG,QAAM,QAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAO5B,KAAK,gBAAgB,kBAAkB,EAAE,GAAG,SAAS,oBAAoB,MAAM,CAAC,GAAG,sBAAsB;AAAA;AAAA;AAAA;AAAA,IAIzG,KAAK,cAAc,gBAAgB,GAAG,eAAe;AAAA,IACrD,KAAK,iBAAiB,eAAe,GAAG,uBAAuB;AAAA,IAC/D,KAAK,kBAAkB,iBAAiB,GAAG,iBAAiB;AAAA,IAC5D,KAAK,2BAA2B,6BAA6B,gBAAgB;AAAA,IAC7E,QAAQ,2BAA2B,aAAa,+BAA+B;AAAA,IAC/E,KAAK,4BAA4B,mBAAmB,iBAAiB;AAAA,IACrE,QAAQ,4BAA4B,aAAa,gCAAgC;AAAA,IACjF,KAAK,2BAA2B,kBAAkB,gBAAgB;AAAA,IAClE,QAAQ,2BAA2B,aAAa,+BAA+B;AAAA,IAC/E,KAAK,0BAA0B,iBAAiB,eAAe;AAAA,IAC/D,QAAQ,0BAA0B,aAAa,8BAA8B;AAAA,IAC7E,KAAK,0BAA0B,iBAAiB,eAAe;AAAA,IAC/D,QAAQ,0BAA0B,aAAa,8BAA8B;AAAA,IAC7E,KAAK,wBAAwB,eAAe,cAAc;AAAA,IAC1D,QAAQ,wBAAwB,aAAa,6BAA6B;AAAA,EAC5E;AAEA,MAAI,QAAQ,yBAAyB;AACnC,UAAM,KAAK,KAAK,iCAAiC,uBAAuB,OAAO,GAAG,uCAAuC,CAAC;AAAA,EAC5H;AAEA,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../src/docs/root.ts","../src/docs/models.ts","../src/docs/providers.ts","../src/docs/prompts.ts","../src/docs/agents.ts","../src/docs/tools.ts","../src/docs/hooks.ts","../src/docs/api.ts","../src/index.ts"],"sourcesContent":["export const ROOT_AGENTS_MD = `# Standard Agents\n\nThis project uses Standard Agents - a framework for building AI agents on Cloudflare Workers.\n\n## Architecture Overview\n\nStandard Agents uses a **composition model** where four core components work together:\n\n\\`\\`\\`\nModel → Prompt → Agent → Thread\n │ │ │ │\n │ │ │ └─ Conversation instance (Durable Object)\n │ │ └─ Orchestrates conversation flow\n │ └─ System instructions + tools\n └─ LLM provider configuration\n\\`\\`\\`\n\n**Models** define which LLM to use (provider, model ID, pricing, fallbacks).\n**Prompts** define what the LLM should do (system instructions, available tools).\n**Agents** orchestrate conversations (which prompt, stop conditions, turn limits).\n**Threads** are individual conversation instances with persistent storage.\n\n## How Components Compose\n\n### Basic Flow\n1. User creates a thread with an agent\n2. Agent uses its configured prompt\n3. Prompt specifies the model and tools\n4. LLM responds, potentially calling tools\n5. Tools execute and return results\n6. Loop continues until stop condition\n\n### Sub-Prompts (Prompts as Tools)\nPrompts can call other prompts as tools. This enables:\n- **Specialized reasoning**: A main prompt delegates to expert sub-prompts\n- **Structured outputs**: Sub-prompt validates and formats data\n- **Context isolation**: Sub-prompt gets fresh context without full history\n\n\\`\\`\\`typescript\n// Main prompt can call 'data_extractor' as a tool\ndefinePrompt({\n name: 'main_assistant',\n tools: ['data_extractor'], // Another prompt exposed as tool\n // ...\n});\n\\`\\`\\`\n\n### Agent Handoffs (Agents as Tools)\nAgents can delegate to other agents entirely:\n- **Specialization**: Route to domain-specific agents\n- **Escalation**: Hand off to more capable agents\n- **Workflows**: Chain agents for multi-step processes\n\n\\`\\`\\`typescript\ndefineAgent({\n name: 'triage_agent',\n exposeAsTool: true,\n toolDescription: 'Hand off to triage for initial assessment',\n // ...\n});\n\\`\\`\\`\n\n## File Structure\n\n\\`\\`\\`\nAGENTS.md # Project guidance for AI coding tools\nCLAUDE.md -> AGENTS.md # Compatibility symlink\nvite.config.ts # Uses builder(); Cloudflare config is generated\ntsconfig.json # Includes agents and generated .agents types\nagents/\n├── agents/ # Agent definitions (defineAgent)\n│ ├── AGENTS.md\n│ └── CLAUDE.md -> AGENTS.md\n├── prompts/ # Prompt definitions (definePrompt)\n│ ├── AGENTS.md\n│ └── CLAUDE.md -> AGENTS.md\n├── models/ # Model configurations (defineModel)\n│ ├── AGENTS.md\n│ └── CLAUDE.md -> AGENTS.md\n├── providers/ # Provider definitions (defineProvider)\n│ ├── AGENTS.md\n│ └── CLAUDE.md -> AGENTS.md\n├── tools/ # Custom tools (defineTool)\n│ ├── AGENTS.md\n│ └── CLAUDE.md -> AGENTS.md\n├── hooks/ # Lifecycle hooks (defineHook)\n│ ├── AGENTS.md\n│ └── CLAUDE.md -> AGENTS.md\n└── api/ # Thread API endpoints (defineThreadEndpoint)\n ├── AGENTS.md\n └── CLAUDE.md -> AGENTS.md\n\\`\\`\\`\n\nThe \\`builder()\\` Vite plugin generates the Worker entry, Durable Object bindings, Cloudflare Vite plugin configuration, and local \\`.agents/\\` support files at build time. Agent files are **auto-discovered** at runtime. No manual registration needed.\n\n## ThreadState\n\n\\`ThreadState\\` is the state object available in tools and hooks:\n\n\\`\\`\\`typescript\ninterface ThreadState {\n // Identity (readonly)\n threadId: string; // Thread identifier\n agentId: string; // Agent identifier\n userId: string | null; // User identifier (if set)\n createdAt: number; // Creation timestamp\n children: SubagentRegistryEntry[]; // Resumable child registry\n terminated: number | null; // Soft-termination timestamp\n arguments: Record<string, unknown>; // Invocation or subagent creation args\n context: Record<string, unknown>; // Current-execution scratch data\n\n // Methods\n getMessages(options?): Promise<MessagesResult>; // Get conversation history\n injectMessage(input): Promise<Message>; // Add message to thread\n queueMessage(input): Promise<void>; // Queue message for next step\n loadModel(name): Promise<ModelConfig>; // Load model definition\n loadPrompt(name): Promise<PromptConfig>; // Load prompt definition\n loadAgent(name): Promise<AgentConfig>; // Load agent definition\n env(propertyName): Promise<string>; // Resolve env value for this thread\n setEnv(propertyName, value): Promise<void>; // Set thread env + propagate to active descendants\n getValue<T = unknown>(key: string): Promise<T | null>; // Read durable per-thread JSON value\n setValue(key: string, value: unknown): Promise<void>; // Write durable value; null/undefined deletes\n notifyParent(content): Promise<void>; // Queue a silent message to the parent when one exists\n setStatus(status): Promise<void>; // Update this child in the parent registry; no-op without a parent\n stopSession(options?): Promise<void>; // Terminally stop the current agent session\n getChildThread(referenceId): Promise<ThreadState | null>; // Resolve child thread\n getParentThread(): Promise<ThreadState | null>; // Resolve parent thread\n terminate(): Promise<void>; // Soft-terminate thread\n runCode(source, options?): CodeExecution; // Run JS/TS in a fresh Dynamic Worker sandbox\n}\n\\`\\`\\`\n\n\\`state.arguments\\` is read-only thread invocation data. Resumable \\`subagent_create.arguments\\` persists with the child thread, is visible to both child sides, and is also available as prompt variables. Use \\`state.context\\` only for mutable scratch data during the current execution; it is not durable storage.\n\n\\`runCode\\` has no implicit access to thread state, filesystem, network, timers, or host globals. Bridge only the exact capabilities needed through \\`imports\\` or \\`globals\\`; use \\`modules\\` for local relative ES modules; use \\`execute\\` to select the export and args to run. \\`modules\\` keys are graph-root relative paths; entry-source imports resolve from \\`filename\\` when supplied, including \\`../\\` parent paths that stay inside the supplied graph. TypeScript input is accepted by default and erased before evaluation. In thread endpoints, \\`runCode\\` is forwarded into the thread Durable Object; pass plain transferable options there and keep function-backed bridges in tools or in-thread execution contexts.\n\n## Subagents\n\n\\`dual_ai\\` agents can be used as subagents from prompt tool configs:\n\n- Each subagent runs in its own thread (\\`DurableThread\\`)\n- Parent/child linkage is tracked in thread metadata\n- Resumable children are visible in \\`state.children\\`\n- Parent threads create/message resumable children via built-ins (\\`subagent_create\\`, \\`subagent_message\\`)\n- \\`subagent_create.arguments\\` is validated from the receiving child side's prompt schema and persists as \\`ThreadState.arguments\\` plus prompt variables for the life of the child thread\n- Child completion results are queued back to the parent when \\`parentCommunication\\` is \\`implicit\\`\n- Explicit relationships can stay idle until code calls \\`state.notifyParent()\\` or \\`state.setStatus()\\`; use \\`state.stopSession({ result, notifyParent, status })\\` when a tool should also terminally end the child session\n\nAccess in tools:\n\\`\\`\\`typescript\nexport default defineTool('...', schema, async (state, args) => {\n const threadId = state.threadId;\n const creationArgs = state.arguments;\n const { messages } = await state.getMessages();\n const count = (await state.getValue<number>('invocation_count')) ?? 0;\n await state.setValue('invocation_count', count + 1);\n // ...\n});\n\\`\\`\\`\n\nAccess in hooks:\n\\`\\`\\`typescript\nexport default defineHook({\n hook: 'before_create_message',\n id: 'my_hook',\n execute: async (state, message) => {\n console.log(\\`Thread: \\${state.threadId}, Agent: \\${state.agentId}\\`);\n return message;\n }\n});\n\\`\\`\\`\n\n## Quick Reference\n\n| Function | Purpose | Directory |\n|----------|---------|-----------|\n| \\`defineModel()\\` | Configure LLM provider | \\`agents/models/\\` |\n| \\`defineProvider()\\` | Custom provider endpoints and overrides | \\`agents/providers/\\` |\n| \\`definePrompt()\\` | System instructions + tools | \\`agents/prompts/\\` |\n| \\`defineAgent()\\` | Conversation orchestration | \\`agents/agents/\\` |\n| \\`defineTool()\\` | Custom tool functions | \\`agents/tools/\\` |\n| \\`defineHook()\\` | Lifecycle interception | \\`agents/hooks/\\` |\n| \\`defineThreadEndpoint()\\` | Custom API routes | \\`agents/api/\\` |\n\n## Runtime Utilities\n\nImport from \\`@standardagents/builder\\`:\n\n\\`\\`\\`typescript\nimport {\n queueTool, // Queue another tool for execution\n injectMessage, // Add message without triggering execution\n getMessages, // Retrieve message history\n emitThreadEvent, // Send custom WebSocket events\n} from '@standardagents/builder';\n\\`\\`\\`\n\n## Documentation\n\nFull documentation: https://docs.standardagentbuilder.com\n\n- [Architecture Overview](https://docs.standardagentbuilder.com/introduction/architecture)\n- [Models](https://docs.standardagentbuilder.com/core-concepts/models)\n- [Prompts](https://docs.standardagentbuilder.com/core-concepts/prompts)\n- [Agents](https://docs.standardagentbuilder.com/core-concepts/agents)\n- [Tools](https://docs.standardagentbuilder.com/core-concepts/tools)\n- [Hooks](https://docs.standardagentbuilder.com/core-concepts/hooks)\n- [ThreadState](https://docs.standardagentbuilder.com/core-concepts/flowstate)\n- [Thread API](https://docs.standardagentbuilder.com/core-concepts/api)\n`;\n\nexport const ROOT_CLAUDE_MD = ROOT_AGENTS_MD;\n","export const MODELS_AGENTS_MD = `# Model Definitions\n\nModels define which LLM provider and model to use for prompts.\n\n## Properties\n\n| Property | Type | Required | Description |\n|----------|------|----------|-------------|\n| \\`name\\` | \\`string\\` | Yes | Unique identifier for this model configuration |\n| \\`provider\\` | \\`ProviderFactory\\` | Yes | Imported provider factory such as \\`openrouter\\`, \\`openai\\`, or a local provider from \\`agents/providers\\` |\n| \\`model\\` | \\`string\\` | Yes | Model ID sent to provider API |\n| \\`fallbacks\\` | \\`string[]\\` | No | Fallback model names to try if primary fails |\n| \\`inputPrice\\` | \\`number\\` | No | Cost per 1M input tokens (USD) |\n| \\`outputPrice\\` | \\`number\\` | No | Cost per 1M output tokens (USD) |\n| \\`cachedPrice\\` | \\`number\\` | No | Cost per 1M cached input tokens |\n| \\`includedProviders\\` | \\`string[]\\` | No | Provider prefixes for OpenRouter routing |\n| \\`providerTools\\` | \\`string[]\\` | No | Provider-built-in tool names to make available for prompts using this model |\n\n## Example\n\n\\`\\`\\`typescript\nimport { defineModel } from '@standardagents/builder';\nimport { openrouter } from '@standardagents/openrouter';\n\nexport default defineModel({\n name: 'default',\n provider: openrouter,\n model: 'google/gemini-3-flash-preview',\n fallbacks: ['fast', 'cheap-heavy'],\n});\n\\`\\`\\`\n\n## Provider Tools\n\nProviders can expose built-in tools such as search, file search, code execution,\nor provider-specific tools through their \\`getTools()\\` implementation. Enable the\nprovider tool names on the model with \\`providerTools\\`; prompts can then include\nthose tools like normal tool names. Provider tools execute on the upstream\nprovider, not in AgentBuilder, and successful calls are logged as provider tool\nentries.\n\nOpenRouter exposes \\`web_search\\`, \\`web_fetch\\`, \\`datetime\\`, and \\`image_generation\\`\nas provider-executed server tools. Configure optional OpenRouter parameters with\n\\`providerOptions.serverTools\\` on the model.\n\n## Recommended Models (OpenRouter)\n\n| Use Case | Model ID | Description |\n|----------|----------|-------------|\n| Fast/Cheap | \\`z-ai/glm-4.5-air\\` | Quick responses, low cost |\n| Mid-tier | \\`google/gemini-3-flash-preview\\` | Good balance of speed and quality |\n| Cheap Heavy | \\`nvidia/nemotron-3-ultra-550b-a55b\\` | Frontier open reasoning and orchestration, still affordable |\n| Heavy | \\`google/gemini-3-pro-preview\\` | Most capable, for complex tasks |\n\n**⚠️ Google Models**: When using Google models (\\`google/gemini-*\\`), you must enable \\`reasoning\\` in your prompt configuration or tool calls will fail. See the prompts AGENTS.md for details.\n\n## Provider API Keys\n\nSet these environment variables in \\`.dev.vars\\` (local) or Cloudflare secrets (production):\n\n| Provider | Environment Variable |\n|----------|---------------------|\n| Cloudflare Workers AI | \\`CLOUDFLARE_API_TOKEN\\` + \\`CLOUDFLARE_ACCOUNT_ID\\` |\n| Cerebras | \\`CEREBRAS_API_KEY\\` |\n| Groq | \\`GROQ_API_KEY\\` |\n| OpenAI | \\`OPENAI_API_KEY\\` |\n| Anthropic | \\`ANTHROPIC_API_KEY\\` |\n| OpenRouter | \\`OPENROUTER_API_KEY\\` |\n| Baseten Model APIs | \\`BASETEN_API_KEY\\` |\n| Google | \\`GOOGLE_API_KEY\\` |\n| xAI | \\`XAI_API_KEY\\` |\n\nIf \\`STANDARD_AGENTS_API_KEY\\` is present and a provider-specific key is not set,\nfirst-party Standard Agents providers route through the hosted Standard Agents\nrouter. Setting a provider-specific key always uses that provider directly.\n\n## User-Defined Providers\n\nCreate \\`agents/providers/<name>.ts\\` when a provider is compatible with an existing\nprovider package but needs its own API key, endpoint, icon, model list, pricing, or\nother provider behavior.\n\n\\`\\`\\`typescript\n// agents/providers/darkbloom.ts\nimport { defineProvider, providerEnv } from '@standardagents/builder';\nimport { openai } from '@standardagents/openai';\n\nexport default defineProvider({\n name: 'darkbloom',\n label: 'Darkbloom',\n baseProvider: openai,\n config: {\n apiKey: providerEnv('DARKBLOOM_API_KEY', { valueType: 'secret' }),\n baseUrl: providerEnv('DARKBLOOM_BASE_URL', {\n valueType: 'url',\n default: 'https://api.darkbloom.dev/v1',\n }),\n },\n});\n\\`\\`\\`\n\n\\`\\`\\`typescript\n// agents/models/darkbloom_chat.ts\nimport { defineModel } from '@standardagents/builder';\nimport darkbloom from '../providers/darkbloom';\n\nexport default defineModel({\n name: 'darkbloom_chat',\n provider: darkbloom,\n model: 'darkbloom-chat',\n});\n\\`\\`\\`\n\nProvider \\`overrides\\` can replace behavior such as \\`getModels\\`, \\`getIcon\\`,\n\\`getTools\\`, pricing/capability lookup, \\`generate\\`, or \\`stream\\`. Call \\`next()\\`\ninside an override to compose with the base provider; return your own value to\nreplace it.\n\n## Fallback Strategy\n\nWhen a model fails, fallbacks are tried in order:\n1. Primary model (2 attempts)\n2. First fallback (2 attempts)\n3. Second fallback (2 attempts)\n4. ...and so on\n\nRetries occur on: network errors, rate limits (429), server errors (5xx), auth errors (401).\n\n## OpenRouter Configuration\n\nFor OpenRouter, use the full model path:\n\n\\`\\`\\`typescript\nimport { defineModel } from '@standardagents/builder';\nimport { openrouter } from '@standardagents/openrouter';\n\nexport default defineModel({\n name: 'heavy',\n provider: openrouter,\n model: 'google/gemini-3-pro-preview',\n includedProviders: ['google'], // Prefer Google's servers\n});\n\\`\\`\\`\n\n## Best Practices\n\n- **Name by use case**, not model ID (e.g., \\`fast\\`, \\`default\\`, \\`heavy\\`)\n- **Configure fallbacks** for production reliability\n- **Set pricing** for cost tracking in logs when your provider or runtime does not supply it automatically\n- **Cerebras note:** documented Cerebras models attach provider-owned \\`usage.cost\\` values for request logs, but custom/private Cerebras models should still set \\`inputPrice\\` and \\`outputPrice\\`\n- **Use environment variables** for API keys, never hardcode\n\n## Documentation\n\nFull reference: https://docs.standardagentbuilder.com/api-reference/define/model\n`;\n\nexport const MODELS_CLAUDE_MD = MODELS_AGENTS_MD;\n","export const PROVIDERS_AGENTS_MD = `# Provider Definitions\n\nProvider definitions create named provider factories that wrap a base provider\npackage with connection config and optional method overrides.\n\nUse \\`defineProvider()\\` and export the result as the default export:\n\n\\`\\`\\`typescript\nimport { defineProvider, providerEnv, providerValue } from '@standardagents/builder';\nimport { openai } from '@standardagents/openai';\n\nexport default defineProvider({\n name: 'my_openai_compatible_provider',\n label: 'My OpenAI-compatible Provider',\n baseProvider: openai,\n config: {\n apiKey: providerEnv('MY_PROVIDER_API_KEY', {\n valueType: 'secret',\n required: true,\n description: 'Provider API key.',\n }),\n baseUrl: providerValue('https://api.example.com/v1'),\n },\n});\n\\`\\`\\`\n\nModels can then import the provider definition and use it like any other provider\nfactory:\n\n\\`\\`\\`typescript\nimport { defineModel } from '@standardagents/builder';\nimport myProvider from '../providers/my_openai_compatible_provider';\n\nexport default defineModel({\n name: 'custom_fast',\n provider: myProvider,\n model: 'gpt-4o-mini',\n});\n\\`\\`\\`\n\nProvider \\`overrides\\` can replace behavior such as \\`getModels\\`, \\`getIcon\\`,\n\\`getTools\\`, pricing/capability lookup, \\`generate\\`, or \\`stream\\`. Call \\`next()\\`\ninside an override to compose with the base provider; return your own value to\nreplace it.\n\nKeep credentials in secret env values. Do not hardcode API keys in provider\ndefinition files.\n`;\n\nexport const PROVIDERS_CLAUDE_MD = PROVIDERS_AGENTS_MD;\n","export const PROMPTS_AGENTS_MD = `# Prompt Definitions\n\nPrompts define system instructions, model selection, and available tools for LLM interactions.\n\n## Properties\n\n| Property | Type | Required | Description |\n|----------|------|----------|-------------|\n| \\`name\\` | \\`string\\` | Yes | Unique identifier for this prompt |\n| \\`toolDescription\\` | \\`string\\` | Yes | Description shown when used as a tool |\n| \\`prompt\\` | \\`string \\\\| StructuredPrompt\\` | Yes | System instructions |\n| \\`model\\` | \\`string\\` | Yes | Model name to use (references \\`agents/models/\\`) |\n| \\`tools\\` | \\`(string \\\\| ToolConfig \\\\| SubagentToolConfig)[]\\` | No | Available tools (include ai_human agent names for handoffs and dual_ai subagent configs) |\n| \\`includeChat\\` | \\`boolean\\` | No | Include full conversation history |\n| \\`includePastTools\\` | \\`boolean\\` | No | Include previous tool results |\n| \\`parallelToolCalls\\` | \\`boolean\\` | No | Allow multiple concurrent tool calls |\n| \\`toolChoice\\` | \\`'auto' \\\\| 'none' \\\\| 'required'\\` | No | Tool calling strategy |\n| \\`requiredSchema\\` | \\`z.ZodObject\\` | No | Input validation when called as tool |\n| \\`variables\\` | \\`VariableDefinition[]\\` | No | Variable declarations (\\`name\\`, \\`type\\`, \\`required\\`, \\`scoped\\`, \\`description\\`) |\n| \\`env\\` | \\`Record<string, string>\\` | No | Prompt-level default values for variables |\n| \\`hooks\\` | \\`string[]\\` | No | Hook IDs to run for this prompt (overrides agent hooks) |\n| \\`reasoning\\` | \\`ReasoningConfig\\` | No | Extended thinking configuration |\n\n## Basic Example\n\n\\`\\`\\`typescript\nimport { definePrompt } from '@standardagents/builder';\n\nexport default definePrompt({\n name: 'customer_support',\n toolDescription: 'Handle customer support inquiries',\n model: 'default',\n prompt: \\`You are a helpful customer support agent.\nAlways be polite and professional.\nIf you cannot help, escalate to a human.\\`,\n tools: ['search_knowledge_base', 'create_ticket'],\n includeChat: true,\n});\n\\`\\`\\`\n\n## Structured Prompts\n\nInclude other prompts for reusable instruction blocks:\n\n\\`\\`\\`typescript\nexport default definePrompt({\n name: 'main_assistant',\n toolDescription: 'Primary assistant',\n model: 'default',\n prompt: [\n { type: 'text', content: 'You are a helpful assistant.\\\\n\\\\n' },\n { type: 'include', prompt: 'common_rules' }, // Includes another prompt\n { type: 'env', property: 'ASSISTANT_TONE' }, // Inject variable value\n { type: 'text', content: '\\\\n\\\\nBe concise.' },\n ],\n});\n\\`\\`\\`\n\n\\`type: 'env'\\` inserts a resolved thread variable value. Use this only for non-secret values that are safe to expose to the LLM.\n\nThe sandboxed coding prompt declares \\`HTTP_HOST\\` as a text variable and injects its resolved value with a structured \\`{ type: 'env', property: 'HTTP_HOST' }\\` prompt part. Its URL helper uses that value as the origin for files exposed from the thread \\`public/\\` directory and endpoints exposed from the thread \\`api/\\` directory. Public URLs should usually omit extensions; extensionless public paths resolve \\`.html\\`, then \\`.js\\`, then \\`.ts\\`, then matching \\`index\\` files in the same order. Browser pages should reference only public files, \\`api/\\` endpoints, or absolute external URLs, using relative asset URLs like \\`./app\\` and \\`./api/todos\\`; private \\`src/\\` files are not served directly. Public \\`.ts\\` files are transformed to browser JavaScript and are not server endpoints. Server-side endpoints live under the thread filesystem \\`api/\\` directory, and the \\`api/\\` directory name stays in the public URL: \\`api/todo.ts\\` is \\`/api/threads/{threadId}/api/todo\\`, while \\`api/todo.ts\\` is not \\`/api/threads/{threadId}/todo\\` or \\`/api/threads/{threadId}/todos\\`. Endpoint files default-export a function that accepts \\`Request\\` and returns \\`Response\\` or \\`Promise<Response>\\`. Endpoint code can import \\`fetch\\`, \\`fs\\`, and \\`storage\\`, and can import private helpers with relative paths such as \\`../src/todo.ts\\`. When the coding agent creates a site, page, or endpoint, it should call \\`get_public_url\\` with the created file path and use the returned URL.\n\nThe sandboxed coding prompt includes \\`set_goal\\` (write the whole goal: a short \\`summary\\`, a \\`description\\` that is the user's objective in their own words captured verbatim, plus ordered steps) and \\`update_goal_step\\` (flip one step's status as you start/finish it), and should check work incrementally, checking steps off as it goes and finishing with a summary once every step is done. \\`coding_validate_typescript\\` is only an early signal; for real verification, call helper exports with \\`coding_run\\`, get public URLs for pages or endpoints, then probe those URLs from \\`coding_run\\` using \\`import { fetch } from \"fetch\"\\`. Side-effecting endpoint checks should use disposable data and clean up through the endpoint, storage, or file cleanup path when practical. The prompt also includes \\`fetch_url\\` for reading known external public http(s) pages; use the \\`coding_run\\` fetch bridge for custom methods, headers, request bodies, or thread endpoint checks.\n\nSandboxed code and \\`api/\\` endpoints can persist small JSON-serializable runtime data through \\`import { storage } from \"storage\"\\`. Use \\`storage.get\\`, \\`storage.set\\`, \\`storage.delete\\`, and \\`storage.has\\` with stable logical keys. Do not expose, mention, or depend on internal storage key prefixes.\n\nThe sandboxed coding prompt includes \\`delete_file\\` for removing files or empty directories from the thread filesystem. Use it to clean up obsolete implementation files, stale public assets, and abandoned endpoint routes after the replacement is working.\n\n## Tool Configuration\n\nTools can be simple names or detailed configs:\n\n\\`\\`\\`typescript\ntools: [\n 'simple_tool', // Just the tool name\n {\n name: 'complex_tool',\n includeTextResponse: true, // Include sub-prompt text in result\n includeToolCalls: false, // Exclude sub-prompt tool calls\n includeErrors: true, // Include error details\n initUserMessageProperty: 'query', // Use this arg as initial message\n },\n],\n\\`\\`\\`\n\nProvider-built-in tools use the same \\`tools\\` list once the selected model enables\nthem with \\`providerTools\\`. AgentBuilder passes them to the provider and records\nprovider-reported calls in request logs; it does not execute those tools locally.\nGenerated prompt files may store these selections as \\`provider:<toolName>\\` to\ndistinguish provider tools from local tools with the same name.\n\n### Subagent Tool Configuration\n\nUse \\`SubagentToolConfig\\` when the tool is a \\`dual_ai\\` agent:\n\n\\`\\`\\`typescript\ntools: [\n // Blocking, non-resumable (default)\n { name: 'data_processor_agent' },\n\n // Non-blocking, resumable with a single instance\n {\n name: 'browser_agent',\n blocking: false,\n immediate: {\n nameEnv: 'BROWSER_AGENT_NAME',\n descriptionEnv: 'BROWSER_AGENT_DESCRIPTION',\n scopedEnv: ['BROWSER_AGENT_API_KEY'],\n },\n optional: 'ENABLE_BROWSER_AGENT',\n initAgentNameProperty: 'name',\n resumable: {\n receives_messages: 'side_a',\n maxInstances: 1,\n parentCommunication: 'explicit',\n },\n },\n]\n\\`\\`\\`\n\nWhen prompt-configured resumable dual_ai subagents exist, the runtime auto-injects:\n- \\`subagent_create\\` for spawning new child instances\n- \\`subagent_message\\` for messaging active resumable instances\n\n\\`subagent_create\\` requires a non-empty \\`name\\` for human-friendly child thread labels.\nAgentBuilder stores that argument as a \\`name:<value>\\` thread tag.\n\\`subagent_create.arguments\\` is shaped by the prompt schema on the child side selected by \\`resumable.receives_messages\\`.\nAgentBuilder persists those initial arguments with the child thread, exposes them as \\`ThreadState.arguments\\` and prompt variables, and keeps them visible to both child sides for later resumptions.\n\nSet \\`immediate: true\\` to run a tool automatically when the prompt activates.\nUse \\`immediate: { nameEnv, descriptionEnv, scopedEnv }\\` when you want safe per-instance bootstrap hints while keeping copied scoped env runtime-only.\nSet \\`optional: 'ENV_NAME'\\` to enable a subagent branch only when env resolves to \\`true\\`, \\`1\\`, or \\`yes\\`.\nSet \\`resumable.parentCommunication: 'explicit'\\` when the child should stay quiet until its own tools or hooks call \\`state.notifyParent()\\`, \\`state.setStatus()\\`, or \\`state.stopSession({ result, notifyParent, status })\\`.\nSet top-level \\`parentCommunication: 'explicit'\\` on a NON-resumable subagent when its completion should not be auto-queued to the parent (so it never wakes the parent) — for background children that deliver results through another channel, e.g. the parent's thread KV. \\`resumable.parentCommunication\\` takes precedence when both are set.\nSet \\`hidden: true\\` to keep a subagent relationship declared and spawnable by runtime code (\\`state.invokeTool()\\`/\\`queueTool()\\` from hooks) while excluding its tool from every LLM request — the model can never call it (for infrastructure children like a background compaction agent).\nIf required scoped vars are missing, the runtime returns \\`error_code: \"subagent_env_required\"\\` with a temporary \\`GET/POST /api/threads/:threadId/variables/:requestId\\` endpoint in \\`error_data.endpoint\\`.\n\n## Input Validation\n\nValidate inputs when prompt is called as a tool:\n\n\\`\\`\\`typescript\nimport { z } from 'zod';\n\nexport default definePrompt({\n name: 'data_extractor',\n toolDescription: 'Extract structured data from text',\n model: 'default',\n prompt: 'Extract the requested data from the input.',\n requiredSchema: z.object({\n text: z.string().describe('Text to extract from'),\n fields: z.array(z.string()).describe('Fields to extract'),\n }),\n});\n\\`\\`\\`\n\n## Extended Thinking (Reasoning)\n\nEnable for complex reasoning tasks:\n\n\\`\\`\\`typescript\nexport default definePrompt({\n name: 'code_reviewer',\n toolDescription: 'Review code for issues',\n model: 'heavy',\n prompt: 'Review the code thoroughly...',\n reasoning: {\n effort: 'high', // 'low' | 'medium' | 'high'\n maxTokens: 16000, // Max thinking tokens\n exclude: true, // Don't include thinking in response\n },\n});\n\\`\\`\\`\n\n**⚠️ Google Models Require Reasoning**: When using Google models (\\`google/gemini-*\\`) via OpenRouter, you **must** include \\`reasoning\\` configuration or tool calls will fail. At minimum:\n\n\\`\\`\\`typescript\nreasoning: {\n effort: 'low', // Can be 'low', 'medium', or 'high'\n},\n\\`\\`\\`\n\n## Hooks\n\nAttach lifecycle hooks to a prompt:\n\n\\`\\`\\`typescript\nexport default definePrompt({\n name: 'customer_support',\n toolDescription: 'Handle customer support',\n model: 'default',\n prompt: 'You are a support agent...',\n hooks: ['limit_to_20', 'redact_pii'], // Hook IDs from agents/hooks/\n});\n\\`\\`\\`\n\nPrompt hooks take precedence over agent hooks. See \\`agents/hooks/AGENTS.md\\` for details.\n\n## Best Practices\n\n- **Write clear instructions** - Structure with headers and bullet points\n- **Describe tools thoroughly** - LLMs decide based on descriptions\n- **Validate inputs with Zod** - Catch errors early\n- **Use \\`includeChat\\`** for conversational context\n- **Name by purpose**, not model (e.g., \\`support_agent\\` not \\`gpt4_prompt\\`)\n\n## Documentation\n\nFull reference: https://docs.standardagentbuilder.com/api-reference/define/prompt\n`;\n\nexport const PROMPTS_CLAUDE_MD = PROMPTS_AGENTS_MD;\n","export const AGENT_DEFINITIONS_AGENTS_MD = `# Agent Definitions\n\nAgents orchestrate conversations by defining prompts, stop conditions, and turn limits.\n\n## Agent Properties\n\n| Property | Type | Required | Description |\n|----------|------|----------|-------------|\n| \\`name\\` | \\`string\\` | Yes | Unique identifier for this agent |\n| \\`type\\` | \\`'ai_human' \\\\| 'dual_ai'\\` | No | Conversation type (default: \\`ai_human\\`) |\n| \\`sideA\\` | \\`SideConfig\\` | Yes | Configuration for side A (AI in ai_human) |\n| \\`sideB\\` | \\`SideConfig\\` | No | Configuration for side B (required for dual_ai) |\n| \\`maxSessionTurns\\` | \\`number\\` | No | Max total turns across both sides |\n| \\`exposeAsTool\\` | \\`boolean\\` | No | Allow other prompts to hand off to this agent |\n| \\`toolDescription\\` | \\`string\\` | No | Description when used as tool (required if exposeAsTool) |\n| \\`env\\` | \\`Record<string, string>\\` | No | Agent-level default variable values |\n| \\`hooks\\` | \\`string[]\\` | No | Hook IDs to run for this agent (fallback if prompt has no hooks) |\n| \\`tags\\` | \\`string[]\\` | No | Tags for categorization and filtering |\n\n## Side Configuration\n\n| Property | Type | Required | Description |\n|----------|------|----------|-------------|\n| \\`label\\` | \\`string\\` | No | Display name for this side |\n| \\`prompt\\` | \\`string\\` | Yes | Prompt name to use (references \\`agents/prompts/\\`) |\n| \\`stopOnResponse\\` | \\`boolean\\` | No | Stop turn when LLM returns text (default: true) |\n| \\`stopTool\\` | \\`string\\` | No | Tool that stops this side's turn |\n| \\`stopToolResponseProperty\\` | \\`string\\` | No | Property to extract from stop tool result |\n| \\`maxSteps\\` | \\`number\\` | No | Maximum step budget for this side |\n| \\`sessionStop\\` | \\`string \\\\| SessionToolBinding\\` | No | Terminal success lifecycle binding |\n| \\`sessionFail\\` | \\`string \\\\| SessionToolBinding\\` | No | Terminal failure lifecycle binding |\n| \\`sessionStatus\\` | \\`string \\\\| SessionToolBinding\\` | No | Non-terminal status lifecycle binding |\n| \\`manualStopCondition\\` | \\`boolean\\` | No | Enable custom stop handling via hooks |\n\n## Basic Example (AI-Human)\n\n\\`\\`\\`typescript\nimport { defineAgent } from '@standardagents/builder';\n\nexport default defineAgent({\n name: 'support_agent',\n type: 'ai_human',\n sideA: {\n label: 'Support',\n prompt: 'customer_support',\n stopOnResponse: true,\n sessionStop: 'close_ticket',\n maxSteps: 50,\n },\n tags: ['support', 'tier-1'],\n});\n\\`\\`\\`\n\n## Dual-AI Example\n\nTwo AI agents conversing (e.g., debate, iterative refinement):\n\n\\`\\`\\`typescript\nexport default defineAgent({\n name: 'code_review_debate',\n type: 'dual_ai',\n maxSessionTurns: 20,\n sideA: {\n label: 'Reviewer',\n prompt: 'code_reviewer',\n stopOnResponse: true,\n },\n sideB: {\n label: 'Developer',\n prompt: 'code_defender',\n stopOnResponse: true,\n },\n});\n\\`\\`\\`\n\n## Dual-AI Subagent Pattern\n\nWhen a \\`dual_ai\\` agent is used as a subagent tool, a common split is:\n- **sideA**: performs work (tools, data gathering, execution)\n- **sideB**: reflection, verification, and quality checks\n\n\\`\\`\\`typescript\nexport default defineAgent({\n name: 'research_subagent',\n type: 'dual_ai',\n exposeAsTool: true,\n toolDescription: 'Researches and validates findings autonomously',\n maxSessionTurns: 16,\n sideA: {\n label: 'Worker',\n prompt: 'research_worker',\n sessionStatus: 'set_subagent_status',\n sessionFail: 'fail_research_subagent',\n sessionStop: 'finish_subagent',\n },\n sideB: {\n label: 'Reviewer',\n prompt: 'research_reviewer',\n stopOnResponse: true,\n },\n});\n\\`\\`\\`\n\n## Agent Handoffs\n\nExpose an agent for handoffs from other prompts:\n\n\\`\\`\\`typescript\nexport default defineAgent({\n name: 'escalation_agent',\n type: 'ai_human',\n exposeAsTool: true,\n toolDescription: 'Escalate to senior support for complex issues',\n sideA: {\n prompt: 'senior_support',\n },\n});\n\\`\\`\\`\n\nOther prompts can then include the agent name in their \\`tools\\` array to enable handoffs.\n\n## Stop Conditions (Priority Order)\n\n1. **sessionFail** - Ends entire conversation with a terminal failure\n2. **sessionStop** - Ends entire conversation successfully\n3. **stopTool** - Ends current side's turn\n4. **maxSteps** - Ends side execution when the safety budget is reached\n5. **stopOnResponse** - Ends turn when LLM returns text\n6. **maxSessionTurns** - Ends conversation (hard limit: 250)\n\n## Hooks\n\nAttach lifecycle hooks at the agent level:\n\n\\`\\`\\`typescript\nexport default defineAgent({\n name: 'support_agent',\n type: 'ai_human',\n hooks: ['log_all_messages', 'sanitize_results'],\n sideA: {\n prompt: 'customer_support',\n },\n});\n\\`\\`\\`\n\nAgent hooks run as a fallback when the active prompt has no hooks defined. Prompt hooks always take precedence. See \\`agents/hooks/AGENTS.md\\` for details.\n\n## Naming Convention\n\nAgent names **must** end with the \\`_agent\\` suffix (e.g., \\`support_agent\\`, \\`research_agent\\`).\nThis convention is enforced by the builder UI and makes agents easily identifiable in logs and code.\n\n## Best Practices\n\n- **Use descriptive names** (\\`customer_support_agent\\` not \\`agent1\\`)\n- **Always use the _agent suffix** - names like \\`support_agent\\`, \\`research_agent\\`\n- **Always set maxSteps or maxSessionTurns** as safety limits\n- **Match stop conditions to use case** - chat apps use stopOnResponse, workflows use stopTool\n- **Use labels** for clarity in logs and UI\n- **Organize with tags** for filtering\n\n## Documentation\n\nFull reference: https://docs.standardagentbuilder.com/api-reference/define/agent\n`;\n\nexport const AGENTS_CLAUDE_MD = AGENT_DEFINITIONS_AGENTS_MD;\n","export const TOOLS_AGENTS_MD = `# Custom Tools\n\nTools extend agent capabilities beyond text generation. They allow LLMs to fetch data, perform calculations, execute side effects, and chain to other prompts or agents.\n\n## Function Signature\n\n\\`\\`\\`typescript\ndefineTool({\n description: string, // What the tool does (shown to LLM)\n args?: z.ZodObject, // Input validation schema (optional)\n execute: (state, args) => ToolResult, // Implementation\n variables?: VariableDefinition[], // Declared variables (optional)\n progressArgument?: string, // Arg holding a short progress label, e.g. \"writing index.html\"\n})\n\\`\\`\\`\n\n## Basic Example\n\n\\`\\`\\`typescript\nimport { defineTool } from '@standardagents/builder';\nimport { z } from 'zod';\n\nexport default defineTool({\n description: 'Search the knowledge base for articles matching a query',\n args: z.object({\n query: z.string().describe('Search query'),\n limit: z.number().optional().default(10).describe('Max results'),\n }),\n execute: async (state, args) => {\n const results = await searchKB(args.query, args.limit);\n return {\n status: 'success',\n result: JSON.stringify(results),\n };\n },\n});\n\\`\\`\\`\n\n## Argument Schemas\n\nTool args must be a top-level \\`z.object(...)\\`. Prefer explicit, bounded schemas made from strings, numbers, booleans, nulls, literals, enums, arrays, objects, optionals, nullables, and defaults. Avoid provider-visible recursive or open-ended schemas such as \\`z.unknown()\\`, \\`z.any()\\`, and \\`z.object({}).catchall(...)\\`; strict tool providers can reject the generated JSON Schema. If a tool needs arbitrary JSON input, accept it as a JSON string and parse it inside \\`execute\\`.\n\n## ToolResult Interface\n\n| Property | Type | Description |\n|----------|------|-------------|\n| \\`status\\` | \\`'success' \\\\| 'error'\\` | Whether the tool succeeded |\n| \\`result\\` | \\`string\\` | Tool output (required for success) |\n| \\`error\\` | \\`string\\` | Error message (for error status) |\n| \\`error_code\\` | \\`string\\` | Machine-readable error code |\n| \\`error_data\\` | \\`Record<string, unknown>\\` | Structured error payload |\n| \\`attachments\\` | \\`ToolAttachment[]\\` | Files to attach (images, etc.) |\n\n## ThreadState Access\n\nThe \\`state\\` parameter provides access to:\n\n\\`\\`\\`typescript\nexecute: async (state, args) => {\n // Thread information\n const threadId = state.thread.id;\n const thread = state.thread.instance;\n const creationArgs = state.arguments; // Invocation or subagent creation args\n\n // Configuration\n const agentName = state.agent.name;\n const modelName = state.model.name;\n\n // Message history\n const messages = state.messages;\n\n // Thread variable resolution\n const apiKey = await state.env('GOOGLE_API_KEY');\n await state.setEnv('LAST_TOOL_RUN_AT', new Date().toISOString());\n\n // Durable per-thread JSON values\n const runCount = (await state.getValue<number>('run_count')) ?? 0;\n await state.setValue('run_count', runCount + 1);\n\n // The thread's user profile (identity only, never credentials) — for\n // per-user personalization or entitlement checks. Null when user-less.\n const user = await state.user();\n\n // Instance-GLOBAL Agent Skills library (agentskills.io SKILL.md format).\n // Skills install once and are visible to every thread; load a skill's body\n // only when it's applicable (progressive disclosure).\n const skills = await state.skills.list();\n const skill = await state.skills.get('pdf-processing');\n const script = await state.skills.readFile('pdf-processing', 'scripts/extract.py');\n\n // Sandboxed JS/TS execution with explicit bridge capabilities\n const run = state.runCode('export async function main(path) { return await read(path) }', {\n execute: { fn: 'main', args: ['/notes.txt'] },\n globals: {\n read: async (path: string) => {\n const data = await state.readFile(path);\n return data ? new TextDecoder().decode(data) : null;\n },\n },\n });\n const codeResult = await run;\n\n // Parent state (for sub-prompts)\n const root = state.rootState;\n}\n\\`\\`\\`\n\nUse \\`state.runCode()\\` instead of \\`eval\\` or \\`new Function\\` for model- or user-authored JavaScript/TypeScript. The sandbox starts with no ambient host capabilities; provide imports/globals explicitly, use \\`modules\\` for local relative ES modules, use \\`execute\\` to select an export and pass args, use \\`report\\` for streamed observations, and call \\`run.terminate(reason)\\` from your own timeout budget when needed. \\`modules\\` keys are graph-root relative paths; entry-source imports resolve from \\`options.filename\\` when supplied. Relative module imports may use \\`./\\` and \\`../\\` as long as they resolve within the supplied module graph. In thread endpoints, \\`runCode\\` is forwarded into the thread Durable Object; pass plain transferable option values there, and do function-backed bridges from tools or in-thread execution contexts.\n\nSandboxed coding code must not use ambient network globals. For HTTP inside \\`coding_run\\`, import \\`{ fetch }\\` from \\`\"fetch\"\\`; the bridge supports \\`fetch(url, init)\\` with methods, headers, and bodies, and returns a Response-like object with \\`text()\\`, \\`json()\\`, \\`arrayBuffer()\\`, and \\`headers.get()\\`. The sandboxed coding prompt includes \\`fetch_url\\` for reading known external public http(s) pages as Markdown. Use the \\`coding_run\\` fetch bridge instead for custom methods, headers, request bodies, or checks against thread public file/API endpoint URLs returned by \\`get_public_url\\`.\n\nSandboxed coding agents should verify runtime behavior as they work. \\`coding_validate_typescript\\` is useful but incomplete; call helper exports with \\`coding_run\\`, probe pages and endpoints with \\`coding_run\\` plus the fetch bridge, inspect status/body, and clean up disposable side-effecting test data when practical.\n\n## Tool Without Arguments\n\n\\`\\`\\`typescript\nexport default defineTool({\n description: 'Get current server time',\n execute: async (state) => {\n return {\n status: 'success',\n result: new Date().toISOString(),\n };\n },\n});\n\\`\\`\\`\n\n## Error Handling\n\nReturn errors gracefully instead of throwing:\n\n\\`\\`\\`typescript\nexport default defineTool({\n description: 'Fetch user data',\n args: z.object({ userId: z.string() }),\n execute: async (state, args) => {\n try {\n const user = await fetchUser(args.userId);\n return { status: 'success', result: JSON.stringify(user) };\n } catch (error) {\n return {\n status: 'error',\n error: \\`Failed to fetch user: \\${error.message}\\`,\n };\n }\n },\n});\n\\`\\`\\`\n\n## Queueing Additional Tools\n\nQueue another tool to run after the current one:\n\n\\`\\`\\`typescript\nimport { queueTool } from '@standardagents/builder';\n\nexport default defineTool({\n description: 'Create order and send confirmation',\n args: z.object({ items: z.array(z.string()) }),\n execute: async (state, args) => {\n const order = await createOrder(args.items);\n\n // Queue email tool to run next\n queueTool(state, 'send_confirmation_email', {\n orderId: order.id,\n email: state.thread.metadata.userEmail,\n });\n\n return { status: 'success', result: JSON.stringify(order) };\n },\n});\n\\`\\`\\`\n\n## Injecting Messages\n\nAdd messages without triggering re-execution:\n\n\\`\\`\\`typescript\nimport { injectMessage } from '@standardagents/builder';\n\nexport default defineTool({\n description: 'Log audit event',\n args: z.object({ event: z.string() }),\n execute: async (state, args) => {\n await injectMessage(state, {\n role: 'system',\n content: \\`[AUDIT] \\${args.event}\\`,\n });\n return { status: 'success', result: 'Logged' };\n },\n});\n\\`\\`\\`\n\n## Stopping Sessions\n\n\\`state.execution.stop()\\` stops the current execution loop. To terminally end the active agent session, including blocking subagent runs that expect a session boundary, use \\`state.stopSession()\\`:\n\n\\`\\`\\`typescript\nawait state.stopSession({\n result: 'Waiting for clarification',\n notifyParent: 'Please clarify the request',\n status: 'waiting for clarification',\n});\n\\`\\`\\`\n\n\\`notifyParent\\` queues a silent message to the parent when one exists; \\`status\\` is ignored without a parent registry entry. Omit \\`notifyParent\\` and \\`status\\` when stopping should not send a parent message or update child status.\n\n## Variables and Env\n\nTools can declare variable requirements with \\`variables\\`, including \\`required\\` and \\`description\\` metadata:\n\n\\`\\`\\`typescript\nexport default defineTool({\n description: 'Search uploaded documents',\n args: z.object({ query: z.string() }),\n execute: async (state, args) => {\n const vectorStoreId = await state.env('VECTOR_STORE_ID');\n const results = await searchVectorStore(vectorStoreId, args.query);\n return { status: 'success', result: JSON.stringify(results) };\n },\n variables: [\n {\n name: 'VECTOR_STORE_ID',\n type: 'text',\n required: true,\n scoped: false,\n description: 'OpenAI Vector Store ID',\n },\n ],\n});\n\\`\\`\\`\n\nUse \\`scoped: true\\` for per-instance values that should not inherit from parent thread env (for example per-account OAuth tokens on subagents).\n\n## Returning Attachments\n\nTools can return file attachments (e.g., generated images):\n\n\\`\\`\\`typescript\nexport default defineTool({\n description: 'Generate a chart from data',\n args: z.object({ data: z.array(z.number()) }),\n execute: async (state, args) => {\n const chartImage = await generateChart(args.data);\n return {\n status: 'success',\n result: 'Chart generated successfully',\n attachments: [{\n name: 'chart.png',\n mimeType: 'image/png',\n data: chartImage.base64,\n width: 800,\n height: 600,\n }],\n };\n },\n});\n\\`\\`\\`\n\n## Best Practices\n\n- **Write clear descriptions** - LLMs decide tool usage based on descriptions\n- **Describe all parameters** with \\`.describe()\\` in Zod schemas\n- **Handle errors gracefully** - return error status, don't throw\n- **Use snake_case** for file names (\\`search_knowledge_base.ts\\`)\n- **Keep tools focused** - one task per tool\n- **Use \\`state.rootState\\`** when queueing from sub-prompts\n\n## Supported Zod Types\n\n- Primitives: \\`string\\`, \\`number\\`, \\`boolean\\`, \\`null\\`\n- Enums: \\`z.enum(['a', 'b', 'c'])\\`\n- Arrays: \\`z.array(z.string())\\`\n- Objects: \\`z.object({ ... })\\`\n- Optional: \\`z.string().optional()\\`\n- Default: \\`z.number().default(10)\\`\n- Nullable: \\`z.string().nullable()\\`\n\n## Documentation\n\nFull reference: https://docs.standardagentbuilder.com/api-reference/define/tool\n`;\n\nexport const TOOLS_CLAUDE_MD = TOOLS_AGENTS_MD;\n","export const HOOKS_AGENTS_MD = `# Lifecycle Hooks\n\nHooks intercept and modify agent execution at specific lifecycle points.\n\n## Available Hooks\n\n| Hook | Signature | Purpose |\n|------|-----------|---------|\n| \\`after_thread_created\\` | \\`(state: ThreadState) => void\\` | Initialize a newly created thread before execution |\n| \\`after_subagent_created\\` | \\`(state: ThreadState, childState: ThreadState) => void\\` | Run parent-side logic after a child thread is created |\n| \\`after_system_message\\` | \\`(state: ThreadState, systemMessage: string) => string \\\\| null \\\\| undefined\\` | Modify the rendered system message for a request |\n| \\`filter_messages\\` | \\`(state: ThreadState, messages: Message[]) => Message[]\\` | Filter raw messages before LLM context |\n| \\`prefilter_llm_history\\` | \\`(state: ThreadState, messages: LLMMessage[]) => LLMMessage[]\\` | Modify chat completion messages before LLM |\n| \\`before_create_message\\` | \\`(state: ThreadState, message: Message) => Message\\` | Modify message before database insert |\n| \\`after_create_message\\` | \\`(state: ThreadState, message: Message) => void\\` | Run logic after message created |\n| \\`before_update_message\\` | \\`(state: ThreadState, id: string, updates: Record) => Record\\` | Modify updates before message update |\n| \\`after_update_message\\` | \\`(state: ThreadState, message: Message) => void\\` | Run logic after message updated |\n| \\`before_store_tool_result\\` | \\`(state: ThreadState, toolCall: HookToolCall, result: HookToolResult) => HookToolResult\\` | Modify tool result before storage |\n| \\`after_tool_call_success\\` | \\`(state: ThreadState, toolCall: HookToolCall, result: HookToolResult) => HookToolResult \\\\| null\\` | Process successful tool execution |\n| \\`after_tool_call_failure\\` | \\`(state: ThreadState, toolCall: HookToolCall, result: HookToolResult) => HookToolResult \\\\| null\\` | Process failed tool execution |\n| \\`tool_call_started\\` | \\`(state: ThreadState, toolCall: HookToolCall, progress?: string) => void\\` | Observe a tool call when it starts streaming (before it runs) |\n| \\`tool_call_done\\` | \\`(state: ThreadState, toolCall: HookToolCall, result: HookToolResult) => void\\` | Observe a tool call after it finishes (success or failure) |\n\nAll hooks receive \\`ThreadState\\` as their first parameter, providing access to thread identity, message history, resource loading, durable per-thread values via \\`getValue\\` / \\`setValue\\`, and sandboxed JS/TS execution via \\`runCode\\`.\n\n## Creating a Hook\n\nEach hook file exports a default \\`defineHook\\` call with three properties:\n\n\\`\\`\\`typescript\nimport { defineHook } from '@standardagents/builder';\n\nexport default defineHook({\n hook: 'filter_messages', // Hook type\n id: 'limit_recent_messages', // Unique ID (snake_case)\n execute: async (state, messages) => {\n return messages.slice(-20);\n }\n});\n\\`\\`\\`\n\n## Hook Scoping\n\nHooks are scoped to **prompts** or **agents** via their ID:\n\n\\`\\`\\`typescript\n// In a prompt definition\ndefinePrompt({\n name: 'customer_support',\n hooks: ['limit_recent_messages', 'redact_pii'],\n // ...\n});\n\n// In an agent definition\ndefineAgent({\n name: 'support_agent',\n hooks: ['log_all_messages'],\n // ...\n});\n\\`\\`\\`\n\n- **Prompt hooks** take precedence over agent hooks\n- If a prompt defines hooks, only those run (agent hooks are skipped)\n- If no prompt hooks are defined, agent hooks run as fallback\n- Hooks are filtered by type at runtime\n\n## File Naming\n\nHook files can use **any name** — the hook type and ID are defined inside the file:\n\n\\`\\`\\`\nagents/hooks/\n├── my_filter.ts # Could contain any hook type\n├── redact_sensitive_data.ts\n├── log_tool_usage.ts\n└── add_metadata.ts\n\\`\\`\\`\n\n## Examples\n\n### Filter Messages (Limit Context)\n\n\\`\\`\\`typescript\nimport { defineHook } from '@standardagents/builder';\n\nexport default defineHook({\n hook: 'filter_messages',\n id: 'limit_to_20',\n execute: async (state, messages) => {\n return messages.slice(-20);\n }\n});\n\\`\\`\\`\n\n### Prefilter LLM History (Redact Content)\n\n\\`\\`\\`typescript\nimport { defineHook } from '@standardagents/builder';\n\nexport default defineHook({\n hook: 'prefilter_llm_history',\n id: 'redact_pii',\n execute: async (state, messages) => {\n return messages.map(msg => ({\n ...msg,\n content: typeof msg.content === 'string'\n ? msg.content.replace(/\\\\b\\\\d{4}-\\\\d{4}-\\\\d{4}-\\\\d{4}\\\\b/g, '[REDACTED]')\n : msg.content,\n }));\n }\n});\n\\`\\`\\`\n\n### Before Create Message (Add Metadata)\n\n\\`\\`\\`typescript\nimport { defineHook } from '@standardagents/builder';\n\nexport default defineHook({\n hook: 'before_create_message',\n id: 'add_version_metadata',\n execute: async (state, message) => {\n if (message.role === 'user' && message.content) {\n return { ...message, content: \\`[v1.0] \\${message.content}\\` };\n }\n return message;\n }\n});\n\\`\\`\\`\n\n### Before Store Tool Result (Sanitize)\n\n\\`\\`\\`typescript\nimport { defineHook } from '@standardagents/builder';\n\nexport default defineHook({\n hook: 'before_store_tool_result',\n id: 'sanitize_results',\n execute: async (state, toolCall, toolResult) => {\n // toolCall: { id, type: 'function', function: { name, arguments } }\n // toolResult: { status, result?, error?, stack?, attachments? }\n if (toolResult.result) {\n return { ...toolResult, result: toolResult.result.replace(/secret/gi, '[REDACTED]') };\n }\n return toolResult;\n }\n});\n\\`\\`\\`\n\n### After Tool Call Success (Logging)\n\n\\`\\`\\`typescript\nimport { defineHook } from '@standardagents/builder';\n\nexport default defineHook({\n hook: 'after_tool_call_success',\n id: 'log_tool_success',\n execute: async (state, toolCall, result) => {\n console.log(\\`Tool \\${toolCall.function.name} succeeded\\`);\n return null; // Return null to use original result\n }\n});\n\\`\\`\\`\n\n### After Tool Call Failure (Recovery)\n\n\\`\\`\\`typescript\nimport { defineHook } from '@standardagents/builder';\n\nexport default defineHook({\n hook: 'after_tool_call_failure',\n id: 'weather_fallback',\n execute: async (state, toolCall, result) => {\n if (toolCall.function.name === 'fetch_weather') {\n return {\n status: 'success',\n result: JSON.stringify({ temp: 'unavailable', fallback: true }),\n };\n }\n return null; // Use original error for other tools\n }\n});\n\\`\\`\\`\n\n## Hook Categories\n\n**Transformation hooks** (return modified data):\n- \\`after_system_message\\` (return replacement string, or null/undefined for no change)\n- \\`filter_messages\\`\n- \\`prefilter_llm_history\\`\n- \\`before_create_message\\`\n- \\`before_update_message\\`\n- \\`before_store_tool_result\\`\n- \\`after_tool_call_success\\` (return modified result or null)\n- \\`after_tool_call_failure\\` (return modified result or null)\n\n**Event hooks** (side effects only):\n- \\`after_thread_created\\`\n- \\`after_subagent_created\\`\n- \\`after_create_message\\`\n- \\`after_update_message\\`\n\n## Best Practices\n\n- **Keep hooks fast** - target <100ms execution\n- **Wrap in try-catch** - hooks continue on error (original data preserved)\n- **Use unique IDs** - hook IDs must be snake_case and unique across the project\n- **Scope appropriately** - assign hooks to prompts or agents that need them\n- **Document purpose** with clear comments\n- **Use for cross-cutting concerns** - logging, redaction, enrichment\n\n## Documentation\n\nFull reference: https://docs.standardagentbuilder.com/api-reference/define/hook\n`;\n\nexport const HOOKS_CLAUDE_MD = HOOKS_AGENTS_MD;\n","export const API_AGENTS_MD = `# Thread-Specific API Endpoints\n\nDefine custom API endpoints that operate on specific threads with access to the thread's ThreadState.\n\n## File-Based Routing\n\n| File Pattern | HTTP Method | Route |\n|--------------|-------------|-------|\n| \\`name.ts\\` | GET | \\`/api/threads/:threadId/name\\` |\n| \\`name.get.ts\\` | GET | \\`/api/threads/:threadId/name\\` |\n| \\`name.post.ts\\` | POST | \\`/api/threads/:threadId/name\\` |\n| \\`name.put.ts\\` | PUT | \\`/api/threads/:threadId/name\\` |\n| \\`name.delete.ts\\` | DELETE | \\`/api/threads/:threadId/name\\` |\n| \\`index.ts\\` | GET | \\`/api/threads/:threadId\\` |\n| \\`nested/route.ts\\` | GET | \\`/api/threads/:threadId/nested/route\\` |\n| \\`items/[id].ts\\` | GET | \\`/api/threads/:threadId/items/:id\\` |\n| \\`files/[*].ts\\` | GET | \\`/api/threads/:threadId/files/*\\` |\n\nFiles without a method suffix default to GET. Method suffixes are case-insensitive and support \\`.get.ts\\`, \\`.post.ts\\`, \\`.put.ts\\`, \\`.patch.ts\\`, and \\`.delete.ts\\`.\n\nDynamic segments use \\`[name]\\` and are passed to the handler as \\`params.name\\`. Catch-all segments use \\`[*]\\` and are passed as \\`params['*']\\`; the catch-all value may contain \\`/\\` for nested paths. Static routes match before dynamic routes, and dynamic routes match before catch-all routes.\n\n## Basic Example\n\n\\`\\`\\`typescript\n// agents/api/status.get.ts -> GET /api/threads/:threadId/status\nimport { defineThreadEndpoint } from '@standardagents/spec';\n\nexport default defineThreadEndpoint(async (req, state, params) => {\n const { messages, total } = await state.getMessages();\n return Response.json({\n threadId: state.threadId,\n messageCount: total,\n status: 'active',\n params,\n });\n});\n\\`\\`\\`\n\n## Handler Parameters\n\n| Parameter | Type | Description |\n|-----------|------|-------------|\n| \\`req\\` | \\`Request\\` | The incoming HTTP request |\n| \\`state\\` | \\`ThreadState\\` | Thread state with messages, identity, \\`arguments\\`, file system, \\`runCode\\`, etc. |\n| \\`params\\` | \\`Record<string, string>\\` | Route parameters captured from \\`[name]\\` and \\`[*]\\` path segments |\n\nNote: \\`state.execution\\` is always \\`null\\` in endpoints since the thread is at rest. \\`state.runCode()\\` is available from endpoints and is forwarded into the thread runtime; pass plain transferable option values there, and do function-backed sandbox bridges from tools or in-thread execution contexts.\n\n## ThreadState Methods\n\nAccess thread data through the state object:\n\n\\`\\`\\`typescript\nimport { defineThreadEndpoint } from '@standardagents/spec';\n\nexport default defineThreadEndpoint(async (req, state) => {\n // Thread identity\n console.log('Thread ID:', state.threadId);\n console.log('Agent ID:', state.agentId);\n console.log('User ID:', state.userId);\n console.log('Arguments:', state.arguments);\n\n // Message operations\n const { messages, total, hasMore } = await state.getMessages({\n limit: 100,\n offset: 0,\n order: 'desc',\n });\n\n // Thread env (thread scope + active descendants)\n const approvalGate = await state.env('TOPDOWN_APPROVAL_GATE');\n await state.setEnv('TOPDOWN_APPROVAL_GATE', approvalGate || 'open');\n\n // Durable per-thread JSON values\n const exports = (await state.getValue<number>('export_count')) ?? 0;\n await state.setValue('export_count', exports + 1);\n\n // File system operations\n const files = await state.findFiles('**/*.json');\n const data = await state.readFile('/data/config.json');\n\n // Resource loading\n const agent = await state.loadAgent('my-agent');\n const prompt = await state.loadPrompt('my-prompt');\n\n return Response.json({ messages, total });\n});\n\\`\\`\\`\n\n## POST with Request Body\n\n\\`\\`\\`typescript\n// agents/api/export.post.ts -> POST /api/threads/:threadId/export\nimport { defineThreadEndpoint } from '@standardagents/spec';\n\nexport default defineThreadEndpoint(async (req, state) => {\n const body = await req.json();\n const { format = 'json' } = body;\n\n const { messages } = await state.getMessages();\n\n if (format === 'csv') {\n const csv = messages.map(m => \\`\\${m.role},\\${m.content}\\`).join('\\\\n');\n return new Response(csv, {\n headers: { 'Content-Type': 'text/csv' },\n });\n }\n\n return Response.json(messages);\n});\n\\`\\`\\`\n\n## Nested Routes\n\nCreate directories for nested routes:\n\n\\`\\`\\`\nagents/api/\n├── status.get.ts -> GET /api/threads/:threadId/status\n├── export.post.ts -> POST /api/threads/:threadId/export\n└── messages/\n ├── count.ts -> GET /api/threads/:threadId/messages/count\n ├── [id].ts -> GET /api/threads/:threadId/messages/:id\n └── [*].ts -> GET /api/threads/:threadId/messages/*\n\\`\\`\\`\n\n## Error Handling\n\n\\`\\`\\`typescript\nimport { defineThreadEndpoint } from '@standardagents/spec';\n\nexport default defineThreadEndpoint(async (req, state) => {\n try {\n const data = await riskyOperation();\n return Response.json(data);\n } catch (error) {\n return Response.json({ error: error.message }, { status: 500 });\n }\n});\n\\`\\`\\`\n\n## File System Operations\n\n\\`\\`\\`typescript\nimport { defineThreadEndpoint } from '@standardagents/spec';\n\nexport default defineThreadEndpoint(async (req, state) => {\n // Read files\n const content = await state.readFile('/data/file.txt');\n\n // Write files\n await state.writeFile('/output/result.json', JSON.stringify(data), 'application/json');\n\n // List directory\n const { entries } = await state.readdirFile('/data');\n\n // Move or rename files and directories (does not overwrite an existing destination)\n await state.moveFile('/data/file.txt', '/archive/file.txt');\n await state.renameFile('/output/result.json', 'final.json');\n\n // Search files\n const matches = await state.grepFiles('pattern');\n const paths = await state.findFiles('**/*.ts');\n\n return Response.json({ success: true });\n});\n\\`\\`\\`\n\n## Best Practices\n\n- **Keep handlers fast** - endpoints are in the request path\n- **Paginate large queries** - use limit/offset for messages\n- **Validate input data** - check request body before processing\n- **Use descriptive file names** - \\`export.post.ts\\` not \\`ep1.ts\\`\n- **Return proper status codes** - 200, 400, 404, 500\n- **Import from spec** - use \\`@standardagents/spec\\` for \\`defineThreadEndpoint\\`\n\n## Documentation\n\nFull reference: https://docs.standardagentbuilder.com/core-concepts/api\n`;\n\nexport const API_CLAUDE_MD = API_AGENTS_MD;\n","import {\n AGENT_DEFINITIONS_AGENTS_MD,\n API_AGENTS_MD,\n HOOKS_AGENTS_MD,\n MODELS_AGENTS_MD,\n PROVIDERS_AGENTS_MD,\n PROMPTS_AGENTS_MD,\n ROOT_AGENTS_MD,\n TOOLS_AGENTS_MD,\n} from './docs/index.js'\n\nexport {\n AGENT_DEFINITIONS_AGENTS_MD,\n AGENT_DEFINITIONS_AGENTS_MD as AGENTS_CLAUDE_MD,\n API_AGENTS_MD,\n API_AGENTS_MD as API_CLAUDE_MD,\n HOOKS_AGENTS_MD,\n HOOKS_AGENTS_MD as HOOKS_CLAUDE_MD,\n MODELS_AGENTS_MD,\n MODELS_AGENTS_MD as MODELS_CLAUDE_MD,\n PROVIDERS_AGENTS_MD,\n PROVIDERS_AGENTS_MD as PROVIDERS_CLAUDE_MD,\n PROMPTS_AGENTS_MD,\n PROMPTS_AGENTS_MD as PROMPTS_CLAUDE_MD,\n ROOT_AGENTS_MD,\n ROOT_AGENTS_MD as ROOT_CLAUDE_MD,\n TOOLS_AGENTS_MD,\n TOOLS_AGENTS_MD as TOOLS_CLAUDE_MD,\n}\n\nexport type PackageManager = 'pnpm' | 'npm' | 'yarn' | 'bun'\n\nexport interface TemplateFile {\n path: string\n content: string\n message: string\n kind?: 'file' | 'symlink'\n}\n\nexport interface TemplateVersions {\n standardAgents: string\n sip: string\n vite: string\n typescript: string\n zod?: string\n}\n\nexport interface AgentBuilderProjectTemplateOptions {\n projectName: string\n packageManager?: PackageManager | null\n versions?: Partial<TemplateVersions>\n includeTemplateMetadata?: boolean\n templateVersion?: string\n /**\n * Include a working `vite build` script in the rendered package manifest.\n * Only the platform build runner should set this. Local manifests get a\n * guard script instead, because customer projects build and deploy on the\n * Standard Agents platform after a git push — never on the user's machine.\n */\n includeBuildScript?: boolean\n}\n\nexport const FIRST_PARTY_PROVIDER_PACKAGES = [\n '@standardagents/anthropic',\n '@standardagents/cloudflare',\n '@standardagents/cerebras',\n '@standardagents/google',\n '@standardagents/groq',\n '@standardagents/openai',\n '@standardagents/openrouter',\n '@standardagents/xai',\n] as const\n\n/**\n * Dependency packages whose install scripts the generated project approves.\n * pnpm 10 blocks dependency build scripts by default and, under CI (the\n * platform build runner sets CI=true), fails the install outright with\n * ERR_PNPM_IGNORED_BUILDS. These are the script-running packages in the\n * default dependency tree (native binaries and codegen) that the project\n * needs for installs and builds to work.\n */\nexport const APPROVED_DEPENDENCY_BUILD_SCRIPTS = [\n '@google/genai',\n '@openrouter/sdk',\n 'esbuild',\n 'protobufjs',\n 'sharp',\n 'workerd',\n] as const\n\n// Pin first-party @standardagents/* packages to a controlled major range\n// rather than \"latest\". Floating on \"latest\" let the installed builder drift\n// out of sync with the generated provider list (e.g. builder shipped the\n// anthropic provider while a stale template omitted it), breaking the build.\n// Caret on a 0.x version accepts patch releases automatically but holds the\n// minor, so only an intentional \"major\" bump of these packages re-challenges\n// the pin. Bump these together when the platform adopts a new release line.\nexport const DEFAULT_TEMPLATE_VERSIONS: TemplateVersions = {\n standardAgents: '^0.21.0',\n sip: '^1.0.1',\n vite: 'latest',\n typescript: 'latest',\n zod: 'latest',\n}\n\nexport const AGENTBUILDER_TEMPLATE_VERSION = '0.22.0'\n\nfunction ensureTrailingNewline(value: string): string {\n return value.endsWith('\\n') ? value : `${value}\\n`\n}\n\nfunction mergeVersions(versions?: Partial<TemplateVersions>): TemplateVersions {\n return {\n ...DEFAULT_TEMPLATE_VERSIONS,\n ...versions,\n }\n}\n\nexport function packageNameFromProjectName(projectName: string): string {\n const normalized = projectName\n .toLowerCase()\n .replace(/^@[^/]+\\//, '')\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n return normalized || 'agentbuilder-project'\n}\n\nfunction file(path: string, content: string, message: string): TemplateFile {\n return {\n path,\n content: ensureTrailingNewline(content),\n message,\n kind: 'file',\n }\n}\n\nfunction symlink(path: string, target: string, message: string): TemplateFile {\n return {\n path,\n content: target,\n message,\n kind: 'symlink',\n }\n}\n\nexport function renderPackageJson(options: AgentBuilderProjectTemplateOptions): string {\n const versions = mergeVersions(options.versions)\n const standardAgentsVersion = versions.standardAgents\n const dependencies: Record<string, string> = {\n '@standardagents/builder': standardAgentsVersion,\n '@standardagents/spec': standardAgentsVersion,\n '@standardagents/sip': versions.sip,\n zod: versions.zod ?? 'latest',\n }\n\n for (const providerPackage of FIRST_PARTY_PROVIDER_PACKAGES) {\n dependencies[providerPackage] = standardAgentsVersion\n }\n\n return `${JSON.stringify({\n name: packageNameFromProjectName(options.projectName),\n version: '0.0.0',\n private: true,\n type: 'module',\n scripts: {\n dev: 'vite --host 0.0.0.0 --port 5173',\n build: options.includeBuildScript\n ? 'vite build'\n : \"echo 'Standard Agents projects build and deploy on the platform. Push your commit (git push or agents deploy) to trigger a build.' && exit 1\",\n typecheck: 'tsc --noEmit',\n },\n dependencies,\n devDependencies: {\n typescript: versions.typescript,\n vite: versions.vite,\n },\n pnpm: {\n onlyBuiltDependencies: [...APPROVED_DEPENDENCY_BUILD_SCRIPTS],\n },\n }, null, 2)}\\n`\n}\n\nexport function renderViteConfig(): string {\n return `import { defineConfig } from \"vite\"\nimport { builder } from \"@standardagents/builder\"\n\nexport default defineConfig({\n plugins: [builder()],\n})\n`\n}\n\nexport function renderTsConfig(): string {\n return `{\n \"compilerOptions\": {\n \"target\": \"ES2022\",\n \"useDefineForClassFields\": true,\n \"module\": \"ESNext\",\n \"lib\": [\"ES2022\", \"DOM\", \"DOM.Iterable\"],\n \"skipLibCheck\": true,\n \"moduleResolution\": \"Bundler\",\n \"allowImportingTsExtensions\": true,\n \"resolveJsonModule\": true,\n \"isolatedModules\": true,\n \"noEmit\": true,\n \"strict\": true\n },\n \"include\": [\"agents\", \".agents\", \"vite.config.ts\"]\n}\n`\n}\n\nexport function renderGitignore(): string {\n // package.json AND the lockfile are committed: the project owns its\n // @standardagents/* versions and the platform build installs them frozen for\n // byte-exact, reproducible deploys (the build runner uses whichever package\n // manager the committed lockfile implies). Only secrets, dependencies, and\n // local build/dev state are ignored.\n return `node_modules\ndist\n.agents\n.wrangler\n.env\n.dev.vars\n.agentbuilder-dev.log\n`\n}\n\nexport function renderDevVarsExample(): string {\n return `# Standard Agents local development environment\n# Copy to .dev.vars for local-only Worker secrets.\n\n# Local data encryption key. Generate with: openssl rand -hex 32\nENCRYPTION_KEY=\n\n# Optional local admin password for development access.\nSUPER_ADMIN_PASSWORD=password\n\n# Platform connection. The CLI writes real values to .dev.vars for platform-created projects.\nSTANDARD_AGENTS_API_KEY=\nPLATFORM_ENDPOINT=\nSTANDARD_AGENTS_API_URL=\n\n# BYOK provider keys. When set, these keys override Standard Agents hosted routing for that provider.\nCLOUDFLARE_API_TOKEN=\nCLOUDFLARE_ACCOUNT_ID=\nCEREBRAS_API_KEY=\nGOOGLE_API_KEY=\nGROQ_API_KEY=\nOPENAI_API_KEY=\nOPENROUTER_API_KEY=\nANTHROPIC_API_KEY=\nXAI_API_KEY=\n`\n}\n\nexport function renderTemplateMetadata(options: AgentBuilderProjectTemplateOptions): string {\n return `${JSON.stringify({\n generator: '@standardagents/agentbuilder-template',\n template_version: options.templateVersion ?? AGENTBUILDER_TEMPLATE_VERSION,\n project_name: options.projectName,\n }, null, 2)}\\n`\n}\n\nexport function renderAgentBuilderSupportFiles(options: AgentBuilderProjectTemplateOptions): TemplateFile[] {\n return [\n file('package.json', renderPackageJson(options), 'Add local AgentBuilder package manifest'),\n ]\n}\n\nexport function renderAgentBuilderProject(options: AgentBuilderProjectTemplateOptions): TemplateFile[] {\n const files: TemplateFile[] = [\n // The project owns its @standardagents/* versions: the committed manifest is\n // the source of truth the platform build honors (what you test locally is\n // what deploys). It ships a guard `build` script that refuses to build\n // off-platform; the build runner swaps in the real `vite build` at build\n // time. Never set includeBuildScript here — a working local build would let\n // a half-configured checkout deploy from the wrong place.\n file('package.json', renderPackageJson({ ...options, includeBuildScript: false }), 'Add package manifest'),\n // Committed alongside package.json so a freshly cloned repo ignores\n // node_modules, lockfiles, secrets, and local build state without depending\n // on the CLI to generate a .gitignore after clone.\n file('.gitignore', renderGitignore(), 'Add gitignore'),\n file('tsconfig.json', renderTsConfig(), 'Add TypeScript config'),\n file('vite.config.ts', renderViteConfig(), 'Add Vite config'),\n file('agents/agents/AGENTS.md', AGENT_DEFINITIONS_AGENTS_MD, 'Add agent docs'),\n symlink('agents/agents/CLAUDE.md', 'AGENTS.md', 'Add Claude agent docs symlink'),\n file('agents/prompts/AGENTS.md', PROMPTS_AGENTS_MD, 'Add prompt docs'),\n symlink('agents/prompts/CLAUDE.md', 'AGENTS.md', 'Add Claude prompt docs symlink'),\n file('agents/models/AGENTS.md', MODELS_AGENTS_MD, 'Add model docs'),\n symlink('agents/models/CLAUDE.md', 'AGENTS.md', 'Add Claude model docs symlink'),\n file('agents/providers/AGENTS.md', PROVIDERS_AGENTS_MD, 'Add provider docs'),\n symlink('agents/providers/CLAUDE.md', 'AGENTS.md', 'Add Claude provider docs symlink'),\n file('agents/tools/AGENTS.md', TOOLS_AGENTS_MD, 'Add tool docs'),\n symlink('agents/tools/CLAUDE.md', 'AGENTS.md', 'Add Claude tool docs symlink'),\n file('agents/hooks/AGENTS.md', HOOKS_AGENTS_MD, 'Add hook docs'),\n symlink('agents/hooks/CLAUDE.md', 'AGENTS.md', 'Add Claude hook docs symlink'),\n file('agents/api/AGENTS.md', API_AGENTS_MD, 'Add API docs'),\n symlink('agents/api/CLAUDE.md', 'AGENTS.md', 'Add Claude API docs symlink'),\n ]\n\n if (options.includeTemplateMetadata) {\n files.push(file('.standardagents/template.json', renderTemplateMetadata(options), 'Add Standard Agents template metadata'))\n }\n\n return files\n}\n"],"mappings":";AAAO,IAAM,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAvB,IAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAzB,IAAM,sBAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACA5B,IAAM,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACA1B,IAAM,8BAA8B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACApC,IAAM,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAxB,IAAM,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAxB,IAAM,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;AC8DtB,IAAM,gCAAgC;AAAA,EAC3C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAUO,IAAM,oCAAoC;AAAA,EAC/C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AASO,IAAM,4BAA8C;AAAA,EACzD,gBAAgB;AAAA,EAChB,KAAK;AAAA,EACL,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,KAAK;AACP;AAEO,IAAM,gCAAgC;AAE7C,SAAS,sBAAsB,OAAuB;AACpD,SAAO,MAAM,SAAS,IAAI,IAAI,QAAQ,GAAG,KAAK;AAAA;AAChD;AAEA,SAAS,cAAc,UAAwD;AAC7E,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAG;AAAA,EACL;AACF;AAEO,SAAS,2BAA2B,aAA6B;AACtE,QAAM,aAAa,YAChB,YAAY,EACZ,QAAQ,aAAa,EAAE,EACvB,QAAQ,eAAe,GAAG,EAC1B,QAAQ,YAAY,EAAE;AACzB,SAAO,cAAc;AACvB;AAEA,SAAS,KAAK,MAAc,SAAiB,SAA+B;AAC1E,SAAO;AAAA,IACL;AAAA,IACA,SAAS,sBAAsB,OAAO;AAAA,IACtC;AAAA,IACA,MAAM;AAAA,EACR;AACF;AAEA,SAAS,QAAQ,MAAc,QAAgB,SAA+B;AAC5E,SAAO;AAAA,IACL;AAAA,IACA,SAAS;AAAA,IACT;AAAA,IACA,MAAM;AAAA,EACR;AACF;AAEO,SAAS,kBAAkB,SAAqD;AACrF,QAAM,WAAW,cAAc,QAAQ,QAAQ;AAC/C,QAAM,wBAAwB,SAAS;AACvC,QAAM,eAAuC;AAAA,IAC3C,2BAA2B;AAAA,IAC3B,wBAAwB;AAAA,IACxB,uBAAuB,SAAS;AAAA,IAChC,KAAK,SAAS,OAAO;AAAA,EACvB;AAEA,aAAW,mBAAmB,+BAA+B;AAC3D,iBAAa,eAAe,IAAI;AAAA,EAClC;AAEA,SAAO,GAAG,KAAK,UAAU;AAAA,IACvB,MAAM,2BAA2B,QAAQ,WAAW;AAAA,IACpD,SAAS;AAAA,IACT,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,MACP,KAAK;AAAA,MACL,OAAO,QAAQ,qBACX,eACA;AAAA,MACJ,WAAW;AAAA,IACb;AAAA,IACA;AAAA,IACA,iBAAiB;AAAA,MACf,YAAY,SAAS;AAAA,MACrB,MAAM,SAAS;AAAA,IACjB;AAAA,IACA,MAAM;AAAA,MACJ,uBAAuB,CAAC,GAAG,iCAAiC;AAAA,IAC9D;AAAA,EACF,GAAG,MAAM,CAAC,CAAC;AAAA;AACb;AAEO,SAAS,mBAA2B;AACzC,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAOT;AAEO,SAAS,iBAAyB;AACvC,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiBT;AAEO,SAAS,kBAA0B;AAMxC,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQT;AAEO,SAAS,uBAA+B;AAC7C,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAyBT;AAEO,SAAS,uBAAuB,SAAqD;AAC1F,SAAO,GAAG,KAAK,UAAU;AAAA,IACvB,WAAW;AAAA,IACX,kBAAkB,QAAQ,mBAAmB;AAAA,IAC7C,cAAc,QAAQ;AAAA,EACxB,GAAG,MAAM,CAAC,CAAC;AAAA;AACb;AAEO,SAAS,+BAA+B,SAA6D;AAC1G,SAAO;AAAA,IACL,KAAK,gBAAgB,kBAAkB,OAAO,GAAG,yCAAyC;AAAA,EAC5F;AACF;AAEO,SAAS,0BAA0B,SAA6D;AACrG,QAAM,QAAwB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAO5B,KAAK,gBAAgB,kBAAkB,EAAE,GAAG,SAAS,oBAAoB,MAAM,CAAC,GAAG,sBAAsB;AAAA;AAAA;AAAA;AAAA,IAIzG,KAAK,cAAc,gBAAgB,GAAG,eAAe;AAAA,IACrD,KAAK,iBAAiB,eAAe,GAAG,uBAAuB;AAAA,IAC/D,KAAK,kBAAkB,iBAAiB,GAAG,iBAAiB;AAAA,IAC5D,KAAK,2BAA2B,6BAA6B,gBAAgB;AAAA,IAC7E,QAAQ,2BAA2B,aAAa,+BAA+B;AAAA,IAC/E,KAAK,4BAA4B,mBAAmB,iBAAiB;AAAA,IACrE,QAAQ,4BAA4B,aAAa,gCAAgC;AAAA,IACjF,KAAK,2BAA2B,kBAAkB,gBAAgB;AAAA,IAClE,QAAQ,2BAA2B,aAAa,+BAA+B;AAAA,IAC/E,KAAK,8BAA8B,qBAAqB,mBAAmB;AAAA,IAC3E,QAAQ,8BAA8B,aAAa,kCAAkC;AAAA,IACrF,KAAK,0BAA0B,iBAAiB,eAAe;AAAA,IAC/D,QAAQ,0BAA0B,aAAa,8BAA8B;AAAA,IAC7E,KAAK,0BAA0B,iBAAiB,eAAe;AAAA,IAC/D,QAAQ,0BAA0B,aAAa,8BAA8B;AAAA,IAC7E,KAAK,wBAAwB,eAAe,cAAc;AAAA,IAC1D,QAAQ,wBAAwB,aAAa,6BAA6B;AAAA,EAC5E;AAEA,MAAI,QAAQ,yBAAyB;AACnC,UAAM,KAAK,KAAK,iCAAiC,uBAAuB,OAAO,GAAG,uCAAuC,CAAC;AAAA,EAC5H;AAEA,SAAO;AACT;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@standardagents/agentbuilder-template",
3
- "version": "0.21.1",
3
+ "version": "0.22.0",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public",