@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.js
CHANGED
|
@@ -18,7 +18,7 @@ Model \u2192 Prompt \u2192 Agent \u2192 Thread
|
|
|
18
18
|
|
|
19
19
|
**Models** define which LLM to use (provider, model ID, pricing, fallbacks).
|
|
20
20
|
**Prompts** define what the LLM should do (system instructions, available tools).
|
|
21
|
-
**Agents** orchestrate conversations (
|
|
21
|
+
**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/\`).
|
|
22
22
|
**Threads** are individual conversation instances with persistent storage.
|
|
23
23
|
|
|
24
24
|
## Packability and Runtime Portability
|
|
@@ -96,6 +96,9 @@ agents/
|
|
|
96
96
|
\u251C\u2500\u2500 prompts/ # Prompt definitions (definePrompt)
|
|
97
97
|
\u2502 \u251C\u2500\u2500 AGENTS.md
|
|
98
98
|
\u2502 \u2514\u2500\u2500 CLAUDE.md -> AGENTS.md
|
|
99
|
+
\u251C\u2500\u2500 handlers/ # Handler definitions (defineHandler)
|
|
100
|
+
\u2502 \u251C\u2500\u2500 AGENTS.md
|
|
101
|
+
\u2502 \u2514\u2500\u2500 CLAUDE.md -> AGENTS.md
|
|
99
102
|
\u251C\u2500\u2500 models/ # Model configurations (defineModel)
|
|
100
103
|
\u2502 \u251C\u2500\u2500 AGENTS.md
|
|
101
104
|
\u2502 \u2514\u2500\u2500 CLAUDE.md -> AGENTS.md
|
|
@@ -137,7 +140,7 @@ interface ThreadState {
|
|
|
137
140
|
agentId: string; // Agent identifier
|
|
138
141
|
userId: string | null; // User identifier (if set)
|
|
139
142
|
createdAt: number; // Creation timestamp
|
|
140
|
-
children: SubagentRegistryEntry[]; //
|
|
143
|
+
children: SubagentRegistryEntry[]; // Child instance registry
|
|
141
144
|
terminated: number | null; // Soft-termination timestamp
|
|
142
145
|
arguments: Record<string, unknown>; // Invocation or subagent creation args
|
|
143
146
|
context: Record<string, unknown>; // Current-execution scratch data
|
|
@@ -182,16 +185,16 @@ reconnecting.
|
|
|
182
185
|
|
|
183
186
|
## Subagents
|
|
184
187
|
|
|
185
|
-
|
|
188
|
+
A 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):
|
|
186
189
|
|
|
187
190
|
- Each subagent runs in its own thread (\`DurableThread\`)
|
|
188
|
-
- Parent/child linkage is tracked in thread metadata
|
|
189
|
-
-
|
|
190
|
-
-
|
|
191
|
-
- \`subagent_create.arguments\` is validated from the receiving child
|
|
191
|
+
- Parent/child linkage is tracked in thread metadata; instances are visible in \`state.children\`
|
|
192
|
+
- 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
|
|
193
|
+
- 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
|
|
194
|
+
- \`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
|
|
192
195
|
- Child completion results are queued back to the parent when \`parentCommunication\` is \`implicit\`
|
|
193
196
|
- 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
|
|
194
|
-
-
|
|
197
|
+
- 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.
|
|
195
198
|
|
|
196
199
|
Access in tools:
|
|
197
200
|
\`\`\`typescript
|
|
@@ -224,6 +227,7 @@ export default defineHook({
|
|
|
224
227
|
| \`defineModel()\` | Configure LLM provider | \`agents/models/\` |
|
|
225
228
|
| \`defineProvider()\` | Custom provider endpoints and overrides | \`agents/providers/\` |
|
|
226
229
|
| \`definePrompt()\` | System instructions + tools | \`agents/prompts/\` |
|
|
230
|
+
| \`defineHandler()\` | Deterministic side turns | \`agents/handlers/\` |
|
|
227
231
|
| \`defineAgent()\` | Conversation orchestration | \`agents/agents/\` |
|
|
228
232
|
| \`defineTool()\` | Custom tool functions | \`agents/tools/\` |
|
|
229
233
|
| \`defineHook()\` | Lifecycle interception | \`agents/hooks/\` |
|
|
@@ -357,7 +361,7 @@ other provider behavior.
|
|
|
357
361
|
|
|
358
362
|
\`\`\`typescript
|
|
359
363
|
// agents/providers/darkbloom.ts
|
|
360
|
-
import { defineProvider, providerEnv } from '@standardagents/
|
|
364
|
+
import { defineProvider, providerEnv } from '@standardagents/spec';
|
|
361
365
|
import { openai } from '@standardagents/openai';
|
|
362
366
|
|
|
363
367
|
export default defineProvider({
|
|
@@ -441,7 +445,7 @@ package with connection config and optional method overrides.
|
|
|
441
445
|
Use \`defineProvider()\` and export the result as the default export:
|
|
442
446
|
|
|
443
447
|
\`\`\`typescript
|
|
444
|
-
import { defineProvider, providerEnv, providerValue } from '@standardagents/
|
|
448
|
+
import { defineProvider, providerEnv, providerValue } from '@standardagents/spec';
|
|
445
449
|
import { openai } from '@standardagents/openai';
|
|
446
450
|
|
|
447
451
|
export default defineProvider({
|
|
@@ -516,7 +520,7 @@ Prompts define system instructions, model selection, and available tools for LLM
|
|
|
516
520
|
| \`toolDescription\` | \`string\` | Yes | Description shown when used as a tool |
|
|
517
521
|
| \`prompt\` | \`string \\| StructuredPrompt\` | Yes | System instructions |
|
|
518
522
|
| \`model\` | \`string\` | Yes | Model name to use (references \`agents/models/\`) |
|
|
519
|
-
| \`tools\` | \`(string \\| ToolConfig
|
|
523
|
+
| \`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 |
|
|
520
524
|
| \`includeChat\` | \`boolean\` | No | Include full conversation history |
|
|
521
525
|
| \`includePastTools\` | \`boolean\` | No | Include previous tool results |
|
|
522
526
|
| \`parallelToolCalls\` | \`boolean\` | No | Allow multiple concurrent tool calls |
|
|
@@ -595,60 +599,40 @@ provider-reported calls in request logs; it does not execute those tools locally
|
|
|
595
599
|
Generated prompt files may store these selections as \`provider:<toolName>\` to
|
|
596
600
|
distinguish provider tools from local tools with the same name.
|
|
597
601
|
|
|
598
|
-
###
|
|
602
|
+
### Subagents Come From the Side, Not the Tools Array
|
|
599
603
|
|
|
600
|
-
|
|
604
|
+
Composition 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:
|
|
601
605
|
|
|
602
606
|
\`\`\`typescript
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
607
|
+
// agents/agents/assistant_agent.ts
|
|
608
|
+
sideA: {
|
|
609
|
+
prompt: 'coordinator',
|
|
610
|
+
subagents: [
|
|
611
|
+
{ agent: 'calendar_agent', as: 'work_calendar', scopedEnv: ['WORK_CAL_ID'] },
|
|
612
|
+
{ agent: 'calendar_agent', as: 'personal_calendar', scopedEnv: ['PERSONAL_CAL_ID'] },
|
|
613
|
+
{ agent: 'research_agent', blocking: true, maxInstances: 1 },
|
|
614
|
+
{ agent: 'compaction_agent', hidden: true },
|
|
615
|
+
{ agent: 'browser_agent', optional: 'ENABLE_BROWSER_AGENT' },
|
|
616
|
+
],
|
|
617
|
+
},
|
|
618
|
+
\`\`\`
|
|
606
619
|
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
620
|
+
For a prompt-backed side with non-hidden relationships, the runtime automatically injects three lifecycle tools scoped to that side's declarations:
|
|
621
|
+
|
|
622
|
+
- \`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.
|
|
623
|
+
- \`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.
|
|
624
|
+
- \`subagent_message\` \u2014 queues a message to an existing instance by reference.
|
|
625
|
+
|
|
626
|
+
These three names are reserved; a relationship \`as\` that collides with them (or with any other tool name) is a definition-time error.
|
|
627
|
+
|
|
628
|
+
\`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.
|
|
629
|
+
|
|
630
|
+
Persistence 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.
|
|
610
631
|
|
|
611
|
-
// Non-blocking, resumable with a single instance
|
|
612
|
-
{
|
|
613
|
-
name: 'browser_agent',
|
|
614
|
-
blocking: false,
|
|
615
|
-
immediate: {
|
|
616
|
-
nameEnv: 'BROWSER_AGENT_NAME',
|
|
617
|
-
descriptionEnv: 'BROWSER_AGENT_DESCRIPTION',
|
|
618
|
-
scopedEnv: ['BROWSER_AGENT_API_KEY'],
|
|
619
|
-
},
|
|
620
|
-
optional: 'ENABLE_BROWSER_AGENT',
|
|
621
|
-
initAgentNameProperty: 'name',
|
|
622
|
-
resumable: {
|
|
623
|
-
receives_messages: 'side_a',
|
|
624
|
-
maxInstances: 1,
|
|
625
|
-
parentCommunication: 'explicit',
|
|
626
|
-
},
|
|
627
|
-
},
|
|
628
|
-
]
|
|
629
|
-
\`\`\`
|
|
630
|
-
|
|
631
|
-
When prompt-configured resumable dual_ai subagents exist, the runtime auto-injects:
|
|
632
|
-
- \`subagent_create\` for spawning new child instances
|
|
633
|
-
- \`subagent_message\` for messaging active resumable instances
|
|
634
|
-
|
|
635
|
-
\`subagent_create\` requires a non-empty \`name\` for human-friendly child thread labels.
|
|
636
|
-
AgentBuilder stores that argument as a \`name:<value>\` thread tag.
|
|
637
|
-
\`subagent_create.arguments\` is shaped by the prompt schema on the child side selected by \`resumable.receives_messages\`.
|
|
638
|
-
AgentBuilder 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.
|
|
639
|
-
|
|
640
|
-
Set \`immediate: true\` to run a tool automatically when the prompt activates.
|
|
641
|
-
Use \`immediate: { nameEnv, descriptionEnv, scopedEnv }\` when you want safe per-instance bootstrap hints while keeping copied scoped env runtime-only.
|
|
642
|
-
Set \`optional: 'ENV_NAME'\` to enable a subagent branch only when env resolves to \`true\`, \`1\`, or \`yes\`.
|
|
643
|
-
Set \`resumable.parentCommunication: 'explicit'\` when the child should stay quiet until its own tools or hooks call \`state.notifyParent()\`, \`state.setStatus()\`, or \`state.stopSession({ result, notifyParent, status })\`.
|
|
644
|
-
Set top-level \`parentCommunication: 'explicit'\` on a NON-resumable subagent when its completion should not be auto-queued to the parent (so it never wakes the parent) \u2014 for background children that deliver results through another channel, e.g. the parent's thread KV. \`resumable.parentCommunication\` takes precedence when both are set.
|
|
645
|
-
Set \`hidden: true\` to keep a subagent relationship declared and spawnable by runtime code (\`state.invokeTool()\`/\`queueTool()\` from hooks) while excluding its tool from every LLM request \u2014 the model can never call it (for infrastructure children like a background compaction agent).
|
|
646
|
-
Adding an enabled child relationship automatically activates the child's
|
|
647
|
-
disclosed \`parentHooks\` on this parent. Disabled optional relationships do
|
|
648
|
-
not; hidden enabled relationships do. \`name\` is the relationship provenance
|
|
649
|
-
and \`agent ?? name\` identifies the implementing child.
|
|
650
632
|
If required scoped vars are missing, the runtime returns \`error_code: "subagent_env_required"\` with a temporary \`GET/POST /api/threads/:threadId/variables/:requestId\` endpoint in \`error_data.endpoint\`.
|
|
651
633
|
|
|
634
|
+
See \`agents/agents/AGENTS.md\` for the full \`SubagentRelationship\` option list (\`immediate\`, \`optional\`, \`hidden\`, \`parentCommunication\`, init mappings) and the ownership rules.
|
|
635
|
+
|
|
652
636
|
## Input Validation
|
|
653
637
|
|
|
654
638
|
Validate inputs when prompt is called as a tool:
|
|
@@ -726,135 +710,207 @@ Full reference: https://docs.standardagentbuilder.com/api-reference/define/promp
|
|
|
726
710
|
// src/docs/agents.ts
|
|
727
711
|
var AGENT_DEFINITIONS_AGENTS_MD = `# Agent Definitions
|
|
728
712
|
|
|
729
|
-
|
|
713
|
+
An 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.
|
|
714
|
+
|
|
715
|
+
| Backing | Who takes this side's turns | Declared as |
|
|
716
|
+
|---------|-----------------------------|-------------|
|
|
717
|
+
| **Human** | A person, via whatever interface the runtime provides | \`{ human: true }\` |
|
|
718
|
+
| **Prompt** | A model, driven by a prompt from \`agents/prompts/\` | \`{ prompt: 'name', ... }\` |
|
|
719
|
+
| **Handler** | Deterministic code from \`agents/handlers/\` | \`{ handler: 'name', ... }\` |
|
|
720
|
+
|
|
721
|
+
Both 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 }\`.
|
|
730
722
|
|
|
731
723
|
## Agent Properties
|
|
732
724
|
|
|
733
725
|
| Property | Type | Required | Description |
|
|
734
726
|
|----------|------|----------|-------------|
|
|
735
727
|
| \`name\` | \`string\` | Yes | Unique identifier for this agent |
|
|
736
|
-
| \`
|
|
737
|
-
| \`
|
|
738
|
-
| \`
|
|
739
|
-
| \`
|
|
740
|
-
| \`
|
|
728
|
+
| \`sideA\` | \`SideConfig\` | Yes | Side A configuration (backing-discriminated) |
|
|
729
|
+
| \`sideB\` | \`SideConfig\` | Yes | Side B configuration (backing-discriminated) |
|
|
730
|
+
| \`maxSessionTurns\` | \`number\` | No | Session exchange safety cap \u2014 optional on every agent shape |
|
|
731
|
+
| \`title\` | \`string\` | No | Human-readable label |
|
|
732
|
+
| \`description\` | \`string\` | No | Agent summary |
|
|
733
|
+
| \`icon\` | \`string\` | No | Display icon (see Icons below) |
|
|
734
|
+
| \`exposeAsTool\` | \`boolean\` | No | Expose a callable entrypoint for handoffs and composition |
|
|
741
735
|
| \`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 |
|
|
742
|
-
| \`toolDescription\` | \`string\` | No |
|
|
736
|
+
| \`toolDescription\` | \`string\` | No | Default model-facing description when this agent is composed or handed off to (required if exposeAsTool) |
|
|
743
737
|
| \`env\` | \`Record<string, string>\` | No | Agent-level default variable values |
|
|
744
738
|
| \`hooks\` | \`string[]\` | No | Hook IDs to run for this agent (fallback if prompt has no hooks) |
|
|
745
|
-
| \`parentHooks\` | \`ParentHookRequirement[]\` | No |
|
|
739
|
+
| \`parentHooks\` | \`ParentHookRequirement[]\` | No | Required hooks automatically contributed to a direct parent composition (legal on any exposed agent) |
|
|
746
740
|
| \`tags\` | \`string[]\` | No | Tags for categorization and filtering |
|
|
747
741
|
|
|
748
742
|
## Side Configuration
|
|
749
743
|
|
|
744
|
+
A side's configuration is discriminated by its backing: exactly one of \`human\`, \`prompt\`, or \`handler\` must be present.
|
|
745
|
+
|
|
746
|
+
**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.
|
|
747
|
+
|
|
748
|
+
**Prompt side**
|
|
749
|
+
|
|
750
750
|
| Property | Type | Required | Description |
|
|
751
751
|
|----------|------|----------|-------------|
|
|
752
|
-
| \`label\` | \`string\` | No | Display name for this side |
|
|
753
752
|
| \`prompt\` | \`string\` | Yes | Prompt name to use (references \`agents/prompts/\`) |
|
|
754
|
-
| \`
|
|
753
|
+
| \`label\` | \`string\` | No | Display name for this side |
|
|
754
|
+
| \`subagents\` | \`SubagentRelationship[]\` | No | Side-owned child relationships (see Subagent Relationships below) |
|
|
755
|
+
| \`stopOnResponse\` | \`boolean\` | No | Stop side turn on text response without tool calls (default: true) |
|
|
755
756
|
| \`stopTool\` | \`string\` | No | Tool that stops this side's turn |
|
|
756
757
|
| \`stopToolResponseProperty\` | \`string\` | No | Property to extract from stop tool result |
|
|
757
758
|
| \`maxSteps\` | \`number\` | No | Maximum step budget for this side |
|
|
758
|
-
| \`sessionStop\` | \`
|
|
759
|
-
| \`sessionFail\` | \`
|
|
760
|
-
| \`sessionStatus\` | \`
|
|
761
|
-
|
|
759
|
+
| \`sessionStop\` | \`SessionToolBinding\` | No | Terminal success lifecycle binding (object form only) |
|
|
760
|
+
| \`sessionFail\` | \`SessionToolBinding\` | No | Terminal failure lifecycle binding (object form only) |
|
|
761
|
+
| \`sessionStatus\` | \`SessionToolBinding\` | No | Non-terminal status lifecycle binding (object form only) |
|
|
762
|
+
|
|
763
|
+
**Handler side**
|
|
764
|
+
|
|
765
|
+
| Property | Type | Required | Description |
|
|
766
|
+
|----------|------|----------|-------------|
|
|
767
|
+
| \`handler\` | \`string\` | Yes | Handler name for this side (references \`agents/handlers/\`) |
|
|
768
|
+
| \`label\` | \`string\` | No | Display name for this side |
|
|
769
|
+
| \`subagents\` | \`SubagentRelationship[]\` | No | Side-owned child relationships |
|
|
770
|
+
|
|
771
|
+
Handler 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\`.
|
|
762
772
|
|
|
763
|
-
|
|
773
|
+
Session lifecycle bindings use the object form only:
|
|
774
|
+
|
|
775
|
+
\`\`\`typescript
|
|
776
|
+
sessionStop: {
|
|
777
|
+
name: 'complete_work', // tool that controls the lifecycle action
|
|
778
|
+
messageProperty: 'summary', // arg field that becomes lifecycle message text
|
|
779
|
+
attachmentsProperty: 'files', // arg field containing attachment path(s)
|
|
780
|
+
}
|
|
781
|
+
\`\`\`
|
|
782
|
+
|
|
783
|
+
## Derivations
|
|
784
|
+
|
|
785
|
+
These follow from the backings and are never declared separately:
|
|
786
|
+
|
|
787
|
+
- **Chat surface** \u2014 the primary conversational interface renders wherever a \`human\` backing is.
|
|
788
|
+
- **Perspective** \u2014 \`role: 'user'\` is the side B perspective, \`role: 'assistant'\` is the side A perspective, for queueing, injection, and rendering alike.
|
|
789
|
+
- **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).
|
|
790
|
+
- **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.
|
|
791
|
+
|
|
792
|
+
## Example: Assistant (human \xD7 prompt)
|
|
793
|
+
|
|
794
|
+
The everyday user-facing assistant \u2014 a person on side B, a model on side A:
|
|
764
795
|
|
|
765
796
|
\`\`\`typescript
|
|
766
797
|
import { defineAgent } from '@standardagents/builder';
|
|
767
798
|
|
|
768
799
|
export default defineAgent({
|
|
769
800
|
name: 'support_agent',
|
|
770
|
-
type: 'ai_human',
|
|
771
801
|
sideA: {
|
|
772
802
|
label: 'Support',
|
|
773
803
|
prompt: 'customer_support',
|
|
774
804
|
stopOnResponse: true,
|
|
775
|
-
sessionStop: 'close_ticket',
|
|
805
|
+
sessionStop: { name: 'close_ticket' },
|
|
776
806
|
maxSteps: 50,
|
|
777
807
|
},
|
|
808
|
+
sideB: { human: true },
|
|
778
809
|
tags: ['support', 'tier-1'],
|
|
779
810
|
});
|
|
780
811
|
\`\`\`
|
|
781
812
|
|
|
782
|
-
##
|
|
813
|
+
## Example: Worker / Reviewer (prompt \xD7 prompt)
|
|
783
814
|
|
|
784
|
-
Two
|
|
815
|
+
Two 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:
|
|
785
816
|
|
|
786
817
|
\`\`\`typescript
|
|
787
818
|
export default defineAgent({
|
|
788
|
-
name: '
|
|
789
|
-
type: 'dual_ai',
|
|
819
|
+
name: 'research_agent',
|
|
790
820
|
maxSessionTurns: 20,
|
|
821
|
+
exposeAsTool: true,
|
|
822
|
+
toolDescription: 'Researches and validates findings autonomously',
|
|
791
823
|
sideA: {
|
|
792
|
-
label: '
|
|
793
|
-
prompt: '
|
|
824
|
+
label: 'Worker',
|
|
825
|
+
prompt: 'research_worker',
|
|
794
826
|
stopOnResponse: true,
|
|
827
|
+
sessionStatus: { name: 'set_research_status', messageProperty: 'status' },
|
|
828
|
+
sessionFail: { name: 'fail_research', messageProperty: 'reason' },
|
|
795
829
|
},
|
|
796
830
|
sideB: {
|
|
797
|
-
label: '
|
|
798
|
-
prompt: '
|
|
831
|
+
label: 'Reviewer',
|
|
832
|
+
prompt: 'research_reviewer',
|
|
799
833
|
stopOnResponse: true,
|
|
834
|
+
sessionStop: { name: 'approve_research', messageProperty: 'summary' },
|
|
800
835
|
},
|
|
801
836
|
});
|
|
802
837
|
\`\`\`
|
|
803
838
|
|
|
804
|
-
##
|
|
839
|
+
## Example: Relay (handler \xD7 human)
|
|
805
840
|
|
|
806
|
-
|
|
807
|
-
- **sideA**: performs work (tools, data gathering, execution)
|
|
808
|
-
- **sideB**: reflection, verification, and quality checks
|
|
841
|
+
A 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:
|
|
809
842
|
|
|
810
843
|
\`\`\`typescript
|
|
811
844
|
export default defineAgent({
|
|
812
|
-
name: '
|
|
813
|
-
type: 'dual_ai',
|
|
814
|
-
exposeAsTool: true,
|
|
815
|
-
toolDescription: 'Researches and validates findings autonomously',
|
|
816
|
-
maxSessionTurns: 16,
|
|
845
|
+
name: 'relay_agent',
|
|
817
846
|
sideA: {
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
sessionStatus: 'set_subagent_status',
|
|
821
|
-
sessionFail: 'fail_research_subagent',
|
|
822
|
-
sessionStop: 'finish_subagent',
|
|
823
|
-
},
|
|
824
|
-
sideB: {
|
|
825
|
-
label: 'Reviewer',
|
|
826
|
-
prompt: 'research_reviewer',
|
|
827
|
-
stopOnResponse: true,
|
|
847
|
+
handler: 'relay_pipe',
|
|
848
|
+
subagents: [{ agent: 'assistant_agent', maxInstances: 1 }],
|
|
828
849
|
},
|
|
850
|
+
sideB: { human: true },
|
|
829
851
|
});
|
|
830
852
|
\`\`\`
|
|
831
853
|
|
|
854
|
+
The \`relay_pipe\` handler lives in \`agents/handlers/relay_pipe.ts\` \u2014 the full worked example is in \`agents/handlers/AGENTS.md\`.
|
|
855
|
+
|
|
856
|
+
## Subagent Relationships
|
|
857
|
+
|
|
858
|
+
Composition 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:
|
|
859
|
+
|
|
860
|
+
\`\`\`typescript
|
|
861
|
+
sideA: {
|
|
862
|
+
prompt: 'coordinator',
|
|
863
|
+
subagents: [
|
|
864
|
+
{ agent: 'calendar_agent', as: 'work_calendar', scopedEnv: ['WORK_CAL_ID'] },
|
|
865
|
+
{ agent: 'calendar_agent', as: 'personal_calendar', scopedEnv: ['PERSONAL_CAL_ID'] },
|
|
866
|
+
{ agent: 'research_agent', blocking: true, maxInstances: 1 },
|
|
867
|
+
],
|
|
868
|
+
},
|
|
869
|
+
\`\`\`
|
|
870
|
+
|
|
871
|
+
- 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.
|
|
872
|
+
- 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\`.
|
|
873
|
+
- 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.
|
|
874
|
+
- **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.
|
|
875
|
+
|
|
876
|
+
See \`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).
|
|
877
|
+
|
|
832
878
|
## Agent Handoffs
|
|
833
879
|
|
|
834
|
-
|
|
880
|
+
When \`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.
|
|
835
881
|
|
|
836
882
|
\`\`\`typescript
|
|
837
883
|
export default defineAgent({
|
|
838
884
|
name: 'escalation_agent',
|
|
839
|
-
type: 'ai_human',
|
|
840
885
|
exposeAsTool: true,
|
|
841
886
|
toolDescription: 'Escalate to senior support for complex issues',
|
|
842
|
-
sideA: {
|
|
843
|
-
|
|
844
|
-
},
|
|
887
|
+
sideA: { prompt: 'senior_support' },
|
|
888
|
+
sideB: { human: true },
|
|
845
889
|
});
|
|
846
890
|
\`\`\`
|
|
847
891
|
|
|
848
|
-
|
|
892
|
+
## Stop Semantics
|
|
893
|
+
|
|
894
|
+
Runtime stop evaluation order for prompt-backed sides:
|
|
895
|
+
|
|
896
|
+
1. **sessionStop / sessionFail** \u2014 end the session (success / terminal failure)
|
|
897
|
+
2. **stopTool** \u2014 ends the current side's turn
|
|
898
|
+
3. **stopOnResponse** \u2014 ends the turn when the LLM returns text without tool calls
|
|
899
|
+
4. **Safety limits** \u2014 \`maxSteps\` (per side), \`maxSessionTurns\` (per session, hard limit: 250)
|
|
849
900
|
|
|
850
|
-
|
|
901
|
+
A 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.
|
|
851
902
|
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
903
|
+
## Definition-Time Errors
|
|
904
|
+
|
|
905
|
+
These shapes are rejected when definitions load:
|
|
906
|
+
|
|
907
|
+
1. Both sides human (reserved \u2014 may lift in a later version)
|
|
908
|
+
2. \`subagents\` declared on a human-backed side
|
|
909
|
+
3. A side with zero backings, or more than one of \`human\` / \`prompt\` / \`handler\`
|
|
910
|
+
4. A handler side referencing an undefined handler; a prompt side referencing an undefined prompt
|
|
911
|
+
5. A relationship name (\`as\`) appearing on both sides, colliding with another tool name, or colliding with a reserved lifecycle tool name
|
|
912
|
+
6. Session bindings, \`maxSteps\`, or stop bindings on a non-prompt side
|
|
913
|
+
7. A session binding that is not in object form
|
|
858
914
|
|
|
859
915
|
## Hooks
|
|
860
916
|
|
|
@@ -863,17 +919,15 @@ Attach lifecycle hooks at the agent level:
|
|
|
863
919
|
\`\`\`typescript
|
|
864
920
|
export default defineAgent({
|
|
865
921
|
name: 'support_agent',
|
|
866
|
-
type: 'ai_human',
|
|
867
922
|
hooks: ['log_all_messages', 'sanitize_results'],
|
|
868
|
-
sideA: {
|
|
869
|
-
|
|
870
|
-
},
|
|
923
|
+
sideA: { prompt: 'customer_support' },
|
|
924
|
+
sideB: { human: true },
|
|
871
925
|
});
|
|
872
926
|
\`\`\`
|
|
873
927
|
|
|
874
928
|
Agent 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.
|
|
875
929
|
|
|
876
|
-
|
|
930
|
+
Any exposed agent can declare required parent integration hooks:
|
|
877
931
|
|
|
878
932
|
\`\`\`typescript
|
|
879
933
|
parentHooks: [{
|
|
@@ -883,12 +937,13 @@ parentHooks: [{
|
|
|
883
937
|
}],
|
|
884
938
|
\`\`\`
|
|
885
939
|
|
|
886
|
-
Installing the package is inert.
|
|
887
|
-
|
|
888
|
-
\`reason\` first. Disabled
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
940
|
+
Installing the package is inert. Declaring a relationship targeting this agent
|
|
941
|
+
(or adding it to a prompt as a handoff) activates the hook automatically on
|
|
942
|
+
that direct parent, and composition UIs disclose the \`reason\` first. Disabled
|
|
943
|
+
optional relationships contribute nothing; enabled hidden relationships still
|
|
944
|
+
contribute hooks. Required hooks run with the parent's \`ThreadState\`, load
|
|
945
|
+
from the child's package namespace, and fail composition closed if missing.
|
|
946
|
+
User-scope hooks cannot be listed.
|
|
892
947
|
|
|
893
948
|
## Naming Convention
|
|
894
949
|
|
|
@@ -908,7 +963,8 @@ and the dashboard warns when a site-relative icon path has no matching file.
|
|
|
908
963
|
|
|
909
964
|
- **Use descriptive names** (\`customer_support_agent\` not \`agent1\`)
|
|
910
965
|
- **Always use the _agent suffix** - names like \`support_agent\`, \`research_agent\`
|
|
911
|
-
- **
|
|
966
|
+
- **Write sideB explicitly** - there is no implicit default; a user-facing agent ends with \`sideB: { human: true }\`
|
|
967
|
+
- **Cap prompt \xD7 prompt agents** - set \`maxSessionTurns\` when both sides are prompt-backed; nothing external stops two models
|
|
912
968
|
- **Match stop conditions to use case** - chat apps use stopOnResponse, workflows use stopTool
|
|
913
969
|
- **Use labels** for clarity in logs and UI
|
|
914
970
|
- **Organize with tags** for filtering
|
|
@@ -918,6 +974,150 @@ and the dashboard warns when a site-relative icon path has no matching file.
|
|
|
918
974
|
Full reference: https://docs.standardagentbuilder.com/api-reference/define/agent
|
|
919
975
|
`;
|
|
920
976
|
|
|
977
|
+
// src/docs/handlers.ts
|
|
978
|
+
var HANDLERS_AGENTS_MD = `# Handler Definitions
|
|
979
|
+
|
|
980
|
+
A 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.
|
|
981
|
+
|
|
982
|
+
A 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.
|
|
983
|
+
|
|
984
|
+
## Properties
|
|
985
|
+
|
|
986
|
+
| Property | Type | Required | Description |
|
|
987
|
+
|----------|------|----------|-------------|
|
|
988
|
+
| \`description\` | \`string\` | No | Human-facing summary |
|
|
989
|
+
| \`execute\` | \`(state: ThreadState, message: Message) => Promise<void>\` | Yes | The turn implementation |
|
|
990
|
+
|
|
991
|
+
The 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.
|
|
992
|
+
|
|
993
|
+
## Basic Example
|
|
994
|
+
|
|
995
|
+
\`\`\`typescript
|
|
996
|
+
// agents/handlers/relay_pipe.ts
|
|
997
|
+
import { defineHandler } from '@standardagents/builder';
|
|
998
|
+
|
|
999
|
+
export default defineHandler({
|
|
1000
|
+
description: 'Forwards inbound user traffic to the assistant child and relays answers back.',
|
|
1001
|
+
execute: async (state, message) => {
|
|
1002
|
+
// full ThreadState \u2014 forward, respond, spawn, stop, read/write KV
|
|
1003
|
+
},
|
|
1004
|
+
});
|
|
1005
|
+
\`\`\`
|
|
1006
|
+
|
|
1007
|
+
Reference it from exactly one place: the \`handler\` property of an agent side:
|
|
1008
|
+
|
|
1009
|
+
\`\`\`typescript
|
|
1010
|
+
export default defineAgent({
|
|
1011
|
+
name: 'relay_agent',
|
|
1012
|
+
sideA: { handler: 'relay_pipe', subagents: [{ agent: 'assistant_agent', maxInstances: 1 }] },
|
|
1013
|
+
sideB: { human: true },
|
|
1014
|
+
});
|
|
1015
|
+
\`\`\`
|
|
1016
|
+
|
|
1017
|
+
## Execution Model
|
|
1018
|
+
|
|
1019
|
+
A handler-backed side's turn is:
|
|
1020
|
+
|
|
1021
|
+
1. An inbound message arrives on the side's perspective.
|
|
1022
|
+
2. The runtime invokes the handler once with the thread's \`ThreadState\` and that message.
|
|
1023
|
+
3. The invocation returns (or throws). The turn is complete.
|
|
1024
|
+
|
|
1025
|
+
There 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.
|
|
1026
|
+
|
|
1027
|
+
## Delivery Semantics
|
|
1028
|
+
|
|
1029
|
+
Delivery to a handler is **exactly-once per message**:
|
|
1030
|
+
|
|
1031
|
+
- The handler is invoked exactly once for each inbound message on the side's perspective, in message persistence order.
|
|
1032
|
+
- 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.
|
|
1033
|
+
- A message whose handler invocation failed is not automatically redelivered. Retry is a userland decision (re-send the message).
|
|
1034
|
+
|
|
1035
|
+
**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.
|
|
1036
|
+
|
|
1037
|
+
## Error Semantics
|
|
1038
|
+
|
|
1039
|
+
A handler that throws is **fatal to the turn, and only the turn**:
|
|
1040
|
+
|
|
1041
|
+
- 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.
|
|
1042
|
+
- The inbound message stays persisted. Nothing is rolled back.
|
|
1043
|
+
- 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.
|
|
1044
|
+
|
|
1045
|
+
If an error should end the session, the handler must do so explicitly with \`state.stopSession()\`.
|
|
1046
|
+
|
|
1047
|
+
## Capabilities
|
|
1048
|
+
|
|
1049
|
+
A handler receives the full \`ThreadState\` and may do anything tools can do:
|
|
1050
|
+
|
|
1051
|
+
- **Forward** \u2014 \`(await state.getChildThread(ref)).queueMessage(...)\` toward a child, or \`state.notifyParent(...)\` toward a parent.
|
|
1052
|
+
- **Respond** \u2014 \`state.injectMessage({ role, content })\` in its own side's role (\`assistant\` for side A, \`user\` for side B).
|
|
1053
|
+
- **Spawn** \u2014 create child instances of the side's declared \`subagents\` relationships via lifecycle APIs.
|
|
1054
|
+
- **Control** \u2014 \`state.stopSession()\`, \`state.setStatus()\`, effects, environment, key-value store, filesystem.
|
|
1055
|
+
|
|
1056
|
+
Handlers 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.)
|
|
1057
|
+
|
|
1058
|
+
## The Outbound Boundary
|
|
1059
|
+
|
|
1060
|
+
Handlers 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.**
|
|
1061
|
+
|
|
1062
|
+
## Livelock Discipline
|
|
1063
|
+
|
|
1064
|
+
Handler 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:
|
|
1065
|
+
|
|
1066
|
+
- reply conditionally, not unconditionally;
|
|
1067
|
+
- or set \`maxSessionTurns\` on the agent (available on every shape) as a hard safety valve;
|
|
1068
|
+
- or end the session explicitly with \`state.stopSession()\` when the work is done.
|
|
1069
|
+
|
|
1070
|
+
## Worked Example: the Relay
|
|
1071
|
+
|
|
1072
|
+
A 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:
|
|
1073
|
+
|
|
1074
|
+
\`\`\`typescript
|
|
1075
|
+
// agents/handlers/relay_pipe.ts
|
|
1076
|
+
import { defineHandler } from '@standardagents/builder';
|
|
1077
|
+
|
|
1078
|
+
export default defineHandler({
|
|
1079
|
+
description: 'Pipe user traffic to the assistant child; relay answers outward.',
|
|
1080
|
+
execute: async (state, message) => {
|
|
1081
|
+
const child = state.children.find(c => c.relationship === 'assistant_agent');
|
|
1082
|
+
if (child) {
|
|
1083
|
+
const thread = await state.getChildThread(child.reference);
|
|
1084
|
+
await thread?.queueMessage({ role: 'user', content: message.content ?? '' });
|
|
1085
|
+
}
|
|
1086
|
+
},
|
|
1087
|
+
});
|
|
1088
|
+
|
|
1089
|
+
// agents/agents/relay_agent.ts
|
|
1090
|
+
import { defineAgent } from '@standardagents/builder';
|
|
1091
|
+
|
|
1092
|
+
export default defineAgent({
|
|
1093
|
+
name: 'relay_agent',
|
|
1094
|
+
sideA: {
|
|
1095
|
+
handler: 'relay_pipe',
|
|
1096
|
+
subagents: [{
|
|
1097
|
+
agent: 'assistant_agent',
|
|
1098
|
+
maxInstances: 1,
|
|
1099
|
+
immediate: true, // spawned at thread creation
|
|
1100
|
+
parentCommunication: 'explicit',
|
|
1101
|
+
}],
|
|
1102
|
+
},
|
|
1103
|
+
sideB: { human: true },
|
|
1104
|
+
});
|
|
1105
|
+
\`\`\`
|
|
1106
|
+
|
|
1107
|
+
The 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.
|
|
1108
|
+
|
|
1109
|
+
## Best Practices
|
|
1110
|
+
|
|
1111
|
+
- **Forward without blocking** \u2014 queue toward children and treat their replies as later turns; never hold the delivery slot on a child session
|
|
1112
|
+
- **Reply conditionally** \u2014 an unconditional reply opposite a prompt side is a ping-pong
|
|
1113
|
+
- **End sessions explicitly** \u2014 \`state.stopSession()\` when the work is done; there are no declarative session bindings on handler sides
|
|
1114
|
+
- **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
|
|
1115
|
+
|
|
1116
|
+
## Documentation
|
|
1117
|
+
|
|
1118
|
+
Full reference: https://docs.standardagentbuilder.com/api-reference/define/handler
|
|
1119
|
+
`;
|
|
1120
|
+
|
|
921
1121
|
// src/docs/tools.ts
|
|
922
1122
|
var TOOLS_AGENTS_MD = `# Custom Tools
|
|
923
1123
|
|
|
@@ -1845,7 +2045,7 @@ var DEFAULT_TEMPLATE_VERSIONS = {
|
|
|
1845
2045
|
typescript: "latest",
|
|
1846
2046
|
zod: "latest"
|
|
1847
2047
|
};
|
|
1848
|
-
var AGENTBUILDER_TEMPLATE_VERSION = "0.
|
|
2048
|
+
var AGENTBUILDER_TEMPLATE_VERSION = "0.41.0";
|
|
1849
2049
|
function ensureTrailingNewline(value) {
|
|
1850
2050
|
return value.endsWith("\n") ? value : `${value}
|
|
1851
2051
|
`;
|
|
@@ -2028,6 +2228,8 @@ function renderAgentBuilderProject(options) {
|
|
|
2028
2228
|
symlink("agents/agents/CLAUDE.md", "AGENTS.md", "Add Claude agent docs symlink"),
|
|
2029
2229
|
file("agents/prompts/AGENTS.md", PROMPTS_AGENTS_MD, "Add prompt docs"),
|
|
2030
2230
|
symlink("agents/prompts/CLAUDE.md", "AGENTS.md", "Add Claude prompt docs symlink"),
|
|
2231
|
+
file("agents/handlers/AGENTS.md", HANDLERS_AGENTS_MD, "Add handler docs"),
|
|
2232
|
+
symlink("agents/handlers/CLAUDE.md", "AGENTS.md", "Add Claude handler docs symlink"),
|
|
2031
2233
|
file("agents/models/AGENTS.md", MODELS_AGENTS_MD, "Add model docs"),
|
|
2032
2234
|
symlink("agents/models/CLAUDE.md", "AGENTS.md", "Add Claude model docs symlink"),
|
|
2033
2235
|
file("agents/providers/AGENTS.md", PROVIDERS_AGENTS_MD, "Add provider docs"),
|
|
@@ -2055,6 +2257,8 @@ export {
|
|
|
2055
2257
|
APPROVED_DEPENDENCY_BUILD_SCRIPTS,
|
|
2056
2258
|
DEFAULT_TEMPLATE_VERSIONS,
|
|
2057
2259
|
FIRST_PARTY_PROVIDER_PACKAGES,
|
|
2260
|
+
HANDLERS_AGENTS_MD,
|
|
2261
|
+
HANDLERS_AGENTS_MD as HANDLERS_CLAUDE_MD,
|
|
2058
2262
|
HOOKS_AGENTS_MD,
|
|
2059
2263
|
HOOKS_AGENTS_MD as HOOKS_CLAUDE_MD,
|
|
2060
2264
|
MODELS_AGENTS_MD,
|