agentopology 0.1.1 → 0.2.1
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/README.md +8 -6
- package/dist/analyzer/index.d.ts +1 -0
- package/dist/analyzer/index.d.ts.map +1 -1
- package/dist/analyzer/index.js +35 -0
- package/dist/analyzer/index.js.map +1 -1
- package/dist/bindings/__tests__/bindings.test.js +11 -11
- package/dist/bindings/__tests__/bindings.test.js.map +1 -1
- package/dist/bindings/claude-code.d.ts.map +1 -1
- package/dist/bindings/claude-code.js +339 -85
- package/dist/bindings/claude-code.js.map +1 -1
- package/dist/bindings/openclaw.d.ts.map +1 -1
- package/dist/bindings/openclaw.js +367 -5
- package/dist/bindings/openclaw.js.map +1 -1
- package/dist/cli/index.js +2 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/docs/__tests__/docs.test.js +2 -1
- package/dist/docs/__tests__/docs.test.js.map +1 -1
- package/dist/docs/content.d.ts.map +1 -1
- package/dist/docs/content.js +730 -4
- package/dist/docs/content.js.map +1 -1
- package/dist/exporters/markdown.d.ts.map +1 -1
- package/dist/exporters/markdown.js +165 -0
- package/dist/exporters/markdown.js.map +1 -1
- package/dist/exporters/mermaid.d.ts.map +1 -1
- package/dist/exporters/mermaid.js +30 -0
- package/dist/exporters/mermaid.js.map +1 -1
- package/dist/import/__tests__/import.test.js +556 -2
- package/dist/import/__tests__/import.test.js.map +1 -1
- package/dist/import/claude-code.d.ts.map +1 -1
- package/dist/import/claude-code.js +2 -0
- package/dist/import/claude-code.js.map +1 -1
- package/dist/import/index.d.ts +1 -0
- package/dist/import/index.d.ts.map +1 -1
- package/dist/import/index.js +7 -1
- package/dist/import/index.js.map +1 -1
- package/dist/import/openclaw.d.ts +70 -0
- package/dist/import/openclaw.d.ts.map +1 -0
- package/dist/import/openclaw.js +1060 -0
- package/dist/import/openclaw.js.map +1 -0
- package/dist/import/serializer.d.ts.map +1 -1
- package/dist/import/serializer.js +171 -4
- package/dist/import/serializer.js.map +1 -1
- package/dist/parser/__tests__/parser.test.js +463 -0
- package/dist/parser/__tests__/parser.test.js.map +1 -1
- package/dist/parser/ast.d.ts +122 -0
- package/dist/parser/ast.d.ts.map +1 -1
- package/dist/parser/index.d.ts +14 -2
- package/dist/parser/index.d.ts.map +1 -1
- package/dist/parser/index.js +226 -5
- package/dist/parser/index.js.map +1 -1
- package/dist/parser/validator.d.ts +1 -1
- package/dist/parser/validator.d.ts.map +1 -1
- package/dist/parser/validator.js +214 -1
- package/dist/parser/validator.js.map +1 -1
- package/dist/visualizer/index.d.ts.map +1 -1
- package/dist/visualizer/index.js +104 -16
- package/dist/visualizer/index.js.map +1 -1
- package/examples/memory-system.at +162 -0
- package/examples/script-agent-pipeline.at +65 -0
- package/package.json +2 -1
- package/skill/SKILL.md +7 -7
- package/spec/grammar.md +345 -10
- package/spec/reserved-keywords.md +25 -1
- package/spec/validation.md +171 -2
|
@@ -222,7 +222,7 @@ function generateOpenClawJson(ast) {
|
|
|
222
222
|
name: toTitle(ast.topology.name) + " Coordinator",
|
|
223
223
|
model: orchModel,
|
|
224
224
|
workspace: `~/.openclaw/workspace-${ast.topology.name}`,
|
|
225
|
-
agentDir:
|
|
225
|
+
agentDir: `~/.openclaw/config/agents/orchestrator/agent`,
|
|
226
226
|
subagents: {
|
|
227
227
|
allowAgents: agentIds,
|
|
228
228
|
},
|
|
@@ -242,7 +242,7 @@ function generateOpenClawJson(ast) {
|
|
|
242
242
|
name: toTitle(agent.id),
|
|
243
243
|
model: agentModel,
|
|
244
244
|
workspace: `~/.openclaw/workspace-${agent.id}`,
|
|
245
|
-
agentDir:
|
|
245
|
+
agentDir: `~/.openclaw/config/agents/${agent.id}/agent`,
|
|
246
246
|
};
|
|
247
247
|
// No per-agent tools in openclaw.json — tool restrictions go in AGENTS.md
|
|
248
248
|
// Sampling params
|
|
@@ -252,6 +252,30 @@ function generateOpenClawJson(ast) {
|
|
|
252
252
|
entry.maxTokens = agent.maxTokens;
|
|
253
253
|
// Note: OpenClaw does NOT support per-agent "timeout" in openclaw.json.
|
|
254
254
|
// Timeouts are documented in AGENTS.md instead.
|
|
255
|
+
// subagents.allowAgents — OpenClaw requires explicit delegation lists
|
|
256
|
+
// for agents to use sessions_spawn. We detect supervisors using:
|
|
257
|
+
// 1. The topology's interface entry point (if defined)
|
|
258
|
+
// 2. The first agent by phase order
|
|
259
|
+
// 3. Any agent that is the target of error edges (error handlers coordinate)
|
|
260
|
+
// Supervisors get allowAgents for ALL other agents in the topology,
|
|
261
|
+
// because OpenClaw delegation is about permission, not flow direction.
|
|
262
|
+
const isSupervisor =
|
|
263
|
+
// Interface entry point
|
|
264
|
+
(ast.interfaceEndpoints?.entry === agent.id) ||
|
|
265
|
+
// First agent by phase (lowest phase = coordinator)
|
|
266
|
+
(agents.length > 0 && agents[0].id === agent.id) ||
|
|
267
|
+
// Error handler target (receives error edges from other agents)
|
|
268
|
+
ast.edges.some((e) => e.isError && e.to === agent.id) ||
|
|
269
|
+
// Topology declares "supervisor" pattern and this is the first agent
|
|
270
|
+
(ast.topology.patterns.includes("supervisor") && agents[0]?.id === agent.id);
|
|
271
|
+
if (isSupervisor) {
|
|
272
|
+
const otherAgentIds = agents
|
|
273
|
+
.filter((a) => a.id !== agent.id)
|
|
274
|
+
.map((a) => a.id);
|
|
275
|
+
if (otherAgentIds.length > 0) {
|
|
276
|
+
entry.subagents = { allowAgents: otherAgentIds };
|
|
277
|
+
}
|
|
278
|
+
}
|
|
255
279
|
// Merge agent-level openclaw extensions
|
|
256
280
|
if (agent.extensions?.openclaw) {
|
|
257
281
|
for (const [k, v] of Object.entries(agent.extensions.openclaw)) {
|
|
@@ -720,6 +744,56 @@ function generateAgentsMd(ast) {
|
|
|
720
744
|
if (agent.writes && agent.writes.length > 0) {
|
|
721
745
|
sections.push(`- **Writes:** ${agent.writes.join(", ")}`);
|
|
722
746
|
}
|
|
747
|
+
// Memory stores — rich details per store
|
|
748
|
+
if (agent.memory && agent.memory.length > 0) {
|
|
749
|
+
const storeMap = new Map((ast.stores ?? []).map(s => [s.id, s]));
|
|
750
|
+
sections.push("- **Memory stores:**");
|
|
751
|
+
for (const storeId of agent.memory) {
|
|
752
|
+
const store = storeMap.get(storeId);
|
|
753
|
+
if (!store) {
|
|
754
|
+
sections.push(` - ${storeId}`);
|
|
755
|
+
continue;
|
|
756
|
+
}
|
|
757
|
+
const parts = [`**${storeId}**`, `type: ${store.type}`, `backend: ${store.backend}`];
|
|
758
|
+
if (store.path)
|
|
759
|
+
parts.push(`path: \`${store.path}\``);
|
|
760
|
+
if (store.scope)
|
|
761
|
+
parts.push(`scope: ${store.scope}`);
|
|
762
|
+
if (store.embedding?.model)
|
|
763
|
+
parts.push(`embedding: ${store.embedding.model} (${store.embedding.dimensions}d)`);
|
|
764
|
+
if (store.search?.strategy)
|
|
765
|
+
parts.push(`search: ${store.search.strategy}`);
|
|
766
|
+
sections.push(` - ${parts.join(" — ")}`);
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
// Retrieval strategy — rich details
|
|
770
|
+
if (agent.retrieval) {
|
|
771
|
+
const retrieval = (ast.retrievals ?? []).find(r => r.id === agent.retrieval);
|
|
772
|
+
if (retrieval) {
|
|
773
|
+
const parts = [`**${retrieval.id}**`];
|
|
774
|
+
if (retrieval.sources)
|
|
775
|
+
parts.push(`sources: ${retrieval.sources.join(", ")}`);
|
|
776
|
+
if (retrieval.budget)
|
|
777
|
+
parts.push(`budget: ${retrieval.budget} tokens`);
|
|
778
|
+
if (retrieval.rerank)
|
|
779
|
+
parts.push(`reranked`);
|
|
780
|
+
if (retrieval.scoring) {
|
|
781
|
+
const weights = [];
|
|
782
|
+
if (retrieval.scoring.semanticWeight != null)
|
|
783
|
+
weights.push(`semantic: ${retrieval.scoring.semanticWeight}`);
|
|
784
|
+
if (retrieval.scoring.recencyWeight != null)
|
|
785
|
+
weights.push(`recency: ${retrieval.scoring.recencyWeight}`);
|
|
786
|
+
if (retrieval.scoring.importanceWeight != null)
|
|
787
|
+
weights.push(`importance: ${retrieval.scoring.importanceWeight}`);
|
|
788
|
+
if (weights.length)
|
|
789
|
+
parts.push(`scoring: ${weights.join(", ")}`);
|
|
790
|
+
}
|
|
791
|
+
sections.push(`- **Retrieval strategy:** ${parts.join(" — ")}`);
|
|
792
|
+
}
|
|
793
|
+
else {
|
|
794
|
+
sections.push(`- **Retrieval strategy:** ${agent.retrieval}`);
|
|
795
|
+
}
|
|
796
|
+
}
|
|
723
797
|
// Outputs
|
|
724
798
|
if (agent.outputs) {
|
|
725
799
|
sections.push("- **Outputs:**");
|
|
@@ -1217,6 +1291,127 @@ function generateMemoryMd(ast) {
|
|
|
1217
1291
|
sections.push(`Mode: ${metrics.mode}`);
|
|
1218
1292
|
sections.push("");
|
|
1219
1293
|
}
|
|
1294
|
+
// Memory Stores — full details
|
|
1295
|
+
const stores = ast.stores ?? [];
|
|
1296
|
+
if (stores.length > 0) {
|
|
1297
|
+
sections.push("## Memory Stores");
|
|
1298
|
+
sections.push("");
|
|
1299
|
+
for (const store of stores) {
|
|
1300
|
+
sections.push(`### ${store.id}`);
|
|
1301
|
+
if (store.description)
|
|
1302
|
+
sections.push(store.description);
|
|
1303
|
+
sections.push("");
|
|
1304
|
+
sections.push(`- **Type**: ${store.type}`);
|
|
1305
|
+
sections.push(`- **Backend**: ${store.backend}`);
|
|
1306
|
+
if (store.path)
|
|
1307
|
+
sections.push(`- **Path**: \`${store.path}\``);
|
|
1308
|
+
if (store.connection)
|
|
1309
|
+
sections.push(`- **Connection**: ${store.connection}`);
|
|
1310
|
+
if (store.scope)
|
|
1311
|
+
sections.push(`- **Scope**: ${store.scope}`);
|
|
1312
|
+
if (store.isolation)
|
|
1313
|
+
sections.push(`- **Isolation**: ${store.isolation}`);
|
|
1314
|
+
if (store.extraction)
|
|
1315
|
+
sections.push(`- **Extraction**: ${store.extraction}`);
|
|
1316
|
+
// Embedding
|
|
1317
|
+
if (store.embedding) {
|
|
1318
|
+
const emb = store.embedding;
|
|
1319
|
+
sections.push(`- **Embedding**: ${emb.model} (${emb.provider}, ${emb.dimensions}d)`);
|
|
1320
|
+
}
|
|
1321
|
+
// Index
|
|
1322
|
+
if (store.index) {
|
|
1323
|
+
const parts = [];
|
|
1324
|
+
if (store.index.collection)
|
|
1325
|
+
parts.push(`collection: ${store.index.collection}`);
|
|
1326
|
+
if (store.index.metric)
|
|
1327
|
+
parts.push(`metric: ${store.index.metric}`);
|
|
1328
|
+
if (parts.length)
|
|
1329
|
+
sections.push(`- **Index**: ${parts.join(", ")}`);
|
|
1330
|
+
}
|
|
1331
|
+
// Search
|
|
1332
|
+
if (store.search) {
|
|
1333
|
+
const parts = [`strategy: ${store.search.strategy}`];
|
|
1334
|
+
if (store.search.topK)
|
|
1335
|
+
parts.push(`top-k: ${store.search.topK}`);
|
|
1336
|
+
if (store.search.rerank)
|
|
1337
|
+
parts.push(`rerank: yes`);
|
|
1338
|
+
sections.push(`- **Search**: ${parts.join(", ")}`);
|
|
1339
|
+
}
|
|
1340
|
+
// Ingestion
|
|
1341
|
+
if (store.ingestion) {
|
|
1342
|
+
const parts = [];
|
|
1343
|
+
if (store.ingestion.sources)
|
|
1344
|
+
parts.push(`sources: ${store.ingestion.sources.join(", ")}`);
|
|
1345
|
+
if (store.ingestion.chunking)
|
|
1346
|
+
parts.push(`chunking: ${store.ingestion.chunking}`);
|
|
1347
|
+
if (store.ingestion.chunkSize)
|
|
1348
|
+
parts.push(`size: ${store.ingestion.chunkSize}`);
|
|
1349
|
+
if (store.ingestion.overlap)
|
|
1350
|
+
parts.push(`overlap: ${store.ingestion.overlap}`);
|
|
1351
|
+
if (parts.length)
|
|
1352
|
+
sections.push(`- **Ingestion**: ${parts.join(", ")}`);
|
|
1353
|
+
}
|
|
1354
|
+
// Lifecycle
|
|
1355
|
+
if (store.lifecycle) {
|
|
1356
|
+
const lc = store.lifecycle;
|
|
1357
|
+
if (lc.retention)
|
|
1358
|
+
sections.push(`- **Retention**: ${lc.retention}`);
|
|
1359
|
+
if (lc.decayHalfLife)
|
|
1360
|
+
sections.push(`- **Decay half-life**: ${lc.decayHalfLife}`);
|
|
1361
|
+
if (lc.consolidation != null)
|
|
1362
|
+
sections.push(`- **Consolidation threshold**: ${lc.consolidation}`);
|
|
1363
|
+
if (lc.contradiction)
|
|
1364
|
+
sections.push(`- **Contradiction handling**: ${lc.contradiction}`);
|
|
1365
|
+
if (lc.auditLog != null)
|
|
1366
|
+
sections.push(`- **Audit log**: ${lc.auditLog}`);
|
|
1367
|
+
}
|
|
1368
|
+
// Which agents use this store
|
|
1369
|
+
const storeAgents = agents.filter(a => a.memory?.includes(store.id));
|
|
1370
|
+
if (storeAgents.length > 0) {
|
|
1371
|
+
sections.push(`- **Used by**: ${storeAgents.map(a => a.id).join(", ")}`);
|
|
1372
|
+
}
|
|
1373
|
+
sections.push("");
|
|
1374
|
+
}
|
|
1375
|
+
}
|
|
1376
|
+
// Retrieval Strategies
|
|
1377
|
+
const retrievals = ast.retrievals ?? [];
|
|
1378
|
+
if (retrievals.length > 0) {
|
|
1379
|
+
sections.push("## Retrieval Strategies");
|
|
1380
|
+
sections.push("");
|
|
1381
|
+
for (const ret of retrievals) {
|
|
1382
|
+
sections.push(`### ${ret.id}`);
|
|
1383
|
+
if (ret.sources)
|
|
1384
|
+
sections.push(`- **Sources**: ${ret.sources.join(", ")}`);
|
|
1385
|
+
if (ret.budget)
|
|
1386
|
+
sections.push(`- **Token budget**: ${ret.budget}`);
|
|
1387
|
+
if (ret.paths)
|
|
1388
|
+
sections.push(`- **Search paths**: ${ret.paths.join(", ")}`);
|
|
1389
|
+
if (ret.rerank)
|
|
1390
|
+
sections.push(`- **Reranking**: enabled`);
|
|
1391
|
+
if (ret.diversity)
|
|
1392
|
+
sections.push(`- **Diversity**: enabled`);
|
|
1393
|
+
if (ret.cacheHitThreshold != null) {
|
|
1394
|
+
sections.push(`- **Cache hit**: threshold ${ret.cacheHitThreshold} → ${ret.cacheHitAction ?? "short-circuit"}`);
|
|
1395
|
+
}
|
|
1396
|
+
if (ret.scoring) {
|
|
1397
|
+
const weights = [];
|
|
1398
|
+
if (ret.scoring.recencyWeight != null)
|
|
1399
|
+
weights.push(`recency: ${ret.scoring.recencyWeight}`);
|
|
1400
|
+
if (ret.scoring.semanticWeight != null)
|
|
1401
|
+
weights.push(`semantic: ${ret.scoring.semanticWeight}`);
|
|
1402
|
+
if (ret.scoring.importanceWeight != null)
|
|
1403
|
+
weights.push(`importance: ${ret.scoring.importanceWeight}`);
|
|
1404
|
+
if (weights.length)
|
|
1405
|
+
sections.push(`- **Scoring**: ${weights.join(", ")}`);
|
|
1406
|
+
}
|
|
1407
|
+
// Which agents use this retrieval
|
|
1408
|
+
const retAgents = agents.filter(a => a.retrieval === ret.id);
|
|
1409
|
+
if (retAgents.length > 0) {
|
|
1410
|
+
sections.push(`- **Used by**: ${retAgents.map(a => a.id).join(", ")}`);
|
|
1411
|
+
}
|
|
1412
|
+
sections.push("");
|
|
1413
|
+
}
|
|
1414
|
+
}
|
|
1220
1415
|
// Agent access rules
|
|
1221
1416
|
const agentsWithAccess = agents.filter((a) => (a.reads && a.reads.length > 0) || (a.writes && a.writes.length > 0));
|
|
1222
1417
|
if (agentsWithAccess.length > 0) {
|
|
@@ -1364,9 +1559,11 @@ function generateSkillFiles(ast) {
|
|
|
1364
1559
|
const files = [];
|
|
1365
1560
|
for (const skill of ast.skills) {
|
|
1366
1561
|
const sections = [];
|
|
1367
|
-
// OpenClaw requires YAML frontmatter with name
|
|
1562
|
+
// OpenClaw requires YAML frontmatter with name, version, AND description.
|
|
1563
|
+
// Missing any of the three = skill silently not registered.
|
|
1368
1564
|
sections.push("---");
|
|
1369
1565
|
sections.push(`name: ${skill.id}`);
|
|
1566
|
+
sections.push(`version: "${ast.topology.version}"`);
|
|
1370
1567
|
if (skill.description) {
|
|
1371
1568
|
sections.push(`description: ${JSON.stringify(skill.description)}`);
|
|
1372
1569
|
}
|
|
@@ -1414,10 +1611,11 @@ function generateSkillFiles(ast) {
|
|
|
1414
1611
|
function generateToolSkills(ast) {
|
|
1415
1612
|
const files = [];
|
|
1416
1613
|
for (const tool of ast.toolDefs) {
|
|
1417
|
-
// SKILL.md wrapper — OpenClaw requires
|
|
1614
|
+
// SKILL.md wrapper — OpenClaw requires name, version, AND description.
|
|
1418
1615
|
const sections = [];
|
|
1419
1616
|
sections.push("---");
|
|
1420
1617
|
sections.push(`name: ${tool.id}`);
|
|
1618
|
+
sections.push(`version: "${ast.topology.version}"`);
|
|
1421
1619
|
sections.push(`description: ${JSON.stringify(tool.description)}`);
|
|
1422
1620
|
sections.push("---");
|
|
1423
1621
|
sections.push("");
|
|
@@ -1514,6 +1712,11 @@ function generateMemoryDirs(ast) {
|
|
|
1514
1712
|
}
|
|
1515
1713
|
// Domains dir
|
|
1516
1714
|
files.push(gitkeep("domains"));
|
|
1715
|
+
// Store directory markers
|
|
1716
|
+
const stores = ast.stores ?? [];
|
|
1717
|
+
for (const store of stores) {
|
|
1718
|
+
files.push(gitkeep(`stores/${store.id}`));
|
|
1719
|
+
}
|
|
1517
1720
|
return files;
|
|
1518
1721
|
}
|
|
1519
1722
|
/** Generate metering script + metrics file. */
|
|
@@ -1550,6 +1753,163 @@ function generateMetering(ast) {
|
|
|
1550
1753
|
});
|
|
1551
1754
|
return files;
|
|
1552
1755
|
}
|
|
1756
|
+
/**
|
|
1757
|
+
* Generate per-agent identity directories.
|
|
1758
|
+
*
|
|
1759
|
+
* OpenClaw reads agent identity from `config/agents/<id>/agent/`.
|
|
1760
|
+
* Each agent gets its own IDENTITY.md, MEMORY.md (scoped to its stores),
|
|
1761
|
+
* and SOUL.md with role-specific instructions.
|
|
1762
|
+
*/
|
|
1763
|
+
function generatePerAgentDirs(ast) {
|
|
1764
|
+
const files = [];
|
|
1765
|
+
const agents = getAgentsSorted(ast);
|
|
1766
|
+
const orchestrator = getOrchestrator(ast);
|
|
1767
|
+
const storeMap = new Map((ast.stores ?? []).map(s => [s.id, s]));
|
|
1768
|
+
const defaultProvider = getDefaultProviderName(ast);
|
|
1769
|
+
// Helper: build per-agent MEMORY.md with only stores this agent uses
|
|
1770
|
+
function agentMemoryMd(agentId, storeIds, retrievalId) {
|
|
1771
|
+
const lines = ["# Memory Stores", ""];
|
|
1772
|
+
lines.push("You have access to the following memory stores. Use them to persist and retrieve knowledge.");
|
|
1773
|
+
lines.push("");
|
|
1774
|
+
for (const sid of storeIds) {
|
|
1775
|
+
const store = storeMap.get(sid);
|
|
1776
|
+
if (!store)
|
|
1777
|
+
continue;
|
|
1778
|
+
lines.push(`## ${store.id}`);
|
|
1779
|
+
if (store.description)
|
|
1780
|
+
lines.push(store.description);
|
|
1781
|
+
lines.push("");
|
|
1782
|
+
lines.push(`- **Type**: ${store.type}`);
|
|
1783
|
+
lines.push(`- **Backend**: ${store.backend}`);
|
|
1784
|
+
if (store.path)
|
|
1785
|
+
lines.push(`- **Path**: \`${store.path}\``);
|
|
1786
|
+
if (store.scope)
|
|
1787
|
+
lines.push(`- **Scope**: ${store.scope}`);
|
|
1788
|
+
if (store.embedding) {
|
|
1789
|
+
lines.push(`- **Embedding**: ${store.embedding.model} (${store.embedding.provider}, ${store.embedding.dimensions}d)`);
|
|
1790
|
+
}
|
|
1791
|
+
if (store.search) {
|
|
1792
|
+
const parts = [`strategy: ${store.search.strategy}`];
|
|
1793
|
+
if (store.search.topK)
|
|
1794
|
+
parts.push(`top-k: ${store.search.topK}`);
|
|
1795
|
+
if (store.search.rerank)
|
|
1796
|
+
parts.push(`rerank: yes`);
|
|
1797
|
+
lines.push(`- **Search**: ${parts.join(", ")}`);
|
|
1798
|
+
}
|
|
1799
|
+
if (store.ingestion?.sources) {
|
|
1800
|
+
lines.push(`- **Ingestion sources**: ${store.ingestion.sources.join(", ")}`);
|
|
1801
|
+
}
|
|
1802
|
+
if (store.lifecycle?.retention)
|
|
1803
|
+
lines.push(`- **Retention**: ${store.lifecycle.retention}`);
|
|
1804
|
+
lines.push("");
|
|
1805
|
+
}
|
|
1806
|
+
// Retrieval strategy
|
|
1807
|
+
if (retrievalId) {
|
|
1808
|
+
const retrieval = (ast.retrievals ?? []).find(r => r.id === retrievalId);
|
|
1809
|
+
if (retrieval) {
|
|
1810
|
+
lines.push("## Retrieval Strategy");
|
|
1811
|
+
lines.push("");
|
|
1812
|
+
lines.push(`**${retrieval.id}** — When you need to recall information:`);
|
|
1813
|
+
lines.push("");
|
|
1814
|
+
if (retrieval.sources)
|
|
1815
|
+
lines.push(`- **Sources**: ${retrieval.sources.join(", ")}`);
|
|
1816
|
+
if (retrieval.budget)
|
|
1817
|
+
lines.push(`- **Token budget**: ${retrieval.budget}`);
|
|
1818
|
+
if (retrieval.paths)
|
|
1819
|
+
lines.push(`- **Search paths**: ${retrieval.paths.join(", ")}`);
|
|
1820
|
+
if (retrieval.rerank)
|
|
1821
|
+
lines.push(`- **Reranking**: enabled`);
|
|
1822
|
+
if (retrieval.scoring) {
|
|
1823
|
+
const w = [];
|
|
1824
|
+
if (retrieval.scoring.semanticWeight != null)
|
|
1825
|
+
w.push(`semantic: ${retrieval.scoring.semanticWeight}`);
|
|
1826
|
+
if (retrieval.scoring.recencyWeight != null)
|
|
1827
|
+
w.push(`recency: ${retrieval.scoring.recencyWeight}`);
|
|
1828
|
+
if (retrieval.scoring.importanceWeight != null)
|
|
1829
|
+
w.push(`importance: ${retrieval.scoring.importanceWeight}`);
|
|
1830
|
+
if (w.length)
|
|
1831
|
+
lines.push(`- **Scoring**: ${w.join(", ")}`);
|
|
1832
|
+
}
|
|
1833
|
+
lines.push("");
|
|
1834
|
+
}
|
|
1835
|
+
}
|
|
1836
|
+
return lines.join("\n");
|
|
1837
|
+
}
|
|
1838
|
+
// Generate per-agent dirs
|
|
1839
|
+
const allAgents = orchestrator
|
|
1840
|
+
? [{ id: "orchestrator", description: `${toTitle(ast.topology.name)} orchestrator`, model: orchestrator.model, memory: undefined, retrieval: undefined, prompt: undefined }]
|
|
1841
|
+
: [];
|
|
1842
|
+
for (const a of agents) {
|
|
1843
|
+
allAgents.push({ id: a.id, description: a.description ?? "", model: a.model ?? "sonnet", memory: a.memory, retrieval: a.retrieval, prompt: a.prompt });
|
|
1844
|
+
}
|
|
1845
|
+
for (const agent of allAgents) {
|
|
1846
|
+
const base = `config/agents/${agent.id}/agent`;
|
|
1847
|
+
// IDENTITY.md
|
|
1848
|
+
files.push({
|
|
1849
|
+
path: `${base}/IDENTITY.md`,
|
|
1850
|
+
content: [
|
|
1851
|
+
`# ${toTitle(agent.id)}`,
|
|
1852
|
+
"",
|
|
1853
|
+
agent.description || `Agent in the ${ast.topology.name} topology.`,
|
|
1854
|
+
"",
|
|
1855
|
+
`Model: ${mapModel(agent.model, defaultProvider)}`,
|
|
1856
|
+
"",
|
|
1857
|
+
].join("\n"),
|
|
1858
|
+
category: "machine",
|
|
1859
|
+
});
|
|
1860
|
+
// MEMORY.md — scoped to this agent's stores
|
|
1861
|
+
if (agent.memory && agent.memory.length > 0) {
|
|
1862
|
+
files.push({
|
|
1863
|
+
path: `${base}/MEMORY.md`,
|
|
1864
|
+
content: agentMemoryMd(agent.id, agent.memory, agent.retrieval) + "\n",
|
|
1865
|
+
category: "machine",
|
|
1866
|
+
});
|
|
1867
|
+
}
|
|
1868
|
+
// SOUL.md — agent-specific instructions
|
|
1869
|
+
const soulLines = [
|
|
1870
|
+
`# ${toTitle(agent.id)} — Soul`,
|
|
1871
|
+
"",
|
|
1872
|
+
`You are the **${toTitle(agent.id)}** agent in the **${toTitle(ast.topology.name)}** topology.`,
|
|
1873
|
+
"",
|
|
1874
|
+
];
|
|
1875
|
+
if (agent.description) {
|
|
1876
|
+
soulLines.push(`## Role`, "", agent.description, "");
|
|
1877
|
+
}
|
|
1878
|
+
if (agent.prompt) {
|
|
1879
|
+
soulLines.push("## Instructions", "", agent.prompt, "");
|
|
1880
|
+
}
|
|
1881
|
+
if (agent.memory && agent.memory.length > 0) {
|
|
1882
|
+
soulLines.push(`## Memory`, "", `You have access to these stores: ${agent.memory.join(", ")}. See MEMORY.md for details.`, "");
|
|
1883
|
+
}
|
|
1884
|
+
files.push({
|
|
1885
|
+
path: `${base}/SOUL.md`,
|
|
1886
|
+
content: soulLines.join("\n"),
|
|
1887
|
+
category: "machine",
|
|
1888
|
+
});
|
|
1889
|
+
}
|
|
1890
|
+
// OpenClaw injects ALL files from agentDir into the agent's system prompt.
|
|
1891
|
+
// The team-level AGENTS.md, TOOLS.md, USER.md, and BOOTSTRAP.md must be
|
|
1892
|
+
// copied into each agent's dir so the gateway can find them.
|
|
1893
|
+
// We re-generate the content here (same functions used for root-level files)
|
|
1894
|
+
// to avoid cross-function dependencies.
|
|
1895
|
+
const sharedContent = {
|
|
1896
|
+
"AGENTS.md": generateAgentsMd(ast).content,
|
|
1897
|
+
"TOOLS.md": generateToolsMd(ast).content,
|
|
1898
|
+
"USER.md": generateUserMd().content,
|
|
1899
|
+
"BOOTSTRAP.md": generateBootstrapMd(ast).content,
|
|
1900
|
+
};
|
|
1901
|
+
for (const agent of allAgents) {
|
|
1902
|
+
const base = `config/agents/${agent.id}/agent`;
|
|
1903
|
+
for (const [filename, content] of Object.entries(sharedContent)) {
|
|
1904
|
+
files.push({
|
|
1905
|
+
path: `${base}/${filename}`,
|
|
1906
|
+
content,
|
|
1907
|
+
category: "machine",
|
|
1908
|
+
});
|
|
1909
|
+
}
|
|
1910
|
+
}
|
|
1911
|
+
return files;
|
|
1912
|
+
}
|
|
1553
1913
|
// ---------------------------------------------------------------------------
|
|
1554
1914
|
// Binding export
|
|
1555
1915
|
// ---------------------------------------------------------------------------
|
|
@@ -1584,7 +1944,9 @@ export const openClawBinding = {
|
|
|
1584
1944
|
// 5. Memory and skills directory markers
|
|
1585
1945
|
files.push(gitkeep("memory"));
|
|
1586
1946
|
files.push(gitkeep("skills"));
|
|
1587
|
-
// 6.
|
|
1947
|
+
// 6. Per-agent identity directories (config/agents/<id>/agent/)
|
|
1948
|
+
files.push(...generatePerAgentDirs(ast));
|
|
1949
|
+
// 7. Workspace protocol
|
|
1588
1950
|
const protocol = generateWorkspaceProtocol(ast);
|
|
1589
1951
|
if (protocol)
|
|
1590
1952
|
files.push(protocol);
|