melchizedek-agents 0.19.0 → 1.0.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 (242) hide show
  1. package/.env.example +4 -5
  2. package/AGENT_SETUP.md +3 -3
  3. package/CHANGELOG.md +492 -76
  4. package/DOCUMENTATION.md +153 -132
  5. package/QUICKSTART.md +14 -10
  6. package/README.md +12 -15
  7. package/config/agents/examples/image_production.yaml +2 -2
  8. package/config/agents/syndicateSchema.yaml +55 -26
  9. package/dist/lib/a2a/app.d.ts +17 -12
  10. package/dist/lib/a2a/app.js +16 -6
  11. package/dist/lib/a2a/executor.d.ts +10 -14
  12. package/dist/lib/a2a/executor.js +10 -18
  13. package/dist/lib/a2a/remoteAgent.d.ts +5 -12
  14. package/dist/lib/a2a/remoteAgent.js +5 -12
  15. package/dist/lib/adkPeer.d.ts +63 -0
  16. package/dist/lib/adkPeer.js +240 -0
  17. package/dist/lib/compile.d.ts +109 -81
  18. package/dist/lib/compile.js +163 -111
  19. package/dist/lib/compileAdk.d.ts +7 -4
  20. package/dist/lib/compileAdk.js +22 -12
  21. package/dist/lib/compileNative.d.ts +63 -49
  22. package/dist/lib/compileNative.js +136 -78
  23. package/dist/lib/config.d.ts +6 -6
  24. package/dist/lib/config.js +6 -6
  25. package/dist/lib/doctor.d.ts +22 -1
  26. package/dist/lib/doctor.js +27 -2
  27. package/dist/lib/index.d.ts +14 -7
  28. package/dist/lib/index.js +11 -7
  29. package/dist/lib/loadSyndicate.d.ts +3 -3
  30. package/dist/lib/loadSyndicate.js +2 -2
  31. package/dist/lib/memory/erase.d.ts +1 -1
  32. package/dist/lib/memory/erase.js +1 -1
  33. package/dist/lib/memory/namespace.d.ts +12 -14
  34. package/dist/lib/memory/namespace.js +13 -14
  35. package/dist/lib/memory/providers.d.ts +4 -5
  36. package/dist/lib/memory/providers.js +12 -6
  37. package/dist/lib/memory/supabaseMemoryService.d.ts +9 -30
  38. package/dist/lib/memory/supabaseMemoryService.js +8 -30
  39. package/dist/lib/model.d.ts +6 -12
  40. package/dist/lib/model.js +6 -12
  41. package/dist/lib/models/adapterResolver.d.ts +21 -38
  42. package/dist/lib/models/adapterResolver.js +33 -40
  43. package/dist/lib/models/adkGeminiAdapter.js +2 -0
  44. package/dist/lib/models/adkShim.d.ts +1 -1
  45. package/dist/lib/models/adkShim.js +1 -1
  46. package/dist/lib/models/capabilities.js +13 -10
  47. package/dist/lib/models/chatCompletionsAdapter.d.ts +12 -33
  48. package/dist/lib/models/chatCompletionsAdapter.js +13 -18
  49. package/dist/lib/models/circuitBreaker.d.ts +5 -5
  50. package/dist/lib/models/circuitBreaker.js +5 -5
  51. package/dist/lib/models/claudeAdapter.d.ts +9 -26
  52. package/dist/lib/models/claudeAdapter.js +11 -15
  53. package/dist/lib/models/claudeLlm.js +2 -2
  54. package/dist/lib/models/claudeModels.d.ts +4 -4
  55. package/dist/lib/models/claudeModels.js +4 -4
  56. package/dist/lib/models/contract.d.ts +11 -11
  57. package/dist/lib/models/contract.js +6 -6
  58. package/dist/lib/models/errorResponse.d.ts +13 -20
  59. package/dist/lib/models/errorResponse.js +0 -12
  60. package/dist/lib/models/fallback.d.ts +1 -1
  61. package/dist/lib/models/fallback.js +1 -1
  62. package/dist/lib/models/fallbackAdapter.d.ts +7 -8
  63. package/dist/lib/models/gatewayAdapter.d.ts +1 -1
  64. package/dist/lib/models/gatewayAdapter.js +1 -1
  65. package/dist/lib/models/gatewayLlm.js +2 -2
  66. package/dist/lib/models/geminiAdapter.d.ts +11 -10
  67. package/dist/lib/models/geminiAdapter.js +37 -15
  68. package/dist/lib/models/geminiState.d.ts +29 -8
  69. package/dist/lib/models/geminiState.js +34 -8
  70. package/dist/lib/models/genaiMapping.d.ts +104 -38
  71. package/dist/lib/models/genaiMapping.js +146 -43
  72. package/dist/lib/models/gptAdapter.d.ts +11 -11
  73. package/dist/lib/models/gptAdapter.js +13 -13
  74. package/dist/lib/models/gptLlm.js +2 -2
  75. package/dist/lib/models/grokLlm.js +2 -2
  76. package/dist/lib/models/kimiAdapter.d.ts +6 -7
  77. package/dist/lib/models/kimiAdapter.js +6 -9
  78. package/dist/lib/models/kimiLlm.js +2 -2
  79. package/dist/lib/models/ollamaAdapter.d.ts +3 -3
  80. package/dist/lib/models/ollamaAdapter.js +3 -3
  81. package/dist/lib/models/ollamaLlm.js +2 -2
  82. package/dist/lib/models/providerMap.d.ts +6 -5
  83. package/dist/lib/models/providerMap.js +6 -5
  84. package/dist/lib/models/providerState.d.ts +3 -2
  85. package/dist/lib/models/providerState.js +3 -2
  86. package/dist/lib/models/reasoning.d.ts +1 -1
  87. package/dist/lib/models/registry.d.ts +26 -69
  88. package/dist/lib/models/registry.js +32 -140
  89. package/dist/lib/models/retry.d.ts +2 -2
  90. package/dist/lib/models/retry.js +2 -2
  91. package/dist/lib/models/schemaNormalize.d.ts +25 -55
  92. package/dist/lib/models/schemaNormalize.js +30 -100
  93. package/dist/lib/models/tracedGemini.d.ts +1 -1
  94. package/dist/lib/models/tracedGemini.js +1 -1
  95. package/dist/lib/observability/lineage.d.ts +3 -3
  96. package/dist/lib/observability/lineage.js +10 -10
  97. package/dist/lib/observability/supabaseSpanExporter.js +1 -1
  98. package/dist/lib/observability/tracer.d.ts +25 -23
  99. package/dist/lib/observability/tracer.js +26 -63
  100. package/dist/lib/persistence/supabaseProvider.d.ts +4 -3
  101. package/dist/lib/runtime/adkSessionBridge.d.ts +1 -1
  102. package/dist/lib/runtime/adkSessionBridge.js +1 -1
  103. package/dist/lib/runtime/approvals.d.ts +6 -1
  104. package/dist/lib/runtime/approvals.js +39 -8
  105. package/dist/lib/runtime/credentials.d.ts +4 -2
  106. package/dist/lib/runtime/credentials.js +6 -1
  107. package/dist/lib/runtime/events.d.ts +3 -4
  108. package/dist/lib/runtime/events.js +3 -4
  109. package/dist/lib/runtime/logging.d.ts +3 -8
  110. package/dist/lib/runtime/logging.js +3 -8
  111. package/dist/lib/runtime/memoryService.d.ts +4 -6
  112. package/dist/lib/runtime/memoryService.js +3 -5
  113. package/dist/lib/runtime/native/agentLoop.d.ts +24 -16
  114. package/dist/lib/runtime/native/agentLoop.js +67 -37
  115. package/dist/lib/runtime/native/compaction.d.ts +10 -11
  116. package/dist/lib/runtime/native/compaction.js +10 -11
  117. package/dist/lib/runtime/native/delegate.d.ts +64 -12
  118. package/dist/lib/runtime/native/delegate.js +101 -25
  119. package/dist/lib/runtime/native/history.d.ts +5 -6
  120. package/dist/lib/runtime/native/history.js +5 -6
  121. package/dist/lib/runtime/native/interrupts.d.ts +12 -9
  122. package/dist/lib/runtime/native/interrupts.js +29 -10
  123. package/dist/lib/runtime/native/request.d.ts +25 -25
  124. package/dist/lib/runtime/native/request.js +36 -25
  125. package/dist/lib/runtime/native/selfCorrection.d.ts +75 -17
  126. package/dist/lib/runtime/native/selfCorrection.js +93 -19
  127. package/dist/lib/runtime/native/step.d.ts +34 -26
  128. package/dist/lib/runtime/native/step.js +78 -32
  129. package/dist/lib/runtime/native/taskMode.d.ts +8 -8
  130. package/dist/lib/runtime/native/taskMode.js +8 -8
  131. package/dist/lib/runtime/native/telemetry.d.ts +11 -11
  132. package/dist/lib/runtime/native/telemetry.js +11 -11
  133. package/dist/lib/runtime/native/tempState.d.ts +4 -4
  134. package/dist/lib/runtime/native/tempState.js +4 -4
  135. package/dist/lib/runtime/nativeTurn.d.ts +29 -32
  136. package/dist/lib/runtime/nativeTurn.js +30 -41
  137. package/dist/lib/runtime/questions.d.ts +8 -9
  138. package/dist/lib/runtime/questions.js +1 -2
  139. package/dist/lib/runtime/runtimeFlag.d.ts +35 -13
  140. package/dist/lib/runtime/runtimeFlag.js +46 -16
  141. package/dist/lib/runtime/sessions.d.ts +10 -12
  142. package/dist/lib/runtime/sessions.js +10 -12
  143. package/dist/lib/runtime/syndicateTurn.d.ts +46 -42
  144. package/dist/lib/runtime/syndicateTurn.js +182 -150
  145. package/dist/lib/runtime/turnControl.d.ts +8 -8
  146. package/dist/lib/runtime/turnControl.js +8 -8
  147. package/dist/lib/runtime/valueDepth.d.ts +23 -0
  148. package/dist/lib/runtime/valueDepth.js +41 -0
  149. package/dist/lib/session/supabaseSessionService.d.ts +7 -21
  150. package/dist/lib/session/supabaseSessionService.js +7 -43
  151. package/dist/lib/session/transcript.d.ts +16 -26
  152. package/dist/lib/session/transcript.js +17 -55
  153. package/dist/lib/storage/postgres/sessionService.d.ts +6 -20
  154. package/dist/lib/storage/postgres/sessionService.js +6 -39
  155. package/dist/lib/syndicateSchema.d.ts +2 -0
  156. package/dist/lib/syndicateSchema.js +32 -10
  157. package/dist/lib/toolRegistry.d.ts +20 -14
  158. package/dist/lib/toolRegistry.js +76 -33
  159. package/dist/lib/tools/adkTool.d.ts +1 -1
  160. package/dist/lib/tools/adkTool.js +1 -1
  161. package/dist/lib/tools/auth.d.ts +1 -1
  162. package/dist/lib/tools/auth.js +1 -1
  163. package/dist/lib/tools/collectionsSearchTool.d.ts +1 -1
  164. package/dist/lib/tools/collectionsSearchTool.js +1 -1
  165. package/dist/lib/tools/examples.d.ts +2 -4
  166. package/dist/lib/tools/examples.js +2 -4
  167. package/dist/lib/tools/generateImageTool.d.ts +3 -3
  168. package/dist/lib/tools/generateImageTool.js +4 -5
  169. package/dist/lib/tools/inspectImageTool.d.ts +2 -2
  170. package/dist/lib/tools/inspectImageTool.js +3 -4
  171. package/dist/lib/tools/mcpToolFactory.d.ts +4 -24
  172. package/dist/lib/tools/mcpToolFactory.js +19 -9
  173. package/dist/lib/tools/memoryTools.d.ts +5 -6
  174. package/dist/lib/tools/memoryTools.js +5 -6
  175. package/dist/lib/tools/nativeTools.d.ts +9 -14
  176. package/dist/lib/tools/nativeTools.js +9 -14
  177. package/dist/lib/tools/openapiTools.d.ts +5 -7
  178. package/dist/lib/tools/openapiTools.js +6 -13
  179. package/dist/lib/tools/scienceTools.d.ts +3 -3
  180. package/dist/lib/tools/scienceTools.js +8 -10
  181. package/dist/lib/tools/skillToolset.d.ts +1 -2
  182. package/dist/lib/tools/skillToolset.js +1 -2
  183. package/dist/lib/tools/skills/executor.d.ts +1 -1
  184. package/dist/lib/tools/skills/executor.js +1 -1
  185. package/dist/lib/tools/skills/frontmatter.d.ts +2 -2
  186. package/dist/lib/tools/skills/frontmatter.js +2 -2
  187. package/dist/lib/tools/skills/tools.d.ts +8 -10
  188. package/dist/lib/tools/skills/tools.js +9 -11
  189. package/dist/lib/tools/tool.d.ts +24 -40
  190. package/dist/lib/tools/tool.js +24 -56
  191. package/dist/lib/tools/toolContract.d.ts +8 -13
  192. package/dist/lib/tools/toolContract.js +6 -17
  193. package/dist/lib/tools/urlContextTool.d.ts +1 -1
  194. package/dist/lib/tools/urlContextTool.js +1 -1
  195. package/dist/lib/tools/webExtractTool.d.ts +2 -2
  196. package/dist/lib/tools/webExtractTool.js +3 -4
  197. package/dist/lib/tools/webSearchTool.d.ts +1 -1
  198. package/dist/lib/tools/webSearchTool.js +1 -1
  199. package/dist/lib/tools/wikiTools.d.ts +2 -2
  200. package/dist/lib/tools/wikiTools.js +5 -6
  201. package/dist/lib/tools/xApiSearchTool.d.ts +2 -2
  202. package/dist/lib/tools/xApiSearchTool.js +3 -4
  203. package/dist/lib/tools/xSearchTool.d.ts +1 -1
  204. package/dist/lib/tools/xSearchTool.js +1 -1
  205. package/dist/lib/tools/xaiSearchParams.d.ts +2 -5
  206. package/dist/lib/tools/xaiSearchParams.js +2 -5
  207. package/dist/lib/wiki/agentRun.d.ts +10 -11
  208. package/dist/lib/wiki/agentRun.js +24 -41
  209. package/dist/lib/workflow/agentNode.d.ts +31 -5
  210. package/dist/lib/workflow/agentNode.js +101 -8
  211. package/dist/lib/workflow/graph.d.ts +13 -13
  212. package/dist/lib/workflow/graph.js +25 -15
  213. package/dist/lib/workflow/nodeEvents.d.ts +5 -5
  214. package/dist/lib/workflow/nodeEvents.js +5 -5
  215. package/dist/lib/workflow/pause.d.ts +5 -4
  216. package/dist/lib/workflow/pause.js +5 -4
  217. package/dist/lib/workflow/resume.d.ts +14 -13
  218. package/dist/lib/workflow/resume.js +17 -16
  219. package/dist/lib/workflow/route.d.ts +7 -7
  220. package/dist/lib/workflow/route.js +8 -8
  221. package/dist/lib/workflow/scheduler.d.ts +54 -9
  222. package/dist/lib/workflow/scheduler.js +75 -8
  223. package/dist/lib/workflow/toolNode.d.ts +18 -29
  224. package/dist/lib/workflow/toolNode.js +29 -35
  225. package/dist/lib/workflow/turn.d.ts +29 -20
  226. package/dist/lib/workflow/turn.js +111 -24
  227. package/dist/lib/workflow.d.ts +38 -42
  228. package/dist/lib/workflow.js +38 -150
  229. package/dist/lib/workflowConfig.d.ts +6 -10
  230. package/dist/lib/workflowConfig.js +2 -27
  231. package/dist/scripts/a2a_server.js +1 -2
  232. package/dist/scripts/assistant_worker.d.ts +2 -2
  233. package/dist/scripts/assistant_worker.js +8 -7
  234. package/dist/scripts/doctor.d.ts +3 -1
  235. package/dist/scripts/doctor.js +4 -2
  236. package/dist/scripts/syndicate_chat.js +14 -24
  237. package/package.json +3 -6
  238. package/skills/briefs/_shared.md +2 -2
  239. package/skills/briefs/melchizedek-author.md +2 -2
  240. package/skills/briefs/melchizedek-models.md +6 -6
  241. package/skills/melchizedek-author/SKILL.md +2 -2
  242. package/skills/melchizedek-models/SKILL.md +5 -5
@@ -1,6 +1,6 @@
1
1
  /**
2
- * lib/compile.ts — the one YAML → agent compiler: a runtime-neutral
3
- * AgentSpec, and the ADK agent graph built from it.
2
+ * lib/compile.ts — the one YAML → agent compiler: an AgentSpec per agent,
3
+ * which lib/compileNative.ts turns into what the runtime runs.
4
4
  *
5
5
  * WHY this file exists:
6
6
  * The A2A server carried this logic as two closures inside its executor,
@@ -12,46 +12,42 @@
12
12
  * So the compiler moved here and both callers import it.
13
13
  *
14
14
  * What it does NOT own: model resolution and nested-config loading. Both are
15
- * injected, because the two callers differ precisely there:
16
- * - the A2A server resolves `model` to a provider INSTANCE carrying the
15
+ * injected, because the callers differ precisely there:
16
+ * - the A2A server resolves `model` to a ModelAdapter carrying the
17
17
  * caller's BYOK key (lib/models/registry.ts resolveModel);
18
- * - the observatory passes the model id through as a string (the
19
- * LLMRegistry routes it) and loads nested syndicates with its
20
- * per-variant overrides already applied.
18
+ * - the observatory passes the model id through as a string (the loop
19
+ * resolves it, lib/models/registry.ts resolveAdapter) and loads nested
20
+ * syndicates with its per-variant overrides already applied.
21
21
  *
22
22
  * ── Two orchestration methods, one compiler ───────────────────────────────
23
- * DELEGATE (no `dispatch:` block): every subagent becomes an AgentTool on
24
- * the orchestrator. PLAN-DISPATCH (`dispatch:` present): the orchestrator
23
+ * DELEGATE (no `dispatch:` block): every subagent becomes a delegation tool
24
+ * on the orchestrator. PLAN-DISPATCH (`dispatch:` present): the orchestrator
25
25
  * is compiled WITHOUT subagent tools — it is a pure classifier — and the
26
- * caller runs `compileSubagent(route)` directly for the chosen route. Both
27
- * paths build subagents through the same function, so the agent a route
28
- * dispatches to is identical to the one DELEGATE would have wrapped.
26
+ * turn runner compiles the chosen route's own spec. Both paths build
27
+ * subagents through the same function, so the agent a route dispatches to
28
+ * is identical to the one DELEGATE would have delegated to.
29
29
  * Contract and rationale: lib/dispatch.ts.
30
30
  *
31
- * ── One spec, two runtimes (ADR 0073) ─────────────────────────────────────
32
- * compileSpec and compileSubagentSpec do the work every runtime shares:
33
- * resolve and gate the tools, append the skills index, resolve the model
34
- * once, build the generateContentConfig. The result is an AgentSpec.
35
- * lib/compileAdk.ts builds ADK's LlmAgent from it (compileGraph and
36
- * compileSubagent are spec + compileAdk), and lib/compileNative.ts builds
37
- * the native loop's NativeAgent (ADR 0045). runSyndicateTurn picks one by
38
- * MELCHIZEDEK_RUNTIME or its `runtime` option.
31
+ * ── The spec (ADR 0073, ADR 0107) ─────────────────────────────────────────
32
+ * compileSpec and compileSubagentSpec resolve and gate the tools, append the
33
+ * skills index, resolve the model once and build the generateContentConfig.
34
+ * The result is an AgentSpec; lib/compileNative.ts builds the loop's
35
+ * NativeAgent from it.
39
36
  */
40
- import { BaseLlm, FunctionTool } from '@google/adk';
41
37
  import { relative } from 'node:path';
42
- import { compileAdk } from './compileAdk.js';
43
38
  import { isDispatchSyndicate } from './dispatch.js';
39
+ import { isWorkflowSyndicate, nodeKind } from './workflowConfig.js';
44
40
  import { loadSyndicate, nestedLoader } from './loadSyndicate.js';
45
41
  import { REASONING_OLDER_SPELLING } from './syndicateSchema.js';
46
42
  import { reasoningConfig } from './models/reasoning.js';
47
43
  import { resolveTools as resolveNamedTools } from './toolRegistry.js';
48
44
  import { createMcpTools } from './tools/mcpToolFactory.js';
49
- import { toAdkInstructionTool, toAdkToolset } from './tools/adkTool.js';
45
+ import { requireApproval, toolOf } from './tools/tool.js';
50
46
  import { examplesInstructionTool } from './tools/examples.js';
51
47
  import { capabilitySummary, describeCapabilities } from './models/capabilities.js';
52
48
  import { buildSkillHarness } from './tools/skillToolset.js';
53
49
  import { buildOpenApiTools, namesTool, openApiOperationId } from './tools/openapiTools.js';
54
- /** generateContentConfig as every entrypoint has always sent it to ADK. */
50
+ /** generateContentConfig as every entrypoint sends it: server-side tool invocations on. */
55
51
  function withServerSideToolInvocations(generateContentConfig) {
56
52
  const cfg = (generateContentConfig ?? {});
57
53
  return {
@@ -64,7 +60,7 @@ function withServerSideToolInvocations(generateContentConfig) {
64
60
  }
65
61
  // ── Reasoning (ADR 0047) ─────────────────────────────────────────────────────
66
62
  // REASONING_BUDGETS and reasoningConfig live in lib/models/reasoning.ts, so a
67
- // model adapter can map `reasoning:` without importing the compiler (and ADK).
63
+ // model adapter can map `reasoning:` without importing the compiler.
68
64
  export { REASONING_BUDGETS, reasoningConfig } from './models/reasoning.js';
69
65
  /**
70
66
  * An agent's generateContentConfig with its `reasoning:` key mapped in for
@@ -84,7 +80,12 @@ export function withReasoning(agent, model) {
84
80
  }
85
81
  /** The model id an agent runs on, from its YAML or its resolved adapter. */
86
82
  function modelIdOf(yamlModel, resolved) {
87
- return yamlModel ?? (typeof resolved === 'string' ? resolved : resolved instanceof BaseLlm ? resolved.model : undefined);
83
+ if (yamlModel !== undefined)
84
+ return yamlModel;
85
+ if (typeof resolved === 'string')
86
+ return resolved;
87
+ const own = resolved && typeof resolved === 'object' ? resolved.model : undefined;
88
+ return typeof own === 'string' ? own : undefined;
88
89
  }
89
90
  export { DEFAULT_KEEP_RECENT_EVENTS } from './runtime/native/compaction.js';
90
91
  /**
@@ -102,44 +103,6 @@ function logCapabilities(opts, agentName, model, tools) {
102
103
  if (line)
103
104
  opts.log(`capability · ${line}`);
104
105
  }
105
- /**
106
- * A copy of a FunctionTool that runs only after a person approves the call
107
- * (ADR 0028). ADK's own gate does the work: the call raises an
108
- * `adk_request_confirmation` interrupt pinning the call and its arguments,
109
- * and only an approval bound to that exact call runs it. The original stays
110
- * ungated for every other agent that lists the same tool.
111
- */
112
- export function requireApprovalOn(tool) {
113
- const gated = Object.create(tool);
114
- Object.defineProperty(gated, 'requireConfirmation', { value: true, enumerable: false });
115
- return gated;
116
- }
117
- /**
118
- * A copy of an ADK BaseTool that runs only after a person approves the
119
- * call: the same confirmation interrupt FunctionTool's own gate raises, so
120
- * the turn pauses and resumes exactly as ADR 0028 says. The engine no
121
- * longer uses it: an OpenAPI operation is a FunctionTool over an own Tool
122
- * (ADR 0067) and takes requireApprovalOn like every registry tool.
123
- * @deprecated Gate a FunctionTool with requireApprovalOn, or an own Tool
124
- * with requireApproval (lib/tools/tool.ts).
125
- */
126
- export function requireApprovalOnBaseTool(tool) {
127
- const gated = Object.create(tool);
128
- Object.defineProperty(gated, 'runAsync', {
129
- value: async (request) => {
130
- const ctx = request.toolContext;
131
- if (!ctx.toolConfirmation) {
132
- ctx.requestConfirmation({ hint: `Approval is required before ${tool.name} runs.`, payload: request.args });
133
- ctx.actions.skipSummarization = true;
134
- return { error: 'This call requires approval, please approve or reject.' };
135
- }
136
- if (!ctx.toolConfirmation.confirmed)
137
- return { error: 'This call was rejected.' };
138
- return tool.runAsync(request);
139
- },
140
- });
141
- return gated;
142
- }
143
106
  function gateTools(tools, names, agentName) {
144
107
  if (!names?.length)
145
108
  return tools;
@@ -154,11 +117,12 @@ function gateTools(tools, names, agentName) {
154
117
  if (!match)
155
118
  return t;
156
119
  wanted.delete(match);
157
- // An OpenAPI operation is a FunctionTool over an own Tool (ADR 0067): one gate for both.
158
- if (!(t instanceof FunctionTool)) {
159
- throw new Error(`${agentName}: '${name}' cannot require approval — only function tools from the registry and OpenAPI operations can be gated (ADR 0028).`);
120
+ // A registry tool, an OpenAPI operation and an MCP tool are own Tools (ADR 0067): one gate for all.
121
+ const own = toolOf(t);
122
+ if (!own) {
123
+ throw new Error(`${agentName}: '${name}' cannot require approval — only function tools from the registry, OpenAPI operations and MCP tools can be gated (ADR 0028).`);
160
124
  }
161
- return requireApprovalOn(t);
125
+ return requireApproval(own);
162
126
  });
163
127
  if (wanted.size) {
164
128
  // Fail closed: a gate on a tool that did not resolve must not leave an
@@ -172,14 +136,13 @@ export function declaresApprovals(config) {
172
136
  return agentGates(config.orchestrator) || (config.subagents ?? []).some((s) => agentGates(s));
173
137
  }
174
138
  /**
175
- * An agent's `examples:` as the ADK tool for their InstructionTool
176
- * (lib/tools/examples.ts): never called by the model, it adds the exchanges
177
- * to every request's instruction as few-shot examples, in the words ADK's
178
- * ExampleTool used.
139
+ * An agent's `examples:` as their InstructionTool (lib/tools/examples.ts):
140
+ * never called by the model, it adds the exchanges to every request's
141
+ * instruction as few-shot examples, in the words ADK's ExampleTool used.
179
142
  */
180
143
  export function examplesTool(examples) {
181
144
  const tool = examplesInstructionTool(examples);
182
- return tool ? [toAdkInstructionTool(tool)] : [];
145
+ return tool ? [tool] : [];
183
146
  }
184
147
  async function resolveAgentTools(toolNames, mcpServerUrl, opts, openapi, examples, mcpAllowed) {
185
148
  const tools = [...resolveNamedTools(toolNames, opts.onUnknownTool), ...examplesTool(examples)];
@@ -232,8 +195,7 @@ async function withSkills(instruction, tools, skills, agentName, opts) {
232
195
  opts.log?.(`skills · ${agentName}: ${count} skill${count === 1 ? '' : 's'} from ${skills.dir}${skills.scripts === 'local' ? ' · scripts run after approval' : ''}`);
233
196
  for (const problem of harness.problems)
234
197
  opts.log?.(`⚠ skills · ${skills.dir}: not loaded — ${problem}`);
235
- // The ADK face of the engine's own toolset; compileNative reads the toolset back (toolsetOf).
236
- return { instruction: `${instruction.trimEnd()}\n\n${harness.instruction}`, tools: [...tools, toAdkToolset(harness.toolset)] };
198
+ return { instruction: `${instruction.trimEnd()}\n\n${harness.instruction}`, tools: [...tools, harness.toolset] };
237
199
  }
238
200
  /** True when a turn running this agent directly may pause for a person (ADR 0028). */
239
201
  export function agentGates(agent) {
@@ -278,10 +240,121 @@ function specOf(yaml, name, description, instruction, tools, opts) {
278
240
  return spec;
279
241
  }
280
242
  const asTools = (tools) => tools.map((tool) => ({ kind: 'tool', tool }));
243
+ /**
244
+ * A nested `yaml_reference:` syndicate, loaded. A nested syndicate runs
245
+ * inside a tool call (or as a route whose own subagents do): a pause there
246
+ * cannot reach the caller (ADR 0028), so one that declares approval gates is
247
+ * refused.
248
+ */
249
+ /** Where the yaml_reference chain a compile is inside is kept: an own symbol on the options, so a spread copy keeps it. */
250
+ const NESTING = Symbol('melchizedek.compile.nesting');
251
+ /** The deepest a yaml_reference chain may go: well past any syndicate the engine ships, short of the stack. */
252
+ const MAX_NESTING_DEPTH = 16;
253
+ /**
254
+ * The options a nested `ref` compiles with: `opts` and the chain of
255
+ * references above it. A reference already on the chain (a syndicate that
256
+ * reaches itself) or a chain past MAX_NESTING_DEPTH is refused by name (WS5-5,
257
+ * ADR 0101): the compile would otherwise recurse until the stack gave out,
258
+ * which took the process with it.
259
+ */
260
+ function nestedOptions(ref, opts) {
261
+ const chain = (opts[NESTING] ?? []);
262
+ if (chain.includes(ref))
263
+ throw new Error(`${ref}: a nested syndicate reaches itself (${[...chain, ref].join(' → ')}); a yaml_reference chain must end.`);
264
+ if (chain.length >= MAX_NESTING_DEPTH)
265
+ throw new Error(`${ref}: nested syndicates go deeper than ${MAX_NESTING_DEPTH} levels (${[...chain, ref].join(' → ')}).`);
266
+ return { ...opts, [NESTING]: [...chain, ref] };
267
+ }
268
+ function loadNestedSyndicate(ref, opts) {
269
+ opts.log?.(`Loading nested syndicate: ${ref}`);
270
+ const nested = (opts.loadNested ?? loadSyndicate)(ref);
271
+ if (declaresApprovals(nested)) {
272
+ throw new Error(`${ref}: approval gates (require_approval) are not supported inside a nested syndicate.`);
273
+ }
274
+ return nested;
275
+ }
276
+ /**
277
+ * The spec of a workflow syndicate: every agent through compileSubagentSpec
278
+ * (the orchestrator first, as a node like any other), and the registry's
279
+ * lookup for its tool nodes. `name` and `description` name a nested one
280
+ * after its subagent entry (ADR 0098); `ref` is the file it came from.
281
+ *
282
+ * A nested workflow runs inside its caller's tool call, so a pause inside it
283
+ * could not reach the caller (ADR 0028, as for any nested syndicate): an
284
+ * `ask_user` node is refused by name here.
285
+ */
286
+ export async function compileWorkflowSpec(config, opts = {}, name, description, ref) {
287
+ if (!isWorkflowSyndicate(config))
288
+ throw new Error(`${config.syndicate_name}: no workflow block`);
289
+ if (name) {
290
+ const asking = Object.entries(config.workflow.nodes ?? {}).find(([, node]) => nodeKind(node) === 'ask_user');
291
+ if (asking) {
292
+ throw new Error(`${ref ?? config.syndicate_name}: the ask_user node '${asking[0]}' pauses for a person, which a workflow nested in another syndicate (${name}) cannot carry to its caller; run the workflow as its own syndicate, or remove the node.`);
293
+ }
294
+ }
295
+ const workflowName = name || config.syndicate_name;
296
+ const agents = [];
297
+ const workflows = [];
298
+ for (const yaml of [{ description: '', ...config.orchestrator }, ...(config.subagents ?? [])]) {
299
+ const entry = await compileEntrySpec(yaml, opts);
300
+ if (entry.kind === 'workflow')
301
+ workflows.push({ yaml, workflow: entry.workflow });
302
+ else
303
+ agents.push({ yaml, spec: entry.spec });
304
+ }
305
+ // A map runs one agent per item; a nested graph is not an agent a map item can be (ADR 0106).
306
+ for (const [node, entry] of Object.entries(config.workflow.nodes ?? {})) {
307
+ const mapped = nodeKind(entry) === 'map' ? workflows.find((w) => w.yaml.name === entry.map) : undefined;
308
+ if (mapped) {
309
+ throw new Error(`${ref ?? config.syndicate_name}: the map node '${node}' runs '${mapped.yaml.name}', a workflow syndicate (${mapped.yaml.yaml_reference}); a map runs one agent per item, so make the workflow a node of its own.`);
310
+ }
311
+ }
312
+ return {
313
+ name: workflowName,
314
+ description: description ?? '',
315
+ config: { ...config, syndicate_name: workflowName },
316
+ agents,
317
+ workflows,
318
+ resolveTool: (tool) => resolveNamedTools([tool], opts.onUnknownTool)[0],
319
+ };
320
+ }
321
+ /** Every agent spec a workflow runs, its nested workflow nodes' agents included, for one adapter lookup (nativeAdapterFor). */
322
+ export function workflowAgentSpecs(spec) {
323
+ return [...spec.agents.map((a) => a.spec), ...spec.workflows.flatMap((w) => workflowAgentSpecs(w.workflow))];
324
+ }
325
+ /**
326
+ * A subagent entry as what it runs: an inline agent or a nested syndicate's
327
+ * orchestrator as one agent, or a `yaml_reference` to a workflow syndicate
328
+ * as its whole graph under the entry's name and description. A delegated
329
+ * subagent, a dispatch route and a workflow node all compile through here,
330
+ * so the graph a file describes is the graph that runs (ADR 0106).
331
+ */
332
+ export async function compileEntrySpec(subCfg, opts = {}) {
333
+ if (subCfg.yaml_reference && !subCfg.a2a_agent_url) {
334
+ const nestedOpts = nestedOptions(subCfg.yaml_reference, opts);
335
+ const nested = loadNestedSyndicate(subCfg.yaml_reference, nestedOpts);
336
+ if (isWorkflowSyndicate(nested)) {
337
+ return { kind: 'workflow', workflow: await compileWorkflowSpec(nested, nestedOpts, subCfg.name, subCfg.description, subCfg.yaml_reference) };
338
+ }
339
+ return { kind: 'agent', spec: await compileSpec(nested, nestedOpts, subCfg.name, subCfg.description) };
340
+ }
341
+ return { kind: 'agent', spec: await compileSubagentSpec(subCfg, opts) };
342
+ }
343
+ /**
344
+ * The names of a syndicate's subagent entries that are `yaml_reference`s to
345
+ * a workflow syndicate. Loads each reference once and compiles nothing, so a
346
+ * runtime can refuse what it cannot run before the session is touched.
347
+ */
348
+ export function workflowEntryNames(config, opts = {}) {
349
+ const load = opts.loadNested ?? (config.bundled_references ? nestedLoader(config) : loadSyndicate);
350
+ return (config.subagents ?? []).filter((s) => !!s.yaml_reference && !s.a2a_agent_url && isWorkflowSyndicate(load(s.yaml_reference))).map((s) => s.name);
351
+ }
281
352
  /**
282
353
  * The spec of ONE agent from a subagent entry. A `yaml_reference` entry is
283
- * the nested syndicate's whole graph under this entry's name and
284
- * description, so the parent sees one tool (or one route) either way.
354
+ * the nested syndicate's orchestrator under this entry's name and
355
+ * description, its own subagents delegated to as in any DELEGATE graph. A
356
+ * `yaml_reference` to a workflow syndicate has no one agent to build: it
357
+ * runs as its whole graph (compileEntrySpec), and is refused here by name.
285
358
  */
286
359
  export async function compileSubagentSpec(subCfg, opts = {}) {
287
360
  if (subCfg.a2a_agent_url) {
@@ -291,14 +364,12 @@ export async function compileSubagentSpec(subCfg, opts = {}) {
291
364
  throw new Error(`'${subCfg.name}' is a remote A2A agent (a2a_agent_url) and has no local agent to compile.`);
292
365
  }
293
366
  if (subCfg.yaml_reference) {
294
- opts.log?.(`Loading nested syndicate: ${subCfg.yaml_reference}`);
295
- const nested = (opts.loadNested ?? loadSyndicate)(subCfg.yaml_reference);
296
- if (declaresApprovals(nested)) {
297
- // A nested syndicate runs inside a tool call (or as a route whose
298
- // own subagents do): a pause there cannot reach the caller (ADR 0028).
299
- throw new Error(`${subCfg.yaml_reference}: approval gates (require_approval) are not supported inside a nested syndicate.`);
367
+ const nestedOpts = nestedOptions(subCfg.yaml_reference, opts);
368
+ const nested = loadNestedSyndicate(subCfg.yaml_reference, nestedOpts);
369
+ if (isWorkflowSyndicate(nested)) {
370
+ throw new Error(`${subCfg.yaml_reference}: '${subCfg.name}' is a workflow syndicate, which runs as its whole graph, not as one agent; compile the entry with compileEntrySpec (ADR 0106).`);
300
371
  }
301
- return compileSpec(nested, opts, subCfg.name, subCfg.description);
372
+ return compileSpec(nested, nestedOpts, subCfg.name, subCfg.description);
302
373
  }
303
374
  const gated = gateTools(await resolveAgentTools(subCfg.tools, subCfg.mcp_server_url, opts, subCfg.openapi, subCfg.examples, subCfg.mcp_tools), subCfg.require_approval, subCfg.name);
304
375
  const { instruction, tools } = await withSkills(subCfg.instruction ?? '', gated, subCfg.skills, subCfg.name, opts);
@@ -308,7 +379,7 @@ export async function compileSubagentSpec(subCfg, opts = {}) {
308
379
  /**
309
380
  * The spec of a syndicate's orchestrator. In DELEGATE mode its subagents
310
381
  * come first among its tools, as delegations; in PLAN-DISPATCH mode it gets
311
- * none (ADK refuses outputSchema + AgentTool on one agent — see
382
+ * none (a classifier answers with its outputSchema — see
312
383
  * config/agents/critic.yaml), and the caller dispatches to a route's own
313
384
  * spec itself.
314
385
  */
@@ -317,13 +388,12 @@ export async function compileSpec(config, opts = {}, overrideName, overrideDescr
317
388
  if (config.bundled_references && !opts.loadNested)
318
389
  opts = { ...opts, loadNested: nestedLoader(config) };
319
390
  // A graph has no orchestrator-with-tools shape to build: its agents are
320
- // nodes (lib/workflow.ts). Nested as a yaml_reference, only its
321
- // orchestrator runs, since ADK cannot yet make a Workflow a subagent.
322
- if (config.workflow && !overrideName) {
323
- throw new Error(`${config.syndicate_name}: a workflow syndicate is compiled with compileWorkflow (lib/workflow.ts), not compileGraph`);
391
+ // nodes (lib/workflow.ts). A yaml_reference to one runs the whole graph, as
392
+ // a delegated tool (ADR 0098), a dispatch route or a workflow node (ADR
393
+ // 0106), through compileEntrySpec, which never compiles one here.
394
+ if (config.workflow) {
395
+ throw new Error(`${config.syndicate_name}: a workflow syndicate is compiled with compileWorkflowSpec, not compileSpec`);
324
396
  }
325
- if (config.workflow)
326
- opts.log?.(`${config.syndicate_name}: nested as a subagent, so only its orchestrator runs (a Workflow cannot be a subagent yet)`);
327
397
  const delegated = isDispatchSyndicate(config)
328
398
  ? []
329
399
  : await Promise.all((config.subagents ?? []).map(async (subCfg) => {
@@ -331,7 +401,8 @@ export async function compileSpec(config, opts = {}, overrideName, overrideDescr
331
401
  opts.log?.(`Remote A2A agent: ${subCfg.name} → ${subCfg.a2a_agent_url}`);
332
402
  return { kind: 'remote', name: subCfg.name, description: subCfg.description, url: subCfg.a2a_agent_url };
333
403
  }
334
- return { kind: 'agent', agent: await compileSubagentSpec(subCfg, opts) };
404
+ const entry = await compileEntrySpec(subCfg, opts);
405
+ return entry.kind === 'workflow' ? entry : { kind: 'agent', agent: entry.spec };
335
406
  }));
336
407
  const name = overrideName || config.orchestrator.name;
337
408
  // Orchestrator tools are registry names only — no entrypoint has ever
@@ -343,22 +414,3 @@ export async function compileSpec(config, opts = {}, overrideName, overrideDescr
343
414
  logCapabilities(opts, name, config.orchestrator.model, config.orchestrator.tools);
344
415
  return specOf(config.orchestrator, name, overrideDescription || config.orchestrator.description, instruction, [...delegated, ...asTools(tools)], opts);
345
416
  }
346
- // ── The ADK runtime's agents (lib/compileAdk.ts) ─────────────────────────────
347
- /**
348
- * Builds ONE runnable ADK agent from a subagent entry: its spec, as
349
- * lib/compileAdk.ts builds it. A workflow node's settings
350
- * (CompileOptions.nodeConfig) apply to a local agent, not to a nested
351
- * syndicate's orchestrator.
352
- */
353
- export async function compileSubagent(subCfg, opts = {}) {
354
- const spec = await compileSubagentSpec(subCfg, opts);
355
- return compileAdk(spec, opts, subCfg.yaml_reference ? {} : (opts.nodeConfig?.(subCfg.name) ?? {}));
356
- }
357
- /**
358
- * Compiles a syndicate's orchestrator for the ADK runtime. In DELEGATE mode
359
- * its subagents are attached as AgentTools; in PLAN-DISPATCH mode it gets
360
- * none, and the caller dispatches to `compileSubagent(route)` itself.
361
- */
362
- export async function compileGraph(config, opts = {}, overrideName, overrideDescription) {
363
- return compileAdk(await compileSpec(config, opts, overrideName, overrideDescription), opts);
364
- }
@@ -8,16 +8,19 @@
8
8
  * model resolved once and its generateContentConfig built for that model.
9
9
  * This file adds what only ADK's LlmAgent takes: the model wrapped in a
10
10
  * FallbackLlm for `fallback_model:`, each delegated subagent as an
11
- * AgentTool (a remote one as its A2A tool), Gemini's code executor, the
11
+ * AgentTool (a nested workflow's whole Workflow too; a remote one as its
12
+ * A2A tool), Gemini's code executor, the
12
13
  * context compactor, task mode and a workflow node's settings. Every field
13
14
  * reaches LlmAgent as compileGraph and compileSubagent always passed it, so
14
15
  * the ADK runtime runs the agent it ran before the split.
15
16
  * lib/compileNative.ts builds the native loop's agent from the same spec.
16
17
  *
17
- * Imports from lib/compile.ts are types only, so the two modules load in
18
- * either order.
18
+ * Imports from lib/compile.ts are types only. A nested workflow's Workflow
19
+ * comes from lib/workflow.ts (assembleWorkflow, ADR 0098), which imports
20
+ * lib/compile.ts; every use of either is inside a function, so the modules
21
+ * load in any order.
19
22
  */
20
- import { LlmAgent } from '@google/adk';
23
+ import type { LlmAgent } from '@google/adk';
21
24
  import type { AgentSpec, CompileOptions } from './compile.ts';
22
25
  import { DEFAULT_KEEP_RECENT_EVENTS } from './runtime/native/compaction.ts';
23
26
  /** Events kept verbatim after a compaction summary when `context:` names none: the native compactor's default. */
@@ -8,17 +8,21 @@
8
8
  * model resolved once and its generateContentConfig built for that model.
9
9
  * This file adds what only ADK's LlmAgent takes: the model wrapped in a
10
10
  * FallbackLlm for `fallback_model:`, each delegated subagent as an
11
- * AgentTool (a remote one as its A2A tool), Gemini's code executor, the
11
+ * AgentTool (a nested workflow's whole Workflow too; a remote one as its
12
+ * A2A tool), Gemini's code executor, the
12
13
  * context compactor, task mode and a workflow node's settings. Every field
13
14
  * reaches LlmAgent as compileGraph and compileSubagent always passed it, so
14
15
  * the ADK runtime runs the agent it ran before the split.
15
16
  * lib/compileNative.ts builds the native loop's agent from the same spec.
16
17
  *
17
- * Imports from lib/compile.ts are types only, so the two modules load in
18
- * either order.
18
+ * Imports from lib/compile.ts are types only. A nested workflow's Workflow
19
+ * comes from lib/workflow.ts (assembleWorkflow, ADR 0098), which imports
20
+ * lib/compile.ts; every use of either is inside a function, so the modules
21
+ * load in any order.
19
22
  */
20
- import { AgentTool, BaseLlm, BuiltInCodeExecutor, LLMRegistry, LlmAgent, LlmSummarizer, LogLevel, TokenBasedContextCompactor, setLogLevel as setAdkLogLevel } from '@google/adk';
23
+ import { BaseLlm, adk, requireAdk } from './adkPeer.js';
21
24
  import { remoteAgentTool } from './a2a/remoteAgent.js';
25
+ import { assembleWorkflow } from './workflow.js';
22
26
  import { FallbackLlm } from './models/fallback.js';
23
27
  import { resolveModel as resolveRegistryModel } from './models/registry.js';
24
28
  import { onLogLevel } from './runtime/logging.js';
@@ -27,13 +31,13 @@ import { DEFAULT_KEEP_RECENT_EVENTS } from './runtime/native/compaction.js';
27
31
  * ADK's logger follows the engine's level (lib/runtime/logging.ts, ADR
28
32
  * 0080), so a surface sets one level and never names ADK to quiet it.
29
33
  */
30
- const ADK_LOG_LEVELS = {
31
- debug: LogLevel.DEBUG,
32
- info: LogLevel.INFO,
33
- warn: LogLevel.WARN,
34
- error: LogLevel.ERROR,
35
- };
36
- onLogLevel((level) => setAdkLogLevel(ADK_LOG_LEVELS[level]));
34
+ if (adk) {
35
+ const { LogLevel: Level, setLogLevel } = adk;
36
+ const levels = { debug: Level.DEBUG, info: Level.INFO, warn: Level.WARN, error: Level.ERROR };
37
+ onLogLevel((level) => setLogLevel(levels[level]));
38
+ }
39
+ /** What compileAdk builds needs @google/adk; without it, this names the package (ADR 0102). */
40
+ const FEATURE = 'Compiling an agent for the ADK runtime (MELCHIZEDEK_RUNTIME=adk, compileGraph, compileSubagent)';
37
41
  /** Events kept verbatim after a compaction summary when `context:` names none: the native compactor's default. */
38
42
  export { DEFAULT_KEEP_RECENT_EVENTS };
39
43
  /**
@@ -66,6 +70,7 @@ function passthroughFields(spec) {
66
70
  * node, its arguments become the node's output).
67
71
  */
68
72
  function executionFields(cfg, opts) {
73
+ const { BuiltInCodeExecutor, LLMRegistry, LlmSummarizer, TokenBasedContextCompactor } = requireAdk(FEATURE);
69
74
  const out = {};
70
75
  if (cfg.codeExecution === 'gemini')
71
76
  out.codeExecutor = new BuiltInCodeExecutor();
@@ -98,8 +103,9 @@ function withFallback(primary, fallbackId, opts) {
98
103
  const asLlm = (m) => (m instanceof BaseLlm ? m : resolveRegistryModel(String(m)));
99
104
  return new FallbackLlm(asLlm(primary), asLlm(resolve(fallbackId)), opts.log ?? ((m) => console.warn(m)));
100
105
  }
101
- /** The spec's tools as LlmAgent takes them: a delegated subagent as an AgentTool, a remote one as its A2A tool. */
106
+ /** The spec's tools as LlmAgent takes them: a delegated subagent (a nested workflow's Workflow included) as an AgentTool, a remote one as its A2A tool. */
102
107
  function adkTools(spec, opts) {
108
+ const { AgentTool } = requireAdk(FEATURE);
103
109
  return spec.tools.map((entry) => {
104
110
  switch (entry.kind) {
105
111
  case 'tool':
@@ -108,6 +114,9 @@ function adkTools(spec, opts) {
108
114
  return new AgentTool({ agent: compileAdk(entry.agent, opts) });
109
115
  case 'remote':
110
116
  return remoteAgentTool({ name: entry.name, description: entry.description, url: entry.url });
117
+ case 'workflow':
118
+ // ADK's AgentTool runs any node its Runner takes, a Workflow included: the whole graph, its last event's text the answer (ADR 0098).
119
+ return new AgentTool({ agent: assembleWorkflow(entry.workflow, opts).workflow });
111
120
  }
112
121
  });
113
122
  }
@@ -116,6 +125,7 @@ function adkTools(spec, opts) {
116
125
  * settings (CompileOptions.nodeConfig), which compileSubagent passes.
117
126
  */
118
127
  export function compileAdk(spec, opts = {}, extra = {}) {
128
+ const { LlmAgent } = requireAdk(FEATURE);
119
129
  const tools = adkTools(spec, opts);
120
130
  return new LlmAgent({
121
131
  name: spec.name,