melchizedek-agents 1.0.2 → 1.0.3

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/CHANGELOG.md CHANGED
@@ -6,6 +6,47 @@ the starter pack and the templates), not the repo's full history.
6
6
 
7
7
  ## Unreleased
8
8
 
9
+ ## 1.0.3 — 2026-10-09
10
+
11
+ Dependency updates and one packaging fix. No export, bin, YAML key or
12
+ adapter behaviour changes; no source file under `lib/` changes.
13
+
14
+ ### Fixed
15
+
16
+ - **`config/agents/syndicate.schema.json` ships in the package.** The
17
+ shipped `config/agents/syndicateSchema.yaml` names it in its
18
+ `yaml-language-server` modeline, and `melchizedek-init` locates the
19
+ package root by it; it was missing from `files`, so editors could not
20
+ resolve the schema and, in an installed package, `melchizedek-init`
21
+ stopped with "config/agents/ not found next to this package".
22
+ `tests/packageSurface.test.ts` now checks that `files` ships it and
23
+ every shipped modeline's target.
24
+
25
+ ### Changed — dependencies
26
+
27
+ - `@anthropic-ai/sdk` ^0.129.0 → ^0.131.0. Additive (Admin and Managed
28
+ Agents endpoints). The SDK now marks `claude-sonnet-4-5` and
29
+ `claude-sonnet-4-5-20250929` deprecated (end of life 2026-11-30) and
30
+ logs a `console.warn` when a request names them; no shipped syndicate
31
+ uses either id.
32
+ - `openai` ^7.23.0 → ^7.28.0. Additive (Agents, Realtime, Responses
33
+ WebSocket features). The client now keeps a base URL's query string
34
+ when joining endpoints; this reaches the GPT adapter only when
35
+ an `OPENAI_BASE_URL` carries a query (the Azure and xAI base URLs carry none;
36
+ the Kimi, Ollama and gateway adapters do not use the SDK).
37
+ - `@modelcontextprotocol/sdk` ^1.29.0 → ^1.32.1 (lock 1.31.0 → 1.32.1).
38
+ The SDK's HTTP client transports now follow redirects only within the
39
+ endpoint's origin unless `redirectPolicy: 'follow'` is set. The MCP
40
+ client's own fetch (`mcpFetch`, `lib/net/redirects.ts`) already follows
41
+ every hop itself under `MCP_REDIRECTS`, so the SDK sees the final
42
+ response and redirect behaviour is unchanged.
43
+ - `@google/genai` 2.25.0 → 2.27.0, still pinned exact. Additive
44
+ (`continuation_token` in GenerateContent and Interactions, new model
45
+ enum values).
46
+ - `@types/node` ^22 → ^25 (dev only). `engines.node` stays `>=22.6.0`; the
47
+ source type-checks against both the Node 22 and Node 25 types.
48
+ - Dockerfile base image `node:22-slim` → `node:25-slim`, pinned by digest.
49
+
9
50
  ## 1.0.2 — 2026-10-09
10
51
 
11
52
  A test and documentation patch. Nothing a consumer imports, configures or
@@ -0,0 +1,1191 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "type": "object",
4
+ "properties": {
5
+ "syndicate_name": {
6
+ "type": "string",
7
+ "minLength": 1,
8
+ "description": "Display name for this syndicate."
9
+ },
10
+ "orchestrator": {
11
+ "type": "object",
12
+ "properties": {
13
+ "name": {
14
+ "type": "string",
15
+ "pattern": "^[A-Za-z_$][A-Za-z0-9_$-]*$",
16
+ "description": "Unique agent name within the tree. A valid identifier; cannot be \"user\"."
17
+ },
18
+ "description": {
19
+ "description": "One line other agents read to decide when to delegate here.",
20
+ "type": "string"
21
+ },
22
+ "model": {
23
+ "type": "string",
24
+ "minLength": 1,
25
+ "description": "Model id; its prefix picks the provider (gemini-*, claude-*, gpt-*/o*, grok-*, ollama/*)."
26
+ },
27
+ "fallback_model": {
28
+ "description": "A model on another provider that answers when this agent's model fails provider-side (5xx, 429, network) before producing anything, or while that provider's circuit is open (ADR 0044).",
29
+ "type": "string",
30
+ "minLength": 1
31
+ },
32
+ "instruction": {
33
+ "type": "string",
34
+ "minLength": 1,
35
+ "description": "System prompt / persona."
36
+ },
37
+ "globalInstruction": {
38
+ "description": "Instruction applied to every agent in the tree; only the root agent's value takes effect.",
39
+ "type": "string"
40
+ },
41
+ "tools": {
42
+ "description": "Named tools from lib/toolRegistry.ts (e.g. web_search, web_extract, wiki_search).",
43
+ "type": "array",
44
+ "items": {
45
+ "type": "string",
46
+ "minLength": 1
47
+ }
48
+ },
49
+ "require_approval": {
50
+ "description": "Tools from this agent's `tools` that run only after a person approves the exact call (ADR 0028): the A2A task ends input-required until the caller answers approve or reject. Allowed on the orchestrator and on plan-dispatch routes.",
51
+ "type": "array",
52
+ "items": {
53
+ "type": "string",
54
+ "minLength": 1
55
+ }
56
+ },
57
+ "includeContents": {
58
+ "description": "\"default\" = include conversation history, \"none\" = stateless.",
59
+ "type": "string",
60
+ "enum": [
61
+ "default",
62
+ "none"
63
+ ]
64
+ },
65
+ "disallowTransferToParent": {
66
+ "type": "boolean"
67
+ },
68
+ "disallowTransferToPeers": {
69
+ "type": "boolean"
70
+ },
71
+ "outputKey": {
72
+ "description": "Session-state key the final reply is saved under.",
73
+ "type": "string"
74
+ },
75
+ "generateContentConfig": {
76
+ "type": "object",
77
+ "properties": {
78
+ "temperature": {
79
+ "type": "number"
80
+ },
81
+ "topP": {
82
+ "type": "number"
83
+ },
84
+ "topK": {
85
+ "type": "number"
86
+ },
87
+ "maxOutputTokens": {
88
+ "type": "integer",
89
+ "exclusiveMinimum": 0,
90
+ "maximum": 9007199254740991
91
+ },
92
+ "stopSequences": {
93
+ "type": "array",
94
+ "items": {
95
+ "type": "string"
96
+ }
97
+ },
98
+ "candidateCount": {
99
+ "type": "integer",
100
+ "exclusiveMinimum": 0,
101
+ "maximum": 9007199254740991
102
+ },
103
+ "presencePenalty": {
104
+ "type": "number"
105
+ },
106
+ "frequencyPenalty": {
107
+ "type": "number"
108
+ },
109
+ "seed": {
110
+ "type": "integer",
111
+ "minimum": -9007199254740991,
112
+ "maximum": 9007199254740991
113
+ },
114
+ "responseMimeType": {
115
+ "type": "string"
116
+ },
117
+ "safetySettings": {
118
+ "type": "array",
119
+ "items": {
120
+ "type": "object",
121
+ "properties": {
122
+ "category": {
123
+ "type": "string"
124
+ },
125
+ "threshold": {
126
+ "type": "string"
127
+ }
128
+ },
129
+ "required": [
130
+ "category",
131
+ "threshold"
132
+ ],
133
+ "additionalProperties": {}
134
+ }
135
+ },
136
+ "thinkingConfig": {
137
+ "type": "object",
138
+ "properties": {
139
+ "thinkingBudget": {
140
+ "description": "Reasoning token budget. 0 = off, -1 = dynamic.",
141
+ "type": "integer",
142
+ "minimum": -9007199254740991,
143
+ "maximum": 9007199254740991
144
+ },
145
+ "includeThoughts": {
146
+ "description": "Stream the thinking trace in the response.",
147
+ "type": "boolean"
148
+ }
149
+ },
150
+ "additionalProperties": {},
151
+ "description": "Older spelling of `reasoning` for Gemini and Claude (thinkingLevel or thinkingBudget). Cannot be combined with `reasoning`."
152
+ },
153
+ "reasoningEffort": {
154
+ "description": "Older spelling of `reasoning` for the chat-completions and Responses providers. Cannot be combined with `reasoning`.",
155
+ "type": "string"
156
+ }
157
+ },
158
+ "additionalProperties": {},
159
+ "description": "Model generation config (@google/genai GenerateContentConfig). Do not set tools here."
160
+ },
161
+ "reasoning": {
162
+ "anyOf": [
163
+ {
164
+ "type": "string",
165
+ "enum": [
166
+ "none",
167
+ "low",
168
+ "medium",
169
+ "high"
170
+ ]
171
+ },
172
+ {
173
+ "type": "object",
174
+ "properties": {
175
+ "budget_tokens": {
176
+ "type": "integer",
177
+ "minimum": 0,
178
+ "maximum": 9007199254740991,
179
+ "description": "Thinking tokens; 0 = none. Effort-only providers take the nearest level at or above it."
180
+ }
181
+ },
182
+ "required": [
183
+ "budget_tokens"
184
+ ],
185
+ "additionalProperties": false
186
+ }
187
+ ],
188
+ "description": "How hard this agent reasons, on any provider: none | low | medium | high, or { budget_tokens: <int> }. Replaces generateContentConfig.thinkingConfig and reasoningEffort (ADR 0047)."
189
+ },
190
+ "outputSchema": {
191
+ "description": "JSON Schema for structured output: the agent answers with one JSON object matching it. Hold it on a leaf; an agent that delegates and holds one ends its turn on that JSON.",
192
+ "type": "object",
193
+ "propertyNames": {
194
+ "type": "string"
195
+ },
196
+ "additionalProperties": {}
197
+ },
198
+ "mcp_server_url": {
199
+ "description": "MCP server (SSE) whose tools are discovered at runtime and merged with `tools`.",
200
+ "type": "string"
201
+ },
202
+ "mcp_tools": {
203
+ "description": "The MCP server's tools this agent may use, by name; any other tool the server lists is not exposed. Without it, every listed tool is. require_approval may name these. Needs mcp_server_url.",
204
+ "minItems": 1,
205
+ "type": "array",
206
+ "items": {
207
+ "type": "string",
208
+ "minLength": 1
209
+ }
210
+ },
211
+ "skills": {
212
+ "type": "object",
213
+ "properties": {
214
+ "dir": {
215
+ "type": "string",
216
+ "minLength": 1,
217
+ "description": "A directory of skills: one subdirectory per skill, named as its SKILL.md frontmatter names it. Relative to the working directory."
218
+ },
219
+ "scripts": {
220
+ "description": "Whether a skill's scripts/ may run. \"local\" runs them on this machine, each after a person approves (ADR 0028); default \"none\".",
221
+ "type": "string",
222
+ "enum": [
223
+ "none",
224
+ "local"
225
+ ]
226
+ },
227
+ "tools": {
228
+ "description": "Registry tool names a skill may unlock through its `allowed-tools` frontmatter once it is loaded. Omitted, no skill unlocks anything.",
229
+ "type": "array",
230
+ "items": {
231
+ "type": "string",
232
+ "minLength": 1
233
+ }
234
+ },
235
+ "env": {
236
+ "description": "Environment variable NAMES (never values) a skill script gets, beyond PATH, HOME, the temp directory, the locale and the OS essentials (ADR 0086). A name that looks like a secret (KEY, TOKEN, SECRET, PASSWORD, AUTH, DATABASE, …) belongs under secret_env.",
237
+ "type": "array",
238
+ "items": {
239
+ "type": "string",
240
+ "pattern": "^[A-Z_][A-Z0-9_]*$"
241
+ }
242
+ },
243
+ "secret_env": {
244
+ "description": "Secret-shaped environment variable names a skill script gets, listed here so passing a credential to a script is a deliberate, reviewable act (ADR 0086).",
245
+ "type": "array",
246
+ "items": {
247
+ "type": "string",
248
+ "pattern": "^[A-Z_][A-Z0-9_]*$"
249
+ }
250
+ }
251
+ },
252
+ "required": [
253
+ "dir"
254
+ ],
255
+ "additionalProperties": false,
256
+ "description": "Agent Skills (SKILL.md directories) this agent reads the way a coding harness does."
257
+ },
258
+ "openapi": {
259
+ "minItems": 1,
260
+ "type": "array",
261
+ "items": {
262
+ "type": "object",
263
+ "properties": {
264
+ "spec": {
265
+ "type": "string",
266
+ "minLength": 1,
267
+ "description": "An OpenAPI 3 spec file (.yaml, .yml, .json), relative to this syndicate file. Files only, never URLs."
268
+ },
269
+ "operations": {
270
+ "description": "Operations to expose, by operationId or tool name. Omitted: every GET operation, and nothing that writes.",
271
+ "minItems": 1,
272
+ "type": "array",
273
+ "items": {
274
+ "type": "string",
275
+ "minLength": 1
276
+ }
277
+ },
278
+ "base_url": {
279
+ "description": "Overrides the spec's servers[0].url. Checked by the SSRF guard.",
280
+ "type": "string",
281
+ "format": "uri"
282
+ },
283
+ "prefix": {
284
+ "description": "Prepended to each tool name, to keep two APIs apart.",
285
+ "type": "string",
286
+ "pattern": "^[a-z][a-z0-9_]*$"
287
+ },
288
+ "auth": {
289
+ "description": "Credentials, always from the environment, never written in YAML.",
290
+ "type": "object",
291
+ "properties": {
292
+ "bearer_env": {
293
+ "description": "Environment variable holding a bearer token.",
294
+ "type": "string",
295
+ "pattern": "^[A-Z_][A-Z0-9_]*$"
296
+ },
297
+ "api_key": {
298
+ "description": "An API key read from `env`, sent in a header or the query under `name`.",
299
+ "type": "object",
300
+ "properties": {
301
+ "env": {
302
+ "type": "string",
303
+ "pattern": "^[A-Z_][A-Z0-9_]*$"
304
+ },
305
+ "in": {
306
+ "type": "string",
307
+ "enum": [
308
+ "header",
309
+ "query"
310
+ ]
311
+ },
312
+ "name": {
313
+ "type": "string",
314
+ "minLength": 1
315
+ }
316
+ },
317
+ "required": [
318
+ "env",
319
+ "in",
320
+ "name"
321
+ ],
322
+ "additionalProperties": false
323
+ }
324
+ },
325
+ "additionalProperties": false
326
+ }
327
+ },
328
+ "required": [
329
+ "spec"
330
+ ],
331
+ "additionalProperties": false,
332
+ "description": "An HTTP API as tools, from its OpenAPI spec (lib/tools/openapiTools.ts)."
333
+ }
334
+ },
335
+ "code_execution": {
336
+ "description": "\"gemini\": the model writes and runs Python in Gemini's server-side sandbox; nothing runs on this host. Gemini models only.",
337
+ "type": "string",
338
+ "const": "gemini"
339
+ },
340
+ "context": {
341
+ "description": "Summarize a long conversation instead of overflowing the window. The orchestrator of a delegate syndicate only.",
342
+ "type": "object",
343
+ "properties": {
344
+ "compact_after_tokens": {
345
+ "type": "integer",
346
+ "minimum": 1000,
347
+ "maximum": 9007199254740991,
348
+ "description": "Compact when the last request's prompt passed this many tokens."
349
+ },
350
+ "keep_recent_events": {
351
+ "description": "Events kept verbatim after the summary. Default 6.",
352
+ "type": "integer",
353
+ "minimum": 1,
354
+ "maximum": 100
355
+ },
356
+ "summary_model": {
357
+ "description": "The model that writes the summary. Default: the agent's own.",
358
+ "type": "string",
359
+ "minLength": 1
360
+ }
361
+ },
362
+ "required": [
363
+ "compact_after_tokens"
364
+ ],
365
+ "additionalProperties": false
366
+ },
367
+ "examples": {
368
+ "description": "Few-shot exchanges (input, output) added to every request's instruction.",
369
+ "minItems": 1,
370
+ "maxItems": 20,
371
+ "type": "array",
372
+ "items": {
373
+ "type": "object",
374
+ "properties": {
375
+ "input": {
376
+ "type": "string",
377
+ "minLength": 1
378
+ },
379
+ "output": {
380
+ "type": "string",
381
+ "minLength": 1
382
+ }
383
+ },
384
+ "required": [
385
+ "input",
386
+ "output"
387
+ ],
388
+ "additionalProperties": false
389
+ }
390
+ },
391
+ "mode": {
392
+ "description": "\"task\": the agent works until it calls finish_task; its arguments (matching outputSchema) are the node's output. Workflow nodes only.",
393
+ "type": "string",
394
+ "const": "task"
395
+ },
396
+ "orchestration": {
397
+ "type": "object",
398
+ "properties": {
399
+ "role": {
400
+ "type": "string",
401
+ "enum": [
402
+ "primary",
403
+ "sub-agent"
404
+ ]
405
+ },
406
+ "delegates": {
407
+ "type": "array",
408
+ "items": {
409
+ "type": "string"
410
+ }
411
+ }
412
+ },
413
+ "additionalProperties": false
414
+ }
415
+ },
416
+ "required": [
417
+ "name",
418
+ "model",
419
+ "instruction"
420
+ ],
421
+ "additionalProperties": false,
422
+ "description": "The root agent, which the engine's agent loop runs (keys spelled after ADK's LlmAgentConfig)."
423
+ },
424
+ "subagents": {
425
+ "description": "The orchestrator's team. Omit it (or write `subagents: []`) for a single-agent syndicate.",
426
+ "type": "array",
427
+ "items": {
428
+ "type": "object",
429
+ "properties": {
430
+ "name": {
431
+ "type": "string",
432
+ "pattern": "^[A-Za-z_$][A-Za-z0-9_$-]*$",
433
+ "description": "Unique agent name within the tree. A valid identifier; cannot be \"user\"."
434
+ },
435
+ "description": {
436
+ "type": "string",
437
+ "minLength": 1,
438
+ "description": "Required: the orchestrator reads it to decide when to call this subagent."
439
+ },
440
+ "model": {
441
+ "description": "Model id. Inherits the orchestrator's when omitted.",
442
+ "type": "string",
443
+ "minLength": 1
444
+ },
445
+ "fallback_model": {
446
+ "description": "A model on another provider that answers when this agent's model fails provider-side (5xx, 429, network) before producing anything, or while that provider's circuit is open (ADR 0044).",
447
+ "type": "string",
448
+ "minLength": 1
449
+ },
450
+ "instruction": {
451
+ "type": "string",
452
+ "minLength": 1,
453
+ "description": "System prompt / persona."
454
+ },
455
+ "globalInstruction": {
456
+ "description": "Instruction applied to every agent in the tree; only the root agent's value takes effect.",
457
+ "type": "string"
458
+ },
459
+ "tools": {
460
+ "description": "Named tools from lib/toolRegistry.ts (e.g. web_search, web_extract, wiki_search).",
461
+ "type": "array",
462
+ "items": {
463
+ "type": "string",
464
+ "minLength": 1
465
+ }
466
+ },
467
+ "require_approval": {
468
+ "description": "Tools from this agent's `tools` that run only after a person approves the exact call (ADR 0028): the A2A task ends input-required until the caller answers approve or reject. Allowed on the orchestrator and on plan-dispatch routes.",
469
+ "type": "array",
470
+ "items": {
471
+ "type": "string",
472
+ "minLength": 1
473
+ }
474
+ },
475
+ "includeContents": {
476
+ "description": "\"default\" = include conversation history, \"none\" = stateless.",
477
+ "type": "string",
478
+ "enum": [
479
+ "default",
480
+ "none"
481
+ ]
482
+ },
483
+ "disallowTransferToParent": {
484
+ "type": "boolean"
485
+ },
486
+ "disallowTransferToPeers": {
487
+ "type": "boolean"
488
+ },
489
+ "outputKey": {
490
+ "description": "Session-state key the final reply is saved under.",
491
+ "type": "string"
492
+ },
493
+ "generateContentConfig": {
494
+ "type": "object",
495
+ "properties": {
496
+ "temperature": {
497
+ "type": "number"
498
+ },
499
+ "topP": {
500
+ "type": "number"
501
+ },
502
+ "topK": {
503
+ "type": "number"
504
+ },
505
+ "maxOutputTokens": {
506
+ "type": "integer",
507
+ "exclusiveMinimum": 0,
508
+ "maximum": 9007199254740991
509
+ },
510
+ "stopSequences": {
511
+ "type": "array",
512
+ "items": {
513
+ "type": "string"
514
+ }
515
+ },
516
+ "candidateCount": {
517
+ "type": "integer",
518
+ "exclusiveMinimum": 0,
519
+ "maximum": 9007199254740991
520
+ },
521
+ "presencePenalty": {
522
+ "type": "number"
523
+ },
524
+ "frequencyPenalty": {
525
+ "type": "number"
526
+ },
527
+ "seed": {
528
+ "type": "integer",
529
+ "minimum": -9007199254740991,
530
+ "maximum": 9007199254740991
531
+ },
532
+ "responseMimeType": {
533
+ "type": "string"
534
+ },
535
+ "safetySettings": {
536
+ "type": "array",
537
+ "items": {
538
+ "type": "object",
539
+ "properties": {
540
+ "category": {
541
+ "type": "string"
542
+ },
543
+ "threshold": {
544
+ "type": "string"
545
+ }
546
+ },
547
+ "required": [
548
+ "category",
549
+ "threshold"
550
+ ],
551
+ "additionalProperties": {}
552
+ }
553
+ },
554
+ "thinkingConfig": {
555
+ "type": "object",
556
+ "properties": {
557
+ "thinkingBudget": {
558
+ "description": "Reasoning token budget. 0 = off, -1 = dynamic.",
559
+ "type": "integer",
560
+ "minimum": -9007199254740991,
561
+ "maximum": 9007199254740991
562
+ },
563
+ "includeThoughts": {
564
+ "description": "Stream the thinking trace in the response.",
565
+ "type": "boolean"
566
+ }
567
+ },
568
+ "additionalProperties": {},
569
+ "description": "Older spelling of `reasoning` for Gemini and Claude (thinkingLevel or thinkingBudget). Cannot be combined with `reasoning`."
570
+ },
571
+ "reasoningEffort": {
572
+ "description": "Older spelling of `reasoning` for the chat-completions and Responses providers. Cannot be combined with `reasoning`.",
573
+ "type": "string"
574
+ }
575
+ },
576
+ "additionalProperties": {},
577
+ "description": "Model generation config (@google/genai GenerateContentConfig). Do not set tools here."
578
+ },
579
+ "reasoning": {
580
+ "anyOf": [
581
+ {
582
+ "type": "string",
583
+ "enum": [
584
+ "none",
585
+ "low",
586
+ "medium",
587
+ "high"
588
+ ]
589
+ },
590
+ {
591
+ "type": "object",
592
+ "properties": {
593
+ "budget_tokens": {
594
+ "type": "integer",
595
+ "minimum": 0,
596
+ "maximum": 9007199254740991,
597
+ "description": "Thinking tokens; 0 = none. Effort-only providers take the nearest level at or above it."
598
+ }
599
+ },
600
+ "required": [
601
+ "budget_tokens"
602
+ ],
603
+ "additionalProperties": false
604
+ }
605
+ ],
606
+ "description": "How hard this agent reasons, on any provider: none | low | medium | high, or { budget_tokens: <int> }. Replaces generateContentConfig.thinkingConfig and reasoningEffort (ADR 0047)."
607
+ },
608
+ "outputSchema": {
609
+ "description": "JSON Schema for structured output: the agent answers with one JSON object matching it. Hold it on a leaf; an agent that delegates and holds one ends its turn on that JSON.",
610
+ "type": "object",
611
+ "propertyNames": {
612
+ "type": "string"
613
+ },
614
+ "additionalProperties": {}
615
+ },
616
+ "mcp_server_url": {
617
+ "description": "MCP server (SSE) whose tools are discovered at runtime and merged with `tools`.",
618
+ "type": "string"
619
+ },
620
+ "mcp_tools": {
621
+ "description": "The MCP server's tools this agent may use, by name; any other tool the server lists is not exposed. Without it, every listed tool is. require_approval may name these. Needs mcp_server_url.",
622
+ "minItems": 1,
623
+ "type": "array",
624
+ "items": {
625
+ "type": "string",
626
+ "minLength": 1
627
+ }
628
+ },
629
+ "skills": {
630
+ "type": "object",
631
+ "properties": {
632
+ "dir": {
633
+ "type": "string",
634
+ "minLength": 1,
635
+ "description": "A directory of skills: one subdirectory per skill, named as its SKILL.md frontmatter names it. Relative to the working directory."
636
+ },
637
+ "scripts": {
638
+ "description": "Whether a skill's scripts/ may run. \"local\" runs them on this machine, each after a person approves (ADR 0028); default \"none\".",
639
+ "type": "string",
640
+ "enum": [
641
+ "none",
642
+ "local"
643
+ ]
644
+ },
645
+ "tools": {
646
+ "description": "Registry tool names a skill may unlock through its `allowed-tools` frontmatter once it is loaded. Omitted, no skill unlocks anything.",
647
+ "type": "array",
648
+ "items": {
649
+ "type": "string",
650
+ "minLength": 1
651
+ }
652
+ },
653
+ "env": {
654
+ "description": "Environment variable NAMES (never values) a skill script gets, beyond PATH, HOME, the temp directory, the locale and the OS essentials (ADR 0086). A name that looks like a secret (KEY, TOKEN, SECRET, PASSWORD, AUTH, DATABASE, …) belongs under secret_env.",
655
+ "type": "array",
656
+ "items": {
657
+ "type": "string",
658
+ "pattern": "^[A-Z_][A-Z0-9_]*$"
659
+ }
660
+ },
661
+ "secret_env": {
662
+ "description": "Secret-shaped environment variable names a skill script gets, listed here so passing a credential to a script is a deliberate, reviewable act (ADR 0086).",
663
+ "type": "array",
664
+ "items": {
665
+ "type": "string",
666
+ "pattern": "^[A-Z_][A-Z0-9_]*$"
667
+ }
668
+ }
669
+ },
670
+ "required": [
671
+ "dir"
672
+ ],
673
+ "additionalProperties": false,
674
+ "description": "Agent Skills (SKILL.md directories) this agent reads the way a coding harness does."
675
+ },
676
+ "openapi": {
677
+ "minItems": 1,
678
+ "type": "array",
679
+ "items": {
680
+ "type": "object",
681
+ "properties": {
682
+ "spec": {
683
+ "type": "string",
684
+ "minLength": 1,
685
+ "description": "An OpenAPI 3 spec file (.yaml, .yml, .json), relative to this syndicate file. Files only, never URLs."
686
+ },
687
+ "operations": {
688
+ "description": "Operations to expose, by operationId or tool name. Omitted: every GET operation, and nothing that writes.",
689
+ "minItems": 1,
690
+ "type": "array",
691
+ "items": {
692
+ "type": "string",
693
+ "minLength": 1
694
+ }
695
+ },
696
+ "base_url": {
697
+ "description": "Overrides the spec's servers[0].url. Checked by the SSRF guard.",
698
+ "type": "string",
699
+ "format": "uri"
700
+ },
701
+ "prefix": {
702
+ "description": "Prepended to each tool name, to keep two APIs apart.",
703
+ "type": "string",
704
+ "pattern": "^[a-z][a-z0-9_]*$"
705
+ },
706
+ "auth": {
707
+ "description": "Credentials, always from the environment, never written in YAML.",
708
+ "type": "object",
709
+ "properties": {
710
+ "bearer_env": {
711
+ "description": "Environment variable holding a bearer token.",
712
+ "type": "string",
713
+ "pattern": "^[A-Z_][A-Z0-9_]*$"
714
+ },
715
+ "api_key": {
716
+ "description": "An API key read from `env`, sent in a header or the query under `name`.",
717
+ "type": "object",
718
+ "properties": {
719
+ "env": {
720
+ "type": "string",
721
+ "pattern": "^[A-Z_][A-Z0-9_]*$"
722
+ },
723
+ "in": {
724
+ "type": "string",
725
+ "enum": [
726
+ "header",
727
+ "query"
728
+ ]
729
+ },
730
+ "name": {
731
+ "type": "string",
732
+ "minLength": 1
733
+ }
734
+ },
735
+ "required": [
736
+ "env",
737
+ "in",
738
+ "name"
739
+ ],
740
+ "additionalProperties": false
741
+ }
742
+ },
743
+ "additionalProperties": false
744
+ }
745
+ },
746
+ "required": [
747
+ "spec"
748
+ ],
749
+ "additionalProperties": false,
750
+ "description": "An HTTP API as tools, from its OpenAPI spec (lib/tools/openapiTools.ts)."
751
+ }
752
+ },
753
+ "code_execution": {
754
+ "description": "\"gemini\": the model writes and runs Python in Gemini's server-side sandbox; nothing runs on this host. Gemini models only.",
755
+ "type": "string",
756
+ "const": "gemini"
757
+ },
758
+ "context": {
759
+ "description": "Summarize a long conversation instead of overflowing the window. The orchestrator of a delegate syndicate only.",
760
+ "type": "object",
761
+ "properties": {
762
+ "compact_after_tokens": {
763
+ "type": "integer",
764
+ "minimum": 1000,
765
+ "maximum": 9007199254740991,
766
+ "description": "Compact when the last request's prompt passed this many tokens."
767
+ },
768
+ "keep_recent_events": {
769
+ "description": "Events kept verbatim after the summary. Default 6.",
770
+ "type": "integer",
771
+ "minimum": 1,
772
+ "maximum": 100
773
+ },
774
+ "summary_model": {
775
+ "description": "The model that writes the summary. Default: the agent's own.",
776
+ "type": "string",
777
+ "minLength": 1
778
+ }
779
+ },
780
+ "required": [
781
+ "compact_after_tokens"
782
+ ],
783
+ "additionalProperties": false
784
+ },
785
+ "examples": {
786
+ "description": "Few-shot exchanges (input, output) added to every request's instruction.",
787
+ "minItems": 1,
788
+ "maxItems": 20,
789
+ "type": "array",
790
+ "items": {
791
+ "type": "object",
792
+ "properties": {
793
+ "input": {
794
+ "type": "string",
795
+ "minLength": 1
796
+ },
797
+ "output": {
798
+ "type": "string",
799
+ "minLength": 1
800
+ }
801
+ },
802
+ "required": [
803
+ "input",
804
+ "output"
805
+ ],
806
+ "additionalProperties": false
807
+ }
808
+ },
809
+ "mode": {
810
+ "description": "\"task\": the agent works until it calls finish_task; its arguments (matching outputSchema) are the node's output. Workflow nodes only.",
811
+ "type": "string",
812
+ "const": "task"
813
+ },
814
+ "orchestration": {
815
+ "type": "object",
816
+ "properties": {
817
+ "role": {
818
+ "type": "string",
819
+ "enum": [
820
+ "primary",
821
+ "sub-agent"
822
+ ]
823
+ },
824
+ "delegates": {
825
+ "type": "array",
826
+ "items": {
827
+ "type": "string"
828
+ }
829
+ }
830
+ },
831
+ "additionalProperties": false
832
+ },
833
+ "yaml_reference": {
834
+ "description": "A whole nested syndicate (filename under the agents dir) used as this subagent.",
835
+ "type": "string",
836
+ "minLength": 1
837
+ },
838
+ "a2a_agent_url": {
839
+ "description": "A remote agent over A2A: the server base URL or its agent-card URL. Needs no model or instruction; credentials come from A2A_AGENT_TOKENS, never YAML.",
840
+ "type": "string",
841
+ "minLength": 1
842
+ }
843
+ },
844
+ "required": [
845
+ "name",
846
+ "description"
847
+ ],
848
+ "additionalProperties": false,
849
+ "description": "A subagent: an inline agent, a nested syndicate (yaml_reference), or a remote A2A agent (a2a_agent_url).",
850
+ "anyOf": [
851
+ {
852
+ "required": [
853
+ "instruction"
854
+ ]
855
+ },
856
+ {
857
+ "required": [
858
+ "yaml_reference"
859
+ ]
860
+ },
861
+ {
862
+ "required": [
863
+ "a2a_agent_url"
864
+ ]
865
+ }
866
+ ],
867
+ "not": {
868
+ "required": [
869
+ "yaml_reference",
870
+ "a2a_agent_url"
871
+ ]
872
+ }
873
+ }
874
+ },
875
+ "dispatch": {
876
+ "type": "object",
877
+ "properties": {
878
+ "default_route": {
879
+ "type": "string",
880
+ "minLength": 1,
881
+ "description": "Subagent used whenever routing yields no usable answer. Must name a declared subagent."
882
+ },
883
+ "route_key": {
884
+ "description": "JSON property holding the chosen route. Default \"route\".",
885
+ "type": "string"
886
+ },
887
+ "reason_key": {
888
+ "description": "JSON property holding the justification. Default \"reason\".",
889
+ "type": "string"
890
+ },
891
+ "route_overrides": {
892
+ "type": "array",
893
+ "items": {
894
+ "type": "object",
895
+ "properties": {
896
+ "route": {
897
+ "type": "string",
898
+ "minLength": 1,
899
+ "description": "Subagent to run on a match."
900
+ },
901
+ "pattern": {
902
+ "type": "string",
903
+ "minLength": 1,
904
+ "description": "JS regular expression source tested against the raw message."
905
+ },
906
+ "flags": {
907
+ "description": "Regex flags. Default \"i\".",
908
+ "type": "string"
909
+ },
910
+ "reason": {
911
+ "description": "Shown to the waiting user as the [STATUS] route note.",
912
+ "type": "string"
913
+ }
914
+ },
915
+ "required": [
916
+ "route",
917
+ "pattern"
918
+ ],
919
+ "additionalProperties": false
920
+ }
921
+ }
922
+ },
923
+ "required": [
924
+ "default_route"
925
+ ],
926
+ "additionalProperties": false,
927
+ "description": "Opts into PLAN-DISPATCH orchestration (lib/dispatch.ts)."
928
+ },
929
+ "workflow": {
930
+ "type": "object",
931
+ "properties": {
932
+ "edges": {
933
+ "minItems": 1,
934
+ "type": "array",
935
+ "items": {
936
+ "minItems": 2,
937
+ "type": "array",
938
+ "items": {
939
+ "anyOf": [
940
+ {
941
+ "type": "string",
942
+ "minLength": 1
943
+ },
944
+ {
945
+ "minItems": 1,
946
+ "type": "array",
947
+ "items": {
948
+ "type": "string",
949
+ "minLength": 1
950
+ },
951
+ "description": "Several nodes: fan-out when they follow one node, fan-in when one node follows them."
952
+ },
953
+ {
954
+ "type": "object",
955
+ "propertyNames": {
956
+ "type": "string",
957
+ "minLength": 1
958
+ },
959
+ "additionalProperties": {
960
+ "anyOf": [
961
+ {
962
+ "type": "string",
963
+ "minLength": 1
964
+ },
965
+ {
966
+ "minItems": 1,
967
+ "type": "array",
968
+ "items": {
969
+ "type": "string",
970
+ "minLength": 1
971
+ }
972
+ }
973
+ ]
974
+ },
975
+ "description": "A routing map after a node: `{ <route>: <node or nodes>, default: <node> }`, matched against that node's output."
976
+ }
977
+ ]
978
+ }
979
+ },
980
+ "description": "Chains of nodes, each a list; `START` begins at least one. A routing map follows the node whose output it routes."
981
+ },
982
+ "nodes": {
983
+ "type": "object",
984
+ "propertyNames": {
985
+ "type": "string",
986
+ "minLength": 1
987
+ },
988
+ "additionalProperties": {
989
+ "type": "object",
990
+ "properties": {
991
+ "ask_user": {
992
+ "description": "Pause and ask the person this; the reply becomes the node's output.",
993
+ "type": "string",
994
+ "minLength": 1
995
+ },
996
+ "schema": {
997
+ "description": "JSON Schema a structured reply to ask_user must satisfy; plain text passes as is.",
998
+ "type": "object",
999
+ "propertyNames": {
1000
+ "type": "string"
1001
+ },
1002
+ "additionalProperties": {}
1003
+ },
1004
+ "join": {
1005
+ "description": "Wait for every predecessor; output `{ <predecessor>: <output> }`.",
1006
+ "type": "boolean",
1007
+ "const": true
1008
+ },
1009
+ "map": {
1010
+ "description": "Run this agent once per item of a list input, concurrently; output the list of results.",
1011
+ "type": "string",
1012
+ "minLength": 1
1013
+ },
1014
+ "max_parallel": {
1015
+ "description": "Concurrency of map. Default 8.",
1016
+ "type": "integer",
1017
+ "exclusiveMinimum": 0,
1018
+ "maximum": 9007199254740991
1019
+ },
1020
+ "tool": {
1021
+ "description": "Run this registry tool with the node input as its arguments.",
1022
+ "type": "string",
1023
+ "minLength": 1
1024
+ },
1025
+ "route_key": {
1026
+ "description": "Property of a JSON output holding the route. Default \"route\".",
1027
+ "type": "string",
1028
+ "minLength": 1
1029
+ },
1030
+ "retry": {
1031
+ "description": "Retry this node on failure. Not on a map node: each item runs under its agent's own retry.",
1032
+ "type": "object",
1033
+ "properties": {
1034
+ "max_attempts": {
1035
+ "description": "Attempts including the first; 1 = no retry. Default 5.",
1036
+ "type": "integer",
1037
+ "exclusiveMinimum": 0,
1038
+ "maximum": 9007199254740991
1039
+ },
1040
+ "initial_delay": {
1041
+ "description": "Seconds before the first retry.",
1042
+ "type": "number",
1043
+ "minimum": 0
1044
+ },
1045
+ "max_delay": {
1046
+ "type": "number",
1047
+ "minimum": 0
1048
+ },
1049
+ "backoff_factor": {
1050
+ "type": "number",
1051
+ "exclusiveMinimum": 0
1052
+ },
1053
+ "jitter": {
1054
+ "description": "Randomness of the backoff; 0 = none. Default 1.",
1055
+ "type": "number",
1056
+ "minimum": 0
1057
+ },
1058
+ "exceptions": {
1059
+ "description": "Error names to retry on (the error's class or its `name`); every error when absent.",
1060
+ "minItems": 1,
1061
+ "type": "array",
1062
+ "items": {
1063
+ "type": "string",
1064
+ "pattern": "^[A-Za-z_$][\\w$]*$"
1065
+ }
1066
+ }
1067
+ },
1068
+ "additionalProperties": false
1069
+ },
1070
+ "timeout": {
1071
+ "description": "Seconds this node may run before it fails. Not on a map node: each item runs under its agent's own timeout.",
1072
+ "type": "number",
1073
+ "exclusiveMinimum": 0
1074
+ }
1075
+ },
1076
+ "additionalProperties": false,
1077
+ "description": "A declared node (exactly one of ask_user, join, map, tool) or modifiers for an agent node (retry, timeout, route_key)."
1078
+ }
1079
+ },
1080
+ "max_concurrency": {
1081
+ "description": "Nodes that may run at once. Default: unbounded.",
1082
+ "type": "integer",
1083
+ "exclusiveMinimum": 0,
1084
+ "maximum": 9007199254740991
1085
+ }
1086
+ },
1087
+ "required": [
1088
+ "edges"
1089
+ ],
1090
+ "additionalProperties": false,
1091
+ "description": "Opts into a WORKFLOW: the syndicate as a graph (lib/workflow.ts). Cannot be combined with dispatch."
1092
+ },
1093
+ "retries": {
1094
+ "description": "Self-correction on model and tool errors: the engine's reflect-and-retry. On by default.",
1095
+ "type": "object",
1096
+ "properties": {
1097
+ "model_errors": {
1098
+ "description": "Retries of a malformed model reply. Default 2; 0 off.",
1099
+ "type": "integer",
1100
+ "minimum": 0,
1101
+ "maximum": 5
1102
+ },
1103
+ "tool_errors": {
1104
+ "description": "Retries of a tool that threw, with reflection guidance. Default 3; 0 off.",
1105
+ "type": "integer",
1106
+ "minimum": 0,
1107
+ "maximum": 5
1108
+ }
1109
+ },
1110
+ "additionalProperties": false
1111
+ },
1112
+ "variables": {
1113
+ "description": "Defaults for {{token}} interpolation. {{current_date}} is built in.",
1114
+ "type": "object",
1115
+ "propertyNames": {
1116
+ "type": "string"
1117
+ },
1118
+ "additionalProperties": {
1119
+ "type": [
1120
+ "string",
1121
+ "number",
1122
+ "boolean"
1123
+ ]
1124
+ }
1125
+ },
1126
+ "memory_system": {
1127
+ "description": "Persistence and semantic-memory layer.",
1128
+ "type": "string",
1129
+ "enum": [
1130
+ "internal-only",
1131
+ "session-only",
1132
+ "long-term"
1133
+ ]
1134
+ },
1135
+ "guards": {
1136
+ "description": "Post-answer guards by name (lib/guards/index.ts).",
1137
+ "type": "array",
1138
+ "items": {
1139
+ "type": "string",
1140
+ "minLength": 1
1141
+ }
1142
+ },
1143
+ "memory_namespace": {
1144
+ "description": "Where long-term memory is stored: the syndicate name plus a generated id, written once and never recomputed (ADR 0020). Syndicates that declare the same namespace share memory.",
1145
+ "type": "string",
1146
+ "pattern": "^[A-Za-z0-9._-]{1,96}$"
1147
+ },
1148
+ "memory_extraction_rules": {
1149
+ "description": "Domain rules appended to the fact-extraction prompt (long-term memory only).",
1150
+ "type": "string"
1151
+ },
1152
+ "memory_extraction_model": {
1153
+ "description": "The model that distils this syndicate's turns into memory records; default MEMORY_EXTRACTION_MODEL (ADR 0020).",
1154
+ "type": "string",
1155
+ "minLength": 1
1156
+ },
1157
+ "memory_retention_days": {
1158
+ "description": "Days a memory fact is kept in this syndicate's namespace; older facts are deleted daily. Needs memory_namespace (ADR 0020).",
1159
+ "type": "integer",
1160
+ "exclusiveMinimum": 0,
1161
+ "maximum": 9007199254740991
1162
+ },
1163
+ "max_steps": {
1164
+ "description": "Hard cap on model calls per turn, subagents included. Default 50 (DEFAULT_MAX_STEPS) when unset.",
1165
+ "type": "integer",
1166
+ "exclusiveMinimum": 0,
1167
+ "maximum": 9007199254740991
1168
+ },
1169
+ "bundled_references": {
1170
+ "description": "Written by the registry publisher, not by hand: every nested yaml_reference this syndicate reaches, as it was when published, so a registry version is one unit (ADR 0018). Nested references load from here instead of from files.",
1171
+ "type": "object",
1172
+ "propertyNames": {
1173
+ "type": "string"
1174
+ },
1175
+ "additionalProperties": {
1176
+ "type": "object",
1177
+ "propertyNames": {
1178
+ "type": "string"
1179
+ },
1180
+ "additionalProperties": {}
1181
+ }
1182
+ }
1183
+ },
1184
+ "required": [
1185
+ "syndicate_name",
1186
+ "orchestrator"
1187
+ ],
1188
+ "additionalProperties": false,
1189
+ "description": "A Melchizedek syndicate definition (lib/loadSyndicate.ts).",
1190
+ "title": "Melchizedek syndicate"
1191
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "melchizedek-agents",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "A multi-model, multi-agent orchestration framework — YAML-defined syndicates on the engine's own agent loop, Supabase or Postgres session persistence, pgvector long-term memory. Companion repo to the lyceumagents.com curriculum.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -60,6 +60,7 @@
60
60
  "dist",
61
61
  "config/agents/README.md",
62
62
  "config/agents/syndicateSchema.yaml",
63
+ "config/agents/syndicate.schema.json",
63
64
  "config/agents/examples",
64
65
  "config/agents/templates",
65
66
  "db",
@@ -132,9 +133,9 @@
132
133
  },
133
134
  "dependencies": {
134
135
  "@a2a-js/sdk": "^1.3.0",
135
- "@anthropic-ai/sdk": "^0.129.0",
136
- "@google/genai": "2.25.0",
137
- "@modelcontextprotocol/sdk": "^1.29.0",
136
+ "@anthropic-ai/sdk": "^0.131.0",
137
+ "@google/genai": "2.27.0",
138
+ "@modelcontextprotocol/sdk": "^1.32.1",
138
139
  "@opentelemetry/api": "^1.9.1",
139
140
  "@opentelemetry/core": "^2.8.0",
140
141
  "@opentelemetry/exporter-trace-otlp-http": "^0.222.0",
@@ -146,14 +147,14 @@
146
147
  "express": "^5.2.1",
147
148
  "express-rate-limit": "^8.5.2",
148
149
  "pg": "^8.23.1",
149
- "openai": "^7.23.0",
150
+ "openai": "^7.28.0",
150
151
  "yaml": "^2.9.0",
151
152
  "zod": "4.6.5"
152
153
  },
153
154
  "devDependencies": {
154
155
  "@types/pg": "^8.23.1",
155
156
  "@types/express": "^5.0.6",
156
- "@types/node": "^22",
157
+ "@types/node": "^25",
157
158
  "typescript": "^7.0.2"
158
159
  },
159
160
  "overrides": {