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.
- package/.env.example +4 -5
- package/AGENT_SETUP.md +3 -3
- package/CHANGELOG.md +492 -76
- package/DOCUMENTATION.md +153 -132
- package/QUICKSTART.md +14 -10
- package/README.md +12 -15
- package/config/agents/examples/image_production.yaml +2 -2
- package/config/agents/syndicateSchema.yaml +55 -26
- package/dist/lib/a2a/app.d.ts +17 -12
- package/dist/lib/a2a/app.js +16 -6
- package/dist/lib/a2a/executor.d.ts +10 -14
- package/dist/lib/a2a/executor.js +10 -18
- package/dist/lib/a2a/remoteAgent.d.ts +5 -12
- package/dist/lib/a2a/remoteAgent.js +5 -12
- package/dist/lib/adkPeer.d.ts +63 -0
- package/dist/lib/adkPeer.js +240 -0
- package/dist/lib/compile.d.ts +109 -81
- package/dist/lib/compile.js +163 -111
- package/dist/lib/compileAdk.d.ts +7 -4
- package/dist/lib/compileAdk.js +22 -12
- package/dist/lib/compileNative.d.ts +63 -49
- package/dist/lib/compileNative.js +136 -78
- package/dist/lib/config.d.ts +6 -6
- package/dist/lib/config.js +6 -6
- package/dist/lib/doctor.d.ts +22 -1
- package/dist/lib/doctor.js +27 -2
- package/dist/lib/index.d.ts +14 -7
- package/dist/lib/index.js +11 -7
- package/dist/lib/loadSyndicate.d.ts +3 -3
- package/dist/lib/loadSyndicate.js +2 -2
- package/dist/lib/memory/erase.d.ts +1 -1
- package/dist/lib/memory/erase.js +1 -1
- package/dist/lib/memory/namespace.d.ts +12 -14
- package/dist/lib/memory/namespace.js +13 -14
- package/dist/lib/memory/providers.d.ts +4 -5
- package/dist/lib/memory/providers.js +12 -6
- package/dist/lib/memory/supabaseMemoryService.d.ts +9 -30
- package/dist/lib/memory/supabaseMemoryService.js +8 -30
- package/dist/lib/model.d.ts +6 -12
- package/dist/lib/model.js +6 -12
- package/dist/lib/models/adapterResolver.d.ts +21 -38
- package/dist/lib/models/adapterResolver.js +33 -40
- package/dist/lib/models/adkGeminiAdapter.js +2 -0
- package/dist/lib/models/adkShim.d.ts +1 -1
- package/dist/lib/models/adkShim.js +1 -1
- package/dist/lib/models/capabilities.js +13 -10
- package/dist/lib/models/chatCompletionsAdapter.d.ts +12 -33
- package/dist/lib/models/chatCompletionsAdapter.js +13 -18
- package/dist/lib/models/circuitBreaker.d.ts +5 -5
- package/dist/lib/models/circuitBreaker.js +5 -5
- package/dist/lib/models/claudeAdapter.d.ts +9 -26
- package/dist/lib/models/claudeAdapter.js +11 -15
- package/dist/lib/models/claudeLlm.js +2 -2
- package/dist/lib/models/claudeModels.d.ts +4 -4
- package/dist/lib/models/claudeModels.js +4 -4
- package/dist/lib/models/contract.d.ts +11 -11
- package/dist/lib/models/contract.js +6 -6
- package/dist/lib/models/errorResponse.d.ts +13 -20
- package/dist/lib/models/errorResponse.js +0 -12
- package/dist/lib/models/fallback.d.ts +1 -1
- package/dist/lib/models/fallback.js +1 -1
- package/dist/lib/models/fallbackAdapter.d.ts +7 -8
- package/dist/lib/models/gatewayAdapter.d.ts +1 -1
- package/dist/lib/models/gatewayAdapter.js +1 -1
- package/dist/lib/models/gatewayLlm.js +2 -2
- package/dist/lib/models/geminiAdapter.d.ts +11 -10
- package/dist/lib/models/geminiAdapter.js +37 -15
- package/dist/lib/models/geminiState.d.ts +29 -8
- package/dist/lib/models/geminiState.js +34 -8
- package/dist/lib/models/genaiMapping.d.ts +104 -38
- package/dist/lib/models/genaiMapping.js +146 -43
- package/dist/lib/models/gptAdapter.d.ts +11 -11
- package/dist/lib/models/gptAdapter.js +13 -13
- package/dist/lib/models/gptLlm.js +2 -2
- package/dist/lib/models/grokLlm.js +2 -2
- package/dist/lib/models/kimiAdapter.d.ts +6 -7
- package/dist/lib/models/kimiAdapter.js +6 -9
- package/dist/lib/models/kimiLlm.js +2 -2
- package/dist/lib/models/ollamaAdapter.d.ts +3 -3
- package/dist/lib/models/ollamaAdapter.js +3 -3
- package/dist/lib/models/ollamaLlm.js +2 -2
- package/dist/lib/models/providerMap.d.ts +6 -5
- package/dist/lib/models/providerMap.js +6 -5
- package/dist/lib/models/providerState.d.ts +3 -2
- package/dist/lib/models/providerState.js +3 -2
- package/dist/lib/models/reasoning.d.ts +1 -1
- package/dist/lib/models/registry.d.ts +26 -69
- package/dist/lib/models/registry.js +32 -140
- package/dist/lib/models/retry.d.ts +2 -2
- package/dist/lib/models/retry.js +2 -2
- package/dist/lib/models/schemaNormalize.d.ts +25 -55
- package/dist/lib/models/schemaNormalize.js +30 -100
- package/dist/lib/models/tracedGemini.d.ts +1 -1
- package/dist/lib/models/tracedGemini.js +1 -1
- package/dist/lib/observability/lineage.d.ts +3 -3
- package/dist/lib/observability/lineage.js +10 -10
- package/dist/lib/observability/supabaseSpanExporter.js +1 -1
- package/dist/lib/observability/tracer.d.ts +25 -23
- package/dist/lib/observability/tracer.js +26 -63
- package/dist/lib/persistence/supabaseProvider.d.ts +4 -3
- package/dist/lib/runtime/adkSessionBridge.d.ts +1 -1
- package/dist/lib/runtime/adkSessionBridge.js +1 -1
- package/dist/lib/runtime/approvals.d.ts +6 -1
- package/dist/lib/runtime/approvals.js +39 -8
- package/dist/lib/runtime/credentials.d.ts +4 -2
- package/dist/lib/runtime/credentials.js +6 -1
- package/dist/lib/runtime/events.d.ts +3 -4
- package/dist/lib/runtime/events.js +3 -4
- package/dist/lib/runtime/logging.d.ts +3 -8
- package/dist/lib/runtime/logging.js +3 -8
- package/dist/lib/runtime/memoryService.d.ts +4 -6
- package/dist/lib/runtime/memoryService.js +3 -5
- package/dist/lib/runtime/native/agentLoop.d.ts +24 -16
- package/dist/lib/runtime/native/agentLoop.js +67 -37
- package/dist/lib/runtime/native/compaction.d.ts +10 -11
- package/dist/lib/runtime/native/compaction.js +10 -11
- package/dist/lib/runtime/native/delegate.d.ts +64 -12
- package/dist/lib/runtime/native/delegate.js +101 -25
- package/dist/lib/runtime/native/history.d.ts +5 -6
- package/dist/lib/runtime/native/history.js +5 -6
- package/dist/lib/runtime/native/interrupts.d.ts +12 -9
- package/dist/lib/runtime/native/interrupts.js +29 -10
- package/dist/lib/runtime/native/request.d.ts +25 -25
- package/dist/lib/runtime/native/request.js +36 -25
- package/dist/lib/runtime/native/selfCorrection.d.ts +75 -17
- package/dist/lib/runtime/native/selfCorrection.js +93 -19
- package/dist/lib/runtime/native/step.d.ts +34 -26
- package/dist/lib/runtime/native/step.js +78 -32
- package/dist/lib/runtime/native/taskMode.d.ts +8 -8
- package/dist/lib/runtime/native/taskMode.js +8 -8
- package/dist/lib/runtime/native/telemetry.d.ts +11 -11
- package/dist/lib/runtime/native/telemetry.js +11 -11
- package/dist/lib/runtime/native/tempState.d.ts +4 -4
- package/dist/lib/runtime/native/tempState.js +4 -4
- package/dist/lib/runtime/nativeTurn.d.ts +29 -32
- package/dist/lib/runtime/nativeTurn.js +30 -41
- package/dist/lib/runtime/questions.d.ts +8 -9
- package/dist/lib/runtime/questions.js +1 -2
- package/dist/lib/runtime/runtimeFlag.d.ts +35 -13
- package/dist/lib/runtime/runtimeFlag.js +46 -16
- package/dist/lib/runtime/sessions.d.ts +10 -12
- package/dist/lib/runtime/sessions.js +10 -12
- package/dist/lib/runtime/syndicateTurn.d.ts +46 -42
- package/dist/lib/runtime/syndicateTurn.js +182 -150
- package/dist/lib/runtime/turnControl.d.ts +8 -8
- package/dist/lib/runtime/turnControl.js +8 -8
- package/dist/lib/runtime/valueDepth.d.ts +23 -0
- package/dist/lib/runtime/valueDepth.js +41 -0
- package/dist/lib/session/supabaseSessionService.d.ts +7 -21
- package/dist/lib/session/supabaseSessionService.js +7 -43
- package/dist/lib/session/transcript.d.ts +16 -26
- package/dist/lib/session/transcript.js +17 -55
- package/dist/lib/storage/postgres/sessionService.d.ts +6 -20
- package/dist/lib/storage/postgres/sessionService.js +6 -39
- package/dist/lib/syndicateSchema.d.ts +2 -0
- package/dist/lib/syndicateSchema.js +32 -10
- package/dist/lib/toolRegistry.d.ts +20 -14
- package/dist/lib/toolRegistry.js +76 -33
- package/dist/lib/tools/adkTool.d.ts +1 -1
- package/dist/lib/tools/adkTool.js +1 -1
- package/dist/lib/tools/auth.d.ts +1 -1
- package/dist/lib/tools/auth.js +1 -1
- package/dist/lib/tools/collectionsSearchTool.d.ts +1 -1
- package/dist/lib/tools/collectionsSearchTool.js +1 -1
- package/dist/lib/tools/examples.d.ts +2 -4
- package/dist/lib/tools/examples.js +2 -4
- package/dist/lib/tools/generateImageTool.d.ts +3 -3
- package/dist/lib/tools/generateImageTool.js +4 -5
- package/dist/lib/tools/inspectImageTool.d.ts +2 -2
- package/dist/lib/tools/inspectImageTool.js +3 -4
- package/dist/lib/tools/mcpToolFactory.d.ts +4 -24
- package/dist/lib/tools/mcpToolFactory.js +19 -9
- package/dist/lib/tools/memoryTools.d.ts +5 -6
- package/dist/lib/tools/memoryTools.js +5 -6
- package/dist/lib/tools/nativeTools.d.ts +9 -14
- package/dist/lib/tools/nativeTools.js +9 -14
- package/dist/lib/tools/openapiTools.d.ts +5 -7
- package/dist/lib/tools/openapiTools.js +6 -13
- package/dist/lib/tools/scienceTools.d.ts +3 -3
- package/dist/lib/tools/scienceTools.js +8 -10
- package/dist/lib/tools/skillToolset.d.ts +1 -2
- package/dist/lib/tools/skillToolset.js +1 -2
- package/dist/lib/tools/skills/executor.d.ts +1 -1
- package/dist/lib/tools/skills/executor.js +1 -1
- package/dist/lib/tools/skills/frontmatter.d.ts +2 -2
- package/dist/lib/tools/skills/frontmatter.js +2 -2
- package/dist/lib/tools/skills/tools.d.ts +8 -10
- package/dist/lib/tools/skills/tools.js +9 -11
- package/dist/lib/tools/tool.d.ts +24 -40
- package/dist/lib/tools/tool.js +24 -56
- package/dist/lib/tools/toolContract.d.ts +8 -13
- package/dist/lib/tools/toolContract.js +6 -17
- package/dist/lib/tools/urlContextTool.d.ts +1 -1
- package/dist/lib/tools/urlContextTool.js +1 -1
- package/dist/lib/tools/webExtractTool.d.ts +2 -2
- package/dist/lib/tools/webExtractTool.js +3 -4
- package/dist/lib/tools/webSearchTool.d.ts +1 -1
- package/dist/lib/tools/webSearchTool.js +1 -1
- package/dist/lib/tools/wikiTools.d.ts +2 -2
- package/dist/lib/tools/wikiTools.js +5 -6
- package/dist/lib/tools/xApiSearchTool.d.ts +2 -2
- package/dist/lib/tools/xApiSearchTool.js +3 -4
- package/dist/lib/tools/xSearchTool.d.ts +1 -1
- package/dist/lib/tools/xSearchTool.js +1 -1
- package/dist/lib/tools/xaiSearchParams.d.ts +2 -5
- package/dist/lib/tools/xaiSearchParams.js +2 -5
- package/dist/lib/wiki/agentRun.d.ts +10 -11
- package/dist/lib/wiki/agentRun.js +24 -41
- package/dist/lib/workflow/agentNode.d.ts +31 -5
- package/dist/lib/workflow/agentNode.js +101 -8
- package/dist/lib/workflow/graph.d.ts +13 -13
- package/dist/lib/workflow/graph.js +25 -15
- package/dist/lib/workflow/nodeEvents.d.ts +5 -5
- package/dist/lib/workflow/nodeEvents.js +5 -5
- package/dist/lib/workflow/pause.d.ts +5 -4
- package/dist/lib/workflow/pause.js +5 -4
- package/dist/lib/workflow/resume.d.ts +14 -13
- package/dist/lib/workflow/resume.js +17 -16
- package/dist/lib/workflow/route.d.ts +7 -7
- package/dist/lib/workflow/route.js +8 -8
- package/dist/lib/workflow/scheduler.d.ts +54 -9
- package/dist/lib/workflow/scheduler.js +75 -8
- package/dist/lib/workflow/toolNode.d.ts +18 -29
- package/dist/lib/workflow/toolNode.js +29 -35
- package/dist/lib/workflow/turn.d.ts +29 -20
- package/dist/lib/workflow/turn.js +111 -24
- package/dist/lib/workflow.d.ts +38 -42
- package/dist/lib/workflow.js +38 -150
- package/dist/lib/workflowConfig.d.ts +6 -10
- package/dist/lib/workflowConfig.js +2 -27
- package/dist/scripts/a2a_server.js +1 -2
- package/dist/scripts/assistant_worker.d.ts +2 -2
- package/dist/scripts/assistant_worker.js +8 -7
- package/dist/scripts/doctor.d.ts +3 -1
- package/dist/scripts/doctor.js +4 -2
- package/dist/scripts/syndicate_chat.js +14 -24
- package/package.json +3 -6
- package/skills/briefs/_shared.md +2 -2
- package/skills/briefs/melchizedek-author.md +2 -2
- package/skills/briefs/melchizedek-models.md +6 -6
- package/skills/melchizedek-author/SKILL.md +2 -2
- package/skills/melchizedek-models/SKILL.md +5 -5
package/DOCUMENTATION.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# melchizedek-agents — reference documentation
|
|
2
2
|
|
|
3
3
|
The framework in one sentence: **a syndicate is a YAML file describing an
|
|
4
|
-
agent graph; the
|
|
4
|
+
agent graph; the engine compiles it into agents on its own loop, with
|
|
5
5
|
tools, sessions, and memory attached.** This document is the reference
|
|
6
6
|
for that file format and the machinery around it. For a guided first run,
|
|
7
7
|
see [`QUICKSTART.md`](./QUICKSTART.md).
|
|
@@ -27,13 +27,14 @@ config/agents/ YOUR syndicate definitions (the engine's input)
|
|
|
27
27
|
config/agents/examples/ the starter pack — shipped example syndicates
|
|
28
28
|
lib/loadSyndicate.ts YAML → validated config (+ variable binding)
|
|
29
29
|
lib/dispatch.ts plan-dispatch route resolution (§6)
|
|
30
|
-
lib/toolRegistry.ts tool name →
|
|
30
|
+
lib/toolRegistry.ts tool name → the engine's own Tool
|
|
31
31
|
lib/models/claudeAdapter.ts Claude on the engine's model contract
|
|
32
|
-
lib/models/claudeLlm.ts that adapter behind the ADK shim, in the ADK registry
|
|
33
32
|
lib/models/ollamaLlm.ts open-weight local adapter (Ollama, keyless)
|
|
34
33
|
lib/models/chatCompletionsAdapter.ts the chat-completions wire on the model contract
|
|
35
|
-
lib/tools/mcpToolFactory.ts MCP client: remote tools →
|
|
34
|
+
lib/tools/mcpToolFactory.ts MCP client: remote tools → the engine's own Tools
|
|
36
35
|
scripts/demo_mcp_server.ts demo MCP server (library catalog, SSE)
|
|
36
|
+
lib/runtime/native/… the native loop: steps, delegation, compaction, interrupts
|
|
37
|
+
lib/workflow/… the workflow scheduler for `workflow:` syndicates
|
|
37
38
|
lib/session/… Supabase-backed session service
|
|
38
39
|
lib/memory/… pgvector long-term memory service
|
|
39
40
|
lib/observability/… OpenTelemetry run tracing
|
|
@@ -48,27 +49,42 @@ tests/agents.test.ts compiles every shipped syndicate; opt-in live check
|
|
|
48
49
|
```
|
|
49
50
|
|
|
50
51
|
Execution flow: `loadSyndicate` reads and validates the YAML and binds
|
|
51
|
-
`{{variables}}` → the
|
|
52
|
-
subagents as
|
|
53
|
-
|
|
54
|
-
on
|
|
55
|
-
|
|
52
|
+
`{{variables}}` → the compiler builds each agent on the engine's own
|
|
53
|
+
loop, wiring subagents as delegation tools and tool names through the
|
|
54
|
+
registry → the loop runs the turn, calling each agent's model through its
|
|
55
|
+
adapter on the engine's model contract and persisting events to the
|
|
56
|
+
session service → on session end, the memory service distills the
|
|
57
|
+
transcript into tagged facts, embeds them (768-d), and stores them for
|
|
58
|
+
future recall.
|
|
56
59
|
|
|
57
60
|
The compiler (`lib/compile.ts`) first builds a runtime-neutral `AgentSpec`
|
|
58
|
-
per agent
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
61
|
+
per agent, and `lib/compileNative.ts` turns it into the native loop's
|
|
62
|
+
agent. The native runtime is the only runtime
|
|
63
|
+
([ADR 0107](./wiki/decisions/0107-release-1-0-0-removes-adk.md)): it owns the
|
|
64
|
+
loop, the model contract and its adapters, the tools, the sessions and
|
|
65
|
+
the workflow scheduler, and runs a single-agent, delegating,
|
|
66
|
+
plan-dispatch or `workflow:` syndicate, `context:` compaction
|
|
64
67
|
([ADR 0078](./wiki/decisions/0078-native-compaction-ports-adk-compactor.md)),
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
68
|
+
`mode: task`, and pause and resume included
|
|
69
|
+
([ADR 0095](./wiki/decisions/0095-native-workflow-turn-drains-through-the-adk-reader.md)).
|
|
70
|
+
Two configurations it refuses with `UnsupportedOnRuntimeError` before any
|
|
71
|
+
model call: a `transformAgent` hook (it transformed ADK agents), and an
|
|
72
|
+
`ask_user` tool on a workflow node (use an `ask_user` node)
|
|
70
73
|
([ADR 0073](./wiki/decisions/0073-one-agent-spec-and-a-runtime-flag.md)).
|
|
71
74
|
|
|
75
|
+
1.0.0 removed Google ADK
|
|
76
|
+
([ADR 0045](./wiki/decisions/0045-own-runtime-behind-the-seam.md),
|
|
77
|
+
[ADR 0107](./wiki/decisions/0107-release-1-0-0-removes-adk.md)).
|
|
78
|
+
`MELCHIZEDEK_RUNTIME=native` (or `runtime: 'native'` on
|
|
79
|
+
`runSyndicateTurn`) changes nothing; `adk` throws `RuntimeRemovedError`,
|
|
80
|
+
naming 1.0.0, at the startup of the A2A server, the chat and the worker,
|
|
81
|
+
and from `runSyndicateTurn` before the session is touched; any other value
|
|
82
|
+
is a configuration error. The engine stores the same event JSON ADK wrote,
|
|
83
|
+
so a session written before 1.0.0 resumes, and `npx melchizedek-doctor`
|
|
84
|
+
prints the runtime in use and where the choice came from. Upgrading from
|
|
85
|
+
0.x: read the 1.0.0 "Breaking — read before upgrading" section of
|
|
86
|
+
[`CHANGELOG.md`](./CHANGELOG.md).
|
|
87
|
+
|
|
72
88
|
## 2. The syndicate YAML
|
|
73
89
|
|
|
74
90
|
Minimal complete example:
|
|
@@ -114,18 +130,18 @@ Field reference:
|
|
|
114
130
|
| `memory_retention_days` | root | Days a fact in this syndicate's namespace is kept; the server deletes older facts when it loads the syndicate and daily after. Requires `memory_namespace` (never applied to the shared default namespace). |
|
|
115
131
|
| `dispatch` | root | Switches the syndicate from DELEGATE to PLAN-DISPATCH routing (§6). `default_route` (required) names the fail-static subagent; `route_key` / `reason_key` name the router's JSON properties (defaults `route` / `reason`). Honoured by every surface (the CLI, the server, the worker, evals). |
|
|
116
132
|
| `workflow` | root | Switches the syndicate to a WORKFLOW (§6): a graph whose nodes are its agents plus declared `join`, `map`, `tool` and `ask_user` nodes, and whose `edges` say what runs after what and on which route. The orchestrator is a node like any other; nothing delegates. Cannot be combined with `dispatch`. Contract: `lib/workflow.ts`; worked example: `examples/pipeline.yaml`. |
|
|
117
|
-
| `retries` | root | Self-correction, on by default ([ADR 0034](./wiki/decisions/0034-self-correction.md)): `model_errors` (default 2) retries a model reply
|
|
133
|
+
| `retries` | root | Self-correction, on by default ([ADR 0034](./wiki/decisions/0034-self-correction.md)): `model_errors` (default 2) retries a model reply marked malformed (`MALFORMED_FUNCTION_CALL`) instead of failing the turn; `tool_errors` (default 3) answers a tool that threw with structured reflection guidance and caps its retries. `0` turns either off. Every retry is a model call under `max_steps`. |
|
|
118
134
|
| `guards` | root | Optional list of post-answer guard NAMES (`lib/guards/index.ts`). Each runs after the answering turn and before the reply publishes, receiving the final text plus every tool-result text of that turn, and rewrites in place rather than re-asking the model; its notes land in the `[STATUS]` stream. Guards declared by a syndicate reached through `yaml_reference:` count too — the server resolves the union via `collectGuards()`. Resolved by name, never by module path, so adding one is a deliberate act in code; **the published registry ships one, `science`** (citation checks for `research.yaml`); `registerGuard()` adds your own from code, and an unregistered name is warned about and skipped. |
|
|
119
135
|
| `name` / `model` / `instruction` | agent | The agent triple. Any Gemini id, `claude-*`, or `ollama/*` for open-weight local models (see §5). |
|
|
120
136
|
| `description` | subagent | **The delegation API.** The orchestrator reads this when deciding to hand off — write it like a function signature ("Use this subagent to…, pass it…"). |
|
|
121
137
|
| `tools` | agent | Names resolved by the tool registry (§3). Long-term memory agents add `preload_memory` / `load_memory`. |
|
|
122
138
|
| `reasoning` | agent | How hard the agent reasons, on any provider: `none`, `low`, `medium`, `high`, or `{ budget_tokens: <int> }`. The compiler sends each provider the field it reads: a thinking level on Gemini 3, a thinking budget on Claude 4.6 and earlier (2,048 / 8,192 / 16,384 tokens for low / medium / high), adaptive thinking with that effort on later Claude models ([ADR 0049](./wiki/decisions/0049-claude-requests-by-model-generation.md)), an effort word on GPT, Grok, Kimi, Ollama and the gateway ([ADR 0047](./wiki/decisions/0047-provider-neutral-reasoning-key.md)). Unset, each adapter keeps its own default. |
|
|
123
139
|
| `generateContentConfig` | agent | Temperature, output caps. Its `thinkingConfig` and `reasoningEffort` are the older, provider-specific spelling of `reasoning`; setting either next to `reasoning` is a load error. |
|
|
124
|
-
| `outputSchema` | agent | Structured-JSON contract. **Constraint:** an agent holding `outputSchema` cannot also hold transfer powers —
|
|
140
|
+
| `outputSchema` | agent | Structured-JSON contract. **Constraint:** an agent holding `outputSchema` cannot also hold transfer powers — structured output does not combine with delegation on one agent. Keep schema-holders as leaf agents (see `critic.yaml`'s header comment for the war story). |
|
|
125
141
|
| `yaml_reference` | subagent | Mount another syndicate file as a nested subagent. |
|
|
126
142
|
| `a2a_agent_url` | subagent | A REMOTE agent over A2A (§6): the orchestrator delegates to it with one `request` argument; in plan-dispatch it can be a route. No `model`/`instruction` — the remote agent has its own. Credentials come from `A2A_AGENT_TOKENS`, never YAML. |
|
|
127
143
|
| `max_steps` | root | Cap on model calls per turn, counted across every agent the turn reaches (orchestrator, subagents, nested syndicates). Exceeding it fails the turn with `STEP_LIMIT`. |
|
|
128
|
-
| `includeContents` / `outputKey` / `globalInstruction` / `disallowTransferToParent` / `disallowTransferToPeers` | agent | Passed through to ADK's LlmAgent. `includeContents: none` makes an agent see only the current message. |
|
|
144
|
+
| `includeContents` / `outputKey` / `globalInstruction` / `disallowTransferToParent` / `disallowTransferToPeers` | agent | Passed through to the agent (the names are ADK's `LlmAgent` fields). `includeContents: none` makes an agent see only the current message. |
|
|
129
145
|
| `fallback_model` | any agent | A model, ideally on another provider, that answers when this agent's model fails provider-side (5xx, 429, a connection reset, after its own retries) before producing any output, or while that provider's circuit is open: after `MODEL_BREAKER_THRESHOLD` consecutive provider failures (default 5; 0 disables) the provider is skipped for `MODEL_BREAKER_COOLDOWN_MS` (default 30 s). A 4xx and a canceled turn are never redirected, and a stream that already produced text is never replayed elsewhere ([ADR 0044](./wiki/decisions/0044-fallback-model-and-circuit-breaker.md)). |
|
|
130
146
|
| `mcp_tools` | subagent | The MCP server's tools this agent may use; any other tool the server lists is not exposed. On a dispatch route `require_approval` may name them ([ADR 0041](./wiki/decisions/0041-tool-vendors-get-least-privilege.md)). |
|
|
131
147
|
| `mcp_server_url` | subagent | Discover this subagent's tools from a remote MCP server at load time (§3). SSRF-guarded; `ALLOW_PRIVATE_MCP=true` permits localhost for development. |
|
|
@@ -134,7 +150,7 @@ Field reference:
|
|
|
134
150
|
| `context` | orchestrator | Compacts a long conversation: when the last request's prompt passed `compact_after_tokens`, earlier turns become one summary (written by `summary_model`, default the agent's own) and the last `keep_recent_events` stay verbatim. The full history stays stored; only what the model reads shrinks. The orchestrator of a delegate syndicate only: a dispatch route already reads a bounded projection, a workflow node sees only its input. |
|
|
135
151
|
| `mode` | workflow node | `"task"`: the agent works with its tools until it calls `finish_task`, whose arguments (matching its `outputSchema`) become the node's output. Workflow nodes only. |
|
|
136
152
|
| `examples` | any agent | Few-shot exchanges, `[{ input, output }]` (up to 20), added to every request's instruction as a few-shot block, the one ADK's `ExampleTool` wrote (an Instruction tool, `lib/tools/examples.ts`); the model never calls it. Keeps worked examples out of the prose of `instruction`. |
|
|
137
|
-
| `skills` | any agent | Agent Skills (a directory of SKILL.md folders) the agent holds the way a coding harness does: every skill's name and description is appended to its instruction at compile time; `load_skill` reads one in full with the names of its files, `load_skill_resource` reads one file. `scripts: local` adds `run_skill_script`, which runs a skill's own scripts on this machine, each after a person approves (the `require_approval` pause), with PATH, HOME, the temp directory and the locale but none of the server's keys, plus the variable names listed under `env:` (or `secret_env:` for a secret-shaped name, ADR 0086), and stdout and stderr each cut at 20,000 characters; `tools:` names registry tools a skill's `allowed-tools` may unlock once loaded. Worked example: `examples/harness.yaml`; engine: `lib/tools/skillToolset.ts` over `lib/tools/skills
|
|
153
|
+
| `skills` | any agent | Agent Skills (a directory of SKILL.md folders) the agent holds the way a coding harness does: every skill's name and description is appended to its instruction at compile time; `load_skill` reads one in full with the names of its files, `load_skill_resource` reads one file. `scripts: local` adds `run_skill_script`, which runs a skill's own scripts on this machine, each after a person approves (the `require_approval` pause), with PATH, HOME, the temp directory and the locale but none of the server's keys, plus the variable names listed under `env:` (or `secret_env:` for a secret-shaped name, ADR 0086), and stdout and stderr each cut at 20,000 characters; `tools:` names registry tools a skill's `allowed-tools` may unlock once loaded. Worked example: `examples/harness.yaml`; engine: `lib/tools/skillToolset.ts` over `lib/tools/skills/`. |
|
|
138
154
|
|
|
139
155
|
Validation happens at load: missing names, legacy option blocks, and
|
|
140
156
|
malformed agents fail with pointed errors before any model is called.
|
|
@@ -143,16 +159,14 @@ skipped with a warning at compile time.
|
|
|
143
159
|
|
|
144
160
|
## 3. Tools
|
|
145
161
|
|
|
146
|
-
Registered in `lib/toolRegistry.ts` — one map from YAML name to
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
only writes into each request's instruction, reaching the ADK runtime
|
|
152
|
-
through `toAdkInstructionTool`. A **server-side tool** is an own marker
|
|
162
|
+
Registered in `lib/toolRegistry.ts` — one map from YAML name to tool. A
|
|
163
|
+
**Contract** is the engine's own Tool (`lib/tools/tool.ts`), defined once
|
|
164
|
+
with `defineTool`; the native loop runs it as it is. An **Instruction
|
|
165
|
+
tool** is the engine's own too: it declares no function and only writes
|
|
166
|
+
into each request's instruction. A **server-side tool** is an own marker
|
|
153
167
|
(`lib/tools/nativeTools.ts`) that names the provider's tool and declares no
|
|
154
|
-
function
|
|
155
|
-
|
|
168
|
+
function, and every adapter recognises it by marker
|
|
169
|
+
([ADR 0062](./wiki/decisions/0062-server-side-tools-as-markers.md)):
|
|
156
170
|
|
|
157
171
|
| Name | Kind | Does |
|
|
158
172
|
|---|---|---|
|
|
@@ -161,7 +175,7 @@ adapter recognises it by marker ([ADR 0062](./wiki/decisions/0062-server-side-to
|
|
|
161
175
|
| `x_search` | xAI-only | Live search over X (Twitter) posts via xAI Agent Tools. Self-gates to `grok-*` agents; a silent no-op on every other provider, so mixed-provider YAMLs stay safe. Optional server-side constraints in `.env`: `XAI_X_SEARCH_FROM_DATE`/`_TO_DATE` (inclusive `YYYY-MM-DD`) and `_ALLOWED_HANDLES`/`_EXCLUDED_HANDLES` (max 20, mutually exclusive — allowlist wins). |
|
|
162
176
|
| `collections_search` | xAI-only | Semantic search over xAI **Collections** — hosted document stores (PDFs/text/CSVs) uploaded at console.x.ai — server-side RAG with `collections://…` citations. Which collections: `XAI_COLLECTION_IDS` in `.env` (optional `XAI_COLLECTIONS_MAX_RESULTS`). Declared with no ids → omitted with a warning; non-xAI providers → silent no-op. |
|
|
163
177
|
| `url_context` | Gemini built-in | Gemini reads the pages at URLs in the conversation, server-side (Google fetches them, not this host). On any other provider it is a no-op the doctor reports as dropped; use `web_extract` there. |
|
|
164
|
-
| `google_search` |
|
|
178
|
+
| `google_search` | Gemini built-in | Live web search — Gemini agents only (legacy alias; use `web_search`). |
|
|
165
179
|
| `preload_memory` | Instruction tool | Silently injects similarity-matched facts into every request's instruction (ambient recall). The model never calls it. |
|
|
166
180
|
| `load_memory` | Contract | Explicit tool call to search the fact store (deliberate recall). Both memory tools read the caller's own silo only and send the model what ADK's tools of the same names sent ([ADR 0059](./wiki/decisions/0059-memory-on-the-engines-own-interfaces.md)). |
|
|
167
181
|
| `generate_image` | Contract | Calls the Gemini image model directly, saves the result under `outputs/`, returns the path. A function tool because binary `inlineData` cannot survive the AgentTool text boundary. |
|
|
@@ -173,8 +187,7 @@ adapter recognises it by marker ([ADR 0062](./wiki/decisions/0062-server-side-to
|
|
|
173
187
|
**MCP tools** are the exception to the registry: a subagent with
|
|
174
188
|
`mcp_server_url:` in its YAML gets its tools from a remote MCP server at
|
|
175
189
|
load time. `lib/tools/mcpToolFactory.ts` dials the server over SSE,
|
|
176
|
-
lists its tools, and makes each one an own Tool (`loadMcpTools`)
|
|
177
|
-
the ADK runtime runs as a `FunctionTool` (`createMcpTools`) — the
|
|
190
|
+
lists its tools, and makes each one an own Tool (`loadMcpTools`) — the
|
|
178
191
|
agent's reach is decided by the server, not compiled in.
|
|
179
192
|
`config/agents/examples/librarian.yaml` plus the demo catalog server
|
|
180
193
|
(`npm run mcp:demo`, `scripts/demo_mcp_server.ts`) are the worked
|
|
@@ -228,8 +241,8 @@ example: `config/agents/examples/weather.yaml`, two keyless Open-Meteo specs
|
|
|
228
241
|
in `examples/specs/`.
|
|
229
242
|
|
|
230
243
|
> **Schema dialects, handled for you.** The factory emits Gemini-style
|
|
231
|
-
> UPPERCASE schema types (`'OBJECT'`, `'STRING'`, …)
|
|
232
|
-
>
|
|
244
|
+
> UPPERCASE schema types (`'OBJECT'`, `'STRING'`, …), the `@google/genai`
|
|
245
|
+
> dialect; every non-Gemini adapter normalizes them back to
|
|
233
246
|
> standard lowercase JSON-Schema at request-build time
|
|
234
247
|
> (`lib/models/schemaNormalize.ts`). MCP tools therefore work on any
|
|
235
248
|
> provider's agents — Gemini, Claude, GPT, Grok, or Kimi.
|
|
@@ -340,13 +353,13 @@ accordingly — model optionality is a single YAML line per agent:
|
|
|
340
353
|
|
|
341
354
|
| Model id | Provider | Adapter | Key | Native `web_search` |
|
|
342
355
|
|---|---|---|---|---|
|
|
343
|
-
| `gemini-*` | Google Gemini |
|
|
344
|
-
| `claude-*` | Anthropic | `lib/models/claudeAdapter.ts` (Messages API
|
|
345
|
-
| `gpt-*`, o-series | OpenAI | `lib/models/
|
|
346
|
-
| `grok-*` | xAI | `lib/models/
|
|
347
|
-
| `kimi-*` | Moonshot AI (Kimi) | `lib/models/
|
|
348
|
-
| `ollama/*` | Local Ollama | `lib/models/
|
|
349
|
-
| *any cloud id whose direct key is absent* | the id's own provider, via a gateway | `lib/models/
|
|
356
|
+
| `gemini-*` | Google Gemini | `lib/models/geminiAdapter.ts` (`@google/genai`) | `GOOGLE_GENAI_API_KEY` | ✅ grounding |
|
|
357
|
+
| `claude-*` | Anthropic | `lib/models/claudeAdapter.ts` (Messages API) | `ANTHROPIC_API_KEY` | ✅ server tool |
|
|
358
|
+
| `gpt-*`, o-series | OpenAI | `lib/models/gptAdapter.ts` (Responses API) | `OPENAI_API_KEY` | ✅ web_search tool |
|
|
359
|
+
| `grok-*` | xAI | `lib/models/grokAdapter.ts` (Responses API) | `XAI_API_KEY` | ✅ Agent Tools search |
|
|
360
|
+
| `kimi-*` | Moonshot AI (Kimi) | `lib/models/kimiAdapter.ts` (chat completions) | `MOONSHOT_API_KEY` | ⚠ omitted + warning |
|
|
361
|
+
| `ollama/*` | Local Ollama | `lib/models/ollamaAdapter.ts` (chat completions) | none | ⚠ omitted + warning |
|
|
362
|
+
| *any cloud id whose direct key is absent* | the id's own provider, via a gateway | `lib/models/gatewayAdapter.ts` (chat completions) | `MODEL_GATEWAY` + `MODEL_GATEWAY_API_KEY` | ⚠ omitted + reported |
|
|
350
363
|
|
|
351
364
|
The xAI adapter carries the deepest capability surface: `grok-4.5`
|
|
352
365
|
requests pin `reasoning.effort: "medium"` (`lib/config.ts`), SSE
|
|
@@ -356,9 +369,8 @@ structured outputs ride `outputSchema` → `text.format`, and two
|
|
|
356
369
|
xAI-only tools — `x_search` and `collections_search` (§3) — turn on
|
|
357
370
|
live X search and hosted-document RAG. All verified live on grok-4.5.
|
|
358
371
|
|
|
359
|
-
**Moonshot AI (Kimi).** `kimi-*` ids route to `
|
|
360
|
-
|
|
361
|
-
chat-completions base), against `https://api.moonshot.ai/v1`
|
|
372
|
+
**Moonshot AI (Kimi).** `kimi-*` ids route to `KimiAdapter`
|
|
373
|
+
(`lib/models/kimiAdapter.ts`, on the chat-completions base), against `https://api.moonshot.ai/v1`
|
|
362
374
|
(`MOONSHOT_BASE_URL` for a proxy). Get a key at platform.moonshot.ai; the
|
|
363
375
|
`.cn` console serves mainland China. The family (USD per 1M tokens, October
|
|
364
376
|
2026): `kimi-k3`, the flagship — 2.8T-parameter open-weight MoE, 1M context,
|
|
@@ -455,11 +467,12 @@ configured platform with its credential source and anything missing. These
|
|
|
455
467
|
paths are tested against mocked SDK clients and have **not** been run against
|
|
456
468
|
the live clouds from this repository.
|
|
457
469
|
|
|
458
|
-
`lib/models/registry.ts` is the single routing seam:
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
470
|
+
`lib/models/registry.ts` is the single routing seam: `resolveAdapter`
|
|
471
|
+
turns the YAML's model string into its provider's adapter, and
|
|
472
|
+
`logProviderStatuses()` reports which providers have a key
|
|
473
|
+
(Ollama needs none) and, given a log function, logs a line per provider;
|
|
474
|
+
it registers nothing. Missing keys produce clear skip messages, and only
|
|
475
|
+
the providers a syndicate actually declares are required.
|
|
463
476
|
Mixed graphs are supported — each agent picks its own provider, one
|
|
464
477
|
line each. `config/agents/examples/claude.yaml` is the minimal Claude example;
|
|
465
478
|
`config/agents/examples/model_zoo.yaml` declares one lightweight agent per
|
|
@@ -469,9 +482,7 @@ prompt to every available provider, printing input, thinking (qwen3
|
|
|
469
482
|
Grok reasoning, Kimi reasoning_content), output, and a per-request token/latency trace; add
|
|
470
483
|
`-- --search` to watch four native web searches plus the local
|
|
471
484
|
omission. Providers without keys are skipped, never fatal. Each agent
|
|
472
|
-
runs as a one-agent syndicate through `runSyndicateTurn
|
|
473
|
-
`MELCHIZEDEK_RUNTIME=native npm run demo:models` runs the same demo on
|
|
474
|
-
the engine's own loop.
|
|
485
|
+
runs as a one-agent syndicate through `runSyndicateTurn`.
|
|
475
486
|
|
|
476
487
|
Reasoning/thinking: scratchpads from every provider are surfaced as
|
|
477
488
|
dimmed THINKING output and kept out of session history. On Claude, any
|
|
@@ -488,44 +499,33 @@ response (ADR 0050).
|
|
|
488
499
|
The engine's own model contract is `lib/models/contract.ts` (ADR 0048),
|
|
489
500
|
importable as `melchizedek-agents/models/contract`. It defines the message
|
|
490
501
|
format, request, response stream and adapter interface of the native
|
|
491
|
-
runtime (ADR 0045), with no `@google/*` in its import graph, and
|
|
492
|
-
|
|
493
|
-
each field's purpose and its mapping onto every provider's wire.
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
`GrokAdapter` (`melchizedek-agents/models/grokAdapter`), and keep the token
|
|
501
|
-
counts and server-side tool record the ledger has always had for them
|
|
502
|
-
(ADR 0056).
|
|
503
|
-
Gemini has two adapters on the contract:
|
|
504
|
-
`melchizedek-agents/models/geminiAdapter` (`GeminiAdapter`, on
|
|
505
|
-
`@google/genai` with no ADK) and, until that one passes its live parity
|
|
506
|
-
run, `melchizedek-agents/models/adkGeminiAdapter` (`AdkGeminiAdapter`,
|
|
507
|
-
a temporary wrapper that runs the request through `TracedGemini`, now in
|
|
508
|
-
`melchizedek-agents/models/tracedGemini`).
|
|
502
|
+
runtime (ADR 0045), with no `@google/*` in its import graph, and every
|
|
503
|
+
provider's adapter implements it. `wiki/models/model-contract.md` gives
|
|
504
|
+
each field's purpose and its mapping onto every provider's wire. The
|
|
505
|
+
native loop calls the adapters directly, charging each call against
|
|
506
|
+
`max_steps`, passing the turn's abort signal and opening the
|
|
507
|
+
`llm.request` span (ADR 0053).
|
|
508
|
+
Gemini's adapter is `GeminiAdapter`
|
|
509
|
+
(`melchizedek-agents/models/geminiAdapter`, on `@google/genai`)
|
|
510
|
+
([ADR 0100](./wiki/decisions/0100-gemini-row-asserted-on-the-engine-adapter.md)).
|
|
509
511
|
`resolveAdapter(modelId, { apiKey, keyProvider, endpoint, gemini })` in
|
|
510
512
|
`melchizedek-agents/models/registry` returns any id's contract adapter
|
|
511
|
-
from the
|
|
512
|
-
`resolveModel
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
model and `fallback_model`
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
513
|
+
from the prefix table, with the gateway rule, BYOK scoping and endpoints;
|
|
514
|
+
`resolveModel` returns the same `ModelAdapter` for a BYOK path (ADR 0060).
|
|
515
|
+
Every Gemini id gets `GeminiAdapter`: `GEMINI_ADAPTER=engine` (or
|
|
516
|
+
`gemini: 'engine'`) changes nothing, and `adk` throws, naming 1.0.0.
|
|
517
|
+
`resolveAdapterWithFallback` wraps an agent's model and `fallback_model`
|
|
518
|
+
in a `FallbackAdapter`.
|
|
519
|
+
|
|
520
|
+
`melchizedek-agents/model` is the model layer on its own (ADR 0068): the
|
|
521
|
+
contract's types,
|
|
519
522
|
`ClaudeAdapter`, `GptAdapter`, `GrokAdapter`, `KimiAdapter`,
|
|
520
523
|
`OllamaAdapter`, `GatewayAdapter`, `GeminiAdapter`, the
|
|
521
524
|
`ChatCompletionsAdapter` base, `resolveAdapter`,
|
|
522
525
|
`resolveAdapterWithFallback`, `FallbackAdapter` and the circuit breaker's
|
|
523
|
-
helpers. A project that only calls models
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
`GEMINI_ADAPTER=adk`) throws and names `melchizedek-agents/models/registry`,
|
|
527
|
-
whose `resolveAdapter` keeps the ADK default above. `AdkGeminiAdapter`, the
|
|
528
|
-
ADK shims, `TracedGemini` and `resolveModel` are not in it.
|
|
526
|
+
helpers. A project that only calls models imports from there. Its
|
|
527
|
+
`resolveAdapter` gives a Gemini id `GeminiAdapter`; `resolveModel` is not
|
|
528
|
+
in it.
|
|
529
529
|
|
|
530
530
|
Every model request also emits an `llm.request` OpenTelemetry span
|
|
531
531
|
(provider, model, input/output/thinking tokens, latency). Scripts print it
|
|
@@ -546,24 +546,24 @@ kept by policy (`TELEMETRY_PAYLOADS=off|errors|sample|all`,
|
|
|
546
546
|
`TELEMETRY_PAYLOAD_SAMPLE`, `TELEMETRY_PAYLOAD_TTL_DAYS`) and expired by
|
|
547
547
|
`melchizedek_prune_telemetry()`. A row from a failed call's `llm.request`
|
|
548
548
|
span holds the request in the model contract's shape (`model`, `system`,
|
|
549
|
-
`messages`, `tools`, …), whichever adapter made the call
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
549
|
+
`messages`, `tools`, …), whichever adapter made the call. The native loop
|
|
550
|
+
opens `agent.invoke <name>`, `model.call` and `tool.execute <name>` spans;
|
|
551
|
+
a clean call's row comes from `model.call` and holds the request and the
|
|
552
|
+
adapter's response in the contract's shapes. Rows written before 1.0.0
|
|
553
|
+
under ADK's `invoke_agent`, `call_llm` and `execute_tool` spans hold ADK's
|
|
554
|
+
request, and the ledger still reads them (ADR 0076). The view `adk_turns_production` excludes
|
|
555
555
|
eval and classifier turns. Operate it with `npm run telemetry:stats`,
|
|
556
556
|
`telemetry:prune` and `telemetry:replay` (the exporter spools failed
|
|
557
557
|
batches to `outputs/telemetry-deadletter.ndjson`).
|
|
558
558
|
|
|
559
559
|
**Open-weight local models**: `ollama/*` ids (e.g. `ollama/qwen3:8b`)
|
|
560
|
-
route through `lib/models/
|
|
560
|
+
route through `lib/models/ollamaAdapter.ts` to a local Ollama daemon over
|
|
561
561
|
its OpenAI-compatible API (`OLLAMA_BASE_URL`, default
|
|
562
562
|
`http://localhost:11434/v1`). No key is required, and a syndicate whose
|
|
563
563
|
*every* agent is `ollama/*` runs with no `.env` at all —
|
|
564
564
|
`config/agents/examples/tutor.yaml` (single agent), `council.yaml` (council)
|
|
565
565
|
and `assistant.yaml` (conversation, summaries, a task list, background jobs)
|
|
566
|
-
are the worked examples. The adapter translates
|
|
566
|
+
are the worked examples. The adapter translates the contract's messages to
|
|
567
567
|
OpenAI-style messages, including tool calls (so delegation works),
|
|
568
568
|
image parts as data URIs (so `ollama/qwen3-vl:8b` can see), and JSON
|
|
569
569
|
response mode; reasoning models' `<think>…</think>` scratchpads are
|
|
@@ -784,11 +784,12 @@ same conversation (same `contextId`; the same `taskId` works too) with the text
|
|
|
784
784
|
`{ "approval": { "id": "<approval_id>", "approved": true } }`. Approved, the
|
|
785
785
|
call runs with the arguments shown; rejected, the model is told and answers
|
|
786
786
|
without it. A message that is not an answer gets the same request back,
|
|
787
|
-
without a model call.
|
|
788
|
-
cannot run a different call.
|
|
787
|
+
without a model call. The paused call and its arguments are pinned, so an
|
|
788
|
+
approval cannot run a different call.
|
|
789
789
|
|
|
790
790
|
Gates are allowed on the orchestrator and on the subagents of a
|
|
791
|
-
plan-dispatch syndicate, which run as the turn's own agent
|
|
791
|
+
plan-dispatch syndicate, which run as the turn's own agent, and on the
|
|
792
|
+
agent nodes of a workflow (§6). A delegated
|
|
792
793
|
subagent runs inside a tool call, where a pause cannot reach the caller, so a
|
|
793
794
|
gate there is a load error, as is any gate inside a nested `yaml_reference`
|
|
794
795
|
syndicate. Only function tools from the registry can be gated, not MCP tools
|
|
@@ -831,8 +832,7 @@ A tool that acts for the person against a third-party API reads their
|
|
|
831
832
|
delegated token with `ctx.accessToken(provider)` from the sealed credential
|
|
832
833
|
store ([ADR 0072](./wiki/decisions/0072-tool-credentials-sealed-per-user.md)).
|
|
833
834
|
When they have not granted the provider yet, the turn pauses for their
|
|
834
|
-
consent ([ADR 0085](./wiki/decisions/0085-oauth-consent-pauses-on-adks-credential-request.md))
|
|
835
|
-
This runs on the native runtime:
|
|
835
|
+
consent ([ADR 0085](./wiki/decisions/0085-oauth-consent-pauses-on-adks-credential-request.md)):
|
|
836
836
|
|
|
837
837
|
```ts
|
|
838
838
|
import { createA2AApp } from 'melchizedek-agents/a2a';
|
|
@@ -875,8 +875,7 @@ No token, code, client secret or verifier is written to a page, an event, a
|
|
|
875
875
|
log line or the model's context. The pending flows live in the process: run
|
|
876
876
|
one replica, or route the callback to the instance that paused the call. In
|
|
877
877
|
code, `runSyndicateTurn({ …, toolCredentials })` returns
|
|
878
|
-
`status: 'input-required'` with `consent`.
|
|
879
|
-
request throws `UnsupportedOnRuntimeError`.
|
|
878
|
+
`status: 'input-required'` with `consent`.
|
|
880
879
|
|
|
881
880
|
#### Limits
|
|
882
881
|
|
|
@@ -1090,9 +1089,9 @@ emitted the bare tool name in place of a 2,599-character answer.
|
|
|
1090
1089
|
Plan-dispatch has no relay turn to fail, and the classifier's output
|
|
1091
1090
|
shrinks from a whole relayed answer to ~15 tokens of JSON.
|
|
1092
1091
|
|
|
1093
|
-
**Why the classifier is tool-less.**
|
|
1094
|
-
|
|
1095
|
-
|
|
1092
|
+
**Why the classifier is tool-less.** Structured output does not combine
|
|
1093
|
+
with delegation on one agent (see `config/agents/examples/critic.yaml`,
|
|
1094
|
+
whose header tells how an orchestrator holding both deadlocked on ADK).
|
|
1096
1095
|
That constraint shapes the method: the classifier is a leaf, and the
|
|
1097
1096
|
hand-off happens in code, where it can be logged, traced, and streamed
|
|
1098
1097
|
to the user as progress.
|
|
@@ -1100,8 +1099,9 @@ to the user as progress.
|
|
|
1100
1099
|
**Sessions.** Every *route* runs in the shared `<contextId>` session, so
|
|
1101
1100
|
one transcript accumulates across routes and long-term memory ingests
|
|
1102
1101
|
real answers instead of a relay copy of them. Sharing the session is
|
|
1103
|
-
necessary but not sufficient:
|
|
1104
|
-
`event.author` against the agent now running,
|
|
1102
|
+
necessary but not sufficient: a stored event is rendered by comparing
|
|
1103
|
+
`event.author` against the agent now running (ADK's rule, which the native
|
|
1104
|
+
loop keeps), and under plan-dispatch
|
|
1105
1105
|
every route is its own root agent, so the whole history fails that
|
|
1106
1106
|
comparison and `convertForeignEvent` rewrites it to `role: "user"`
|
|
1107
1107
|
prefixed "For context:". A route reading the raw shared session
|
|
@@ -1128,11 +1128,11 @@ traffic before any prompt, and the memory service's `serializeEvents` walks
|
|
|
1128
1128
|
~90% of every byte stored (`thoughtSignature` alone 73.3%), so they are
|
|
1129
1129
|
stripped from the SERIALIZED COPY — the live in-memory session keeps them,
|
|
1130
1130
|
or the agent's own tool loop breaks mid-turn. An elided tool result keeps
|
|
1131
|
-
its `id` and `name` and gains a size marker, because
|
|
1132
|
-
responses by id and
|
|
1131
|
+
its `id` and `name` and gains a size marker, because the loop pairs
|
|
1132
|
+
calls to responses by id and a widowed half breaks the history. 21.72 MB → 4.88 MB; existing
|
|
1133
1133
|
rows shrink retroactively on their next write. Note the constraint this
|
|
1134
1134
|
rests on: dropping the signature is safe only because stored events are
|
|
1135
|
-
never replayed to a model. The quadratic upload is untouched — `
|
|
1135
|
+
never replayed to a model. The quadratic upload is untouched — `append`
|
|
1136
1136
|
still rewrites the whole array per event — and is the next lever if row size
|
|
1137
1137
|
returns.
|
|
1138
1138
|
|
|
@@ -1159,9 +1159,9 @@ contract lives in `lib/dispatch.ts`.
|
|
|
1159
1159
|
specialist runs, so an A2A client can show a waiting user what is
|
|
1160
1160
|
happening. The `reason` field is written for that reader, not for logs.
|
|
1161
1161
|
|
|
1162
|
-
Implemented in `
|
|
1163
|
-
|
|
1164
|
-
|
|
1162
|
+
Implemented in `runSyndicateTurn`, so every surface honours it: the A2A
|
|
1163
|
+
server, the CLI runner (`scripts/syndicate_chat.ts`), the worker and the
|
|
1164
|
+
evals.
|
|
1165
1165
|
|
|
1166
1166
|
### Workflows (`workflow:`) — the third orchestration method
|
|
1167
1167
|
|
|
@@ -1199,7 +1199,11 @@ the list of results); `tool: <registry name>` (runs the tool with the
|
|
|
1199
1199
|
node input as its arguments); `ask_user: "<question>"` (below). An entry
|
|
1200
1200
|
named after an agent carries modifiers only: `route_key`, `retry`
|
|
1201
1201
|
(`max_attempts`, `initial_delay`, `max_delay`, `backoff_factor`, in
|
|
1202
|
-
seconds
|
|
1202
|
+
seconds; `jitter`, the backoff's randomness, 0 for none; `exceptions`,
|
|
1203
|
+
the error names to retry on, every error when absent) and `timeout`
|
|
1204
|
+
(seconds), which any node but a `map` may carry. A map's items run under
|
|
1205
|
+
the mapped agent's own `retry` and `timeout`, so a `map` entry refuses
|
|
1206
|
+
both and the load error names the agent's entry instead.
|
|
1203
1207
|
|
|
1204
1208
|
**The pause.** An `ask_user` node ends the turn `input-required`
|
|
1205
1209
|
(`result.input`: the node, the question, and what it was asked about).
|
|
@@ -1224,17 +1228,35 @@ again (the attempt is recorded in `answer.nodeErrors`), and a node that
|
|
|
1224
1228
|
gives up fails the turn with `NODE_FAILED` naming it. `max_steps` and
|
|
1225
1229
|
the deadline cap the whole graph as they cap any turn.
|
|
1226
1230
|
|
|
1227
|
-
**
|
|
1228
|
-
and
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
the
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1231
|
+
**Approval gates.** A tool in a node agent's `require_approval` pauses
|
|
1232
|
+
that node, and the graph with it: the turn ends `input-required` with
|
|
1233
|
+
`result.approval`, as any approval does, and the next message, the
|
|
1234
|
+
person's decision, resumes the node's own run, which runs or refuses the
|
|
1235
|
+
pinned call once and walks on. Any other message repeats the request and
|
|
1236
|
+
runs nothing. Skill scripts (`skills.scripts: local`) on a node agent
|
|
1237
|
+
pause the same way, each `run_skill_script` call waiting for its approval,
|
|
1238
|
+
with the minimal script environment of ADR 0086. The schema refuses a gate or skill scripts on an agent a `map`
|
|
1239
|
+
node runs.
|
|
1240
|
+
|
|
1241
|
+
**Nested.** A `yaml_reference` to a workflow syndicate runs the whole
|
|
1242
|
+
graph, under the entry's name and description, wherever it appears: as a
|
|
1243
|
+
DELEGATE subagent its last output is the tool's answer; as a plan-dispatch
|
|
1244
|
+
route it is the turn's answer, and the conversation keeps the message and
|
|
1245
|
+
that answer; as a node of another workflow it is the node's output. The
|
|
1246
|
+
graph's events are kept in the entry's own session, as for any subagent.
|
|
1247
|
+
A nested workflow may not have an `ask_user` node (a pause inside it
|
|
1248
|
+
cannot reach the caller); it is refused by name, as is a `map` over one.
|
|
1249
|
+
|
|
1250
|
+
**Not yet.** Remote `a2a_agent_url` subagents are refused inside a
|
|
1251
|
+
workflow by the schema. An `ask_user` tool on a node agent is refused
|
|
1252
|
+
too: use an `ask_user` node. The records are [ADR 0030](./wiki/decisions/0030-workflow-graphs.md),
|
|
1253
|
+
[ADR 0098](./wiki/decisions/0098-workflow-subagent-and-node-approvals.md) and
|
|
1254
|
+
[ADR 0106](./wiki/decisions/0106-nested-workflow-routes-nodes-and-node-skill-scripts.md);
|
|
1255
|
+
the turn is `lib/workflow/turn.ts`, on the engine's own scheduler
|
|
1256
|
+
([ADR 0095](./wiki/decisions/0095-native-workflow-turn-drains-through-the-adk-reader.md)),
|
|
1257
|
+
and `lib/workflow.ts` holds the `workflow:` block's contract. A conversation paused inside an agent node on anything
|
|
1258
|
+
but an approval, or inside a map item, fails the next turn with
|
|
1259
|
+
`RESUME_UNSUPPORTED`.
|
|
1238
1260
|
|
|
1239
1261
|
## 7. Extending the framework
|
|
1240
1262
|
|
|
@@ -1245,7 +1267,7 @@ the canonical minimal block on the engine's model contract:
|
|
|
1245
1267
|
`adapter.generate({ model, system, messages, stream })`, reading partial
|
|
1246
1268
|
and final responses. The id's prefix picks the provider (`gemini-*`,
|
|
1247
1269
|
`claude-*`, `gpt-*`, `grok-*`, `kimi-*`, `ollama/*`), the key comes from
|
|
1248
|
-
the environment
|
|
1270
|
+
the environment. A turn
|
|
1249
1271
|
with tools, sessions and telemetry is `runSyndicateTurn`.
|
|
1250
1272
|
|
|
1251
1273
|
**Add a syndicate**: create `config/agents/<name>.yaml` — copy the
|
|
@@ -1257,17 +1279,16 @@ closest starter-pack file from `config/agents/examples/` or start from
|
|
|
1257
1279
|
**Add a tool**: write a `defineTool` contract in `lib/tools/` (name,
|
|
1258
1280
|
description, zod schema, execute), register the name in
|
|
1259
1281
|
`lib/toolRegistry.ts` (or call `registerTool` from your own code),
|
|
1260
|
-
reference it from YAML. The
|
|
1282
|
+
reference it from YAML. The native loop runs the contract as it is; see
|
|
1261
1283
|
`wiki/tools/tool-contracts.md`. The two image tools are the worked
|
|
1262
1284
|
examples — including why binary data forces function tools over
|
|
1263
1285
|
subagents, and how a tool signature can enforce an epistemic rule (the
|
|
1264
1286
|
blind inventory).
|
|
1265
1287
|
|
|
1266
1288
|
**Add a provider**: follow `claudeAdapter.ts` (SDK-based, key-gated, a
|
|
1267
|
-
`ModelAdapter` on the engine's model contract,
|
|
1268
|
-
`
|
|
1269
|
-
|
|
1270
|
-
by its shim `ollamaLlm.ts`), and register it behind a model-id prefix.
|
|
1289
|
+
`ModelAdapter` on the engine's model contract) or, for a chat-completions
|
|
1290
|
+
API, `ollamaAdapter.ts` (fetch-based, keyless: a `ChatCompletionsAdapter`
|
|
1291
|
+
subclass), and register it behind a model-id prefix.
|
|
1271
1292
|
|
|
1272
1293
|
**Point an agent at an MCP server**: set `mcp_server_url:` on a
|
|
1273
1294
|
subagent. `scripts/demo_mcp_server.ts` is a complete server to copy —
|
package/QUICKSTART.md
CHANGED
|
@@ -82,9 +82,10 @@ after answering:
|
|
|
82
82
|
npm run syndicate:critic -- "In two sentences, why did the Library of Alexandria decline?"
|
|
83
83
|
```
|
|
84
84
|
|
|
85
|
-
The syndicate layer itself is optional. `scripts/direct_call.ts`
|
|
86
|
-
a single
|
|
87
|
-
|
|
85
|
+
The syndicate layer itself is optional. `scripts/direct_call.ts` makes
|
|
86
|
+
a single model call with no YAML at all — the engine's model contract on
|
|
87
|
+
its own (`melchizedek-agents/model`), and the block to copy when embedding
|
|
88
|
+
a model call in your own code:
|
|
88
89
|
|
|
89
90
|
```bash
|
|
90
91
|
npm run demo:direct -- "In one sentence: what is an agent?"
|
|
@@ -180,23 +181,22 @@ Everything above runs inside a clone. When your syndicates deserve their
|
|
|
180
181
|
own repo, the same engine is a typed dependency:
|
|
181
182
|
|
|
182
183
|
```bash
|
|
183
|
-
npm install melchizedek-agents
|
|
184
|
+
npm install melchizedek-agents
|
|
184
185
|
npx melchizedek-init # config/agents/conversational.yaml + .env; --list for others
|
|
185
186
|
npx melchizedek-doctor # which keys it needs, and whether it is ready
|
|
186
187
|
```
|
|
187
188
|
|
|
188
189
|
```typescript
|
|
189
|
-
import {
|
|
190
|
-
import { loadSyndicate, registerAvailableProviders, runSyndicateTurn } from 'melchizedek-agents';
|
|
190
|
+
import { InProcessSessionService, loadSyndicate, logProviderStatuses, runSyndicateTurn } from 'melchizedek-agents';
|
|
191
191
|
|
|
192
|
-
|
|
192
|
+
logProviderStatuses(console.log); // reports which providers have a key
|
|
193
193
|
const config = loadSyndicate('mine.yaml'); // reads <your-repo>/config/agents/mine.yaml
|
|
194
194
|
|
|
195
195
|
const result = await runSyndicateTurn({
|
|
196
196
|
config,
|
|
197
197
|
parts: [{ text: 'Hello' }],
|
|
198
198
|
appName: 'my-app', userId: 'u1', sessionId: 'c1',
|
|
199
|
-
sessionService: new
|
|
199
|
+
sessionService: new InProcessSessionService(),
|
|
200
200
|
});
|
|
201
201
|
console.log(result.text);
|
|
202
202
|
```
|
|
@@ -222,8 +222,12 @@ console.log(result.text);
|
|
|
222
222
|
`config/agents/`.
|
|
223
223
|
- Deeper imports are available as subpaths — `melchizedek-agents/models/registry`,
|
|
224
224
|
`melchizedek-agents/tools/webExtractTool`, `melchizedek-agents/memory`,
|
|
225
|
-
and friends — all typed.
|
|
226
|
-
|
|
225
|
+
and friends — all typed.
|
|
226
|
+
- **One engine, no ADK.** Every turn runs on the engine's own agent loop;
|
|
227
|
+
1.0.0 removed Google ADK, and `MELCHIZEDEK_RUNTIME=adk` is an error.
|
|
228
|
+
Upgrading from 0.x: read the 1.0.0 "Breaking — read before upgrading"
|
|
229
|
+
section of [`CHANGELOG.md`](./CHANGELOG.md).
|
|
230
|
+
`npx melchizedek-doctor` prints which runtime is in use.
|
|
227
231
|
- **Your coding agent can learn all of this.** The package ships a
|
|
228
232
|
six-skill suite (`skills/`, the open SKILL.md standard) covering the
|
|
229
233
|
catalog, authoring, serving, memory, models, and the Scribe:
|