agentopology 0.1.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.
Files changed (174) hide show
  1. package/LICENSE +191 -0
  2. package/README.md +450 -0
  3. package/dist/analyzer/__tests__/analyzer.test.d.ts +2 -0
  4. package/dist/analyzer/__tests__/analyzer.test.d.ts.map +1 -0
  5. package/dist/analyzer/__tests__/analyzer.test.js +258 -0
  6. package/dist/analyzer/__tests__/analyzer.test.js.map +1 -0
  7. package/dist/analyzer/index.d.ts +44 -0
  8. package/dist/analyzer/index.d.ts.map +1 -0
  9. package/dist/analyzer/index.js +308 -0
  10. package/dist/analyzer/index.js.map +1 -0
  11. package/dist/bindings/__tests__/bindings.test.d.ts +2 -0
  12. package/dist/bindings/__tests__/bindings.test.d.ts.map +1 -0
  13. package/dist/bindings/__tests__/bindings.test.js +2089 -0
  14. package/dist/bindings/__tests__/bindings.test.js.map +1 -0
  15. package/dist/bindings/claude-code.d.ts +12 -0
  16. package/dist/bindings/claude-code.d.ts.map +1 -0
  17. package/dist/bindings/claude-code.js +2063 -0
  18. package/dist/bindings/claude-code.js.map +1 -0
  19. package/dist/bindings/codex.d.ts +18 -0
  20. package/dist/bindings/codex.d.ts.map +1 -0
  21. package/dist/bindings/codex.js +1633 -0
  22. package/dist/bindings/codex.js.map +1 -0
  23. package/dist/bindings/copilot-cli.d.ts +20 -0
  24. package/dist/bindings/copilot-cli.d.ts.map +1 -0
  25. package/dist/bindings/copilot-cli.js +1515 -0
  26. package/dist/bindings/copilot-cli.js.map +1 -0
  27. package/dist/bindings/cursor.d.ts +17 -0
  28. package/dist/bindings/cursor.d.ts.map +1 -0
  29. package/dist/bindings/cursor.js +1715 -0
  30. package/dist/bindings/cursor.js.map +1 -0
  31. package/dist/bindings/gemini-cli.d.ts +18 -0
  32. package/dist/bindings/gemini-cli.d.ts.map +1 -0
  33. package/dist/bindings/gemini-cli.js +1327 -0
  34. package/dist/bindings/gemini-cli.js.map +1 -0
  35. package/dist/bindings/index.d.ts +20 -0
  36. package/dist/bindings/index.d.ts.map +1 -0
  37. package/dist/bindings/index.js +33 -0
  38. package/dist/bindings/index.js.map +1 -0
  39. package/dist/bindings/kiro.d.ts +17 -0
  40. package/dist/bindings/kiro.d.ts.map +1 -0
  41. package/dist/bindings/kiro.js +1624 -0
  42. package/dist/bindings/kiro.js.map +1 -0
  43. package/dist/bindings/openclaw.d.ts +18 -0
  44. package/dist/bindings/openclaw.d.ts.map +1 -0
  45. package/dist/bindings/openclaw.js +1578 -0
  46. package/dist/bindings/openclaw.js.map +1 -0
  47. package/dist/bindings/types.d.ts +33 -0
  48. package/dist/bindings/types.d.ts.map +1 -0
  49. package/dist/bindings/types.js +23 -0
  50. package/dist/bindings/types.js.map +1 -0
  51. package/dist/cli/index.d.ts +19 -0
  52. package/dist/cli/index.d.ts.map +1 -0
  53. package/dist/cli/index.js +679 -0
  54. package/dist/cli/index.js.map +1 -0
  55. package/dist/docs/__tests__/docs.test.d.ts +2 -0
  56. package/dist/docs/__tests__/docs.test.d.ts.map +1 -0
  57. package/dist/docs/__tests__/docs.test.js +438 -0
  58. package/dist/docs/__tests__/docs.test.js.map +1 -0
  59. package/dist/docs/content.d.ts +16 -0
  60. package/dist/docs/content.d.ts.map +1 -0
  61. package/dist/docs/content.js +3273 -0
  62. package/dist/docs/content.js.map +1 -0
  63. package/dist/docs/index.d.ts +17 -0
  64. package/dist/docs/index.d.ts.map +1 -0
  65. package/dist/docs/index.js +117 -0
  66. package/dist/docs/index.js.map +1 -0
  67. package/dist/exporters/__tests__/exporters.test.d.ts +2 -0
  68. package/dist/exporters/__tests__/exporters.test.d.ts.map +1 -0
  69. package/dist/exporters/__tests__/exporters.test.js +731 -0
  70. package/dist/exporters/__tests__/exporters.test.js.map +1 -0
  71. package/dist/exporters/index.d.ts +13 -0
  72. package/dist/exporters/index.d.ts.map +1 -0
  73. package/dist/exporters/index.js +18 -0
  74. package/dist/exporters/index.js.map +1 -0
  75. package/dist/exporters/json.d.ts +8 -0
  76. package/dist/exporters/json.d.ts.map +1 -0
  77. package/dist/exporters/json.js +25 -0
  78. package/dist/exporters/json.js.map +1 -0
  79. package/dist/exporters/markdown.d.ts +9 -0
  80. package/dist/exporters/markdown.d.ts.map +1 -0
  81. package/dist/exporters/markdown.js +686 -0
  82. package/dist/exporters/markdown.js.map +1 -0
  83. package/dist/exporters/mermaid.d.ts +11 -0
  84. package/dist/exporters/mermaid.d.ts.map +1 -0
  85. package/dist/exporters/mermaid.js +161 -0
  86. package/dist/exporters/mermaid.js.map +1 -0
  87. package/dist/exporters/types.d.ts +22 -0
  88. package/dist/exporters/types.d.ts.map +1 -0
  89. package/dist/exporters/types.js +10 -0
  90. package/dist/exporters/types.js.map +1 -0
  91. package/dist/import/__tests__/import.test.d.ts +2 -0
  92. package/dist/import/__tests__/import.test.d.ts.map +1 -0
  93. package/dist/import/__tests__/import.test.js +781 -0
  94. package/dist/import/__tests__/import.test.js.map +1 -0
  95. package/dist/import/claude-code.d.ts +38 -0
  96. package/dist/import/claude-code.d.ts.map +1 -0
  97. package/dist/import/claude-code.js +897 -0
  98. package/dist/import/claude-code.js.map +1 -0
  99. package/dist/import/index.d.ts +18 -0
  100. package/dist/import/index.d.ts.map +1 -0
  101. package/dist/import/index.js +28 -0
  102. package/dist/import/index.js.map +1 -0
  103. package/dist/import/serializer.d.ts +11 -0
  104. package/dist/import/serializer.d.ts.map +1 -0
  105. package/dist/import/serializer.js +960 -0
  106. package/dist/import/serializer.js.map +1 -0
  107. package/dist/index.d.ts +26 -0
  108. package/dist/index.d.ts.map +1 -0
  109. package/dist/index.js +21 -0
  110. package/dist/index.js.map +1 -0
  111. package/dist/parser/__tests__/parser.test.d.ts +2 -0
  112. package/dist/parser/__tests__/parser.test.d.ts.map +1 -0
  113. package/dist/parser/__tests__/parser.test.js +6514 -0
  114. package/dist/parser/__tests__/parser.test.js.map +1 -0
  115. package/dist/parser/ast.d.ts +708 -0
  116. package/dist/parser/ast.d.ts.map +1 -0
  117. package/dist/parser/ast.js +12 -0
  118. package/dist/parser/ast.js.map +1 -0
  119. package/dist/parser/index.d.ts +253 -0
  120. package/dist/parser/index.d.ts.map +1 -0
  121. package/dist/parser/index.js +1985 -0
  122. package/dist/parser/index.js.map +1 -0
  123. package/dist/parser/lexer.d.ts +100 -0
  124. package/dist/parser/lexer.d.ts.map +1 -0
  125. package/dist/parser/lexer.js +304 -0
  126. package/dist/parser/lexer.js.map +1 -0
  127. package/dist/parser/validator.d.ts +42 -0
  128. package/dist/parser/validator.d.ts.map +1 -0
  129. package/dist/parser/validator.js +2568 -0
  130. package/dist/parser/validator.js.map +1 -0
  131. package/dist/scaffold/__tests__/scaffold.test.d.ts +7 -0
  132. package/dist/scaffold/__tests__/scaffold.test.d.ts.map +1 -0
  133. package/dist/scaffold/__tests__/scaffold.test.js +295 -0
  134. package/dist/scaffold/__tests__/scaffold.test.js.map +1 -0
  135. package/dist/scaffold/incremental.d.ts +43 -0
  136. package/dist/scaffold/incremental.d.ts.map +1 -0
  137. package/dist/scaffold/incremental.js +185 -0
  138. package/dist/scaffold/incremental.js.map +1 -0
  139. package/dist/scaffold/index.d.ts +13 -0
  140. package/dist/scaffold/index.d.ts.map +1 -0
  141. package/dist/scaffold/index.js +13 -0
  142. package/dist/scaffold/index.js.map +1 -0
  143. package/dist/scaffold/manifest.d.ts +30 -0
  144. package/dist/scaffold/manifest.d.ts.map +1 -0
  145. package/dist/scaffold/manifest.js +71 -0
  146. package/dist/scaffold/manifest.js.map +1 -0
  147. package/dist/scaffold/merge.d.ts +52 -0
  148. package/dist/scaffold/merge.d.ts.map +1 -0
  149. package/dist/scaffold/merge.js +134 -0
  150. package/dist/scaffold/merge.js.map +1 -0
  151. package/dist/scaffold/types.d.ts +51 -0
  152. package/dist/scaffold/types.d.ts.map +1 -0
  153. package/dist/scaffold/types.js +10 -0
  154. package/dist/scaffold/types.js.map +1 -0
  155. package/dist/sync/index.d.ts +34 -0
  156. package/dist/sync/index.d.ts.map +1 -0
  157. package/dist/sync/index.js +392 -0
  158. package/dist/sync/index.js.map +1 -0
  159. package/dist/visualizer/index.d.ts +17 -0
  160. package/dist/visualizer/index.d.ts.map +1 -0
  161. package/dist/visualizer/index.js +1976 -0
  162. package/dist/visualizer/index.js.map +1 -0
  163. package/examples/code-review.at +167 -0
  164. package/examples/data-processing.at +296 -0
  165. package/examples/openclaw-assistant.at +142 -0
  166. package/examples/scheduled-monitor.at +193 -0
  167. package/examples/simple-pipeline.at +163 -0
  168. package/package.json +77 -0
  169. package/skill/SKILL.md +403 -0
  170. package/skill/scripts/emit.ts +853 -0
  171. package/skill/scripts/visualize.ts +89 -0
  172. package/spec/grammar.md +1466 -0
  173. package/spec/reserved-keywords.md +147 -0
  174. package/spec/validation.md +535 -0
@@ -0,0 +1,3273 @@
1
+ /**
2
+ * AgenTopology language reference documentation content.
3
+ *
4
+ * Each topic is a static reference page for `npx agentopology docs [topic]`.
5
+ * Content is derived from the formal grammar (spec/grammar.md) and AST types
6
+ * (src/parser/ast.ts).
7
+ *
8
+ * @module
9
+ */
10
+ export const topics = {
11
+ // -------------------------------------------------------------------------
12
+ // 1. topology
13
+ // -------------------------------------------------------------------------
14
+ topology: {
15
+ name: "topology",
16
+ description: "Top-level block that wraps an entire .at file",
17
+ content: () => `# topology
18
+
19
+ The \`topology\` block is the root container for every AgenTopology file. It declares the system name, pattern tags, and contains all other blocks.
20
+
21
+ ## Syntax
22
+
23
+ \`\`\`at
24
+ topology NAME : [pattern, ...] {
25
+ meta { ... }
26
+ # all other blocks go here
27
+ }
28
+ \`\`\`
29
+
30
+ The pattern list after the colon is optional. If omitted, no pattern tags are set:
31
+
32
+ \`\`\`at
33
+ topology my-system {
34
+ meta { ... }
35
+ }
36
+ \`\`\`
37
+
38
+ ## Header Fields
39
+
40
+ | Field | Type | Required | Description |
41
+ |-------|------|----------|-------------|
42
+ | NAME | identifier | yes | Unique topology name (lowercase, kebab-case) |
43
+ | patterns | name-list | no | Pattern tags declared in the header |
44
+
45
+ ## Meta Block Fields
46
+
47
+ | Field | Type | Required | Default | Description |
48
+ |-------|------|----------|---------|-------------|
49
+ | version | string | yes | -- | Semantic version (e.g. "1.0.0") |
50
+ | description | string | yes | -- | Human-readable description |
51
+ | domain | identifier | no | -- | Domain identifier (e.g. "legal", "marketing") |
52
+ | foundations | name-list | no | [] | Foundation pattern names |
53
+ | advanced | name-list | no | [] | Advanced pattern names |
54
+ | timeout | string | no | -- | Topology-level timeout (e.g. "30m", "2h") |
55
+ | error-handler | identifier | no | -- | Node ID for catch-all error handler |
56
+ | durable | boolean | no | false | Enable durable execution (requires checkpoint block) |
57
+
58
+ ## Available Patterns
59
+
60
+ \`pipeline\`, \`supervisor\`, \`blackboard\`, \`orchestrator-worker\`, \`debate\`, \`market-routing\`, \`consensus\`, \`fan-out\`, \`event-driven\`, \`human-gate\`
61
+
62
+ ## Example
63
+
64
+ \`\`\`at
65
+ topology content-pipeline : [pipeline, human-gate] {
66
+ meta {
67
+ version: "1.0.0"
68
+ description: "Research, write, review"
69
+ domain: marketing
70
+ timeout: "2h"
71
+ }
72
+ # ... agents, flow, etc.
73
+ }
74
+ \`\`\`
75
+
76
+ ## Notes
77
+
78
+ - Every .at file must have exactly one \`topology\` block (or one \`fragment\` block).
79
+ - The topology name must be globally unique and follow identifier rules (lowercase, hyphens allowed).
80
+ - Pattern tags are informational metadata -- they don't enforce behavior but document intent.
81
+ `,
82
+ },
83
+ // -------------------------------------------------------------------------
84
+ // 2. agent
85
+ // -------------------------------------------------------------------------
86
+ agent: {
87
+ name: "agent",
88
+ description: "Agent node -- the primary compute unit (47 fields)",
89
+ content: () => `# agent
90
+
91
+ The \`agent\` node is the primary compute unit in AgenTopology. Each agent represents an LLM-powered worker with a model, prompt, tools, and data access.
92
+
93
+ ## Syntax
94
+
95
+ \`\`\`at
96
+ agent NAME {
97
+ model: MODEL
98
+ permissions: MODE
99
+ phase: N
100
+ prompt {
101
+ Multi-line prompt text here.
102
+ }
103
+ tools: [tool1, tool2]
104
+ # ... additional fields
105
+ }
106
+ \`\`\`
107
+
108
+ ## All Fields (47)
109
+
110
+ ### Identity & Execution
111
+
112
+ | Field | Type | Required | Default | Description |
113
+ |-------|------|----------|---------|-------------|
114
+ | model | string | yes (V7) | -- | Model identifier (e.g. "opus", "gpt-4o") |
115
+ | phase | number | no | -- | Decimal ordering value (e.g. 1, 2.5) |
116
+ | permissions | string | no | -- | Permission mode (see below) |
117
+ | role | identifier | no | -- | Role name (resolved from roles block) |
118
+ | description | string | no | -- | Human-readable description for delegation |
119
+ | invocation | string | no | "auto" | "manual" or "auto" (V4: manual exempts from orphan check) |
120
+ | background | boolean | no | false | Run in background |
121
+ | isolation | string | no | -- | Isolation mode: "worktree" |
122
+ | maxTurns | number | no | -- | Max agentic turns before stopping |
123
+ | sandbox | string or boolean | no | -- | "docker", "none", "network-only", true, false |
124
+ | skip | string | no | -- | Skip condition: "not identifier" or "identifier.identifier op value" |
125
+
126
+ ### Prompt & Output
127
+
128
+ | Field | Type | Required | Default | Description |
129
+ |-------|------|----------|---------|-------------|
130
+ | prompt | string | no (V10) | -- | Multi-line via \`prompt {}\` block or file path string |
131
+ | outputs | OutputsMap | no | -- | Enum outputs: \`{ field: val1 \\| val2 }\` (V5) |
132
+ | outputFormat | string | no | "text" | "text", "json", "json-schema" |
133
+ | inputSchema | SchemaFieldDef[] | no | -- | Typed input schema fields |
134
+ | outputSchema | SchemaFieldDef[] | no | -- | Typed output schema fields |
135
+
136
+ ### Tools & Data
137
+
138
+ | Field | Type | Required | Default | Description |
139
+ |-------|------|----------|---------|-------------|
140
+ | tools | string[] | no | -- | Allowed tools (supports wildcards like \`mcp.server.*\`) |
141
+ | disallowedTools | string[] | no | -- | Denied tools (mutually exclusive with tools -- V14) |
142
+ | skills | string[] | no | -- | Skill IDs this agent can use |
143
+ | reads | string[] | no | -- | Memory keys this agent reads (V11) |
144
+ | writes | string[] | no | -- | Memory keys this agent writes (V11) |
145
+ | mcpServers | string[] | no | -- | MCP server names this agent uses |
146
+ | produces | string[] | no | -- | Artifact IDs this agent produces |
147
+ | consumes | string[] | no | -- | Artifact IDs this agent consumes |
148
+
149
+ ### Behavior & Flow
150
+
151
+ | Field | Type | Required | Default | Description |
152
+ |-------|------|----------|---------|-------------|
153
+ | behavior | string | no | -- | "advisory" or "blocking" |
154
+ | join | string | no | -- | Fan-in: "all", "any", "all-done", "none-failed" |
155
+ | onFail | string | no | -- | "halt", "retry", "skip", "continue", "fallback <agent-id>" |
156
+ | timeout | string | no | -- | Duration: "5m", "2h" |
157
+ | fallbackChain | string[] | no | -- | Ordered model IDs to try (V22) |
158
+ | compensates | string | no | -- | Agent ID (saga pattern compensation) |
159
+
160
+ ### Retry & Resilience
161
+
162
+ | Field | Type | Required | Default | Description |
163
+ |-------|------|----------|---------|-------------|
164
+ | retry | number or RetryConfig | no | -- | Simple count or structured config |
165
+ | circuitBreaker | CircuitBreakerConfig | no | -- | \`{ threshold, window, cooldown }\` |
166
+ | rateLimit | string | no | -- | "60/min", "1000/hour", "5/sec" |
167
+
168
+ ### Sampling Parameters
169
+
170
+ | Field | Type | Required | Default | Description |
171
+ |-------|------|----------|---------|-------------|
172
+ | temperature | number | no | -- | Sampling temperature (0-2) |
173
+ | maxTokens | number | no | -- | Max tokens to generate |
174
+ | topP | number | no | -- | Nucleus sampling (0-1) |
175
+ | topK | number | no | -- | Top-k sampling |
176
+ | stop | string[] | no | -- | Stop sequences |
177
+ | seed | number | no | -- | Random seed for reproducibility |
178
+ | thinking | string | no | -- | "off", "low", "medium", "high", "max" |
179
+ | thinkingBudget | number | no | -- | Token budget for reasoning (min 1000) |
180
+
181
+ ### Observability
182
+
183
+ | Field | Type | Required | Default | Description |
184
+ |-------|------|----------|---------|-------------|
185
+ | logLevel | string | no | -- | "debug", "info", "warn", "error" |
186
+
187
+ ### Scaling
188
+
189
+ | Field | Type | Required | Default | Description |
190
+ |-------|------|----------|---------|-------------|
191
+ | scale | ScaleDef | no | -- | Parallel execution config (see \`scale\` topic) |
192
+
193
+ ### A/B Testing
194
+
195
+ | Field | Type | Required | Default | Description |
196
+ |-------|------|----------|---------|-------------|
197
+ | variants | PromptVariant[] | no | -- | \`{ id, prompt?, weight (0-1), temperature?, model? }\` |
198
+
199
+ ### Extensibility
200
+
201
+ | Field | Type | Required | Default | Description |
202
+ |-------|------|----------|---------|-------------|
203
+ | hooks | HookDef[] | no | -- | Per-agent hook definitions |
204
+ | extensions | Record | no | -- | Binding-specific fields |
205
+
206
+ ## Permission Modes
207
+
208
+ | Long form | Short form | Description |
209
+ |-----------|------------|-------------|
210
+ | autonomous | auto | Agent acts without human approval |
211
+ | supervised | plan | Agent presents a plan, then executes after approval |
212
+ | interactive | confirm | Agent asks for confirmation on each action |
213
+ | unrestricted | bypass | No safety checks (use with caution) |
214
+
215
+ ## RetryConfig Fields
216
+
217
+ \`\`\`at
218
+ retry {
219
+ max: 3
220
+ backoff: exponential # none | linear | exponential
221
+ interval: "1s"
222
+ max-interval: "30s"
223
+ jitter: true
224
+ non-retryable: ["AuthError", "NotFound"]
225
+ }
226
+ \`\`\`
227
+
228
+ ## Validation Rules
229
+
230
+ - **V7**: Every agent must have a \`model\` field
231
+ - **V10**: Prompt blocks should not be empty (warning)
232
+ - **V11**: reads/writes must match flow order
233
+ - **V14**: Cannot have both \`tools\` and \`disallowed-tools\`
234
+ - **V4**: Agents must appear in flow or have \`invocation: manual\`
235
+ - **V5**: \`[when x.y == z]\` must reference declared outputs
236
+ - **V22**: Fallback chain models should exist in a provider (warning)
237
+ - **V27**: Permission mode should be a recognized value (warning)
238
+
239
+ ## Example
240
+
241
+ \`\`\`at
242
+ agent reviewer {
243
+ role: reviewer
244
+ model: opus
245
+ permissions: supervised
246
+ phase: 2
247
+ tools: [Read, Grep, Glob]
248
+ reads: ["workspace/draft.md"]
249
+ writes: ["workspace/review.md"]
250
+ timeout: "10m"
251
+ retry: 2
252
+ outputs: {
253
+ verdict: approve | revise | reject
254
+ }
255
+ prompt {
256
+ You are a code reviewer. Check for correctness,
257
+ clarity, and test coverage.
258
+ }
259
+ }
260
+ \`\`\`
261
+ `,
262
+ },
263
+ // -------------------------------------------------------------------------
264
+ // 3. orchestrator
265
+ // -------------------------------------------------------------------------
266
+ orchestrator: {
267
+ name: "orchestrator",
268
+ description: "Orchestrator node -- coordinates agents and handles actions",
269
+ content: () => `# orchestrator
270
+
271
+ The \`orchestrator\` node coordinates the overall topology. It routes work, generates plans, and handles action responses.
272
+
273
+ ## Syntax
274
+
275
+ \`\`\`at
276
+ orchestrator {
277
+ model: MODEL
278
+ generates: "path/to/plan.md"
279
+ handles: [action1, action2]
280
+ outputs: {
281
+ field: val1 | val2
282
+ }
283
+ }
284
+ \`\`\`
285
+
286
+ ## Fields
287
+
288
+ | Field | Type | Required | Default | Description |
289
+ |-------|------|----------|---------|-------------|
290
+ | model | string | yes (V7) | -- | Model identifier |
291
+ | generates | string | no | -- | Path to the plan/template file the orchestrator creates |
292
+ | handles | string[] | yes (V9) | -- | Action IDs this orchestrator handles |
293
+ | outputs | OutputsMap | no | -- | Enum output definitions (V5) |
294
+
295
+ ## Validation Rules
296
+
297
+ - **V7**: Model is required
298
+ - **V9**: All actions referenced in the flow must appear in \`handles\`
299
+ - **V5**: Output values must match \`[when]\` conditions in edges
300
+
301
+ ## Example
302
+
303
+ \`\`\`at
304
+ orchestrator {
305
+ model: opus
306
+ generates: "commands/plan.md"
307
+ handles: [intake, deliver]
308
+ outputs: {
309
+ mode: batch | realtime
310
+ }
311
+ }
312
+ \`\`\`
313
+
314
+ ## Notes
315
+
316
+ - A topology has at most one orchestrator node.
317
+ - The orchestrator is typically the entry point that delegates to agents via actions.
318
+ `,
319
+ },
320
+ // -------------------------------------------------------------------------
321
+ // 4. action
322
+ // -------------------------------------------------------------------------
323
+ action: {
324
+ name: "action",
325
+ description: "Action node -- external commands, scripts, or decisions",
326
+ content: () => `# action
327
+
328
+ An \`action\` node represents a discrete operation: an external call, git command, inline decision, or report generation.
329
+
330
+ ## Syntax
331
+
332
+ \`\`\`at
333
+ action NAME {
334
+ kind: KIND
335
+ description: "What this action does"
336
+ source: "source-reference"
337
+ commands: ["cmd1", "cmd2"]
338
+ timeout: "5m"
339
+ on-fail: halt
340
+ join: all
341
+ }
342
+ \`\`\`
343
+
344
+ ## Fields
345
+
346
+ | Field | Type | Required | Default | Description |
347
+ |-------|------|----------|---------|-------------|
348
+ | kind | string | yes (V26) | -- | "external", "git", "decision", "inline", "report" |
349
+ | source | string | no | -- | Source reference (file path or URL) |
350
+ | description | string | no | -- | Human-readable description |
351
+ | commands | string[] | no | -- | Shell commands to execute |
352
+ | timeout | string | no | -- | Duration string (e.g. "5m", "2h") |
353
+ | on-fail | string | no | -- | "halt", "retry", "skip", "continue", "fallback <agent-id>" |
354
+ | join | string | no | -- | Fan-in: "all", "any", "all-done", "none-failed" |
355
+
356
+ ## Action Kinds
357
+
358
+ | Kind | Description |
359
+ |------|-------------|
360
+ | external | External API call or service invocation |
361
+ | git | Git operation (commit, branch, PR) |
362
+ | decision | Routing decision point |
363
+ | inline | Inline logic, no external side effects |
364
+ | report | Compile and deliver output |
365
+
366
+ ## Validation Rules
367
+
368
+ - **V26**: \`kind\` must be one of: external, git, decision, inline, report
369
+ - **V9**: Actions in the flow must be listed in the orchestrator's \`handles\`
370
+
371
+ ## Example
372
+
373
+ \`\`\`at
374
+ action intake {
375
+ kind: external
376
+ source: "github-pr"
377
+ description: "Fetch PR diff and metadata from GitHub"
378
+ timeout: "2m"
379
+ }
380
+
381
+ action deliver {
382
+ kind: report
383
+ description: "Deliver final output to the user"
384
+ }
385
+ \`\`\`
386
+ `,
387
+ },
388
+ // -------------------------------------------------------------------------
389
+ // 5. gate
390
+ // -------------------------------------------------------------------------
391
+ gate: {
392
+ name: "gate",
393
+ description: "Gate node -- quality or security checkpoint between agents",
394
+ content: () => `# gate
395
+
396
+ A \`gate\` node is a checkpoint that runs between two agents. Gates enforce quality, security, or compliance checks before work proceeds.
397
+
398
+ ## Syntax
399
+
400
+ Gates are declared inside a \`gates {}\` block:
401
+
402
+ \`\`\`at
403
+ gates {
404
+ gate NAME {
405
+ after: AGENT_ID
406
+ before: AGENT_ID
407
+ run: "scripts/check.sh"
408
+ checks: [check1, check2]
409
+ retry: 2
410
+ on-fail: bounce-back
411
+ behavior: blocking
412
+ timeout: "5m"
413
+ }
414
+ }
415
+ \`\`\`
416
+
417
+ ## Fields
418
+
419
+ | Field | Type | Required | Default | Description |
420
+ |-------|------|----------|---------|-------------|
421
+ | after | identifier | no (V13) | -- | Node this gate runs after |
422
+ | before | identifier | no (V13) | -- | Node this gate runs before |
423
+ | run | string | no | -- | Script to execute for the check |
424
+ | checks | string[] | no | -- | List of check identifiers |
425
+ | retry | number | no | -- | Max retries on failure |
426
+ | on-fail | string | no | "halt" | "halt" or "bounce-back" |
427
+ | behavior | string | no | "blocking" | "advisory" or "blocking" |
428
+ | timeout | string | no | -- | Duration string |
429
+ | extensions | Record | no | -- | Binding-specific fields |
430
+
431
+ ## On-Fail Behaviors
432
+
433
+ | Value | Description |
434
+ |-------|-------------|
435
+ | halt | Stop the topology on gate failure |
436
+ | bounce-back | Return work to the \`after\` agent for correction |
437
+
438
+ ## Validation Rules
439
+
440
+ - **V13**: \`after\` and \`before\` must reference declared nodes
441
+ - **V25**: \`on-fail: bounce-back\` is advisory on CLI platforms (warning)
442
+
443
+ ## Example
444
+
445
+ \`\`\`at
446
+ gates {
447
+ gate security-scan {
448
+ after: writer
449
+ before: reviewer
450
+ run: "scripts/security-scan.sh"
451
+ checks: [secrets, dependencies, permissions]
452
+ retry: 1
453
+ on-fail: halt
454
+ behavior: blocking
455
+ }
456
+ }
457
+ \`\`\`
458
+
459
+ ## Notes
460
+
461
+ - Gates are positioned hooks -- they compile to the strongest enforcement the target platform supports.
462
+ - A gate with \`behavior: advisory\` logs failures but does not block the flow.
463
+ `,
464
+ },
465
+ // -------------------------------------------------------------------------
466
+ // 6. human
467
+ // -------------------------------------------------------------------------
468
+ human: {
469
+ name: "human",
470
+ description: "Human-in-the-loop node requiring manual input or approval",
471
+ content: () => `# human
472
+
473
+ A \`human\` node represents a point in the flow where human input or approval is required.
474
+
475
+ ## Syntax
476
+
477
+ \`\`\`at
478
+ human NAME {
479
+ description: "What the human needs to do"
480
+ timeout: "1h"
481
+ on-timeout: skip
482
+ }
483
+ \`\`\`
484
+
485
+ ## Fields
486
+
487
+ | Field | Type | Required | Default | Description |
488
+ |-------|------|----------|---------|-------------|
489
+ | description | string | no | -- | What the human should do |
490
+ | timeout | string | no | -- | How long to wait (e.g. "1h", "30m") |
491
+ | on-timeout | string | no | "halt" | "halt", "skip", or "fallback <agent-id>" |
492
+
493
+ ## Example
494
+
495
+ \`\`\`at
496
+ human manager-approval {
497
+ description: "Review the generated report and approve or reject"
498
+ timeout: "4h"
499
+ on-timeout: fallback auto-approver
500
+ }
501
+ \`\`\`
502
+
503
+ ## Notes
504
+
505
+ - Human nodes appear in the flow graph like any other node.
506
+ - If no \`on-timeout\` is set, the topology halts when the timeout expires.
507
+ - Use the \`human-gate\` pattern tag when your topology includes human nodes.
508
+ `,
509
+ },
510
+ // -------------------------------------------------------------------------
511
+ // 7. group
512
+ // -------------------------------------------------------------------------
513
+ group: {
514
+ name: "group",
515
+ description: "Group chat node -- multi-agent conversation or debate",
516
+ content: () => `# group
517
+
518
+ A \`group\` node defines a multi-agent conversation where several agents interact in rounds, simulating debate, brainstorming, or consensus.
519
+
520
+ ## Syntax
521
+
522
+ \`\`\`at
523
+ group NAME {
524
+ members: [agent1, agent2, agent3]
525
+ speaker-selection: round-robin
526
+ max-rounds: 5
527
+ termination: "All members agree on a solution"
528
+ description: "Debate the best approach"
529
+ timeout: "30m"
530
+ }
531
+ \`\`\`
532
+
533
+ ## Fields
534
+
535
+ | Field | Type | Required | Default | Description |
536
+ |-------|------|----------|---------|-------------|
537
+ | members | string[] | yes | -- | Agent IDs that participate |
538
+ | speaker-selection | string | no | -- | "round-robin" or "random" |
539
+ | max-rounds | number | no | -- | Maximum conversation rounds |
540
+ | termination | string | no | -- | Natural language termination condition |
541
+ | description | string | no | -- | Human-readable description |
542
+ | timeout | string | no | -- | Duration string |
543
+
544
+ ## Example
545
+
546
+ \`\`\`at
547
+ group design-review {
548
+ members: [architect, security-lead, ux-lead]
549
+ speaker-selection: round-robin
550
+ max-rounds: 10
551
+ termination: "All members approve the design"
552
+ timeout: "1h"
553
+ }
554
+ \`\`\`
555
+
556
+ ## Notes
557
+
558
+ - Member agents must be declared as \`agent\` nodes in the same topology.
559
+ - Groups appear in the flow graph and can have edges to/from other nodes.
560
+ - Use the \`debate\` or \`consensus\` pattern tag when using groups.
561
+ `,
562
+ },
563
+ // -------------------------------------------------------------------------
564
+ // 8. flow
565
+ // -------------------------------------------------------------------------
566
+ flow: {
567
+ name: "flow",
568
+ description: "Edge syntax -- arrows, fan-out, conditions, error edges",
569
+ content: () => `# flow
570
+
571
+ The \`flow\` block defines the directed graph of edges between nodes. It uses arrow syntax to describe how work moves through the topology.
572
+
573
+ ## Syntax
574
+
575
+ \`\`\`at
576
+ flow {
577
+ # Simple edge
578
+ from -> to
579
+
580
+ # Fan-out (parallel)
581
+ from -> [to1, to2, to3]
582
+
583
+ # Edge with attributes
584
+ from -> to [when from.field == value]
585
+
586
+ # Error edge
587
+ from -x-> error-handler
588
+
589
+ # Typed error edge
590
+ from -x[TimeoutError]-> timeout-handler
591
+ }
592
+ \`\`\`
593
+
594
+ ## Arrow Types
595
+
596
+ | Syntax | Description |
597
+ |--------|-------------|
598
+ | \`->\` | Normal directed edge |
599
+ | \`-x->\` | Error edge (fires on failure, sets isError) |
600
+ | \`-x[Type]->\` | Typed error edge (sets errorType to the specified type) |
601
+
602
+ ## Edge Attributes
603
+
604
+ Attributes appear in brackets after the target. Order matters (V12):
605
+
606
+ | Attribute | Syntax | Description |
607
+ |-----------|--------|-------------|
608
+ | when | \`[when agent.field == value]\` | Conditional edge (V5, V15) |
609
+ | max | \`[max N]\` | Loop bound for back-edges (V6) |
610
+ | per | \`[per agent-id]\` | Scoping per agent instance |
611
+ | tolerance | \`[tolerance N]\` or \`[tolerance "33%"]\` | Fan-out failure tolerance |
612
+ | race | \`[race]\` | First-to-finish wins |
613
+ | wait | \`[wait 30s]\` | Timer delay before edge fires |
614
+ | weight | \`[weight 0.7]\` | Routing probability (0-1) |
615
+ | reflection | \`[reflection]\` | Marks an evaluator/reflection loop |
616
+
617
+ Multiple attributes can be combined:
618
+
619
+ \`\`\`at
620
+ reviewer -> writer [when reviewer.verdict == revise, max 3]
621
+ \`\`\`
622
+
623
+ ## Fan-Out
624
+
625
+ Fan-out sends work to multiple agents in parallel:
626
+
627
+ \`\`\`at
628
+ flow {
629
+ intake -> [analyzer, scanner, checker]
630
+ analyzer -> reviewer
631
+ scanner -> reviewer
632
+ checker -> reviewer
633
+ }
634
+ \`\`\`
635
+
636
+ ## Conditional Edges
637
+
638
+ Conditional edges require the source agent to have matching \`outputs\`:
639
+
640
+ \`\`\`at
641
+ agent reviewer {
642
+ outputs: {
643
+ verdict: approve | revise | reject
644
+ }
645
+ }
646
+
647
+ flow {
648
+ reviewer -> done [when reviewer.verdict == approve]
649
+ reviewer -> writer [when reviewer.verdict == revise, max 2]
650
+ reviewer -> intake [when reviewer.verdict == reject]
651
+ }
652
+ \`\`\`
653
+
654
+ ## Validation Rules
655
+
656
+ - **V3**: All node references in flow must be declared
657
+ - **V5**: \`[when x.y == z]\` must reference declared outputs with valid values
658
+ - **V6**: Back-edges (loops) must have \`[max N]\` to prevent infinite loops
659
+ - **V12**: Edge attributes must appear in order: when, max, per
660
+ - **V15**: Conditional edges must exhaustively cover all output values
661
+
662
+ ## Notes
663
+
664
+ - Fan-in happens automatically when multiple edges point to the same target.
665
+ - The \`join\` field on the target node controls fan-in semantics (all, any, etc.).
666
+ - Error edges provide explicit error routing instead of relying on \`on-fail\`.
667
+ `,
668
+ },
669
+ // -------------------------------------------------------------------------
670
+ // 9. memory
671
+ // -------------------------------------------------------------------------
672
+ memory: {
673
+ name: "memory",
674
+ description: "Memory block -- workspace, domains, references, metrics",
675
+ content: () => `# memory
676
+
677
+ The \`memory\` block declares the shared data layer for the topology. It defines where agents read and write data.
678
+
679
+ ## Syntax
680
+
681
+ \`\`\`at
682
+ memory {
683
+ workspace {
684
+ path: "workspace/"
685
+ structure: [folder1, folder2]
686
+ }
687
+
688
+ domains {
689
+ path: "domains/"
690
+ routing: "domain-routing.md"
691
+ }
692
+
693
+ references {
694
+ path: "references/"
695
+ }
696
+
697
+ external-docs {
698
+ path: "docs/"
699
+ }
700
+
701
+ metrics {
702
+ path: "metrics/data.jsonl"
703
+ mode: append-only
704
+ }
705
+ }
706
+ \`\`\`
707
+
708
+ ## Sub-Blocks
709
+
710
+ | Sub-block | Description |
711
+ |-----------|-------------|
712
+ | workspace | Primary working directory for agent I/O |
713
+ | domains | Domain knowledge files |
714
+ | references | Reference documentation |
715
+ | external-docs | External documentation |
716
+ | metrics | Metrics output (supports append-only mode) |
717
+
718
+ ### workspace Fields
719
+
720
+ | Field | Type | Description |
721
+ |-------|------|-------------|
722
+ | path | string | Directory path |
723
+ | structure | name-list | Expected folder structure |
724
+
725
+ ### domains Fields
726
+
727
+ | Field | Type | Description |
728
+ |-------|------|-------------|
729
+ | path | string | Directory path |
730
+ | routing | string | Routing config file path |
731
+
732
+ ### references / external-docs Fields
733
+
734
+ | Field | Type | Description |
735
+ |-------|------|-------------|
736
+ | path | string | Directory path |
737
+
738
+ ### metrics Fields
739
+
740
+ | Field | Type | Description |
741
+ |-------|------|-------------|
742
+ | path | string | Output file path |
743
+ | mode | string | "append-only" for log-style output |
744
+
745
+ ## Validation Rules
746
+
747
+ - **V11**: Agent \`reads\` and \`writes\` must be consistent with flow order
748
+ - **V24**: Only known sub-block names are expected (warning)
749
+
750
+ ## Notes
751
+
752
+ - Memory paths are relative to the topology's root directory.
753
+ - Agents declare which memory keys they access via \`reads\` and \`writes\` fields.
754
+ - The workspace structure is informational -- it documents expected folders but does not create them.
755
+ `,
756
+ },
757
+ // -------------------------------------------------------------------------
758
+ // 10. hooks
759
+ // -------------------------------------------------------------------------
760
+ hooks: {
761
+ name: "hooks",
762
+ description: "Hook definitions -- global and per-agent event handlers",
763
+ content: () => `# hooks
764
+
765
+ Hooks are event-driven handlers that fire at specific points in the topology lifecycle. They can be global (topology-level) or per-agent.
766
+
767
+ ## Syntax
768
+
769
+ ### Global Hooks
770
+
771
+ \`\`\`at
772
+ hooks {
773
+ hook NAME {
774
+ on: EVENT
775
+ matcher: "pattern"
776
+ run: "scripts/handler.sh"
777
+ type: command
778
+ timeout: 5000
779
+ }
780
+ }
781
+ \`\`\`
782
+
783
+ ### Per-Agent Hooks
784
+
785
+ \`\`\`at
786
+ agent my-agent {
787
+ hooks {
788
+ hook NAME {
789
+ on: EVENT
790
+ run: "scripts/handler.sh"
791
+ type: command
792
+ }
793
+ }
794
+ }
795
+ \`\`\`
796
+
797
+ ## Fields
798
+
799
+ | Field | Type | Required | Default | Description |
800
+ |-------|------|----------|---------|-------------|
801
+ | name | identifier | yes | -- | Hook identifier |
802
+ | on | string | yes | -- | Event name to listen for |
803
+ | matcher | string | no | -- | Pattern to match against event payload |
804
+ | run | string | yes | -- | Command or script to execute |
805
+ | type | string | no | -- | "command" or "prompt" |
806
+ | timeout | number | no | -- | Timeout in milliseconds |
807
+ | extensions | Record | no | -- | Binding-specific fields |
808
+
809
+ ## Events (23 total)
810
+
811
+ ### Agent Lifecycle
812
+ \`AgentStart\`, \`AgentStop\`, \`SubagentStart\`, \`SubagentStop\`, \`Stop\`
813
+
814
+ ### Tool Events
815
+ \`ToolUse\`, \`PreToolUse\`, \`PostToolUse\`, \`PostToolUseFailure\`
816
+
817
+ ### Session Events
818
+ \`SessionStart\`, \`SessionEnd\`
819
+
820
+ ### User Events
821
+ \`UserPromptSubmit\`, \`PermissionRequest\`, \`Notification\`
822
+
823
+ ### System Events
824
+ \`Error\`, \`InstructionsLoaded\`, \`TeammateIdle\`, \`TaskCompleted\`, \`ConfigChange\`
825
+
826
+ ### Worktree Events
827
+ \`WorktreeCreate\`, \`WorktreeRemove\`
828
+
829
+ ### Memory Events
830
+ \`PreCompact\`
831
+
832
+ ## Example
833
+
834
+ \`\`\`at
835
+ hooks {
836
+ hook block-dangerous-tools {
837
+ on: PreToolUse
838
+ matcher: "Bash(rm -rf *)"
839
+ run: "exit 1"
840
+ type: command
841
+ }
842
+
843
+ hook log-completions {
844
+ on: AgentStop
845
+ run: "scripts/log-completion.sh"
846
+ type: command
847
+ timeout: 5000
848
+ }
849
+ }
850
+ \`\`\`
851
+
852
+ ## Notes
853
+
854
+ - \`type: command\` runs a shell command; \`type: prompt\` injects text into the agent's context.
855
+ - The \`matcher\` field filters events by payload pattern (e.g. tool name for ToolUse events).
856
+ - Global hooks fire for all agents; per-agent hooks fire only for that agent.
857
+ `,
858
+ },
859
+ // -------------------------------------------------------------------------
860
+ // 11. triggers
861
+ // -------------------------------------------------------------------------
862
+ triggers: {
863
+ name: "triggers",
864
+ description: "Command triggers -- user-invocable slash commands",
865
+ content: () => `# triggers
866
+
867
+ Triggers define slash commands that users can invoke to start or control the topology.
868
+
869
+ ## Syntax
870
+
871
+ \`\`\`at
872
+ triggers {
873
+ command NAME {
874
+ pattern: "REGEX_OR_PATTERN"
875
+ argument: VAR
876
+ }
877
+ }
878
+ \`\`\`
879
+
880
+ ## Fields
881
+
882
+ | Field | Type | Required | Default | Description |
883
+ |-------|------|----------|---------|-------------|
884
+ | pattern | string | yes | -- | Regex or glob pattern with optional \`<VAR>\` placeholders |
885
+ | argument | template-var | no | -- | Variable name captured from the pattern |
886
+
887
+ ## Example
888
+
889
+ \`\`\`at
890
+ triggers {
891
+ command review {
892
+ pattern: "/review <PR_URL>"
893
+ argument: PR_URL
894
+ }
895
+
896
+ command status {
897
+ pattern: "/status"
898
+ }
899
+
900
+ command deploy {
901
+ pattern: "/deploy <ENV>"
902
+ argument: ENV
903
+ }
904
+ }
905
+ \`\`\`
906
+
907
+ ## Notes
908
+
909
+ - Template variables use UPPER_CASE (e.g. \`PR_URL\`, \`BATCH_ID\`).
910
+ - The \`argument\` field names the captured value from the angle-bracket placeholder in the pattern.
911
+ - Triggers compile to platform-specific command mechanisms (e.g. Claude Code slash commands).
912
+ `,
913
+ },
914
+ // -------------------------------------------------------------------------
915
+ // 12. settings
916
+ // -------------------------------------------------------------------------
917
+ settings: {
918
+ name: "settings",
919
+ description: "Permission settings -- allow, deny, ask tool lists",
920
+ content: () => `# settings
921
+
922
+ The \`settings\` block defines tool permission lists that apply topology-wide.
923
+
924
+ ## Syntax
925
+
926
+ \`\`\`at
927
+ settings {
928
+ allow: ["Tool1", "Tool2"]
929
+ deny: ["Tool3", "Bash(rm -rf *)"]
930
+ ask: ["Bash(aws s3 *)"]
931
+ sandbox: true
932
+ fallback-chain: [opus, sonnet, haiku]
933
+ }
934
+ \`\`\`
935
+
936
+ ## Fields
937
+
938
+ | Field | Type | Required | Default | Description |
939
+ |-------|------|----------|---------|-------------|
940
+ | allow | string[] | no | -- | Tools permitted without prompting |
941
+ | deny | string[] | no | -- | Tools blocked entirely |
942
+ | ask | string[] | no | -- | Tools that require user confirmation |
943
+ | sandbox | boolean or string | no | -- | Enable sandboxing |
944
+ | fallback-chain | name-list | no | -- | Default model fallback order |
945
+
946
+ ## Notes
947
+
948
+ - Tool names can include argument patterns: \`"Bash(rm -rf *)"\` denies only that specific invocation.
949
+ - \`allow\`, \`deny\`, and \`ask\` are evaluated in that priority order.
950
+ - Individual agents can override these with their own \`tools\` or \`disallowed-tools\` fields.
951
+ `,
952
+ },
953
+ // -------------------------------------------------------------------------
954
+ // 13. tools
955
+ // -------------------------------------------------------------------------
956
+ tools: {
957
+ name: "tools",
958
+ description: "Custom tool definitions -- scripts agents can invoke",
959
+ content: () => `# tools
960
+
961
+ The \`tools\` block defines custom tools implemented as scripts that agents can invoke.
962
+
963
+ ## Syntax
964
+
965
+ \`\`\`at
966
+ tools {
967
+ tool NAME {
968
+ script: "path/to/script.py"
969
+ args: [arg1, arg2]
970
+ lang: python
971
+ description: "What this tool does"
972
+ }
973
+ }
974
+ \`\`\`
975
+
976
+ ## Fields
977
+
978
+ | Field | Type | Required | Default | Description |
979
+ |-------|------|----------|---------|-------------|
980
+ | id | identifier | yes | -- | Tool identifier (the NAME) |
981
+ | script | string | yes | -- | Path to the implementing script |
982
+ | args | string[] | no | -- | Positional argument names |
983
+ | lang | string | no | "auto" | "bash", "python", "node", "auto" |
984
+ | description | string | yes | -- | Human-readable description |
985
+
986
+ ## Example
987
+
988
+ \`\`\`at
989
+ tools {
990
+ tool extract-pdf {
991
+ script: "scripts/extract-pdf.py"
992
+ args: [input-path, output-path]
993
+ lang: python
994
+ description: "Extract text from PDF documents"
995
+ }
996
+
997
+ tool run-tests {
998
+ script: "scripts/run-tests.sh"
999
+ lang: bash
1000
+ description: "Run the test suite and return results"
1001
+ }
1002
+ }
1003
+ \`\`\`
1004
+
1005
+ ## Notes
1006
+
1007
+ - Custom tools are referenced by name in agent \`tools\` lists.
1008
+ - The \`lang\` field determines how the script is executed. \`auto\` infers from the file extension.
1009
+ - Tool scripts receive arguments positionally in the order declared.
1010
+ `,
1011
+ },
1012
+ // -------------------------------------------------------------------------
1013
+ // 14. skills
1014
+ // -------------------------------------------------------------------------
1015
+ skills: {
1016
+ name: "skills",
1017
+ description: "Skill definitions -- reusable capability bundles",
1018
+ content: () => `# skills
1019
+
1020
+ Skills are reusable capability bundles that package scripts, domain knowledge, and configuration together.
1021
+
1022
+ ## Syntax
1023
+
1024
+ \`\`\`at
1025
+ skill NAME {
1026
+ description: "What this skill enables"
1027
+ scripts: [tool1, tool2]
1028
+ domains: ["domains/rubric.md"]
1029
+ references: ["refs/guide.md"]
1030
+ prompt: "prompts/skill-prompt.md"
1031
+ disable-model-invocation: false
1032
+ user-invocable: true
1033
+ context: fork
1034
+ agent: sub-agent-id
1035
+ allowed-tools: ["Read", "Write"]
1036
+ }
1037
+ \`\`\`
1038
+
1039
+ ## Fields
1040
+
1041
+ | Field | Type | Required | Default | Description |
1042
+ |-------|------|----------|---------|-------------|
1043
+ | id | identifier | yes | -- | Skill identifier (the NAME) |
1044
+ | description | string | yes | -- | Human-readable description |
1045
+ | scripts | string[] | no | -- | Tool/script names belonging to this skill |
1046
+ | domains | string[] | no | -- | Domain knowledge file paths |
1047
+ | references | string[] | no | -- | Reference file paths |
1048
+ | prompt | string | no | -- | Prompt file path |
1049
+ | disable-model-invocation | boolean | no | false | Disable automatic model invocation |
1050
+ | user-invocable | boolean | no | false | Show in user-facing skill menu |
1051
+ | context | string | no | -- | "fork" for subagent isolation |
1052
+ | agent | identifier | no | -- | Agent type for fork context |
1053
+ | allowed-tools | string[] | no | -- | Tools allowed without permission |
1054
+ | extensions | Record | no | -- | Binding-specific fields |
1055
+
1056
+ ## Example
1057
+
1058
+ \`\`\`at
1059
+ skill data-extraction {
1060
+ description: "Document extraction -- PDF, DOC, images"
1061
+ scripts: [extract-pdf, extract-doc]
1062
+ domains: ["domains/extraction-rules.md"]
1063
+ user-invocable: true
1064
+ }
1065
+ \`\`\`
1066
+
1067
+ ## Notes
1068
+
1069
+ - Agents reference skills via the \`skills\` field: \`skills: [data-extraction]\`.
1070
+ - Skills with \`context: fork\` run in an isolated subagent.
1071
+ - The \`scripts\` field references tools declared in the \`tools\` block.
1072
+ `,
1073
+ },
1074
+ // -------------------------------------------------------------------------
1075
+ // 15. mcp-servers
1076
+ // -------------------------------------------------------------------------
1077
+ "mcp-servers": {
1078
+ name: "mcp-servers",
1079
+ description: "MCP server configurations for tool connectivity",
1080
+ content: () => `# mcp-servers
1081
+
1082
+ The \`mcp-servers\` block configures Model Context Protocol servers that provide additional tools and capabilities to agents.
1083
+
1084
+ ## Syntax
1085
+
1086
+ \`\`\`at
1087
+ mcp-servers {
1088
+ NAME {
1089
+ type: TYPE
1090
+ command: "command"
1091
+ args: ["arg1", "arg2"]
1092
+ url: "https://..."
1093
+ env: {
1094
+ KEY: "value"
1095
+ }
1096
+ }
1097
+ }
1098
+ \`\`\`
1099
+
1100
+ ## Fields
1101
+
1102
+ | Field | Type | Required | Default | Description |
1103
+ |-------|------|----------|---------|-------------|
1104
+ | type | string | yes | -- | "stdio", "http", or "sse" |
1105
+ | command | string | conditional | -- | Command to run (required for stdio) |
1106
+ | url | string | conditional | -- | Server URL (required for http/sse) |
1107
+ | args | string[] | no | -- | Command arguments (for stdio) |
1108
+ | env | key-value | no | -- | Environment variables for the server |
1109
+
1110
+ ## Server Types
1111
+
1112
+ | Type | Description | Required Fields |
1113
+ |------|-------------|-----------------|
1114
+ | stdio | Local process communicating via stdin/stdout | command |
1115
+ | http | Remote HTTP endpoint | url |
1116
+ | sse | Server-Sent Events stream | url |
1117
+
1118
+ ## Example
1119
+
1120
+ \`\`\`at
1121
+ mcp-servers {
1122
+ database {
1123
+ type: stdio
1124
+ command: "npx"
1125
+ args: ["-y", "@modelcontextprotocol/server-postgres"]
1126
+ env: {
1127
+ DATABASE_URL: "\${POSTGRES_URL}"
1128
+ }
1129
+ }
1130
+
1131
+ analytics {
1132
+ type: http
1133
+ url: "https://mcp.analytics.example.com"
1134
+ }
1135
+ }
1136
+ \`\`\`
1137
+
1138
+ ## Notes
1139
+
1140
+ - Agents reference MCP servers via the \`mcp-servers\` field: \`mcp-servers: [database]\`.
1141
+ - Tool names from MCP servers can be referenced with wildcards: \`tools: [mcp.database.*]\`.
1142
+ - Environment variables in \`env\` should use \`\${ENV_VAR}\` syntax for secrets.
1143
+ `,
1144
+ },
1145
+ // -------------------------------------------------------------------------
1146
+ // 16. metering
1147
+ // -------------------------------------------------------------------------
1148
+ metering: {
1149
+ name: "metering",
1150
+ description: "Cost tracking and usage metering configuration",
1151
+ content: () => `# metering
1152
+
1153
+ The \`metering\` block configures cost tracking and usage metrics for the topology.
1154
+
1155
+ ## Syntax
1156
+
1157
+ \`\`\`at
1158
+ metering {
1159
+ track: [tokens-in, tokens-out, cost, wall-time, agent-count]
1160
+ per: [agent, run, phase]
1161
+ output: "metrics/"
1162
+ format: jsonl
1163
+ pricing: anthropic-current
1164
+ }
1165
+ \`\`\`
1166
+
1167
+ ## Fields
1168
+
1169
+ | Field | Type | Required | Default | Description |
1170
+ |-------|------|----------|---------|-------------|
1171
+ | track | string[] | yes | -- | Metrics to track |
1172
+ | per | string[] | yes | -- | Dimensions to aggregate by |
1173
+ | output | string | yes | -- | Output file or directory path |
1174
+ | format | string | yes (V28) | -- | "json", "jsonl", or "csv" |
1175
+ | pricing | string | yes (V29) | -- | Pricing model identifier |
1176
+
1177
+ ## Track Metrics
1178
+
1179
+ \`tokens-in\`, \`tokens-out\`, \`cost\`, \`wall-time\`, \`agent-count\`
1180
+
1181
+ ## Per Dimensions
1182
+
1183
+ \`agent\`, \`run\`, \`phase\`, \`topology\`
1184
+
1185
+ ## Pricing Models
1186
+
1187
+ | Value | Description |
1188
+ |-------|-------------|
1189
+ | anthropic-current | Current Anthropic API pricing |
1190
+ | custom | Custom pricing configuration |
1191
+ | none | No cost calculation |
1192
+
1193
+ ## Validation Rules
1194
+
1195
+ - **V28**: \`format\` must be "json", "jsonl", or "csv"
1196
+ - **V29**: \`pricing\` should be a recognized pricing model (warning)
1197
+
1198
+ ## Example
1199
+
1200
+ \`\`\`at
1201
+ metering {
1202
+ track: [tokens-in, tokens-out, cost]
1203
+ per: [agent, run]
1204
+ output: "metrics/usage.jsonl"
1205
+ format: jsonl
1206
+ pricing: none
1207
+ }
1208
+ \`\`\`
1209
+ `,
1210
+ },
1211
+ // -------------------------------------------------------------------------
1212
+ // 17. providers
1213
+ // -------------------------------------------------------------------------
1214
+ providers: {
1215
+ name: "providers",
1216
+ description: "API provider configurations for model routing",
1217
+ content: () => `# providers
1218
+
1219
+ The \`providers\` block declares API providers for model credentials and routing.
1220
+
1221
+ ## Syntax
1222
+
1223
+ \`\`\`at
1224
+ providers {
1225
+ NAME {
1226
+ api-key: "\${ENV_VAR}"
1227
+ base-url: "https://api.example.com"
1228
+ models: [model1, model2]
1229
+ default: true
1230
+ auth {
1231
+ type: oidc
1232
+ issuer: "https://auth.example.com"
1233
+ audience: "api"
1234
+ }
1235
+ }
1236
+ }
1237
+ \`\`\`
1238
+
1239
+ ## Fields
1240
+
1241
+ | Field | Type | Required | Default | Description |
1242
+ |-------|------|----------|---------|-------------|
1243
+ | name | identifier | yes | -- | Provider name (the block key) |
1244
+ | api-key | string | no (V16) | -- | Must use \`\${ENV_VAR}\` format |
1245
+ | base-url | string | no | -- | Custom API endpoint |
1246
+ | models | name-list | yes | -- | Model identifiers this provider serves |
1247
+ | default | boolean | no | false | Mark as default provider (V17, V19) |
1248
+
1249
+ ## Auth Block Fields
1250
+
1251
+ | Field | Type | Required | Description |
1252
+ |-------|------|----------|-------------|
1253
+ | type | string | yes | "oidc", "oauth2", "api-key", "aws-iam", "gcp-sa", "azure-msi" |
1254
+ | issuer | string | no | Token issuer URL |
1255
+ | audience | string | no | Expected audience claim |
1256
+ | token-url | string | no | Token endpoint URL |
1257
+ | client-id | string | no | OAuth2 client ID |
1258
+ | scopes | string[] | no | OAuth2 scopes |
1259
+
1260
+ ## Validation Rules
1261
+
1262
+ - **V16**: \`api-key\` must use \`\${ENV_VAR}\` syntax (never inline secrets)
1263
+ - **V17**: At most one provider can be \`default: true\`
1264
+ - **V18**: Agent models should exist in a declared provider (warning)
1265
+ - **V19**: Provider names must be unique
1266
+
1267
+ ## Example
1268
+
1269
+ \`\`\`at
1270
+ providers {
1271
+ anthropic {
1272
+ api-key: "\${ANTHROPIC_API_KEY}"
1273
+ models: [opus, sonnet, haiku]
1274
+ default: true
1275
+ }
1276
+
1277
+ openai {
1278
+ api-key: "\${OPENAI_API_KEY}"
1279
+ models: [gpt-4o, gpt-4o-mini]
1280
+ }
1281
+
1282
+ ollama {
1283
+ base-url: "http://localhost:11434"
1284
+ models: [llama3, codellama]
1285
+ }
1286
+ }
1287
+ \`\`\`
1288
+ `,
1289
+ },
1290
+ // -------------------------------------------------------------------------
1291
+ // 18. env
1292
+ // -------------------------------------------------------------------------
1293
+ env: {
1294
+ name: "env",
1295
+ description: "Environment variables and secrets configuration",
1296
+ content: () => `# env
1297
+
1298
+ The \`env\` block declares environment variables for the topology, including support for secret references.
1299
+
1300
+ ## Syntax
1301
+
1302
+ \`\`\`at
1303
+ env {
1304
+ KEY: "value"
1305
+ KEY: "\${ENV_VAR}"
1306
+ KEY: secret "vault://path/to/secret#field"
1307
+ }
1308
+ \`\`\`
1309
+
1310
+ ## Value Types
1311
+
1312
+ | Form | Description |
1313
+ |------|-------------|
1314
+ | \`"literal"\` | Inline string value |
1315
+ | \`"\${ENV_VAR}"\` | Reference to a runtime environment variable |
1316
+ | \`secret "URI"\` | Sensitive value from a secret manager |
1317
+
1318
+ ## Secret Schemes
1319
+
1320
+ | Scheme | Description | Example URI |
1321
+ |--------|-------------|-------------|
1322
+ | vault | HashiCorp Vault | \`vault://secret/data/prod#api-key\` |
1323
+ | op | 1Password CLI | \`op://vault/item/field\` |
1324
+ | awssm | AWS Secrets Manager | \`awssm://prod/api-key\` |
1325
+ | ssm | AWS SSM Parameter Store | \`ssm:///prod/config/key\` |
1326
+ | gcpsm | GCP Secret Manager | \`gcpsm://project/secret/version\` |
1327
+ | azurekv | Azure Key Vault | \`azurekv://vault-name/secret-name\` |
1328
+
1329
+ ## Example
1330
+
1331
+ \`\`\`at
1332
+ env {
1333
+ DATABASE_URL: "\${DATABASE_URL}"
1334
+ API_KEY: secret "vault://secret/data/prod#api-key"
1335
+ LOG_LEVEL: "info"
1336
+ REGION: "us-east-1"
1337
+ }
1338
+ \`\`\`
1339
+
1340
+ ## Validation Rules
1341
+
1342
+ - **V21**: Sensitive fields must use \`\${ENV_VAR}\` or \`secret\` syntax (never inline credentials)
1343
+
1344
+ ## Notes
1345
+
1346
+ - Values marked with \`secret\` are treated as sensitive and are not echoed in logs.
1347
+ - SOPS-encrypted values (\`ENC[METHOD,...]\`) are also supported for encrypted-at-rest secrets.
1348
+ `,
1349
+ },
1350
+ // -------------------------------------------------------------------------
1351
+ // 19. environments
1352
+ // -------------------------------------------------------------------------
1353
+ environments: {
1354
+ name: "environments",
1355
+ description: "Environment-specific configuration overrides",
1356
+ content: () => `# environments
1357
+
1358
+ The \`environments\` block defines per-environment configuration overrides (development, staging, production, etc.).
1359
+
1360
+ ## Syntax
1361
+
1362
+ \`\`\`at
1363
+ environments {
1364
+ development {
1365
+ bucket: "dev-bucket"
1366
+ log-level: "debug"
1367
+ }
1368
+
1369
+ production {
1370
+ bucket: "prod-bucket"
1371
+ log-level: "warn"
1372
+ }
1373
+ }
1374
+ \`\`\`
1375
+
1376
+ ## Structure
1377
+
1378
+ Each environment is a named block containing key-value pairs. The keys and values are free-form -- they are not validated against a schema.
1379
+
1380
+ ## Example
1381
+
1382
+ \`\`\`at
1383
+ environments {
1384
+ development {
1385
+ api-url: "http://localhost:3000"
1386
+ debug: "true"
1387
+ }
1388
+
1389
+ staging {
1390
+ api-url: "https://staging.example.com"
1391
+ }
1392
+
1393
+ production {
1394
+ api-url: "https://api.example.com"
1395
+ replicas: "3"
1396
+ }
1397
+ }
1398
+ \`\`\`
1399
+
1400
+ ## Notes
1401
+
1402
+ - Environment names are identifiers (lowercase, kebab-case).
1403
+ - Values are always strings (quoted).
1404
+ - Bindings select the active environment at compile/deploy time.
1405
+ `,
1406
+ },
1407
+ // -------------------------------------------------------------------------
1408
+ // 20. batch
1409
+ // -------------------------------------------------------------------------
1410
+ batch: {
1411
+ name: "batch",
1412
+ description: "Batch processing configuration",
1413
+ content: () => `# batch
1414
+
1415
+ The \`batch\` block configures how the topology handles batch processing -- parallel execution, conflict resolution, and workspace isolation.
1416
+
1417
+ ## Syntax
1418
+
1419
+ \`\`\`at
1420
+ batch {
1421
+ parallel: true
1422
+ per: ticket
1423
+ conflicts: {
1424
+ detect: ["workspace/output.json"]
1425
+ resolve: sequential-rebase
1426
+ }
1427
+ workspace: "runs/_batch/{BATCH_ID}/"
1428
+ }
1429
+ \`\`\`
1430
+
1431
+ ## Fields
1432
+
1433
+ | Field | Type | Required | Default | Description |
1434
+ |-------|------|----------|---------|-------------|
1435
+ | parallel | boolean | no | false | Enable parallel batch execution |
1436
+ | per | string | no | -- | Batch scoping: "ticket" or an agent ID |
1437
+ | conflicts.detect | string[] | no | -- | File paths to monitor for conflicts |
1438
+ | conflicts.resolve | string | no | -- | Resolution strategy: "sequential-rebase" |
1439
+ | workspace | string | no | -- | Workspace path template (\`{BATCH_ID}\` is replaced) |
1440
+
1441
+ ## Example
1442
+
1443
+ \`\`\`at
1444
+ batch {
1445
+ parallel: true
1446
+ per: ticket
1447
+ conflicts: {
1448
+ detect: ["workspace/synthesis.json"]
1449
+ resolve: sequential-rebase
1450
+ }
1451
+ workspace: "runs/_batch/{BATCH_ID}/"
1452
+ }
1453
+ \`\`\`
1454
+
1455
+ ## Notes
1456
+
1457
+ - \`{BATCH_ID}\` in the workspace path is replaced with the actual batch identifier at runtime.
1458
+ - \`per: ticket\` creates one batch instance per incoming ticket/request.
1459
+ - Conflict detection monitors specified files and applies the resolution strategy when concurrent writes occur.
1460
+ `,
1461
+ },
1462
+ // -------------------------------------------------------------------------
1463
+ // 21. depth
1464
+ // -------------------------------------------------------------------------
1465
+ depth: {
1466
+ name: "depth",
1467
+ description: "Depth levels -- progressive complexity control",
1468
+ content: () => `# depth
1469
+
1470
+ The \`depth\` block defines progressive complexity levels, allowing the same topology to run at different levels of thoroughness.
1471
+
1472
+ ## Syntax
1473
+
1474
+ \`\`\`at
1475
+ depth {
1476
+ factors: [complexity, risk]
1477
+
1478
+ level 1 "quick" {
1479
+ omit: [security-scanner, deep-analyzer]
1480
+ }
1481
+
1482
+ level 2 "standard" {
1483
+ omit: [deep-analyzer]
1484
+ }
1485
+
1486
+ level 3 "thorough" {
1487
+ omit: []
1488
+ }
1489
+ }
1490
+ \`\`\`
1491
+
1492
+ ## Fields
1493
+
1494
+ | Field | Type | Required | Description |
1495
+ |-------|------|----------|-------------|
1496
+ | factors | string[] | yes | Factors that determine depth selection |
1497
+
1498
+ ### Level Fields
1499
+
1500
+ | Field | Type | Required | Description |
1501
+ |-------|------|----------|-------------|
1502
+ | level | number | yes | Numeric depth value |
1503
+ | label | string | yes | Human-readable label (quoted after level number) |
1504
+ | omit | string[] | yes | Agent IDs to skip at this depth |
1505
+
1506
+ ## Example
1507
+
1508
+ \`\`\`at
1509
+ depth {
1510
+ factors: [file-count, change-type]
1511
+
1512
+ level 1 "fast" {
1513
+ omit: [deep-review, security-audit]
1514
+ }
1515
+
1516
+ level 2 "normal" {
1517
+ omit: [security-audit]
1518
+ }
1519
+
1520
+ level 3 "full" {
1521
+ omit: []
1522
+ }
1523
+ }
1524
+ \`\`\`
1525
+
1526
+ ## Notes
1527
+
1528
+ - Higher depth levels include more agents (fewer omissions).
1529
+ - The \`factors\` list documents what determines which depth to use.
1530
+ - Depth selection happens at runtime based on the input characteristics.
1531
+ `,
1532
+ },
1533
+ // -------------------------------------------------------------------------
1534
+ // 22. scale
1535
+ // -------------------------------------------------------------------------
1536
+ scale: {
1537
+ name: "scale",
1538
+ description: "Parallel execution and auto-scaling configuration",
1539
+ content: () => `# scale
1540
+
1541
+ The \`scale\` block configures parallel execution for an agent. It can appear as a sub-block inside an \`agent\` node.
1542
+
1543
+ ## Syntax
1544
+
1545
+ \`\`\`at
1546
+ agent my-agent {
1547
+ scale {
1548
+ mode: auto
1549
+ by: doc-count
1550
+ min: 2
1551
+ max: 8
1552
+ batch-size: 50
1553
+ }
1554
+ }
1555
+ \`\`\`
1556
+
1557
+ ## Fields
1558
+
1559
+ | Field | Type | Required | Default | Description |
1560
+ |-------|------|----------|---------|-------------|
1561
+ | mode | string | yes | -- | "auto", "fixed", or "config" |
1562
+ | by | string | yes | -- | Scaling dimension (see below) |
1563
+ | min | number | yes | -- | Minimum concurrent instances |
1564
+ | max | number | yes | -- | Maximum concurrent instances |
1565
+ | batch-size | number | no | -- | Items per instance |
1566
+
1567
+ ## Scaling Modes
1568
+
1569
+ | Mode | Description |
1570
+ |------|-------------|
1571
+ | auto | Scale based on workload |
1572
+ | fixed | Always run exactly \`min\` instances |
1573
+ | config | Scale based on external configuration |
1574
+
1575
+ ## Scaling Dimensions
1576
+
1577
+ | Dimension | Description |
1578
+ |-----------|-------------|
1579
+ | batch-count | Number of batches |
1580
+ | doc-count | Number of documents |
1581
+ | token-volume | Total token count |
1582
+ | source-count | Number of source files |
1583
+
1584
+ ## Example
1585
+
1586
+ \`\`\`at
1587
+ agent processor {
1588
+ model: sonnet
1589
+ scale {
1590
+ mode: auto
1591
+ by: batch-count
1592
+ min: 1
1593
+ max: 16
1594
+ batch-size: 25
1595
+ }
1596
+ }
1597
+ \`\`\`
1598
+ `,
1599
+ },
1600
+ // -------------------------------------------------------------------------
1601
+ // 23. extensions
1602
+ // -------------------------------------------------------------------------
1603
+ extensions: {
1604
+ name: "extensions",
1605
+ description: "Binding-specific extension fields",
1606
+ content: () => `# extensions
1607
+
1608
+ The \`extensions\` block provides binding-specific configuration that is passed through to a particular target platform.
1609
+
1610
+ ## Syntax
1611
+
1612
+ \`\`\`at
1613
+ extensions {
1614
+ binding-name {
1615
+ field: value
1616
+ another-field: "string value"
1617
+ }
1618
+ }
1619
+ \`\`\`
1620
+
1621
+ ## Scopes
1622
+
1623
+ Extensions can appear at multiple levels:
1624
+
1625
+ | Scope | Location | Description |
1626
+ |-------|----------|-------------|
1627
+ | topology | Top-level block | Topology-wide binding config |
1628
+ | agent | Inside agent block | Agent-specific binding config |
1629
+ | skill | Inside skill block | Skill-specific binding config |
1630
+ | gate | Inside gate block | Gate-specific binding config |
1631
+ | hook | Inside hook block | Hook-specific binding config |
1632
+
1633
+ ## Example
1634
+
1635
+ \`\`\`at
1636
+ # Topology-level
1637
+ extensions {
1638
+ claude-code {
1639
+ project-type: "monorepo"
1640
+ }
1641
+ }
1642
+
1643
+ # Agent-level
1644
+ agent reviewer {
1645
+ model: opus
1646
+ extensions {
1647
+ claude-code {
1648
+ worktree-base: "reviews/"
1649
+ }
1650
+ }
1651
+ }
1652
+ \`\`\`
1653
+
1654
+ ## Notes
1655
+
1656
+ - Unknown binding namespaces are silently ignored. This allows a single .at file to target multiple platforms.
1657
+ - Extension fields are free-form key-value pairs -- they are not validated by the parser.
1658
+ - Each binding defines its own set of recognized extension fields.
1659
+ `,
1660
+ },
1661
+ // -------------------------------------------------------------------------
1662
+ // 24. schemas
1663
+ // -------------------------------------------------------------------------
1664
+ schemas: {
1665
+ name: "schemas",
1666
+ description: "Named schema definitions for typed input/output",
1667
+ content: () => `# schemas
1668
+
1669
+ The \`schemas\` block defines named schemas for structured agent input and output.
1670
+
1671
+ ## Syntax
1672
+
1673
+ \`\`\`at
1674
+ schemas {
1675
+ schema NAME {
1676
+ field: TYPE
1677
+ optional-field?: TYPE
1678
+ }
1679
+ }
1680
+ \`\`\`
1681
+
1682
+ ## Primitive Types
1683
+
1684
+ | Type | Description |
1685
+ |------|-------------|
1686
+ | string | Text value |
1687
+ | number | Floating-point number |
1688
+ | integer | Whole number |
1689
+ | boolean | true or false |
1690
+ | object | Untyped object |
1691
+
1692
+ ## Complex Types
1693
+
1694
+ | Syntax | Description |
1695
+ |--------|-------------|
1696
+ | \`array of TYPE\` | Array of a type |
1697
+ | \`enum(val1, val2)\` | Enumerated values |
1698
+ | \`ref(schema-name)\` | Reference to another schema |
1699
+
1700
+ ## Optional Fields
1701
+
1702
+ Append \`?\` to the field name to mark it as optional:
1703
+
1704
+ \`\`\`at
1705
+ schema review-result {
1706
+ verdict: enum(approve, revise, reject)
1707
+ score: number
1708
+ comments?: string
1709
+ details?: ref(review-details)
1710
+ }
1711
+ \`\`\`
1712
+
1713
+ ## Usage
1714
+
1715
+ Reference schemas in agent \`input-schema\` and \`output-schema\` fields:
1716
+
1717
+ \`\`\`at
1718
+ agent reviewer {
1719
+ model: opus
1720
+ output-schema {
1721
+ verdict: enum(approve, reject)
1722
+ confidence: number
1723
+ }
1724
+ }
1725
+ \`\`\`
1726
+
1727
+ ## Example
1728
+
1729
+ \`\`\`at
1730
+ schemas {
1731
+ schema pr-info {
1732
+ url: string
1733
+ title: string
1734
+ files-changed: integer
1735
+ labels?: array of string
1736
+ }
1737
+
1738
+ schema review-output {
1739
+ verdict: enum(approve, request-changes, reject)
1740
+ risk: enum(low, medium, high)
1741
+ summary: string
1742
+ line-comments?: array of ref(line-comment)
1743
+ }
1744
+
1745
+ schema line-comment {
1746
+ file: string
1747
+ line: integer
1748
+ comment: string
1749
+ }
1750
+ }
1751
+ \`\`\`
1752
+ `,
1753
+ },
1754
+ // -------------------------------------------------------------------------
1755
+ // 25. defaults
1756
+ // -------------------------------------------------------------------------
1757
+ defaults: {
1758
+ name: "defaults",
1759
+ description: "Topology-wide default sampling parameters",
1760
+ content: () => `# defaults
1761
+
1762
+ The \`defaults\` block sets topology-wide default values for sampling parameters and shared agent configuration. Individual agents can override any default.
1763
+
1764
+ ## Syntax
1765
+
1766
+ \`\`\`at
1767
+ defaults {
1768
+ temperature: 0.7
1769
+ max-tokens: 4096
1770
+ top-p: 0.9
1771
+ thinking: medium
1772
+ thinking-budget: 5000
1773
+ output-format: text
1774
+ timeout: "10m"
1775
+ log-level: info
1776
+ }
1777
+ \`\`\`
1778
+
1779
+ ## Fields
1780
+
1781
+ | Field | Type | Default | Description |
1782
+ |-------|------|---------|-------------|
1783
+ | temperature | number | -- | Sampling temperature (0-2) |
1784
+ | max-tokens | number | -- | Max tokens to generate |
1785
+ | top-p | number | -- | Nucleus sampling (0-1) |
1786
+ | top-k | number | -- | Top-k sampling |
1787
+ | stop | string[] | -- | Stop sequences |
1788
+ | seed | number | -- | Random seed for reproducibility |
1789
+ | thinking | string | -- | "off", "low", "medium", "high", "max" |
1790
+ | thinking-budget | number | -- | Token budget for reasoning (min 1000) |
1791
+ | output-format | string | -- | "text", "json", "json-schema" |
1792
+ | timeout | string | -- | Duration string (e.g. "5m", "2h") |
1793
+ | log-level | string | -- | "debug", "info", "warn", "error" |
1794
+
1795
+ ## Notes
1796
+
1797
+ - Defaults apply to all agents unless overridden at the agent level.
1798
+ - Only sampling-related and shared config fields are valid in defaults -- not agent-specific fields like \`tools\` or \`reads\`.
1799
+ - A topology can have at most one \`defaults\` block (V23).
1800
+ `,
1801
+ },
1802
+ // -------------------------------------------------------------------------
1803
+ // 26. observability
1804
+ // -------------------------------------------------------------------------
1805
+ observability: {
1806
+ name: "observability",
1807
+ description: "Tracing and observability configuration",
1808
+ content: () => `# observability
1809
+
1810
+ The \`observability\` block configures distributed tracing and telemetry for the topology.
1811
+
1812
+ ## Syntax
1813
+
1814
+ \`\`\`at
1815
+ observability {
1816
+ enabled: true
1817
+ level: "info"
1818
+ exporter: otlp
1819
+ endpoint: "https://otel.example.com:4317"
1820
+ service: "my-topology"
1821
+ sample-rate: 0.5
1822
+
1823
+ capture {
1824
+ prompts: true
1825
+ completions: true
1826
+ tool-args: true
1827
+ tool-results: false
1828
+ }
1829
+
1830
+ spans {
1831
+ agents: true
1832
+ tools: true
1833
+ gates: true
1834
+ memory: false
1835
+ }
1836
+ }
1837
+ \`\`\`
1838
+
1839
+ ## Top-Level Fields
1840
+
1841
+ | Field | Type | Required | Default | Description |
1842
+ |-------|------|----------|---------|-------------|
1843
+ | enabled | boolean | yes | -- | Enable/disable observability |
1844
+ | level | string | no | -- | Log level for output |
1845
+ | exporter | string | yes | -- | Backend exporter |
1846
+ | endpoint | string | no | -- | Exporter endpoint URL |
1847
+ | service | string | no | -- | Service name for trace attribution |
1848
+ | sample-rate | number | no | 1.0 | Sampling rate (0-1) |
1849
+
1850
+ ## Exporters
1851
+
1852
+ \`otlp\`, \`langsmith\`, \`datadog\`, \`stdout\`, \`none\`
1853
+
1854
+ ## Capture Fields
1855
+
1856
+ | Field | Type | Default | Description |
1857
+ |-------|------|---------|-------------|
1858
+ | prompts | boolean | -- | Capture prompt text sent to models |
1859
+ | completions | boolean | -- | Capture completion text from models |
1860
+ | tool-args | boolean | -- | Capture tool invocation arguments |
1861
+ | tool-results | boolean | -- | Capture tool invocation results |
1862
+
1863
+ ## Span Fields
1864
+
1865
+ | Field | Type | Default | Description |
1866
+ |-------|------|---------|-------------|
1867
+ | agents | boolean | -- | Emit spans for agent execution |
1868
+ | tools | boolean | -- | Emit spans for tool invocations |
1869
+ | gates | boolean | -- | Emit spans for gate checks |
1870
+ | memory | boolean | -- | Emit spans for memory reads/writes |
1871
+
1872
+ ## Notes
1873
+
1874
+ - Observability data can contain sensitive information -- use \`capture\` settings carefully.
1875
+ - \`sample-rate: 0.5\` means approximately 50% of traces are recorded.
1876
+ `,
1877
+ },
1878
+ // -------------------------------------------------------------------------
1879
+ // 27. schedule
1880
+ // -------------------------------------------------------------------------
1881
+ schedule: {
1882
+ name: "schedule",
1883
+ description: "Scheduled job definitions -- cron and interval triggers",
1884
+ content: () => `# schedule
1885
+
1886
+ The \`schedule\` block defines time-based triggers that invoke agents or actions on a schedule.
1887
+
1888
+ ## Syntax
1889
+
1890
+ \`\`\`at
1891
+ schedule {
1892
+ job NAME {
1893
+ cron: "0 9 * * 1-5"
1894
+ agent: daily-reporter
1895
+ enabled: true
1896
+ }
1897
+
1898
+ job NAME {
1899
+ every: "6 hours"
1900
+ action: health-check
1901
+ }
1902
+ }
1903
+ \`\`\`
1904
+
1905
+ ## Fields
1906
+
1907
+ | Field | Type | Required | Default | Description |
1908
+ |-------|------|----------|---------|-------------|
1909
+ | id | identifier | yes | -- | Job identifier (the NAME) |
1910
+ | cron | string | conditional (V20) | -- | 5-field cron expression (mutually exclusive with \`every\`) |
1911
+ | every | string | conditional (V20) | -- | Human-readable interval (mutually exclusive with \`cron\`) |
1912
+ | agent | identifier | conditional (V20) | -- | Agent ID to invoke |
1913
+ | action | identifier | conditional (V20) | -- | Action ID to invoke |
1914
+ | enabled | boolean | no | true | Whether this job is active |
1915
+
1916
+ ## Validation Rules
1917
+
1918
+ - **V20**: \`cron\` and \`every\` are mutually exclusive -- use one or the other
1919
+ - **V20**: Job must reference a declared agent or action node
1920
+
1921
+ ## Example
1922
+
1923
+ \`\`\`at
1924
+ schedule {
1925
+ job daily-report {
1926
+ cron: "0 9 * * 1-5"
1927
+ agent: reporter
1928
+ }
1929
+
1930
+ job health-check {
1931
+ every: "30 minutes"
1932
+ action: check-health
1933
+ enabled: true
1934
+ }
1935
+
1936
+ job weekly-cleanup {
1937
+ cron: "0 0 * * 0"
1938
+ action: cleanup
1939
+ enabled: false
1940
+ }
1941
+ }
1942
+ \`\`\`
1943
+
1944
+ ## Notes
1945
+
1946
+ - Cron uses standard 5-field format: minute, hour, day-of-month, month, day-of-week.
1947
+ - Disabled jobs (\`enabled: false\`) are parsed but not executed.
1948
+ `,
1949
+ },
1950
+ // -------------------------------------------------------------------------
1951
+ // 28. interfaces
1952
+ // -------------------------------------------------------------------------
1953
+ interfaces: {
1954
+ name: "interfaces",
1955
+ description: "External interface definitions -- webhooks, HTTP, SSE",
1956
+ content: () => `# interfaces
1957
+
1958
+ The \`interfaces\` block defines external communication endpoints for the topology.
1959
+
1960
+ ## Syntax
1961
+
1962
+ \`\`\`at
1963
+ interfaces {
1964
+ NAME {
1965
+ type: webhook
1966
+ url: "https://hooks.example.com/incoming"
1967
+ channel: "#alerts"
1968
+ }
1969
+ }
1970
+ \`\`\`
1971
+
1972
+ ## Fields
1973
+
1974
+ | Field | Type | Required | Default | Description |
1975
+ |-------|------|----------|---------|-------------|
1976
+ | id | identifier | yes | -- | Interface identifier (the NAME) |
1977
+ | type | string | no | -- | "webhook", "http", "sse", "email" |
1978
+ | config | key-value | no | -- | All non-type fields (free-form) |
1979
+
1980
+ ## Interface Endpoints
1981
+
1982
+ A separate \`interface\` block (singular) defines composition entry/exit points:
1983
+
1984
+ \`\`\`at
1985
+ interface {
1986
+ entry: first-agent
1987
+ exit: last-agent
1988
+ }
1989
+ \`\`\`
1990
+
1991
+ ## Example
1992
+
1993
+ \`\`\`at
1994
+ interfaces {
1995
+ slack-notify {
1996
+ type: webhook
1997
+ url: "\${SLACK_WEBHOOK_URL}"
1998
+ channel: "#deployments"
1999
+ }
2000
+
2001
+ health-endpoint {
2002
+ type: http
2003
+ port: "8080"
2004
+ path: "/health"
2005
+ }
2006
+ }
2007
+ \`\`\`
2008
+
2009
+ ## Validation Rules
2010
+
2011
+ - **V21**: Sensitive fields (URLs with credentials, tokens) must use \`\${ENV_VAR}\` syntax
2012
+ `,
2013
+ },
2014
+ // -------------------------------------------------------------------------
2015
+ // 29. checkpoint
2016
+ // -------------------------------------------------------------------------
2017
+ checkpoint: {
2018
+ name: "checkpoint",
2019
+ description: "Durable execution and checkpoint configuration",
2020
+ content: () => `# checkpoint
2021
+
2022
+ The \`checkpoint\` block configures durable execution -- persisting topology state for resumability, replay, and time-travel debugging.
2023
+
2024
+ ## Syntax
2025
+
2026
+ \`\`\`at
2027
+ checkpoint {
2028
+ backend: "redis"
2029
+ connection: "\${REDIS_URL}"
2030
+ strategy: "after-each-agent"
2031
+ ttl: "7d"
2032
+
2033
+ replay {
2034
+ enabled: true
2035
+ max-history: 100
2036
+ branch: true
2037
+ }
2038
+ }
2039
+ \`\`\`
2040
+
2041
+ ## Fields
2042
+
2043
+ | Field | Type | Required | Default | Description |
2044
+ |-------|------|----------|---------|-------------|
2045
+ | backend | string | yes | -- | Storage backend (e.g. "redis", "postgres", "s3") |
2046
+ | connection | string | no | -- | Connection string or secret reference |
2047
+ | strategy | string | yes | -- | When to checkpoint (e.g. "after-each-agent") |
2048
+ | ttl | string | no | -- | Time-to-live for checkpoint data (e.g. "7d", "30d") |
2049
+
2050
+ ## Replay Fields
2051
+
2052
+ | Field | Type | Required | Default | Description |
2053
+ |-------|------|----------|---------|-------------|
2054
+ | enabled | boolean | yes | -- | Enable replay/time-travel |
2055
+ | max-history | number | no | -- | Max historical states to retain |
2056
+ | branch | boolean | no | false | Allow branching from a historical state |
2057
+
2058
+ ## Notes
2059
+
2060
+ - Requires \`durable: true\` in the topology \`meta\` block.
2061
+ - Connection strings should use \`\${ENV_VAR}\` or \`secret\` syntax for credentials.
2062
+ - Replay allows re-executing from any checkpointed state, useful for debugging failures.
2063
+ `,
2064
+ },
2065
+ // -------------------------------------------------------------------------
2066
+ // 30. artifacts
2067
+ // -------------------------------------------------------------------------
2068
+ artifacts: {
2069
+ name: "artifacts",
2070
+ description: "Artifact definitions for asset lineage tracking",
2071
+ content: () => `# artifacts
2072
+
2073
+ The \`artifacts\` block defines named outputs with types, storage, retention, and dependency tracking.
2074
+
2075
+ ## Syntax
2076
+
2077
+ \`\`\`at
2078
+ artifacts {
2079
+ NAME {
2080
+ type: "markdown"
2081
+ path: "output/report.md"
2082
+ retention: "30d"
2083
+ depends-on: [source-data, analysis]
2084
+ }
2085
+ }
2086
+ \`\`\`
2087
+
2088
+ ## Fields
2089
+
2090
+ | Field | Type | Required | Default | Description |
2091
+ |-------|------|----------|---------|-------------|
2092
+ | id | identifier | yes | -- | Artifact identifier (the NAME) |
2093
+ | type | string | yes | -- | File type (e.g. "markdown", "json", "csv", "pdf") |
2094
+ | path | string | no | -- | Storage path or prefix |
2095
+ | retention | string | no | -- | How long to keep (e.g. "30d", "1y") |
2096
+ | depends-on | string[] | no | -- | IDs of upstream artifacts |
2097
+
2098
+ ## Agent Integration
2099
+
2100
+ Agents reference artifacts via \`produces\` and \`consumes\`:
2101
+
2102
+ \`\`\`at
2103
+ agent writer {
2104
+ produces: [draft]
2105
+ consumes: [research-notes]
2106
+ }
2107
+ \`\`\`
2108
+
2109
+ ## Example
2110
+
2111
+ \`\`\`at
2112
+ artifacts {
2113
+ research-notes {
2114
+ type: "markdown"
2115
+ path: "workspace/research/"
2116
+ retention: "90d"
2117
+ }
2118
+
2119
+ draft {
2120
+ type: "markdown"
2121
+ path: "workspace/drafts/"
2122
+ retention: "30d"
2123
+ depends-on: [research-notes]
2124
+ }
2125
+
2126
+ final-report {
2127
+ type: "pdf"
2128
+ path: "output/"
2129
+ retention: "1y"
2130
+ depends-on: [draft]
2131
+ }
2132
+ }
2133
+ \`\`\`
2134
+
2135
+ ## Notes
2136
+
2137
+ - \`depends-on\` creates an explicit lineage graph between artifacts.
2138
+ - Retention durations use human-readable strings: "30d", "6m", "1y".
2139
+ - Artifact type is informational -- it does not enforce file format.
2140
+ `,
2141
+ },
2142
+ // -------------------------------------------------------------------------
2143
+ // 31. composition
2144
+ // -------------------------------------------------------------------------
2145
+ composition: {
2146
+ name: "composition",
2147
+ description: "Imports, includes, params, fragments, and libraries",
2148
+ content: () => `# composition
2149
+
2150
+ AgenTopology supports composing topologies from reusable parts: imports, includes, params, fragments, and libraries.
2151
+
2152
+ ## import
2153
+
2154
+ Import another topology and use it as a sub-topology:
2155
+
2156
+ \`\`\`at
2157
+ import reviewer from ./review.at
2158
+ import linter from registry:@org/linter@1.2.0
2159
+ import auditor from ./audit.at sha256 "abc123..."
2160
+ \`\`\`
2161
+
2162
+ ### Import with Overrides
2163
+
2164
+ \`\`\`at
2165
+ use reviewer {
2166
+ model: opus
2167
+ timeout: "30m"
2168
+ }
2169
+ \`\`\`
2170
+
2171
+ ## include
2172
+
2173
+ Include a fragment file, merging its contents into the current topology:
2174
+
2175
+ \`\`\`at
2176
+ include "./shared/common-hooks.at"
2177
+ \`\`\`
2178
+
2179
+ ## params
2180
+
2181
+ Declare typed parameters for a composable topology:
2182
+
2183
+ \`\`\`at
2184
+ params {
2185
+ param model {
2186
+ type: string
2187
+ default: "sonnet"
2188
+ }
2189
+
2190
+ param max-retries {
2191
+ type: number
2192
+ default: 3
2193
+ }
2194
+
2195
+ param strict-mode {
2196
+ type: boolean
2197
+ }
2198
+ }
2199
+ \`\`\`
2200
+
2201
+ ### Param Fields
2202
+
2203
+ | Field | Type | Required | Description |
2204
+ |-------|------|----------|-------------|
2205
+ | name | identifier | yes | Parameter name |
2206
+ | type | string | yes | "string", "number", "boolean" |
2207
+ | default | value | no | Default value (if absent, param is required) |
2208
+
2209
+ ## fragment
2210
+
2211
+ A fragment is a partial topology for inclusion. Uses \`fragment\` instead of \`topology\`:
2212
+
2213
+ \`\`\`at
2214
+ fragment {
2215
+ agent shared-reviewer {
2216
+ model: opus
2217
+ tools: [Read, Grep]
2218
+ }
2219
+
2220
+ hooks {
2221
+ hook log-all {
2222
+ on: AgentStop
2223
+ run: "scripts/log.sh"
2224
+ type: command
2225
+ }
2226
+ }
2227
+ }
2228
+ \`\`\`
2229
+
2230
+ ## library
2231
+
2232
+ A library defines reusable agent definitions:
2233
+
2234
+ \`\`\`at
2235
+ library shared-agents {
2236
+ agent reviewer {
2237
+ model: opus
2238
+ tools: [Read, Grep, Glob]
2239
+ }
2240
+ }
2241
+ \`\`\`
2242
+
2243
+ ## interface (entry/exit)
2244
+
2245
+ Define composition endpoints for a topology:
2246
+
2247
+ \`\`\`at
2248
+ interface {
2249
+ entry: first-agent
2250
+ exit: last-agent
2251
+ }
2252
+ \`\`\`
2253
+
2254
+ ## Integrity
2255
+
2256
+ SHA-256 hashes ensure import integrity:
2257
+
2258
+ \`\`\`at
2259
+ import reviewer from ./review.at sha256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
2260
+ \`\`\`
2261
+
2262
+ ## Validation Rules
2263
+
2264
+ - **V8**: Import paths must resolve to existing files
2265
+ - **V1**: Imported names must be globally unique
2266
+ `,
2267
+ },
2268
+ // -------------------------------------------------------------------------
2269
+ // 32. validation
2270
+ // -------------------------------------------------------------------------
2271
+ validation: {
2272
+ name: "validation",
2273
+ description: "All 29 validation rules with descriptions and fixes",
2274
+ content: () => `# validation
2275
+
2276
+ AgenTopology enforces 29 validation rules during parsing. Errors prevent compilation; warnings are informational.
2277
+
2278
+ ## Rules
2279
+
2280
+ ### V1: Unique Names (error)
2281
+ All node names must be globally unique across agents, actions, gates, orchestrators, groups, and humans.
2282
+
2283
+ **Violation:** Two nodes named \`reviewer\`.
2284
+ **Fix:** Rename one to a unique identifier.
2285
+
2286
+ ### V2: No Keyword Names (error)
2287
+ Node names cannot match reserved keywords.
2288
+
2289
+ **Violation:** \`agent flow { ... }\` (\`flow\` is reserved).
2290
+ **Fix:** Choose a non-reserved name.
2291
+
2292
+ ### V3: Flow Resolves (error)
2293
+ Every node referenced in a flow edge must be declared.
2294
+
2295
+ **Violation:** \`analyzer -> checker\` where \`checker\` is not declared.
2296
+ **Fix:** Declare the missing node or fix the typo.
2297
+
2298
+ ### V4: No Orphans (error)
2299
+ Every agent must appear in at least one flow edge, or have \`invocation: manual\`.
2300
+
2301
+ **Violation:** An agent declared but never referenced in flow.
2302
+ **Fix:** Add the agent to the flow or set \`invocation: manual\`.
2303
+
2304
+ ### V5: Outputs Exist (error)
2305
+ \`[when x.y == z]\` conditions must reference declared output fields with valid values.
2306
+
2307
+ **Violation:** \`[when reviewer.verdict == pass]\` but \`verdict\` only has \`approve | reject\`.
2308
+ **Fix:** Use a declared output value.
2309
+
2310
+ ### V6: Bounded Loops (error)
2311
+ Back-edges (loops) must have \`[max N]\` to prevent infinite iteration.
2312
+
2313
+ **Violation:** \`reviewer -> writer\` without \`[max N]\`.
2314
+ **Fix:** Add \`[max N]\`: \`reviewer -> writer [max 3]\`.
2315
+
2316
+ ### V7: Model Required (error)
2317
+ Every agent and orchestrator must have a \`model\` field.
2318
+
2319
+ **Violation:** \`agent reviewer { tools: [Read] }\` (no model).
2320
+ **Fix:** Add \`model: MODEL\`.
2321
+
2322
+ ### V8: Imports Resolve (error)
2323
+ Import source paths must point to existing files.
2324
+
2325
+ **Violation:** \`import x from ./nonexistent.at\`.
2326
+ **Fix:** Correct the path or create the file.
2327
+
2328
+ ### V9: Actions Handled (error)
2329
+ Actions referenced in flow must appear in the orchestrator's \`handles\` list.
2330
+
2331
+ **Violation:** \`intake -> agent\` but \`handles\` doesn't include \`intake\`.
2332
+ **Fix:** Add the action to \`handles: [intake, ...]\`.
2333
+
2334
+ ### V10: Prompts Exist (warning)
2335
+ Prompt blocks should not be empty.
2336
+
2337
+ **Violation:** \`prompt {}\` with no content.
2338
+ **Fix:** Add prompt text or remove the empty block.
2339
+
2340
+ ### V11: Reads/Writes Consistent (error)
2341
+ Data dependencies (\`reads\`/\`writes\`) must be consistent with flow order. An agent cannot read a key that no upstream agent writes.
2342
+
2343
+ **Violation:** Agent B reads "output.md" but no upstream agent writes it.
2344
+ **Fix:** Ensure an upstream agent writes the key, or remove the read.
2345
+
2346
+ ### V12: Edge Attribute Order (error)
2347
+ Edge attributes must appear in order: \`when\`, \`max\`, \`per\`.
2348
+
2349
+ **Violation:** \`[max 3, when x.y == z]\`.
2350
+ **Fix:** Reorder to \`[when x.y == z, max 3]\`.
2351
+
2352
+ ### V13: Gate Placement (error)
2353
+ Gate \`after\` and \`before\` fields must reference declared nodes.
2354
+
2355
+ **Violation:** \`after: nonexistent-agent\`.
2356
+ **Fix:** Reference a declared node.
2357
+
2358
+ ### V14: Tool Exclusivity (error)
2359
+ An agent cannot have both \`tools\` and \`disallowed-tools\`.
2360
+
2361
+ **Violation:** \`tools: [Read] disallowed-tools: [Bash]\`.
2362
+ **Fix:** Use one or the other.
2363
+
2364
+ ### V15: Exhaustive Conditions (error)
2365
+ Conditional edges from a node must cover all declared output values.
2366
+
2367
+ **Violation:** Agent has \`verdict: approve | revise | reject\` but only edges for approve and revise.
2368
+ **Fix:** Add an edge for the \`reject\` case.
2369
+
2370
+ ### V16: API Key Env Vars (error)
2371
+ Provider \`api-key\` must use \`\${ENV_VAR}\` syntax, never inline secrets.
2372
+
2373
+ **Violation:** \`api-key: "sk-abc123"\`.
2374
+ **Fix:** Use \`api-key: "\${ANTHROPIC_API_KEY}"\`.
2375
+
2376
+ ### V17: Single Default Provider (error)
2377
+ At most one provider can be marked \`default: true\`.
2378
+
2379
+ **Violation:** Two providers with \`default: true\`.
2380
+ **Fix:** Remove \`default: true\` from one.
2381
+
2382
+ ### V18: Model in Provider (warning)
2383
+ Agent model identifiers should exist in a declared provider's \`models\` list.
2384
+
2385
+ **Violation:** \`model: gpt-5\` but no provider lists \`gpt-5\`.
2386
+ **Fix:** Add the model to a provider's \`models\` list.
2387
+
2388
+ ### V19: Unique Provider Names (error)
2389
+ Provider names must be unique.
2390
+
2391
+ **Violation:** Two providers named \`anthropic\`.
2392
+ **Fix:** Use unique names.
2393
+
2394
+ ### V20: Schedule Job References (error)
2395
+ Scheduled jobs must reference declared agent or action nodes. \`cron\` and \`every\` are mutually exclusive.
2396
+
2397
+ **Violation:** \`agent: nonexistent\` or both \`cron\` and \`every\` specified.
2398
+ **Fix:** Reference a declared node; use only one of cron/every.
2399
+
2400
+ ### V21: Interface Secret Detection (error)
2401
+ Sensitive interface fields (URLs, tokens) must use \`\${ENV_VAR}\` syntax.
2402
+
2403
+ **Violation:** Inline URL with embedded credentials.
2404
+ **Fix:** Use \`\${ENV_VAR}\` references.
2405
+
2406
+ ### V22: Fallback Chain Models (warning)
2407
+ Models in \`fallback-chain\` should exist in a declared provider.
2408
+
2409
+ **Violation:** \`fallback-chain: [nonexistent-model]\`.
2410
+ **Fix:** Add the model to a provider.
2411
+
2412
+ ### V23: Duplicate Sections (warning)
2413
+ Singleton sections (meta, memory, flow, etc.) should appear at most once.
2414
+
2415
+ **Violation:** Two \`flow {}\` blocks.
2416
+ **Fix:** Merge into a single block.
2417
+
2418
+ ### V24: Unknown Memory Sub-Blocks (warning)
2419
+ Memory sub-blocks should be known names (workspace, domains, references, external-docs, metrics).
2420
+
2421
+ **Violation:** \`memory { custom-block { ... } }\`.
2422
+ **Fix:** Use a recognized sub-block name or move to extensions.
2423
+
2424
+ ### V25: Bounce-Back Advisory (warning)
2425
+ \`on-fail: bounce-back\` is advisory on CLI platforms -- enforcement varies by binding.
2426
+
2427
+ **Violation:** None (this is informational).
2428
+ **Fix:** Be aware that bounce-back may not be enforced on all platforms.
2429
+
2430
+ ### V26: Action Kind Enum (error)
2431
+ Action \`kind\` must be: external, git, decision, inline, or report.
2432
+
2433
+ **Violation:** \`kind: custom\`.
2434
+ **Fix:** Use a recognized kind value.
2435
+
2436
+ ### V27: Agent Permissions Enum (warning)
2437
+ Agent \`permissions\` should be a recognized mode: autonomous/auto, supervised/plan, interactive/confirm, unrestricted/bypass.
2438
+
2439
+ **Violation:** \`permissions: custom-mode\`.
2440
+ **Fix:** Use a recognized permission mode.
2441
+
2442
+ ### V28: Metering Format Enum (error)
2443
+ Metering \`format\` must be: json, jsonl, or csv.
2444
+
2445
+ **Violation:** \`format: xml\`.
2446
+ **Fix:** Use json, jsonl, or csv.
2447
+
2448
+ ### V29: Metering Pricing Enum (warning)
2449
+ Metering \`pricing\` should be a recognized model: anthropic-current, custom, or none.
2450
+
2451
+ **Violation:** \`pricing: azure-current\`.
2452
+ **Fix:** Use a recognized pricing model.
2453
+
2454
+ ## Summary
2455
+
2456
+ | Rule | Severity | Name |
2457
+ |------|----------|------|
2458
+ | V1 | error | Unique Names |
2459
+ | V2 | error | No Keyword Names |
2460
+ | V3 | error | Flow Resolves |
2461
+ | V4 | error | No Orphans |
2462
+ | V5 | error | Outputs Exist |
2463
+ | V6 | error | Bounded Loops |
2464
+ | V7 | error | Model Required |
2465
+ | V8 | error | Imports Resolve |
2466
+ | V9 | error | Actions Handled |
2467
+ | V10 | warning | Prompts Exist |
2468
+ | V11 | error | Reads/Writes Consistent |
2469
+ | V12 | error | Edge Attribute Order |
2470
+ | V13 | error | Gate Placement |
2471
+ | V14 | error | Tool Exclusivity |
2472
+ | V15 | error | Exhaustive Conditions |
2473
+ | V16 | error | API Key Env Vars |
2474
+ | V17 | error | Single Default Provider |
2475
+ | V18 | warning | Model in Provider |
2476
+ | V19 | error | Unique Provider Names |
2477
+ | V20 | error | Schedule Job References |
2478
+ | V21 | error | Interface Secret Detection |
2479
+ | V22 | warning | Fallback Chain Models |
2480
+ | V23 | warning | Duplicate Sections |
2481
+ | V24 | warning | Unknown Memory Sub-Blocks |
2482
+ | V25 | warning | Bounce-Back Advisory |
2483
+ | V26 | error | Action Kind Enum |
2484
+ | V27 | warning | Agent Permissions Enum |
2485
+ | V28 | error | Metering Format Enum |
2486
+ | V29 | warning | Metering Pricing Enum |
2487
+ `,
2488
+ },
2489
+ // -------------------------------------------------------------------------
2490
+ // 33. patterns
2491
+ // -------------------------------------------------------------------------
2492
+ patterns: {
2493
+ name: "patterns",
2494
+ description: "All 10 topology patterns with descriptions and examples",
2495
+ content: () => `# patterns
2496
+
2497
+ AgenTopology supports 10 built-in patterns. Patterns are declared in the topology header and document the system's coordination style.
2498
+
2499
+ ## pipeline
2500
+
2501
+ **Description:** Linear sequence of agents, each feeding the next.
2502
+ **When to use:** Sequential workflows where each step depends on the previous.
2503
+
2504
+ \`\`\`at
2505
+ flow {
2506
+ intake -> researcher
2507
+ researcher -> writer
2508
+ writer -> reviewer
2509
+ reviewer -> done
2510
+ }
2511
+ \`\`\`
2512
+
2513
+ ## supervisor
2514
+
2515
+ **Description:** A central agent oversees and delegates to worker agents.
2516
+ **When to use:** When one agent needs to coordinate and review others' work.
2517
+
2518
+ \`\`\`at
2519
+ flow {
2520
+ intake -> supervisor
2521
+ supervisor -> [worker-a, worker-b]
2522
+ worker-a -> supervisor
2523
+ worker-b -> supervisor
2524
+ supervisor -> done [max 3]
2525
+ }
2526
+ \`\`\`
2527
+
2528
+ ## blackboard
2529
+
2530
+ **Description:** Agents read/write to a shared data store and react to changes.
2531
+ **When to use:** Loosely coupled agents that collaborate through shared state.
2532
+
2533
+ \`\`\`at
2534
+ flow {
2535
+ trigger -> [analyzer, monitor, updater]
2536
+ analyzer -> blackboard-sync
2537
+ monitor -> blackboard-sync
2538
+ updater -> blackboard-sync
2539
+ blackboard-sync -> done
2540
+ }
2541
+ \`\`\`
2542
+
2543
+ ## orchestrator-worker
2544
+
2545
+ **Description:** An orchestrator generates plans and dispatches work to agents.
2546
+ **When to use:** Complex workflows where a planner delegates specialized tasks.
2547
+
2548
+ \`\`\`at
2549
+ flow {
2550
+ intake -> planner
2551
+ planner -> [coder, tester, documenter]
2552
+ coder -> review
2553
+ tester -> review
2554
+ documenter -> review
2555
+ review -> done
2556
+ }
2557
+ \`\`\`
2558
+
2559
+ ## debate
2560
+
2561
+ **Description:** Multiple agents argue opposing positions to reach a conclusion.
2562
+ **When to use:** Decision-making that benefits from adversarial reasoning.
2563
+
2564
+ \`\`\`at
2565
+ flow {
2566
+ topic -> [advocate, critic]
2567
+ advocate -> judge
2568
+ critic -> judge
2569
+ judge -> advocate [when judge.verdict == continue, max 3]
2570
+ judge -> done [when judge.verdict == resolved]
2571
+ }
2572
+ \`\`\`
2573
+
2574
+ ## market-routing
2575
+
2576
+ **Description:** Incoming work is routed to the best-suited agent based on criteria.
2577
+ **When to use:** Multi-domain systems where different agents handle different request types.
2578
+
2579
+ \`\`\`at
2580
+ flow {
2581
+ intake -> router
2582
+ router -> specialist-a [when router.domain == legal]
2583
+ router -> specialist-b [when router.domain == technical]
2584
+ router -> specialist-c [when router.domain == financial]
2585
+ specialist-a -> done
2586
+ specialist-b -> done
2587
+ specialist-c -> done
2588
+ }
2589
+ \`\`\`
2590
+
2591
+ ## consensus
2592
+
2593
+ **Description:** Multiple agents must agree before proceeding.
2594
+ **When to use:** High-stakes decisions requiring agreement from multiple perspectives.
2595
+
2596
+ \`\`\`at
2597
+ flow {
2598
+ proposal -> [reviewer-a, reviewer-b, reviewer-c]
2599
+ reviewer-a -> aggregator
2600
+ reviewer-b -> aggregator
2601
+ reviewer-c -> aggregator
2602
+ aggregator -> done
2603
+ }
2604
+ \`\`\`
2605
+
2606
+ ## fan-out
2607
+
2608
+ **Description:** Work is split across parallel agents, then merged.
2609
+ **When to use:** Independent subtasks that can run concurrently.
2610
+
2611
+ \`\`\`at
2612
+ flow {
2613
+ intake -> [analyzer, scanner, checker]
2614
+ analyzer -> merger
2615
+ scanner -> merger
2616
+ checker -> merger
2617
+ merger -> done
2618
+ }
2619
+ \`\`\`
2620
+
2621
+ ## event-driven
2622
+
2623
+ **Description:** Agents react to events rather than following a fixed flow.
2624
+ **When to use:** Systems that respond to external signals, webhooks, or schedules.
2625
+
2626
+ \`\`\`at
2627
+ flow {
2628
+ webhook-event -> dispatcher
2629
+ dispatcher -> handler-a [when dispatcher.type == deploy]
2630
+ dispatcher -> handler-b [when dispatcher.type == alert]
2631
+ handler-a -> done
2632
+ handler-b -> done
2633
+ }
2634
+ \`\`\`
2635
+
2636
+ ## human-gate
2637
+
2638
+ **Description:** Human approval is required at one or more points in the flow.
2639
+ **When to use:** Workflows that need human oversight before critical actions.
2640
+
2641
+ \`\`\`at
2642
+ flow {
2643
+ draft -> review
2644
+ review -> human-approval
2645
+ human-approval -> publish [when human-approval.decision == approve]
2646
+ human-approval -> draft [when human-approval.decision == revise, max 2]
2647
+ }
2648
+ \`\`\`
2649
+
2650
+ ## Combining Patterns
2651
+
2652
+ Patterns are often combined. Declare multiple in the header:
2653
+
2654
+ \`\`\`at
2655
+ topology code-review : [pipeline, fan-out, human-gate] {
2656
+ # ...
2657
+ }
2658
+ \`\`\`
2659
+ `,
2660
+ },
2661
+ // -------------------------------------------------------------------------
2662
+ // 34. keywords
2663
+ // -------------------------------------------------------------------------
2664
+ keywords: {
2665
+ name: "keywords",
2666
+ description: "Complete keyword reference organized by category",
2667
+ content: () => `# keywords
2668
+
2669
+ Reserved keywords cannot be used as agent, action, or gate identifiers. They are organized into block keywords, field keywords, and wave keywords.
2670
+
2671
+ ## Block Keywords (40)
2672
+
2673
+ These introduce grammar constructs:
2674
+
2675
+ \`\`\`
2676
+ topology library import from use
2677
+ agent action orchestrator meta roles
2678
+ memory flow gates gate depth
2679
+ batch environments triggers command event
2680
+ level hooks hook settings mcp-servers
2681
+ metering tools tool scale skill
2682
+ context env extensions providers schedule
2683
+ job interfaces defaults schemas schema
2684
+ observability fragment interface params
2685
+ \`\`\`
2686
+
2687
+ ## Field Keywords (100+)
2688
+
2689
+ These are used as field names or enum values:
2690
+
2691
+ ### Node & Agent Fields
2692
+ \`\`\`
2693
+ model tools disallowed-tools reads writes
2694
+ outputs skip retry isolation phase
2695
+ kind role version description
2696
+ permissions prompt generates handles argument
2697
+ behavior invocation background skills sandbox
2698
+ fallback-chain max-turns
2699
+ \`\`\`
2700
+
2701
+ ### Flow & Edge Fields
2702
+ \`\`\`
2703
+ when max parallel per manual
2704
+ advisory blocking min join all
2705
+ any all-done none-failed tolerance race
2706
+ wait weight error-handler
2707
+ \`\`\`
2708
+
2709
+ ### Scale Fields
2710
+ \`\`\`
2711
+ batch-size batch-count doc-count token-volume source-count
2712
+ fixed config
2713
+ \`\`\`
2714
+
2715
+ ### Metering Fields
2716
+ \`\`\`
2717
+ track tokens-in tokens-out cost wall-time
2718
+ agent-count format pricing anthropic-current
2719
+ custom none json jsonl csv
2720
+ \`\`\`
2721
+
2722
+ ### Gate Fields
2723
+ \`\`\`
2724
+ pass fail plan-gap bounce-back halt
2725
+ on-fail after before run checks
2726
+ load-when
2727
+ \`\`\`
2728
+
2729
+ ### Permission Modes
2730
+ \`\`\`
2731
+ autonomous supervised interactive unrestricted
2732
+ \`\`\`
2733
+
2734
+ ### Memory Fields
2735
+ \`\`\`
2736
+ path mode files routing protocol
2737
+ structure blueprints domains references external-docs
2738
+ metrics workspace conflicts detect resolve
2739
+ sequential-rebase source commands append-only
2740
+ \`\`\`
2741
+
2742
+ ### Hook Events
2743
+ \`\`\`
2744
+ AgentStart AgentStop ToolUse Error
2745
+ SessionStart SessionEnd PreToolUse PostToolUse
2746
+ PostToolUseFailure SubagentStart SubagentStop Stop
2747
+ UserPromptSubmit InstructionsLoaded PermissionRequest
2748
+ Notification TeammateIdle TaskCompleted ConfigChange
2749
+ PreCompact WorktreeCreate WorktreeRemove
2750
+ \`\`\`
2751
+
2752
+ ### Other Fields
2753
+ \`\`\`
2754
+ on matcher timeout command prompt
2755
+ allow deny ask http stdio
2756
+ sse args env url script
2757
+ lang bash python node worktree
2758
+ user project local inherit
2759
+ external git decision inline report
2760
+ not ticket true false
2761
+ disable-model-invocation user-invocable allowed-tools
2762
+ domain fork api-key base-url default
2763
+ cron every enabled webhook channel
2764
+ auth port docker network-only
2765
+ \`\`\`
2766
+
2767
+ ### Pattern Keywords
2768
+ \`\`\`
2769
+ pipeline supervisor blackboard orchestrator-worker
2770
+ debate market-routing consensus fan-out
2771
+ event-driven human-gate
2772
+ \`\`\`
2773
+
2774
+ ## Wave 1: Error Handling, Model Config, Secrets
2775
+ \`\`\`
2776
+ backoff interval max-interval jitter
2777
+ non-retryable exponential linear
2778
+ temperature max-tokens top-p top-k stop
2779
+ seed thinking thinking-budget
2780
+ off low medium high
2781
+ sensitive log-level debug info warn
2782
+ error output-format json-schema text
2783
+ \`\`\`
2784
+
2785
+ ## Wave 2: Flow Enhancements
2786
+ \`\`\`
2787
+ join all any all-done none-failed
2788
+ tolerance race wait weight error-handler
2789
+ \`\`\`
2790
+
2791
+ ## Wave 3: Infrastructure
2792
+ \`\`\`
2793
+ input-schema output-schema array of optional
2794
+ exporter endpoint service sample-rate capture
2795
+ prompts completions tool-args tool-results spans
2796
+ agents otlp langsmith datadog stdout
2797
+ secret vault op awssm ssm
2798
+ gcpsm azurekv
2799
+ \`\`\`
2800
+
2801
+ ## Wave 4: Composition
2802
+ \`\`\`
2803
+ as with include entry exit
2804
+ sha256
2805
+ \`\`\`
2806
+
2807
+ ## Wave 5: Advanced Patterns
2808
+ \`\`\`
2809
+ circuit-breaker threshold window cooldown
2810
+ compensates human checkpoint durable
2811
+ \`\`\`
2812
+
2813
+ ## Wave 7: Group Chat, Reflection, Rate Limiting
2814
+ \`\`\`
2815
+ group members speaker-selection max-rounds
2816
+ termination round-robin random reflection rate-limit
2817
+ \`\`\`
2818
+
2819
+ ## Roadmap Reserved
2820
+ \`\`\`
2821
+ event
2822
+ \`\`\`
2823
+
2824
+ ## Not Reserved
2825
+
2826
+ These are free-form values and can be used as names:
2827
+
2828
+ \`\`\`
2829
+ branch render supabase target-branch
2830
+ \`\`\`
2831
+
2832
+ Environment block field names, custom role names, and user-defined enum values are not reserved.
2833
+ `,
2834
+ },
2835
+ // -------------------------------------------------------------------------
2836
+ // 35. examples
2837
+ // -------------------------------------------------------------------------
2838
+ examples: {
2839
+ name: "examples",
2840
+ description: "Full annotated .at examples -- pipeline, fan-out, advanced",
2841
+ content: () => `# examples
2842
+
2843
+ Complete, annotated AgenTopology examples demonstrating common patterns.
2844
+
2845
+ ## Example 1: Simple 3-Agent Pipeline
2846
+
2847
+ A minimal content pipeline: research, write, review.
2848
+
2849
+ \`\`\`at
2850
+ topology content-pipeline : [pipeline] {
2851
+
2852
+ meta {
2853
+ version: "1.0.0"
2854
+ description: "Research, write, and review content"
2855
+ }
2856
+
2857
+ # Orchestrator coordinates the flow
2858
+ orchestrator {
2859
+ model: sonnet
2860
+ handles: [start, finish]
2861
+ }
2862
+
2863
+ # Entry and exit actions
2864
+ action start {
2865
+ kind: inline
2866
+ description: "Parse user request"
2867
+ }
2868
+
2869
+ action finish {
2870
+ kind: report
2871
+ description: "Deliver final content"
2872
+ }
2873
+
2874
+ # Three agents in sequence
2875
+ agent researcher {
2876
+ model: gpt-4o
2877
+ permissions: supervised
2878
+ phase: 1
2879
+ tools: [Read, Grep, WebSearch]
2880
+ writes: ["workspace/research.md"]
2881
+ prompt {
2882
+ Research the given topic thoroughly.
2883
+ Compile findings with citations.
2884
+ }
2885
+ }
2886
+
2887
+ agent writer {
2888
+ model: sonnet
2889
+ permissions: autonomous
2890
+ phase: 2
2891
+ tools: [Read, Write]
2892
+ reads: ["workspace/research.md"]
2893
+ writes: ["workspace/draft.md"]
2894
+ prompt {
2895
+ Write a polished draft based on the research.
2896
+ }
2897
+ }
2898
+
2899
+ agent reviewer {
2900
+ model: opus
2901
+ permissions: supervised
2902
+ phase: 3
2903
+ tools: [Read]
2904
+ reads: ["workspace/draft.md"]
2905
+ outputs: {
2906
+ verdict: approve | revise
2907
+ }
2908
+ prompt {
2909
+ Review the draft for accuracy and clarity.
2910
+ }
2911
+ }
2912
+
2913
+ # Linear flow with one revision loop
2914
+ flow {
2915
+ start -> researcher
2916
+ researcher -> writer
2917
+ writer -> reviewer
2918
+ reviewer -> writer [when reviewer.verdict == revise, max 2]
2919
+ reviewer -> finish [when reviewer.verdict == approve]
2920
+ }
2921
+
2922
+ memory {
2923
+ workspace {
2924
+ path: "workspace/"
2925
+ structure: [research, drafts]
2926
+ }
2927
+ }
2928
+ }
2929
+ \`\`\`
2930
+
2931
+ ## Example 2: Fan-Out with Conditional Edges
2932
+
2933
+ Parallel analysis agents feeding into a reviewer with conditional routing.
2934
+
2935
+ \`\`\`at
2936
+ topology code-review : [fan-out, human-gate] {
2937
+
2938
+ meta {
2939
+ version: "1.0.0"
2940
+ description: "Parallel code analysis with conditional review"
2941
+ }
2942
+
2943
+ orchestrator {
2944
+ model: opus
2945
+ handles: [intake, done]
2946
+ }
2947
+
2948
+ action intake {
2949
+ kind: external
2950
+ source: "github-pr"
2951
+ description: "Fetch PR diff"
2952
+ }
2953
+
2954
+ action done {
2955
+ kind: report
2956
+ description: "Post review results"
2957
+ }
2958
+
2959
+ # Parallel analyzers (phase 1)
2960
+ agent static-analyzer {
2961
+ model: sonnet
2962
+ permissions: autonomous
2963
+ phase: 1
2964
+ tools: [Read, Grep, Glob]
2965
+ writes: ["workspace/static-analysis.md"]
2966
+ outputs: {
2967
+ risk: low | medium | high
2968
+ }
2969
+ prompt {
2970
+ Analyze code complexity and dependencies.
2971
+ }
2972
+ }
2973
+
2974
+ agent security-scanner {
2975
+ model: sonnet
2976
+ permissions: autonomous
2977
+ phase: 1
2978
+ tools: [Read, Grep]
2979
+ writes: ["workspace/security.md"]
2980
+ behavior: advisory
2981
+ outputs: {
2982
+ has-issues: yes | no
2983
+ }
2984
+ prompt {
2985
+ Scan for security vulnerabilities.
2986
+ }
2987
+ }
2988
+
2989
+ # Reviewer combines results (phase 2)
2990
+ agent reviewer {
2991
+ model: opus
2992
+ permissions: supervised
2993
+ phase: 2
2994
+ tools: [Read, Grep]
2995
+ reads: ["workspace/static-analysis.md", "workspace/security.md"]
2996
+ outputs: {
2997
+ verdict: approve | request-changes | reject
2998
+ }
2999
+ prompt {
3000
+ Review all findings and make a final decision.
3001
+ }
3002
+ }
3003
+
3004
+ flow {
3005
+ # Fan-out to parallel analyzers
3006
+ intake -> [static-analyzer, security-scanner]
3007
+
3008
+ # Both feed into reviewer
3009
+ static-analyzer -> reviewer
3010
+ security-scanner -> reviewer
3011
+
3012
+ # Conditional routing based on verdict
3013
+ reviewer -> done [when reviewer.verdict == approve]
3014
+ reviewer -> done [when reviewer.verdict == request-changes]
3015
+ reviewer -> done [when reviewer.verdict == reject]
3016
+ }
3017
+
3018
+ gates {
3019
+ gate human-check {
3020
+ after: reviewer
3021
+ before: done
3022
+ run: "scripts/human-approve.sh"
3023
+ on-fail: halt
3024
+ }
3025
+ }
3026
+ }
3027
+ \`\`\`
3028
+
3029
+ ## Example 3: Advanced Topology
3030
+
3031
+ Demonstrates hooks, gates, metering, scale, providers, and MCP servers.
3032
+
3033
+ \`\`\`at
3034
+ topology data-pipeline : [pipeline, fan-out] {
3035
+
3036
+ meta {
3037
+ version: "2.0.0"
3038
+ description: "Production data processing pipeline"
3039
+ domain: data-engineering
3040
+ timeout: "4h"
3041
+ durable: true
3042
+ }
3043
+
3044
+ providers {
3045
+ anthropic {
3046
+ api-key: "\${ANTHROPIC_API_KEY}"
3047
+ models: [opus, sonnet, haiku]
3048
+ default: true
3049
+ }
3050
+ }
3051
+
3052
+ defaults {
3053
+ temperature: 0.3
3054
+ max-tokens: 8192
3055
+ thinking: medium
3056
+ log-level: info
3057
+ }
3058
+
3059
+ orchestrator {
3060
+ model: opus
3061
+ handles: [ingest, deliver]
3062
+ }
3063
+
3064
+ action ingest {
3065
+ kind: external
3066
+ source: "s3"
3067
+ description: "Pull documents from S3"
3068
+ timeout: "5m"
3069
+ }
3070
+
3071
+ action deliver {
3072
+ kind: report
3073
+ description: "Upload results"
3074
+ }
3075
+
3076
+ agent extractor {
3077
+ model: sonnet
3078
+ permissions: autonomous
3079
+ phase: 1
3080
+ tools: [Read, Write, extract-pdf]
3081
+ writes: ["workspace/extracted/"]
3082
+ background: true
3083
+ retry {
3084
+ max: 3
3085
+ backoff: exponential
3086
+ interval: "5s"
3087
+ }
3088
+ scale {
3089
+ mode: auto
3090
+ by: doc-count
3091
+ min: 2
3092
+ max: 10
3093
+ batch-size: 25
3094
+ }
3095
+ }
3096
+
3097
+ agent classifier {
3098
+ model: haiku
3099
+ permissions: autonomous
3100
+ phase: 2
3101
+ tools: [Read, Write]
3102
+ reads: ["workspace/extracted/"]
3103
+ writes: ["workspace/classified/"]
3104
+ rate-limit: "100/min"
3105
+ }
3106
+
3107
+ agent synthesizer {
3108
+ model: opus
3109
+ permissions: autonomous
3110
+ phase: 3
3111
+ tools: [Read, Write]
3112
+ reads: ["workspace/classified/"]
3113
+ writes: ["workspace/output.json"]
3114
+ timeout: "30m"
3115
+ on-fail: retry
3116
+ outputs: {
3117
+ quality: complete | partial | failed
3118
+ }
3119
+ }
3120
+
3121
+ flow {
3122
+ ingest -> extractor
3123
+ extractor -> classifier
3124
+ classifier -> synthesizer
3125
+ synthesizer -> deliver [when synthesizer.quality == complete]
3126
+ synthesizer -> deliver [when synthesizer.quality == partial]
3127
+ synthesizer -> extractor [when synthesizer.quality == failed, max 2]
3128
+ }
3129
+
3130
+ gates {
3131
+ gate quality-gate {
3132
+ after: classifier
3133
+ before: synthesizer
3134
+ run: "scripts/validate.sh"
3135
+ checks: [completeness, schema]
3136
+ retry: 1
3137
+ on-fail: bounce-back
3138
+ }
3139
+ }
3140
+
3141
+ tools {
3142
+ tool extract-pdf {
3143
+ script: "scripts/extract-pdf.py"
3144
+ args: [input, output]
3145
+ lang: python
3146
+ description: "Extract text from PDFs"
3147
+ }
3148
+ }
3149
+
3150
+ mcp-servers {
3151
+ storage {
3152
+ type: stdio
3153
+ command: "npx"
3154
+ args: ["-y", "storage-server"]
3155
+ }
3156
+ }
3157
+
3158
+ hooks {
3159
+ hook track-cost {
3160
+ on: AgentStop
3161
+ run: "scripts/track-cost.sh"
3162
+ type: command
3163
+ }
3164
+
3165
+ hook block-delete {
3166
+ on: PreToolUse
3167
+ matcher: "Bash(rm *)"
3168
+ run: "exit 1"
3169
+ type: command
3170
+ }
3171
+ }
3172
+
3173
+ metering {
3174
+ track: [tokens-in, tokens-out, cost, wall-time]
3175
+ per: [agent, run, phase]
3176
+ output: "metrics/"
3177
+ format: jsonl
3178
+ pricing: anthropic-current
3179
+ }
3180
+
3181
+ checkpoint {
3182
+ backend: "redis"
3183
+ connection: "\${REDIS_URL}"
3184
+ strategy: "after-each-agent"
3185
+ ttl: "7d"
3186
+ replay {
3187
+ enabled: true
3188
+ max-history: 50
3189
+ }
3190
+ }
3191
+
3192
+ memory {
3193
+ workspace {
3194
+ path: "workspace/"
3195
+ structure: [extracted, classified, output]
3196
+ }
3197
+ }
3198
+
3199
+ settings {
3200
+ allow: ["Read", "Write", "Glob", "Grep"]
3201
+ deny: ["Bash(rm -rf *)"]
3202
+ }
3203
+ }
3204
+ \`\`\`
3205
+ `,
3206
+ },
3207
+ // -------------------------------------------------------------------------
3208
+ // 36. bindings
3209
+ // -------------------------------------------------------------------------
3210
+ bindings: {
3211
+ name: "bindings",
3212
+ description: "All binding targets and what they generate",
3213
+ content: () => `# bindings
3214
+
3215
+ AgenTopology compiles to multiple target platforms via bindings. Each binding reads the parsed AST and generates platform-specific configuration files.
3216
+
3217
+ ## Available Bindings
3218
+
3219
+ ### claude-code
3220
+
3221
+ **Target:** Anthropic Claude Code CLI
3222
+ **Generates:** \`AGENTS.md\`, \`.claude/settings.json\`, \`.claude/commands/\`, hook scripts
3223
+ **Description:** Full-featured binding for Claude Code multi-agent workflows. Generates agent markdown files with prompts, tool permissions, and coordination instructions. Supports hooks, gates (as positioned hooks), triggers (as slash commands), and MCP server configuration.
3224
+
3225
+ ### codex
3226
+
3227
+ **Target:** OpenAI Codex CLI
3228
+ **Generates:** \`codex.yaml\`, agent configuration files
3229
+ **Description:** Generates Codex CLI configuration for OpenAI-powered agent workflows. Maps AgenTopology permissions to Codex approval modes (suggest, auto-edit, full-auto).
3230
+
3231
+ ### gemini-cli
3232
+
3233
+ **Target:** Google Gemini CLI
3234
+ **Generates:** \`.gemini/\` configuration directory, agent files
3235
+ **Description:** Generates Gemini CLI configuration. Maps tools to Gemini function declarations and supports Gemini-specific model identifiers.
3236
+
3237
+ ### copilot-cli
3238
+
3239
+ **Target:** GitHub Copilot CLI
3240
+ **Generates:** \`.github/copilot/\` configuration
3241
+ **Description:** Generates GitHub Copilot CLI agent configuration. Maps AgenTopology concepts to Copilot's instruction and tool systems.
3242
+
3243
+ ### openclaw
3244
+
3245
+ **Target:** OpenClaw framework
3246
+ **Generates:** OpenClaw project configuration
3247
+ **Description:** Generates configuration for the OpenClaw multi-agent framework. Supports OpenClaw's native agent orchestration model.
3248
+
3249
+ ### kiro
3250
+
3251
+ **Target:** Anthropic Kiro
3252
+ **Generates:** \`.kiro/\` configuration directory with specs
3253
+ **Description:** Generates Kiro project configuration. Maps agents to Kiro specs with steering prompts and tool configurations.
3254
+
3255
+ ## Usage
3256
+
3257
+ \`\`\`bash
3258
+ # Scaffold a project for a specific binding
3259
+ npx agentopology scaffold --target claude-code topology.at
3260
+
3261
+ # List available targets
3262
+ npx agentopology targets
3263
+ \`\`\`
3264
+
3265
+ ## Notes
3266
+
3267
+ - All bindings read the same .at file -- write once, deploy to any platform.
3268
+ - Bindings use the \`extensions\` block for platform-specific configuration that doesn't fit the universal model.
3269
+ - Unknown extension namespaces are silently ignored, so a single .at file can target multiple platforms.
3270
+ `,
3271
+ },
3272
+ };
3273
+ //# sourceMappingURL=content.js.map