@standardagents/agentbuilder-template 0.40.12 → 0.41.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 +9 -7
- package/dist/index.js +332 -128
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
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## Packability and Runtime Portability\n\nTreat an agent project as an installable Standard Agent package, not as a\nprivileged extension of one runtime. Everything required for the declared\nagents to execute must use capabilities defined by the Standard Agent\nSpecification and exported with the package.\n\nDo not make required behavior depend on private Durable Object methods,\nimplementation-specific storage schemas or bindings, undocumented HTTP or\nWebSocket events, product sidecars that replace runtime behavior, or\nThreadState._notPackableRuntimeContext. Client-side state may be an\noptimistic cache, but it must not become the only source of truth for agent\nsemantics.\n\nIf the specification lacks a required primitive, define the runtime-neutral\ncapability in @standardagents/spec, document it in the public specification,\nimplement it generically in the runtime, and add conformance coverage before\nthe agent relies on it. Authentication, billing, deployment, and branded UI\nservices may remain external as long as they are not required for the packed\nagent's core execution semantics.\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\nFor remote local development, opt exact hostnames into the authoring boundary:\n\n```typescript\nbuilder({ trustedDevHosts: ['macbookserver.tail13bd39.ts.net'] })\n```\n\nThis never changes hosted behavior. Adding a hostname grants anyone who can\nreach the dev server through that name the ability to attempt authoring access;\nsame-origin and normal authoring credential checks still apply. Wildcards,\nschemes, ports, and paths are rejected.\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 runtimeStreams?: RuntimeStreams; // Optional live execution-host byte streams\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 emit(event, data): void; // Broadcast a custom event to connected thread clients\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`state.runtimeStreams` is optional. Feature-detect it before opening a live\nbyte stream. Capability names and metadata are runtime-defined; streams never\npark or survive an execution-host disconnect. See the tools guide for a full\nfeature-detection, write, read, and cleanup example.\n\n`state.emit(event, data)` works from tools, hooks, and thread endpoints. In\nan endpoint it broadcasts immediately even though there is no active\nexecution, which is useful for invalidating client snapshots after a durable\n`setValue()`. Events are not durable; clients must re-read state after\nreconnecting.\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- A resumable child's session ending never terminates its thread. The same reference remains addressable for later `subagent_message` calls; only explicit `state.terminate()` tears the thread down.\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 cost safety\n\nAgentBuilder bounds each Durable Object alarm invocation to 1,000,000 SQLite\nrows read and 10,000 rows written. A breach persistently quarantines that one\nobject, clears its alarm, preserves all storage, and requires an explicit\nresume. Routine alarm rows are deleted when completed; effect history remains\navailable with bounded retention. Deployments integrated with Brolly configure\n`BROLLY_CONTROL_PUBLIC_KEY_JWK` and `BROLLY_ACCOUNT_ID`; the built-in signed\n`POST /api/auth/brolly-control` route can then quarantine an exact object ID.\n\nDo not expose the Brolly private signing key to the AgentBuilder Worker. Do not\ndisable the retention sweeper except as a temporary rollback while diagnosing\na deployment.\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. An agent has exactly two sides; each side is backed by a human (`{ human: true }`), a prompt (`{ prompt: 'name' }`), or a handler (`{ handler: 'name' }` \u2014 deterministic code from `agents/handlers/`).\n**Threads** are individual conversation instances with persistent storage.\n\n## Packability and Runtime Portability\n\nTreat an agent project as an installable Standard Agent package, not as a\nprivileged extension of one runtime. Everything required for the declared\nagents to execute must use capabilities defined by the Standard Agent\nSpecification and exported with the package.\n\nDo not make required behavior depend on private Durable Object methods,\nimplementation-specific storage schemas or bindings, undocumented HTTP or\nWebSocket events, product sidecars that replace runtime behavior, or\nThreadState._notPackableRuntimeContext. Client-side state may be an\noptimistic cache, but it must not become the only source of truth for agent\nsemantics.\n\nIf the specification lacks a required primitive, define the runtime-neutral\ncapability in @standardagents/spec, document it in the public specification,\nimplement it generically in the runtime, and add conformance coverage before\nthe agent relies on it. Authentication, billing, deployment, and branded UI\nservices may remain external as long as they are not required for the packed\nagent's core execution semantics.\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 handlers/ # Handler definitions (defineHandler)\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\nFor remote local development, opt exact hostnames into the authoring boundary:\n\n```typescript\nbuilder({ trustedDevHosts: ['macbookserver.tail13bd39.ts.net'] })\n```\n\nThis never changes hosted behavior. Adding a hostname grants anyone who can\nreach the dev server through that name the ability to attempt authoring access;\nsame-origin and normal authoring credential checks still apply. Wildcards,\nschemes, ports, and paths are rejected.\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[]; // Child instance 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 runtimeStreams?: RuntimeStreams; // Optional live execution-host byte streams\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 emit(event, data): void; // Broadcast a custom event to connected thread clients\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`state.runtimeStreams` is optional. Feature-detect it before opening a live\nbyte stream. Capability names and metadata are runtime-defined; streams never\npark or survive an execution-host disconnect. See the tools guide for a full\nfeature-detection, write, read, and cleanup example.\n\n`state.emit(event, data)` works from tools, hooks, and thread endpoints. In\nan endpoint it broadcasts immediately even though there is no active\nexecution, which is useful for invalidating client snapshots after a durable\n`setValue()`. Events are not durable; clients must re-read state after\nreconnecting.\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\nA subagent is any agent composed as a child of another agent. Relationships are declared in the `subagents` array of a prompt- or handler-backed agent side (never inside a prompt's `tools` array):\n\n- Each subagent runs in its own thread (`DurableThread`)\n- Parent/child linkage is tracked in thread metadata; instances are visible in `state.children`\n- The relationship's owning side is where child traffic lands; parent\u2192child traffic enters in the child's side B perspective (`role: 'user'`), so the child's side A acts on it\n- For a prompt-backed owning side, the runtime injects the lifecycle tools `subagents`, `subagent_create`, and `subagent_message`; handler-backed sides reach children through `ThreadState` directly\n- `subagent_create.arguments` is validated from the receiving child's side A 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- Persistence is universal: a child's session ending never terminates its thread. The same reference remains addressable for later `subagent_message` calls; only explicit `state.terminate()` tears the thread down.\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| `defineHandler()` | Deterministic side turns | `agents/handlers/` |\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 cost safety\n\nAgentBuilder bounds each Durable Object alarm invocation to 1,000,000 SQLite\nrows read and 10,000 rows written. A breach persistently quarantines that one\nobject, clears its alarm, preserves all storage, and requires an explicit\nresume. Routine alarm rows are deleted when completed; effect history remains\navailable with bounded retention. Deployments integrated with Brolly configure\n`BROLLY_CONTROL_PUBLIC_KEY_JWK` and `BROLLY_ACCOUNT_ID`; the built-in signed\n`POST /api/auth/brolly-control` route can then quarantine an exact object ID.\n\nDo not expose the Brolly private signing key to the AgentBuilder Worker. Do not\ndisable the retention sweeper except as a temporary rollback while diagnosing\na deployment.\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` | `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| DeepInfra | `DEEPINFRA_API_KEY` |\n| Groq | `GROQ_API_KEY` |\n| Novita AI | `NOVITA_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/
|
|
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| DeepInfra | `DEEPINFRA_API_KEY` |\n| Groq | `GROQ_API_KEY` |\n| Novita AI | `NOVITA_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/spec';\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- **DeepInfra note:** the provider reads live pricing from `/v1/models` and preserves response-level `usage.estimated_cost`; custom catalog endpoints can be configured with the provider's `modelsUrl` slot\n- **Novita note:** the Novita provider reads live catalog pricing from `/openai/v1/models`, including cache-read prices when available, but custom/private Novita models should still set `inputPrice`, `outputPrice`, and `cachedPrice`\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 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/
|
|
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/spec';\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## Error attribution\n\nWhen an override catches and rethrows an upstream failure, preserve structured\nattribution with `ProviderError` instead of putting the provider name only in\nthe message:\n\n```typescript\nimport { ProviderError } from '@standardagents/builder';\n\nthrow new ProviderError(message, 'server_error', status, retryAfter, {\n cause: error,\n origin: 'provider:my_openai_compatible_provider',\n upstream: 'example-backend',\n});\n```\n\n`origin` is machine-readable (`provider:<id>` for provider failures), while\n`upstream` names the actual backend when it differs from the adapter. Builder\nrequest logs retain these fields and render them separately from the human\nmessage. Do not make operators infer the failing layer from prose.\n";
|
|
6
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 // The same agent exposed under a task-specific tool name: `name` is what\n // the model calls; `agent` is the dual_ai agent that implements it.\n { name: 'summarize_report', agent: 'data_processor_agent', blocking: true },\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).\nAdding an enabled child relationship automatically activates the child's\ndisclosed `parentHooks` on this parent. Disabled optional relationships do\nnot; hidden enabled relationships do. `name` is the relationship provenance\nand `agent ?? name` identifies the implementing child.\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";
|
|
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)[]` | No | Available tools: tool names, sub-prompt names, provider tools, and exposed agent names for handoffs. Subagent relationships never appear here \u2014 they are declared on the agent side's `subagents` array |\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### Subagents Come From the Side, Not the Tools Array\n\nComposition into a child thread is not a prompt-tools concern. A subagent relationship is part of the agent's structure: it is declared in the `subagents` array of the agent side this prompt backs, never inside the prompt's `tools` array (a `tools` entry attempting to configure a subagent relationship is a definition-time error). The side's declaration is the grant:\n\n```typescript\n// agents/agents/assistant_agent.ts\nsideA: {\n prompt: 'coordinator',\n subagents: [\n { agent: 'calendar_agent', as: 'work_calendar', scopedEnv: ['WORK_CAL_ID'] },\n { agent: 'calendar_agent', as: 'personal_calendar', scopedEnv: ['PERSONAL_CAL_ID'] },\n { agent: 'research_agent', blocking: true, maxInstances: 1 },\n { agent: 'compaction_agent', hidden: true },\n { agent: 'browser_agent', optional: 'ENABLE_BROWSER_AGENT' },\n ],\n},\n```\n\nFor a prompt-backed side with non-hidden relationships, the runtime automatically injects three lifecycle tools scoped to that side's declarations:\n\n- `subagents` \u2014 pull-based visibility: returns the registry snapshot (reference, relationship name, agent name, status, initial arguments, creation time). Call it before `subagent_create` so existing instances are reused rather than duplicated.\n- `subagent_create` \u2014 creates (or continues) an instance. Its `agent` argument enumerates the side's enabled relationship *names* (`as`, defaulting to `agent`), never internal agent identifiers. It requires a non-empty `name` for the spawned instance; AgentBuilder stores that as a `name:<value>` thread tag for human-friendly labels.\n- `subagent_message` \u2014 queues a message to an existing instance by reference.\n\nThese three names are reserved; a relationship `as` that collides with them (or with any other tool name) is a definition-time error.\n\n`subagent_create.arguments` is shaped by the `requiredSchema` of the receiving child's side A prompt (parent traffic enters the child in the side B perspective, `role: 'user'`, so side A acts on it exactly as for an external caller). AgentBuilder validates and persists those arguments for the life of the child thread, exposes them as `ThreadState.arguments` and prompt variables to **both** child sides, and rehydrates them on every later activation. Missing required arguments fail creation with a structured `subagent_arguments_required` error.\n\nPersistence is universal: every child instance is a persistent thread. Session end never terminates a child \u2014 a later `subagent_message` starts a new session with history intact; only explicit `state.terminate()` destroys an instance. `blocking: true` makes `subagent_create` await the child session's close and return its result; combined with `maxInstances: 1` and an existing instance it behaves as create-or-continue.\n\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\nSee `agents/agents/AGENTS.md` for the full `SubagentRelationship` option list (`immediate`, `optional`, `hidden`, `parentCommunication`, init mappings) and the ownership rules.\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";
|
|
8
8
|
|
|
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| `primary` | `boolean` | No | Default true. Set false on internal handoff-target agents (e.g. domain-gearbox variants) to hide them from top-level UI agent lists; they stay fully addressable for handoffs and thread resumption |\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| `parentHooks` | `ParentHookRequirement[]` | No | Hooks an exposed dual-AI child automatically contributes to each direct parent |\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\nAn exposed `dual_ai` child can declare required parent integration hooks:\n\n```typescript\nparentHooks: [{\n hook: 'sync_gmail_context',\n reason: 'Makes synchronized Gmail context available to the coordinator.',\n stage: 'before_parent', // default: after_parent\n}],\n```\n\nInstalling the package is inert. Adding this child to a prompt activates the\nhook automatically on that direct parent and composition UIs can show the\n`reason` first. Disabled optional relationships contribute nothing; enabled\nhidden relationships still contribute hooks. Required hooks run with the\nparent's `ThreadState`, load from the child's package namespace, and fail\ncomposition closed if missing. User-scope hooks cannot be listed.\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## Icons\n\nGive an agent a custom icon with the `icon` property: a full URL, a data URI,\nor a site-relative path served from your project's `public/` directory \u2014\n`icon: '/icons/support.svg'` expects the file at `public/icons/support.svg`.\nThe file is served in dev and deployed with your project's assets. Agents\nwithout an icon (or whose icon fails to load) render a generated identicon,\nand the dashboard warns when a site-relative icon path has no matching file.\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";
|
|
9
|
+
declare const AGENT_DEFINITIONS_AGENTS_MD = "# Agent Definitions\n\nAn agent is the top-level conversation orchestrator. An agent has **exactly two sides**, and each side is **backed** by exactly one of three things: a human, a prompt, or a handler. There is no agent \"type\" \u2014 everything about how an agent converses, composes, and terminates is derived from the backings of its two sides.\n\n| Backing | Who takes this side's turns | Declared as |\n|---------|-----------------------------|-------------|\n| **Human** | A person, via whatever interface the runtime provides | `{ human: true }` |\n| **Prompt** | A model, driven by a prompt from `agents/prompts/` | `{ prompt: 'name', ... }` |\n| **Handler** | Deterministic code from `agents/handlers/` | `{ handler: 'name', ... }` |\n\nBoth sides are explicit. There is no implicit \"missing side B is a human\" default \u2014 if a person takes side B's turns, write `sideB: { human: true }`.\n\n## Agent Properties\n\n| Property | Type | Required | Description |\n|----------|------|----------|-------------|\n| `name` | `string` | Yes | Unique identifier for this agent |\n| `sideA` | `SideConfig` | Yes | Side A configuration (backing-discriminated) |\n| `sideB` | `SideConfig` | Yes | Side B configuration (backing-discriminated) |\n| `maxSessionTurns` | `number` | No | Session exchange safety cap \u2014 optional on every agent shape |\n| `title` | `string` | No | Human-readable label |\n| `description` | `string` | No | Agent summary |\n| `icon` | `string` | No | Display icon (see Icons below) |\n| `exposeAsTool` | `boolean` | No | Expose a callable entrypoint for handoffs and composition |\n| `primary` | `boolean` | No | Default true. Set false on internal handoff-target agents (e.g. domain-gearbox variants) to hide them from top-level UI agent lists; they stay fully addressable for handoffs and thread resumption |\n| `toolDescription` | `string` | No | Default model-facing description when this agent is composed or handed off to (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| `parentHooks` | `ParentHookRequirement[]` | No | Required hooks automatically contributed to a direct parent composition (legal on any exposed agent) |\n| `tags` | `string[]` | No | Tags for categorization and filtering |\n\n## Side Configuration\n\nA side's configuration is discriminated by its backing: exactly one of `human`, `prompt`, or `handler` must be present.\n\n**Human side** \u2014 `{ human: true, label? }`. No other properties are legal on a human side. In particular, `subagents` on a human side is a definition-time error (nothing there can invoke them), and stop/session bindings are meaningless.\n\n**Prompt side**\n\n| Property | Type | Required | Description |\n|----------|------|----------|-------------|\n| `prompt` | `string` | Yes | Prompt name to use (references `agents/prompts/`) |\n| `label` | `string` | No | Display name for this side |\n| `subagents` | `SubagentRelationship[]` | No | Side-owned child relationships (see Subagent Relationships below) |\n| `stopOnResponse` | `boolean` | No | Stop side turn on text response without tool calls (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` | `SessionToolBinding` | No | Terminal success lifecycle binding (object form only) |\n| `sessionFail` | `SessionToolBinding` | No | Terminal failure lifecycle binding (object form only) |\n| `sessionStatus` | `SessionToolBinding` | No | Non-terminal status lifecycle binding (object form only) |\n\n**Handler side**\n\n| Property | Type | Required | Description |\n|----------|------|----------|-------------|\n| `handler` | `string` | Yes | Handler name for this side (references `agents/handlers/`) |\n| `label` | `string` | No | Display name for this side |\n| `subagents` | `SubagentRelationship[]` | No | Side-owned child relationships |\n\nHandler sides have no `maxSteps`, `stopOnResponse`, or session bindings: a handler turn is a single invocation, and handlers end sessions through `state.stopSession()` rather than declarative bindings. See `agents/handlers/AGENTS.md`.\n\nSession lifecycle bindings use the object form only:\n\n```typescript\nsessionStop: {\n name: 'complete_work', // tool that controls the lifecycle action\n messageProperty: 'summary', // arg field that becomes lifecycle message text\n attachmentsProperty: 'files', // arg field containing attachment path(s)\n}\n```\n\n## Derivations\n\nThese follow from the backings and are never declared separately:\n\n- **Chat surface** \u2014 the primary conversational interface renders wherever a `human` backing is.\n- **Perspective** \u2014 `role: 'user'` is the side B perspective, `role: 'assistant'` is the side A perspective, for queueing, injection, and rendering alike.\n- **Subagent eligibility** \u2014 any agent may be composed as a subagent. Composing a child with a human side puts a person's step inside the composition (the child parks `awaiting_human` until that person responds).\n- **Termination discipline** \u2014 `maxSessionTurns` is optional on every agent shape, with uniform exchange counting across backings (a handler turn counts like a prompt turn). Two prompt-backed sides can ping-pong indefinitely \u2014 the cap is a voluntary safety valve, and prompt and handler authors own their termination discipline.\n\n## Example: Assistant (human \u00D7 prompt)\n\nThe everyday user-facing assistant \u2014 a person on side B, a model on side A:\n\n```typescript\nimport { defineAgent } from '@standardagents/builder';\n\nexport default defineAgent({\n name: 'support_agent',\n sideA: {\n label: 'Support',\n prompt: 'customer_support',\n stopOnResponse: true,\n sessionStop: { name: 'close_ticket' },\n maxSteps: 50,\n },\n sideB: { human: true },\n tags: ['support', 'tier-1'],\n});\n```\n\n## Example: Worker / Reviewer (prompt \u00D7 prompt)\n\nTwo models converse; each side sees itself as `assistant` and the other as `user`. `maxSessionTurns` is optional but strongly recommended here \u2014 nothing external stops two models:\n\n```typescript\nexport default defineAgent({\n name: 'research_agent',\n maxSessionTurns: 20,\n exposeAsTool: true,\n toolDescription: 'Researches and validates findings autonomously',\n sideA: {\n label: 'Worker',\n prompt: 'research_worker',\n stopOnResponse: true,\n sessionStatus: { name: 'set_research_status', messageProperty: 'status' },\n sessionFail: { name: 'fail_research', messageProperty: 'reason' },\n },\n sideB: {\n label: 'Reviewer',\n prompt: 'research_reviewer',\n stopOnResponse: true,\n sessionStop: { name: 'approve_research', messageProperty: 'summary' },\n },\n});\n```\n\n## Example: Relay (handler \u00D7 human)\n\nA deterministic, model-less surface: a person talks to a handler that forwards traffic to a composed child and relays answers back. Zero LLM calls happen on this thread:\n\n```typescript\nexport default defineAgent({\n name: 'relay_agent',\n sideA: {\n handler: 'relay_pipe',\n subagents: [{ agent: 'assistant_agent', maxInstances: 1 }],\n },\n sideB: { human: true },\n});\n```\n\nThe `relay_pipe` handler lives in `agents/handlers/relay_pipe.ts` \u2014 the full worked example is in `agents/handlers/AGENTS.md`.\n\n## Subagent Relationships\n\nComposition into a child thread is declared on the side that owns it \u2014 never inside a prompt's `tools` array. The side's declaration is the grant:\n\n```typescript\nsideA: {\n prompt: 'coordinator',\n subagents: [\n { agent: 'calendar_agent', as: 'work_calendar', scopedEnv: ['WORK_CAL_ID'] },\n { agent: 'calendar_agent', as: 'personal_calendar', scopedEnv: ['PERSONAL_CAL_ID'] },\n { agent: 'research_agent', blocking: true, maxInstances: 1 },\n ],\n},\n```\n\n- The owning side is where child traffic lands: completion, failure, and status messages arrive on the owning side's perspective. Parent\u2192child traffic enters in the child's side B perspective (`role: 'user'`), so the child's side A acts on it.\n- A relationship name (`as`, defaulting to `agent`) may appear on at most one side, must not collide with another tool name, and must not collide with the reserved lifecycle tool names `subagents`, `subagent_create`, `subagent_message`.\n- For a prompt-backed owning side, the runtime injects those lifecycle tools automatically. Handler-backed owning sides need no tool grant \u2014 handlers reach children through `ThreadState` directly.\n- **Persistence is universal**: every child instance is a persistent thread. Session end never terminates a thread; only explicit `state.terminate()` destroys an instance. `blocking` is purely a waiting style.\n\nSee `agents/prompts/AGENTS.md` for the lifecycle tools from the prompt's point of view, and the relationship option list (`immediate`, `optional`, `hidden`, `parentCommunication`, init mappings).\n\n## Agent Handoffs\n\nWhen `exposeAsTool: true`, an agent referenced directly in a prompt's `tools` array is a **handoff**: the tool call transfers control of the *same thread* to the target agent, preserving history. Handoff requires the target agent to have a human side matching the thread's conversational surface.\n\n```typescript\nexport default defineAgent({\n name: 'escalation_agent',\n exposeAsTool: true,\n toolDescription: 'Escalate to senior support for complex issues',\n sideA: { prompt: 'senior_support' },\n sideB: { human: true },\n});\n```\n\n## Stop Semantics\n\nRuntime stop evaluation order for prompt-backed sides:\n\n1. **sessionStop / sessionFail** \u2014 end the session (success / terminal failure)\n2. **stopTool** \u2014 ends the current side's turn\n3. **stopOnResponse** \u2014 ends the turn when the LLM returns text without tool calls\n4. **Safety limits** \u2014 `maxSteps` (per side), `maxSessionTurns` (per session, hard limit: 250)\n\nA handler-backed side's turn ends when its handler invocation returns. A human-backed side's turn ends when the human's inbound message is persisted.\n\n## Definition-Time Errors\n\nThese shapes are rejected when definitions load:\n\n1. Both sides human (reserved \u2014 may lift in a later version)\n2. `subagents` declared on a human-backed side\n3. A side with zero backings, or more than one of `human` / `prompt` / `handler`\n4. A handler side referencing an undefined handler; a prompt side referencing an undefined prompt\n5. A relationship name (`as`) appearing on both sides, colliding with another tool name, or colliding with a reserved lifecycle tool name\n6. Session bindings, `maxSteps`, or stop bindings on a non-prompt side\n7. A session binding that is not in object form\n\n## Hooks\n\nAttach lifecycle hooks at the agent level:\n\n```typescript\nexport default defineAgent({\n name: 'support_agent',\n hooks: ['log_all_messages', 'sanitize_results'],\n sideA: { prompt: 'customer_support' },\n sideB: { human: true },\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\nAny exposed agent can declare required parent integration hooks:\n\n```typescript\nparentHooks: [{\n hook: 'sync_gmail_context',\n reason: 'Makes synchronized Gmail context available to the coordinator.',\n stage: 'before_parent', // default: after_parent\n}],\n```\n\nInstalling the package is inert. Declaring a relationship targeting this agent\n(or adding it to a prompt as a handoff) activates the hook automatically on\nthat direct parent, and composition UIs disclose the `reason` first. Disabled\noptional relationships contribute nothing; enabled hidden relationships still\ncontribute hooks. Required hooks run with the parent's `ThreadState`, load\nfrom the child's package namespace, and fail composition closed if missing.\nUser-scope hooks cannot be listed.\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## Icons\n\nGive an agent a custom icon with the `icon` property: a full URL, a data URI,\nor a site-relative path served from your project's `public/` directory \u2014\n`icon: '/icons/support.svg'` expects the file at `public/icons/support.svg`.\nThe file is served in dev and deployed with your project's assets. Agents\nwithout an icon (or whose icon fails to load) render a generated identicon,\nand the dashboard warns when a site-relative icon path has no matching file.\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- **Write sideB explicitly** - there is no implicit default; a user-facing agent ends with `sideB: { human: true }`\n- **Cap prompt \u00D7 prompt agents** - set `maxSessionTurns` when both sides are prompt-backed; nothing external stops two models\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";
|
|
10
|
+
|
|
11
|
+
declare const HANDLERS_AGENTS_MD = "# Handler Definitions\n\nA handler is a function that takes one side's turns in a conversation. When a side of an agent is backed by a handler, the runtime does not call a model to answer an inbound message \u2014 it calls the handler function once, with the thread state and the message, and whatever that function does is the side's turn.\n\nA handler is **not** a hook (hooks decorate turns owned by something else, and their failures are non-fatal), **not** a tool (tools are capabilities a turn-owner chooses to invoke), and **not** an effect (effects run outside the conversation flow). Its only role is backing a side of an agent. Handlers may not be referenced by prompt `tools` arrays, hook lists, or effect schedules \u2014 such references are definition-time errors.\n\n## Properties\n\n| Property | Type | Required | Description |\n|----------|------|----------|-------------|\n| `description` | `string` | No | Human-facing summary |\n| `execute` | `(state: ThreadState, message: Message) => Promise<void>` | Yes | The turn implementation |\n\nThe handler's name comes from its filename: `agents/handlers/relay_pipe.ts` defines the handler `relay_pipe`. The `message` parameter is the full persisted message \u2014 id, role, content, silent flag, metadata, timestamps. Handlers are trusted definition code, like tools.\n\n## Basic Example\n\n```typescript\n// agents/handlers/relay_pipe.ts\nimport { defineHandler } from '@standardagents/builder';\n\nexport default defineHandler({\n description: 'Forwards inbound user traffic to the assistant child and relays answers back.',\n execute: async (state, message) => {\n // full ThreadState \u2014 forward, respond, spawn, stop, read/write KV\n },\n});\n```\n\nReference it from exactly one place: the `handler` property of an agent side:\n\n```typescript\nexport default defineAgent({\n name: 'relay_agent',\n sideA: { handler: 'relay_pipe', subagents: [{ agent: 'assistant_agent', maxInstances: 1 }] },\n sideB: { human: true },\n});\n```\n\n## Execution Model\n\nA handler-backed side's turn is:\n\n1. An inbound message arrives on the side's perspective.\n2. The runtime invokes the handler once with the thread's `ThreadState` and that message.\n3. The invocation returns (or throws). The turn is complete.\n\nThere are no steps, no tool-choice loop, and no model requests for this side. `maxSteps`, `stopOnResponse`, `stopTool`, and session bindings are not legal on handler sides \u2014 a handler turn has no steps to cap and ends when `execute` returns. Handlers end sessions explicitly via `state.stopSession()`. When the agent sets `maxSessionTurns`, a handler turn counts toward the exchange cap exactly like a prompt turn.\n\n## Delivery Semantics\n\nDelivery to a handler is **exactly-once per message**:\n\n- The handler is invoked exactly once for each inbound message on the side's perspective, in message persistence order.\n- The handler is never invoked concurrently for the same thread. Messages that arrive while a handler turn is in flight wait in the queue and are delivered one at a time, in order.\n- A message whose handler invocation failed is not automatically redelivered. Retry is a userland decision (re-send the message).\n\n**Warning:** Because queued messages wait behind the in-flight turn, a long-running handler stalls its thread. A handler that awaits a `blocking` child session holds the delivery slot for that session's entire duration \u2014 and if that child can only finish after *another* inbound message on this thread, the thread deadlocks. Relay-style handlers should forward without blocking (`queueMessage` toward the child) and treat the child's replies as ordinary later turns.\n\n## Error Semantics\n\nA handler that throws is **fatal to the turn, and only the turn**:\n\n- The turn is marked failed and the error is surfaced in the runtime's request/execution log as a runtime-origin failure \u2014 a throwing handler never silently swallows a message.\n- The inbound message stays persisted. Nothing is rolled back.\n- The **session continues**: the failure does not end the session, terminate the thread, or poison the queue. The next inbound message gets a fresh handler invocation.\n\nIf an error should end the session, the handler must do so explicitly with `state.stopSession()`.\n\n## Capabilities\n\nA handler receives the full `ThreadState` and may do anything tools can do:\n\n- **Forward** \u2014 `(await state.getChildThread(ref)).queueMessage(...)` toward a child, or `state.notifyParent(...)` toward a parent.\n- **Respond** \u2014 `state.injectMessage({ role, content })` in its own side's role (`assistant` for side A, `user` for side B).\n- **Spawn** \u2014 create child instances of the side's declared `subagents` relationships via lifecycle APIs.\n- **Control** \u2014 `state.stopSession()`, `state.setStatus()`, effects, environment, key-value store, filesystem.\n\nHandlers need no tool grants for children: the side's `subagents` declarations establish existence and lifecycle, and the handler reaches children through `ThreadState` directly. (The injected lifecycle *tools* exist for prompts \u2014 a handler calls the same operations as code.)\n\n## The Outbound Boundary\n\nHandlers get no auto-injected reply channel. If a handler (or the side it feeds) should speak to a user or an external surface, that is userland code \u2014 a tool or handler calling the messaging surface it chooses (the `message_user` pattern). **The runtime routes inbound; userland decides outbound.**\n\n## Livelock Discipline\n\nHandler sides do not run away on their own \u2014 a handler runs only when a message arrives. But a handler that *replies to every inbound message* paired with a prompt-backed side creates a message ping-pong with no natural stop. Handler authors own their termination discipline:\n\n- reply conditionally, not unconditionally;\n- or set `maxSessionTurns` on the agent (available on every shape) as a hard safety valve;\n- or end the session explicitly with `state.stopSession()` when the work is done.\n\n## Worked Example: the Relay\n\nA user-facing thread that does **zero model work**: every inbound user message is forwarded verbatim to a composed assistant child; every child answer is relayed back out through userland messaging. One handler expresses the entire surface:\n\n```typescript\n// agents/handlers/relay_pipe.ts\nimport { defineHandler } from '@standardagents/builder';\n\nexport default defineHandler({\n description: 'Pipe user traffic to the assistant child; relay answers outward.',\n execute: async (state, message) => {\n const child = state.children.find(c => c.relationship === 'assistant_agent');\n if (child) {\n const thread = await state.getChildThread(child.reference);\n await thread?.queueMessage({ role: 'user', content: message.content ?? '' });\n }\n },\n});\n\n// agents/agents/relay_agent.ts\nimport { defineAgent } from '@standardagents/builder';\n\nexport default defineAgent({\n name: 'relay_agent',\n sideA: {\n handler: 'relay_pipe',\n subagents: [{\n agent: 'assistant_agent',\n maxInstances: 1,\n immediate: true, // spawned at thread creation\n parentCommunication: 'explicit',\n }],\n },\n sideB: { human: true },\n});\n```\n\nThe child's answers arrive as inbound messages on side A (the owning side) and get their own handler turns, where the handler calls the project's outbound messaging tool. No model participates at any point.\n\n## Best Practices\n\n- **Forward without blocking** \u2014 queue toward children and treat their replies as later turns; never hold the delivery slot on a child session\n- **Reply conditionally** \u2014 an unconditional reply opposite a prompt side is a ping-pong\n- **End sessions explicitly** \u2014 `state.stopSession()` when the work is done; there are no declarative session bindings on handler sides\n- **Keep handlers deterministic** \u2014 code that wants a model writes a prompt; code that wants a capability writes a tool; code that decorates writes a hook\n\n## Documentation\n\nFull reference: https://docs.standardagentbuilder.com/api-reference/define/handler\n";
|
|
10
12
|
|
|
11
13
|
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\n### Optional Runtime Streams\n\nSome runtimes expose live, authorized byte streams through\n`state.runtimeStreams`. Always feature-detect the optional surface. The\nfollowing neutral example streams media to a workstation-hosted transcoder,\nhalf-closes the writable side, reads the encoded result, and cleans up:\n\n```typescript\nconst runtimeStreams = state.runtimeStreams;\nif (!runtimeStreams) {\n return { status: 'error', error: 'This runtime has no workstation streams.' };\n}\n\nconst opened = await runtimeStreams.open({\n capability: 'workstation_transcoder',\n metadata: { inputFormat: 'wav', outputFormat: 'opus' },\n timeoutMs: 10_000,\n});\nif (!opened.ok) {\n return { status: 'error', error: opened.error, error_code: opened.code };\n}\n\ntry {\n const writer = opened.stream.writable.getWriter();\n try {\n await writer.write(sourceMedia);\n await writer.close();\n } finally {\n writer.releaseLock();\n }\n\n const reader = opened.stream.readable.getReader();\n const encoded: Uint8Array[] = [];\n try {\n for (;;) {\n const { value, done } = await reader.read();\n if (done) break;\n encoded.push(value);\n }\n } finally {\n reader.releaseLock();\n }\n\n const closed = await opened.stream.closed;\n if (!closed.ok) throw new Error(closed.error ?? 'Transcoding failed.');\n return { status: 'success', result: `Received ${encoded.length} chunks.` };\n} finally {\n opened.stream.close();\n}\n```\n\n`readable` carries host-to-runtime bytes; `writable` carries\nruntime-to-host bytes. Streams are live and non-durable. `close()` is\nidempotent, and the `closed` promise settles once.\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";
|
|
12
14
|
|
|
@@ -62,7 +64,7 @@ declare const FIRST_PARTY_PROVIDER_PACKAGES: readonly ["@standardagents/anthropi
|
|
|
62
64
|
*/
|
|
63
65
|
declare const APPROVED_DEPENDENCY_BUILD_SCRIPTS: readonly ["@google/genai", "@openrouter/sdk", "esbuild", "protobufjs", "sharp", "workerd"];
|
|
64
66
|
declare const DEFAULT_TEMPLATE_VERSIONS: TemplateVersions;
|
|
65
|
-
declare const AGENTBUILDER_TEMPLATE_VERSION = "0.
|
|
67
|
+
declare const AGENTBUILDER_TEMPLATE_VERSION = "0.41.0";
|
|
66
68
|
declare function packageNameFromProjectName(projectName: string): string;
|
|
67
69
|
declare function renderPackageJson(options: AgentBuilderProjectTemplateOptions): string;
|
|
68
70
|
/**
|
|
@@ -81,4 +83,4 @@ declare function renderTemplateMetadata(options: AgentBuilderProjectTemplateOpti
|
|
|
81
83
|
declare function renderAgentBuilderSupportFiles(options: AgentBuilderProjectTemplateOptions): TemplateFile[];
|
|
82
84
|
declare function renderAgentBuilderProject(options: AgentBuilderProjectTemplateOptions): TemplateFile[];
|
|
83
85
|
|
|
84
|
-
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, USERS_AGENTS_MD, USERS_AGENTS_MD as USERS_CLAUDE_MD, packageNameFromProjectName, renderAgentBuilderProject, renderAgentBuilderSupportFiles, renderDevVarsExample, renderGitignore, renderPackageJson, renderPnpmWorkspaceYaml, renderTemplateMetadata, renderTsConfig, renderViteConfig };
|
|
86
|
+
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, HANDLERS_AGENTS_MD, HANDLERS_AGENTS_MD as HANDLERS_CLAUDE_MD, 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, USERS_AGENTS_MD, USERS_AGENTS_MD as USERS_CLAUDE_MD, packageNameFromProjectName, renderAgentBuilderProject, renderAgentBuilderSupportFiles, renderDevVarsExample, renderGitignore, renderPackageJson, renderPnpmWorkspaceYaml, renderTemplateMetadata, renderTsConfig, renderViteConfig };
|