@axiom-lattice/core 2.1.57 → 2.1.59

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/dist/index.js CHANGED
@@ -51,7 +51,7 @@ __export(index_exports, {
51
51
  EmbeddingsLatticeManager: () => EmbeddingsLatticeManager,
52
52
  FileSystemSkillStore: () => FileSystemSkillStore,
53
53
  FilesystemBackend: () => FilesystemBackend,
54
- HumanMessage: () => import_messages4.HumanMessage,
54
+ HumanMessage: () => import_messages5.HumanMessage,
55
55
  InMemoryAssistantStore: () => InMemoryAssistantStore,
56
56
  InMemoryChunkBuffer: () => InMemoryChunkBuffer,
57
57
  InMemoryDatabaseConfigStore: () => InMemoryDatabaseConfigStore,
@@ -120,6 +120,7 @@ __export(index_exports, {
120
120
  createListMetricsServersTool: () => createListMetricsServersTool,
121
121
  createListTablesSqlTool: () => createListTablesSqlTool,
122
122
  createModelSelectorMiddleware: () => createModelSelectorMiddleware,
123
+ createProcessingAgent: () => createProcessingAgent,
123
124
  createQueryCheckerSqlTool: () => createQueryCheckerSqlTool,
124
125
  createQueryMetricDefinitionTool: () => createQueryMetricDefinitionTool,
125
126
  createQueryMetricsListTool: () => createQueryMetricsListTool,
@@ -867,11 +868,11 @@ var ToolLatticeManager = class _ToolLatticeManager extends BaseLatticeManager {
867
868
  * @param key Lattice键名
868
869
  * @param tool 已有的StructuredTool实例
869
870
  */
870
- registerExistingTool(key, tool50) {
871
+ registerExistingTool(key, tool51) {
871
872
  const config = {
872
- name: tool50.name,
873
- description: tool50.description,
874
- schema: tool50.schema,
873
+ name: tool51.name,
874
+ description: tool51.description,
875
+ schema: tool51.schema,
875
876
  // StructuredTool的schema已经是Zod兼容的
876
877
  needUserApprove: false
877
878
  // MCP工具默认不需要用户批准
@@ -879,7 +880,7 @@ var ToolLatticeManager = class _ToolLatticeManager extends BaseLatticeManager {
879
880
  const toolLattice = {
880
881
  key,
881
882
  config,
882
- client: tool50
883
+ client: tool51
883
884
  };
884
885
  this.register(key, toolLattice);
885
886
  }
@@ -905,7 +906,7 @@ var ToolLatticeManager = class _ToolLatticeManager extends BaseLatticeManager {
905
906
  };
906
907
  var toolLatticeManager = ToolLatticeManager.getInstance();
907
908
  var registerToolLattice = (key, config, executor) => toolLatticeManager.registerLattice(key, config, executor);
908
- var registerExistingTool = (key, tool50) => toolLatticeManager.registerExistingTool(key, tool50);
909
+ var registerExistingTool = (key, tool51) => toolLatticeManager.registerExistingTool(key, tool51);
909
910
  var getToolLattice = (key) => toolLatticeManager.getToolLattice(key);
910
911
  var getToolDefinition = (key) => toolLatticeManager.getToolDefinition(key);
911
912
  var getToolClient = (key) => toolLatticeManager.getToolClient(key);
@@ -1339,14 +1340,14 @@ var import_zod3 = __toESM(require("zod"));
1339
1340
  var import_langchain = require("langchain");
1340
1341
 
1341
1342
  // src/tool_lattice/sql/utils.ts
1342
- function getTenantIdFromConfig(exeConfig, getTenantId) {
1343
+ function getTenantIdFromConfig(exeConfig, getTenantId2) {
1343
1344
  const runConfig = exeConfig?.configurable?.runConfig || {};
1344
- return runConfig.tenantId || (getTenantId ? getTenantId() : "default");
1345
+ return runConfig.tenantId || (getTenantId2 ? getTenantId2() : "default");
1345
1346
  }
1346
1347
 
1347
1348
  // src/tool_lattice/sql/list_tables_sql.ts
1348
1349
  var LIST_TABLES_SQL_DESCRIPTION = `List all tables in the connected SQL database. Returns a comma-separated list of table names. Use this tool first to understand what tables are available before querying the database.`;
1349
- var createListTablesSqlTool = ({ databaseKeys, databaseDescriptions, getTenantId }) => {
1350
+ var createListTablesSqlTool = ({ databaseKeys, databaseDescriptions, getTenantId: getTenantId2 }) => {
1350
1351
  const availableDbsText = databaseKeys.length > 0 ? `
1351
1352
 
1352
1353
  Available databases:
@@ -1356,7 +1357,7 @@ ${databaseKeys.map(
1356
1357
  return (0, import_langchain.tool)(
1357
1358
  async ({ databaseKey }, _exeConfig) => {
1358
1359
  try {
1359
- const tenantId = getTenantIdFromConfig(_exeConfig, getTenantId);
1360
+ const tenantId = getTenantIdFromConfig(_exeConfig, getTenantId2);
1360
1361
  if (!databaseKey) {
1361
1362
  return "Error: databaseKey parameter is required. Available databases: " + databaseKeys.join(", ");
1362
1363
  }
@@ -1390,7 +1391,7 @@ ${databaseKeys.map(
1390
1391
  var import_zod4 = __toESM(require("zod"));
1391
1392
  var import_langchain2 = require("langchain");
1392
1393
  var INFO_SQL_DESCRIPTION = `Get detailed schema information for specified tables, including column names, types, constraints (primary keys, foreign keys), and sample rows. Input should be a comma-separated list of table names.`;
1393
- var createInfoSqlTool = ({ databaseKeys, databaseDescriptions, getTenantId }) => {
1394
+ var createInfoSqlTool = ({ databaseKeys, databaseDescriptions, getTenantId: getTenantId2 }) => {
1394
1395
  const availableDbsText = databaseKeys.length > 0 ? `
1395
1396
 
1396
1397
  Available databases:
@@ -1403,7 +1404,7 @@ ${databaseKeys.map(
1403
1404
  databaseKey
1404
1405
  }, _exeConfig) => {
1405
1406
  try {
1406
- const tenantId = getTenantIdFromConfig(_exeConfig, getTenantId);
1407
+ const tenantId = getTenantIdFromConfig(_exeConfig, getTenantId2);
1407
1408
  if (!databaseKey) {
1408
1409
  return "Error: databaseKey parameter is required. Available databases: " + databaseKeys.join(", ");
1409
1410
  }
@@ -1522,7 +1523,7 @@ function checkDangerousOperations(query) {
1522
1523
  }
1523
1524
  return warnings;
1524
1525
  }
1525
- var createQueryCheckerSqlTool = ({ databaseKeys, databaseDescriptions, getTenantId }) => {
1526
+ var createQueryCheckerSqlTool = ({ databaseKeys, databaseDescriptions, getTenantId: getTenantId2 }) => {
1526
1527
  const availableDbsText = databaseKeys.length > 0 ? `
1527
1528
 
1528
1529
  Available databases:
@@ -1535,7 +1536,7 @@ ${databaseKeys.map(
1535
1536
  databaseKey
1536
1537
  }, _exeConfig) => {
1537
1538
  try {
1538
- const tenantId = getTenantIdFromConfig(_exeConfig, getTenantId);
1539
+ const tenantId = getTenantIdFromConfig(_exeConfig, getTenantId2);
1539
1540
  const trimmedQuery = query.trim();
1540
1541
  if (!trimmedQuery) {
1541
1542
  return "Error: Empty query provided. Please provide a SQL query to check.";
@@ -1644,7 +1645,7 @@ function formatQueryResult(rows, fields) {
1644
1645
  Total rows: ${rows.length}`);
1645
1646
  return lines.join("\n");
1646
1647
  }
1647
- var createQuerySqlTool = ({ databaseKeys, databaseDescriptions, getTenantId }) => {
1648
+ var createQuerySqlTool = ({ databaseKeys, databaseDescriptions, getTenantId: getTenantId2 }) => {
1648
1649
  const availableDbsText = databaseKeys.length > 0 ? `
1649
1650
 
1650
1651
  Available databases:
@@ -1657,7 +1658,7 @@ ${databaseKeys.map(
1657
1658
  databaseKey
1658
1659
  }, _exeConfig) => {
1659
1660
  try {
1660
- const tenantId = getTenantIdFromConfig(_exeConfig, getTenantId);
1661
+ const tenantId = getTenantIdFromConfig(_exeConfig, getTenantId2);
1661
1662
  if (!databaseKey) {
1662
1663
  return "Error: databaseKey parameter is required. Available databases: " + databaseKeys.join(", ");
1663
1664
  }
@@ -1689,9 +1690,9 @@ ${databaseKeys.map(
1689
1690
  };
1690
1691
 
1691
1692
  // src/tool_lattice/metrics/utils.ts
1692
- function getTenantIdFromConfig2(exeConfig, getTenantId) {
1693
+ function getTenantIdFromConfig2(exeConfig, getTenantId2) {
1693
1694
  const runConfig = exeConfig?.configurable?.runConfig || {};
1694
- return runConfig.tenantId || (getTenantId ? getTenantId() : "default");
1695
+ return runConfig.tenantId || (getTenantId2 ? getTenantId2() : "default");
1695
1696
  }
1696
1697
  function filterServerKeysByTenant(serverKeys, tenantId, manager = metricsServerManager) {
1697
1698
  return serverKeys.filter((key) => {
@@ -2543,7 +2544,7 @@ var metricsServerManager = MetricsServerManager.getInstance();
2543
2544
  var import_zod7 = __toESM(require("zod"));
2544
2545
  var import_langchain5 = require("langchain");
2545
2546
  var LIST_METRICS_SERVERS_DESCRIPTION = `List all registered metrics servers. Returns a list of available metrics servers with their keys and types. Use this tool first to understand what metrics servers are available.`;
2546
- var createListMetricsServersTool = ({ serverKeys, serverDescriptions, getTenantId }) => {
2547
+ var createListMetricsServersTool = ({ serverKeys, serverDescriptions, getTenantId: getTenantId2 }) => {
2547
2548
  const availableServersText = serverKeys.length > 0 ? `
2548
2549
 
2549
2550
  Available metrics servers:
@@ -2553,7 +2554,7 @@ ${serverKeys.map(
2553
2554
  return (0, import_langchain5.tool)(
2554
2555
  async (_input, _exeConfig) => {
2555
2556
  try {
2556
- const tenantId = getTenantIdFromConfig2(_exeConfig, getTenantId);
2557
+ const tenantId = getTenantIdFromConfig2(_exeConfig, getTenantId2);
2557
2558
  const servers = metricsServerManager.getServerKeys(tenantId);
2558
2559
  if (servers.length === 0) {
2559
2560
  return "No metrics servers registered.";
@@ -2580,7 +2581,7 @@ ${lines.join("\n")}`;
2580
2581
  var import_zod8 = __toESM(require("zod"));
2581
2582
  var import_langchain6 = require("langchain");
2582
2583
  var LIST_METRICS_DATASOURCES_DESCRIPTION = `List all available datasources from all configured metrics servers. Returns a table with Server Key, DataSource ID, and DataSource Name. Use this tool first to discover what datasources are available before querying metrics.`;
2583
- var createListMetricsDataSourcesTool = ({ serverKeys, serverDescriptions, getTenantId, connectAll }) => {
2584
+ var createListMetricsDataSourcesTool = ({ serverKeys, serverDescriptions, getTenantId: getTenantId2, connectAll }) => {
2584
2585
  const availableServersText = serverKeys.length > 0 ? `
2585
2586
 
2586
2587
  Configured metrics servers:
@@ -2590,7 +2591,7 @@ ${serverKeys.map(
2590
2591
  return (0, import_langchain6.tool)(
2591
2592
  async (_input, _exeConfig) => {
2592
2593
  try {
2593
- const tenantId = getTenantIdFromConfig2(_exeConfig, getTenantId);
2594
+ const tenantId = getTenantIdFromConfig2(_exeConfig, getTenantId2);
2594
2595
  let effectiveServerKeys = serverKeys;
2595
2596
  if (connectAll) {
2596
2597
  effectiveServerKeys = metricsServerManager.getServerKeys(tenantId).map((s) => s.key);
@@ -2696,7 +2697,7 @@ Response Fields Reference
2696
2697
 
2697
2698
  Next Step
2698
2699
  After finding relevant metrics, call query_metric_definition with the metricName to get detailed metadata including time dimensions and supported filters.`;
2699
- var createQueryMetricsListTool = ({ serverKeys, serverDescriptions, getTenantId, connectAll }) => {
2700
+ var createQueryMetricsListTool = ({ serverKeys, serverDescriptions, getTenantId: getTenantId2, connectAll }) => {
2700
2701
  const availableServersText = serverKeys.length > 0 ? `
2701
2702
 
2702
2703
  Available metrics servers:
@@ -2709,7 +2710,7 @@ ${serverKeys.map(
2709
2710
  datasourceIds
2710
2711
  }, _exeConfig) => {
2711
2712
  try {
2712
- const tenantId = getTenantIdFromConfig2(_exeConfig, getTenantId);
2713
+ const tenantId = getTenantIdFromConfig2(_exeConfig, getTenantId2);
2713
2714
  let effectiveServerKeys = serverKeys;
2714
2715
  if (connectAll) {
2715
2716
  effectiveServerKeys = metricsServerManager.getServerKeys(tenantId).map((s) => s.key);
@@ -2853,7 +2854,7 @@ Rules
2853
2854
 
2854
2855
  Next Step
2855
2856
  Call query_semantic_metric_data with parameters derived from this definition.`;
2856
- var createQueryMetricDefinitionTool = ({ serverKeys, serverDescriptions, getTenantId, connectAll }) => {
2857
+ var createQueryMetricDefinitionTool = ({ serverKeys, serverDescriptions, getTenantId: getTenantId2, connectAll }) => {
2857
2858
  const availableServersText = serverKeys.length > 0 ? `
2858
2859
 
2859
2860
  Available metrics servers:
@@ -2867,7 +2868,7 @@ ${serverKeys.map(
2867
2868
  datasourceId: inputDatasourceId
2868
2869
  }, _exeConfig) => {
2869
2870
  try {
2870
- const tenantId = getTenantIdFromConfig2(_exeConfig, getTenantId);
2871
+ const tenantId = getTenantIdFromConfig2(_exeConfig, getTenantId2);
2871
2872
  let effectiveServerKeys = serverKeys;
2872
2873
  if (connectAll) {
2873
2874
  effectiveServerKeys = metricsServerManager.getServerKeys(tenantId).map((s) => s.key);
@@ -3086,7 +3087,7 @@ Semantic Model: ${semanticModel}`;
3086
3087
  `);
3087
3088
  return lines.join("\n");
3088
3089
  }
3089
- var createQuerySemanticMetricDataTool = ({ serverKeys, serverDescriptions, getTenantId, connectAll }) => {
3090
+ var createQuerySemanticMetricDataTool = ({ serverKeys, serverDescriptions, getTenantId: getTenantId2, connectAll }) => {
3090
3091
  const availableServersText = serverKeys.length > 0 ? `
3091
3092
 
3092
3093
  Available metrics servers:
@@ -3103,7 +3104,7 @@ ${serverKeys.map(
3103
3104
  limit
3104
3105
  }, _exeConfig) => {
3105
3106
  try {
3106
- const tenantId = getTenantIdFromConfig2(_exeConfig, getTenantId);
3107
+ const tenantId = getTenantIdFromConfig2(_exeConfig, getTenantId2);
3107
3108
  let effectiveServerKeys = serverKeys;
3108
3109
  if (connectAll) {
3109
3110
  effectiveServerKeys = metricsServerManager.getServerKeys(tenantId).map((s) => s.key);
@@ -3171,7 +3172,7 @@ ${serverKeys.map(
3171
3172
  var import_zod12 = __toESM(require("zod"));
3172
3173
  var import_langchain10 = require("langchain");
3173
3174
  var QUERY_TABLES_LIST_DESCRIPTION = `Query available tables from a semantic metrics server. Returns a list of data tables with their schemas and descriptions. Use this tool to discover what tables are available in the data source.`;
3174
- var createQueryTablesListTool = ({ serverKeys, serverDescriptions, getTenantId, connectAll }) => {
3175
+ var createQueryTablesListTool = ({ serverKeys, serverDescriptions, getTenantId: getTenantId2, connectAll }) => {
3175
3176
  const availableServersText = serverKeys.length > 0 ? `
3176
3177
 
3177
3178
  Available metrics servers:
@@ -3184,7 +3185,7 @@ ${serverKeys.map(
3184
3185
  datasourceIds
3185
3186
  }, _exeConfig) => {
3186
3187
  try {
3187
- const tenantId = getTenantIdFromConfig2(_exeConfig, getTenantId);
3188
+ const tenantId = getTenantIdFromConfig2(_exeConfig, getTenantId2);
3188
3189
  let effectiveServerKeys = serverKeys;
3189
3190
  if (connectAll) {
3190
3191
  effectiveServerKeys = metricsServerManager.getServerKeys(tenantId).map((s) => s.key);
@@ -3275,7 +3276,7 @@ ${serverKeys.map(
3275
3276
  var import_zod13 = __toESM(require("zod"));
3276
3277
  var import_langchain11 = require("langchain");
3277
3278
  var QUERY_TABLE_DEFINITION_DESCRIPTION = `Get detailed definition and schema for a specific table from a semantic metrics server. Returns comprehensive information including column definitions, SQL query, and table relationships.`;
3278
- var createQueryTableDefinitionTool = ({ serverKeys, serverDescriptions, getTenantId, connectAll }) => {
3279
+ var createQueryTableDefinitionTool = ({ serverKeys, serverDescriptions, getTenantId: getTenantId2, connectAll }) => {
3279
3280
  const availableServersText = serverKeys.length > 0 ? `
3280
3281
 
3281
3282
  Available metrics servers:
@@ -3289,7 +3290,7 @@ ${serverKeys.map(
3289
3290
  datasourceId: inputDatasourceId
3290
3291
  }, _exeConfig) => {
3291
3292
  try {
3292
- const tenantId = getTenantIdFromConfig2(_exeConfig, getTenantId);
3293
+ const tenantId = getTenantIdFromConfig2(_exeConfig, getTenantId2);
3293
3294
  let effectiveServerKeys = serverKeys;
3294
3295
  if (connectAll) {
3295
3296
  effectiveServerKeys = metricsServerManager.getServerKeys(tenantId).map((s) => s.key);
@@ -3413,7 +3414,7 @@ Example:
3413
3414
  },
3414
3415
  "limit": 100
3415
3416
  }`;
3416
- var createExecuteSqlQueryTool = ({ serverKeys, serverDescriptions, getTenantId, connectAll }) => {
3417
+ var createExecuteSqlQueryTool = ({ serverKeys, serverDescriptions, getTenantId: getTenantId2, connectAll }) => {
3417
3418
  const availableServersText = serverKeys.length > 0 ? `
3418
3419
 
3419
3420
  Available metrics servers:
@@ -3429,7 +3430,7 @@ ${serverKeys.map(
3429
3430
  limit
3430
3431
  }, _exeConfig) => {
3431
3432
  try {
3432
- const tenantId = getTenantIdFromConfig2(_exeConfig, getTenantId);
3433
+ const tenantId = getTenantIdFromConfig2(_exeConfig, getTenantId2);
3433
3434
  let effectiveServerKeys = serverKeys;
3434
3435
  if (connectAll) {
3435
3436
  effectiveServerKeys = metricsServerManager.getServerKeys(tenantId).map((s) => s.key);
@@ -4740,7 +4741,7 @@ var createBrowserGetInfoTool = ({ vmIsolation }) => {
4740
4741
  };
4741
4742
 
4742
4743
  // src/index.ts
4743
- var import_messages4 = require("@langchain/core/messages");
4744
+ var import_messages5 = require("@langchain/core/messages");
4744
4745
 
4745
4746
  // src/agent_lattice/types.ts
4746
4747
  var import_protocols = require("@axiom-lattice/protocols");
@@ -11032,6 +11033,125 @@ var InMemoryThreadMessageQueueStore = class {
11032
11033
  }
11033
11034
  };
11034
11035
 
11036
+ // src/store_lattice/InMemoryWorkflowTrackingStore.ts
11037
+ var InMemoryWorkflowTrackingStore = class {
11038
+ constructor() {
11039
+ this.runs = /* @__PURE__ */ new Map();
11040
+ this.steps = /* @__PURE__ */ new Map();
11041
+ }
11042
+ async createWorkflowRun(request) {
11043
+ const now = /* @__PURE__ */ new Date();
11044
+ const run = {
11045
+ id: `${request.threadId}_${Date.now()}`,
11046
+ tenantId: request.tenantId,
11047
+ assistantId: request.assistantId,
11048
+ threadId: request.threadId,
11049
+ status: "running",
11050
+ topologyEdges: request.topologyEdges,
11051
+ totalEdges: request.topologyEdges.length,
11052
+ completedEdges: 0,
11053
+ metadata: request.metadata || {},
11054
+ startedAt: now,
11055
+ createdAt: now,
11056
+ updatedAt: now
11057
+ };
11058
+ this.runs.set(run.id, run);
11059
+ this.steps.set(run.id, []);
11060
+ return run;
11061
+ }
11062
+ async getWorkflowRun(runId) {
11063
+ return this.runs.get(runId) || null;
11064
+ }
11065
+ async updateWorkflowRun(runId, updates) {
11066
+ const run = this.runs.get(runId);
11067
+ if (!run) return null;
11068
+ const updated = {
11069
+ ...run,
11070
+ ...updates,
11071
+ updatedAt: /* @__PURE__ */ new Date()
11072
+ };
11073
+ this.runs.set(runId, updated);
11074
+ return updated;
11075
+ }
11076
+ async getWorkflowRunsByThreadId(tenantId, threadId) {
11077
+ const results = [];
11078
+ for (const run of this.runs.values()) {
11079
+ if (run.tenantId === tenantId && run.threadId === threadId) {
11080
+ results.push(run);
11081
+ }
11082
+ }
11083
+ return results;
11084
+ }
11085
+ async getWorkflowRunsByAssistantId(tenantId, assistantId) {
11086
+ const results = [];
11087
+ for (const run of this.runs.values()) {
11088
+ if (run.tenantId === tenantId && run.assistantId === assistantId) {
11089
+ results.push(run);
11090
+ }
11091
+ }
11092
+ return results;
11093
+ }
11094
+ async getWorkflowRunsByTenantId(tenantId) {
11095
+ const results = [];
11096
+ for (const run of this.runs.values()) {
11097
+ if (run.tenantId === tenantId) {
11098
+ results.push(run);
11099
+ }
11100
+ }
11101
+ return results;
11102
+ }
11103
+ async createRunStep(request) {
11104
+ const now = /* @__PURE__ */ new Date();
11105
+ const step = {
11106
+ id: `step_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`,
11107
+ runId: request.runId,
11108
+ tenantId: request.tenantId,
11109
+ stepType: request.stepType,
11110
+ stepName: request.stepName,
11111
+ edgeFrom: request.edgeFrom,
11112
+ edgeTo: request.edgeTo,
11113
+ edgePurpose: request.edgePurpose,
11114
+ input: request.input,
11115
+ status: "running",
11116
+ startedAt: now,
11117
+ createdAt: now,
11118
+ updatedAt: now
11119
+ };
11120
+ const runSteps = this.steps.get(request.runId) || [];
11121
+ runSteps.push(step);
11122
+ this.steps.set(request.runId, runSteps);
11123
+ return step;
11124
+ }
11125
+ async updateRunStep(runId, stepId, updates) {
11126
+ const runSteps = this.steps.get(runId);
11127
+ if (!runSteps) return null;
11128
+ const idx = runSteps.findIndex((s) => s.id === stepId);
11129
+ if (idx === -1) return null;
11130
+ const now = /* @__PURE__ */ new Date();
11131
+ runSteps[idx] = {
11132
+ ...runSteps[idx],
11133
+ ...updates,
11134
+ updatedAt: now
11135
+ };
11136
+ return runSteps[idx];
11137
+ }
11138
+ async getRunSteps(runId) {
11139
+ return this.steps.get(runId) || [];
11140
+ }
11141
+ async getRunStepsByType(runId, stepType) {
11142
+ const runSteps = this.steps.get(runId) || [];
11143
+ return runSteps.filter((s) => s.stepType === stepType);
11144
+ }
11145
+ async getInterruptedSteps(runId) {
11146
+ const runSteps = this.steps.get(runId) || [];
11147
+ return runSteps.filter((s) => s.status === "interrupted");
11148
+ }
11149
+ clear() {
11150
+ this.runs.clear();
11151
+ this.steps.clear();
11152
+ }
11153
+ };
11154
+
11035
11155
  // src/store_lattice/StoreLatticeManager.ts
11036
11156
  var StoreLatticeManager = class _StoreLatticeManager extends BaseLatticeManager {
11037
11157
  /**
@@ -11188,6 +11308,12 @@ storeLatticeManager.registerLattice(
11188
11308
  "threadMessageQueue",
11189
11309
  defaultThreadMessageQueueStore
11190
11310
  );
11311
+ var defaultWorkflowTrackingStore = new InMemoryWorkflowTrackingStore();
11312
+ storeLatticeManager.registerLattice(
11313
+ "default",
11314
+ "workflowTracking",
11315
+ defaultWorkflowTrackingStore
11316
+ );
11191
11317
 
11192
11318
  // src/services/Agent.ts
11193
11319
  var import_langgraph6 = require("@langchain/langgraph");
@@ -11526,6 +11652,7 @@ var Agent = class {
11526
11652
  this.abortController = null;
11527
11653
  this.queueMode = this.getDefaultQueueConfig();
11528
11654
  this.isWaitingForQueueEnd = false;
11655
+ this.asyncTasks = [];
11529
11656
  this.agentExecutor = async ({ input, command, custom_run_config }, signal) => {
11530
11657
  const { runnable_agent, runConfig } = await this.getLatticeClientAndRuntimeConfig(custom_run_config);
11531
11658
  const { messages, ...rest } = input;
@@ -12304,6 +12431,23 @@ var Agent = class {
12304
12431
  console.log(namespacedEvent);
12305
12432
  event_bus_default.publish(namespacedEvent, data);
12306
12433
  }
12434
+ addAsyncTask(task) {
12435
+ this.asyncTasks.push(task);
12436
+ }
12437
+ getAsyncTasks() {
12438
+ return this.asyncTasks;
12439
+ }
12440
+ getAsyncTask(taskId) {
12441
+ return this.asyncTasks.find((t) => t.taskId === taskId);
12442
+ }
12443
+ updateAsyncTaskStatus(taskId, status) {
12444
+ const task = this.getAsyncTask(taskId);
12445
+ if (!task) return;
12446
+ task.status = status;
12447
+ if (status === "completed" || status === "failed" || status === "cancelled") {
12448
+ task.completedAt = Date.now();
12449
+ }
12450
+ }
12307
12451
  };
12308
12452
 
12309
12453
  // src/services/AgentInstanceManager.ts
@@ -12929,9 +13073,9 @@ var ReActAgentGraphBuilder = class {
12929
13073
  */
12930
13074
  async build(agentLattice, params) {
12931
13075
  const tools = params.tools.map((t) => {
12932
- const tool50 = getToolClient(t.key);
12933
- return tool50;
12934
- }).filter((tool50) => tool50 !== void 0);
13076
+ const tool51 = getToolClient(t.key);
13077
+ return tool51;
13078
+ }).filter((tool51) => tool51 !== void 0);
12935
13079
  const stateSchema2 = createReactAgentSchema(params.stateSchema);
12936
13080
  const middlewareConfigs = params.middleware || [];
12937
13081
  const filesystemBackend = createFilesystemBackendFactory(middlewareConfigs);
@@ -13339,6 +13483,25 @@ function getSubagents(options) {
13339
13483
  }
13340
13484
  return { agents, descriptions: subagentDescriptions };
13341
13485
  }
13486
+ function getAsyncPromptText() {
13487
+ return `
13488
+
13489
+ ## Async Task Usage
13490
+
13491
+ When tasks are independent and can run in parallel, use \`async: true\` to launch
13492
+ background tasks. The task returns immediately with a task ID.
13493
+
13494
+ CRITICAL: After launching with \`async: true\`, move on immediately.
13495
+ - NEVER call check_async_task or list_async_tasks right after starting a task.
13496
+ - NEVER poll for task completion. The result will arrive as a notification.
13497
+ - Only check task status when the USER explicitly asks for an update.
13498
+ - If you receive an [Async task completed] notification, read it and incorporate
13499
+ the result into your next response. Do not then call check_async_task repeatedly.
13500
+ - Task statuses in conversation history are stale \u2014 always use fresh tool calls
13501
+ when the user asks.
13502
+ - Use cancel_async_task if the user wants to stop a running task.
13503
+ - Keep the full task_id: never truncate or abbreviate it.`;
13504
+ }
13342
13505
  function createTaskTool(options) {
13343
13506
  const {
13344
13507
  defaultModel,
@@ -13347,7 +13510,8 @@ function createTaskTool(options) {
13347
13510
  defaultInterruptOn,
13348
13511
  subagents,
13349
13512
  generalPurposeAgent,
13350
- taskDescription
13513
+ taskDescription,
13514
+ allowAsync
13351
13515
  } = options;
13352
13516
  const { agents: subagentGraphs, descriptions: subagentDescriptions } = getSubagents({
13353
13517
  defaultModel,
@@ -13360,7 +13524,7 @@ function createTaskTool(options) {
13360
13524
  const finalTaskDescription = taskDescription ? taskDescription : getTaskToolDescription(subagentDescriptions);
13361
13525
  return (0, import_langchain57.tool)(
13362
13526
  async (input, config) => {
13363
- const { description, subagent_type } = input;
13527
+ const { description, subagent_type, async } = input;
13364
13528
  let assistant_id = subagent_type;
13365
13529
  if (subagent_type === "general-purpose") {
13366
13530
  assistant_id = config.configurable?.runConfig?.assistant_id + "-general-purpose";
@@ -13390,6 +13554,57 @@ function createTaskTool(options) {
13390
13554
  const subagentState = filterStateForSubagent(currentState);
13391
13555
  subagentState.messages = [new import_messages2.HumanMessage({ content: description })];
13392
13556
  const subagent_thread_id = config.configurable?.thread_id + "____" + assistant_id + "_" + config.toolCall.id;
13557
+ if (async) {
13558
+ const tenantId = config.configurable?.runConfig?.tenantId;
13559
+ const mainAssistantId = config.configurable?.runConfig?.assistant_id;
13560
+ const mainThreadId = config.configurable?.runConfig?.thread_id;
13561
+ const mainRuntimeAgent = agentInstanceManager.getAgent({
13562
+ assistant_id: mainAssistantId,
13563
+ thread_id: mainThreadId,
13564
+ tenant_id: tenantId
13565
+ });
13566
+ if (mainRuntimeAgent) {
13567
+ mainRuntimeAgent.addAsyncTask({
13568
+ taskId: subagent_thread_id,
13569
+ assistantId: assistant_id,
13570
+ description: description.substring(0, 200),
13571
+ status: "running",
13572
+ createdAt: Date.now()
13573
+ });
13574
+ }
13575
+ AgentManager.getInstance().callAgentInQueue({
13576
+ assistant_id,
13577
+ thread_id: subagent_thread_id,
13578
+ input: { ...subagentState, message: description },
13579
+ "x-tenant-id": tenantId,
13580
+ runConfig: {
13581
+ ...config.configurable?.runConfig,
13582
+ assistant_id,
13583
+ thread_id: subagent_thread_id
13584
+ },
13585
+ main_thread_id: mainThreadId,
13586
+ main_tenant_id: tenantId,
13587
+ main_assistant_id: mainAssistantId
13588
+ }, false).catch((err) => {
13589
+ console.error(`Failed to start async subagent ${subagent_thread_id}:`, err);
13590
+ });
13591
+ if (!config.toolCall?.id) {
13592
+ throw new Error("Tool call ID is required for subagent invocation");
13593
+ }
13594
+ return new import_langgraph8.Command({
13595
+ update: {
13596
+ messages: [
13597
+ new import_langchain57.ToolMessage({
13598
+ content: `Async task started: ${subagent_thread_id}
13599
+ ${description}
13600
+ The result will be delivered as a notification when complete. Do not poll.`,
13601
+ tool_call_id: config.toolCall.id,
13602
+ name: "task"
13603
+ })
13604
+ ]
13605
+ }
13606
+ });
13607
+ }
13393
13608
  const workerResult = await agentWorkerGraph.invoke({
13394
13609
  assistant_id,
13395
13610
  thread_id: subagent_thread_id,
@@ -13431,7 +13646,186 @@ function createTaskTool(options) {
13431
13646
  `Name of the agent to use. Available: ${Object.keys(
13432
13647
  subagentGraphs
13433
13648
  ).join(", ")}`
13434
- )
13649
+ ),
13650
+ ...allowAsync ? {
13651
+ async: import_v32.z.boolean().default(false).describe(
13652
+ "When true, runs the task in the background and returns immediately. Use for independent tasks that can run in parallel. The result is delivered as a notification when complete. Use check_async_task or list_async_tasks to monitor progress."
13653
+ )
13654
+ } : {}
13655
+ })
13656
+ }
13657
+ );
13658
+ }
13659
+ function getMainAgentFromConfig(config) {
13660
+ const tenantId = config.configurable?.runConfig?.tenantId;
13661
+ const mainAssistantId = config.configurable?.runConfig?.assistant_id;
13662
+ const mainThreadId = config.configurable?.runConfig?.thread_id;
13663
+ return agentInstanceManager.getAgent({
13664
+ assistant_id: mainAssistantId,
13665
+ thread_id: mainThreadId,
13666
+ tenant_id: tenantId
13667
+ });
13668
+ }
13669
+ function createCheckAsyncTaskTool() {
13670
+ return (0, import_langchain57.tool)(
13671
+ async (input, config) => {
13672
+ const { task_id } = input;
13673
+ const mainAgent = getMainAgentFromConfig(config);
13674
+ if (!mainAgent) {
13675
+ return "Cannot access main agent state.";
13676
+ }
13677
+ const cached = mainAgent.getAsyncTask(task_id);
13678
+ if (!cached) {
13679
+ return `Task ${task_id} not found. Use list_async_tasks to see all tasks.`;
13680
+ }
13681
+ try {
13682
+ if (!agentInstanceManager.hasAgent({
13683
+ assistant_id: cached.assistantId,
13684
+ thread_id: task_id,
13685
+ tenant_id: mainAgent.tenant_id
13686
+ })) {
13687
+ return `Task ${task_id}: not found (may have been cleaned up). Status was: ${cached.status}`;
13688
+ }
13689
+ const subAgent = agentInstanceManager.getAgent({
13690
+ assistant_id: cached.assistantId,
13691
+ thread_id: task_id,
13692
+ tenant_id: mainAgent.tenant_id
13693
+ });
13694
+ const status = await subAgent.getRunStatus();
13695
+ if (status === "busy") {
13696
+ return `Task ${task_id}: still running.
13697
+ Description: ${cached.description}`;
13698
+ }
13699
+ if (status === "idle") {
13700
+ const state = await subAgent.getCurrentState();
13701
+ const messages = state.values.messages || [];
13702
+ const lastAI = [...messages].reverse().find(
13703
+ (m) => m.type === "ai" || m.getType?.() === "ai"
13704
+ );
13705
+ mainAgent.updateAsyncTaskStatus(task_id, "completed");
13706
+ const result = lastAI?.content ?? "(completed, no output)";
13707
+ return `Task ${task_id}: COMPLETED.
13708
+ Description: ${cached.description}
13709
+ Result:
13710
+ ${result}`;
13711
+ }
13712
+ if (status === "error") {
13713
+ mainAgent.updateAsyncTaskStatus(task_id, "failed");
13714
+ return `Task ${task_id}: failed.
13715
+ Description: ${cached.description}`;
13716
+ }
13717
+ if (status === "interrupted") {
13718
+ return `Task ${task_id}: interrupted (waiting for input).
13719
+ Description: ${cached.description}`;
13720
+ }
13721
+ return `Task ${task_id}: ${status}.
13722
+ Description: ${cached.description}`;
13723
+ } catch (err) {
13724
+ return `Task ${task_id}: error checking status: ${err instanceof Error ? err.message : String(err)}`;
13725
+ }
13726
+ },
13727
+ {
13728
+ name: "check_async_task",
13729
+ description: "Get the current status and result of an async background task. Use this to check if a previously launched async task has completed.",
13730
+ schema: import_v32.z.object({
13731
+ task_id: import_v32.z.string().describe("The task ID returned when the async task was started")
13732
+ })
13733
+ }
13734
+ );
13735
+ }
13736
+ function createListAsyncTasksTool() {
13737
+ return (0, import_langchain57.tool)(
13738
+ async (_input, config) => {
13739
+ const mainAgent = getMainAgentFromConfig(config);
13740
+ if (!mainAgent) {
13741
+ return "Cannot access main agent state.";
13742
+ }
13743
+ const tasks = mainAgent.getAsyncTasks();
13744
+ if (tasks.length === 0) {
13745
+ return "No async tasks have been launched.";
13746
+ }
13747
+ for (const task of tasks) {
13748
+ if (task.status === "completed" || task.status === "failed" || task.status === "cancelled") continue;
13749
+ try {
13750
+ if (!agentInstanceManager.hasAgent({
13751
+ assistant_id: task.assistantId,
13752
+ thread_id: task.taskId,
13753
+ tenant_id: mainAgent.tenant_id
13754
+ })) continue;
13755
+ const subAgent = agentInstanceManager.getAgent({
13756
+ assistant_id: task.assistantId,
13757
+ thread_id: task.taskId,
13758
+ tenant_id: mainAgent.tenant_id
13759
+ });
13760
+ const status = await subAgent.getRunStatus();
13761
+ if (status === "idle") {
13762
+ mainAgent.updateAsyncTaskStatus(task.taskId, "completed");
13763
+ } else if (status === "error") {
13764
+ mainAgent.updateAsyncTaskStatus(task.taskId, "failed");
13765
+ }
13766
+ } catch {
13767
+ }
13768
+ }
13769
+ const lines = tasks.map((t) => {
13770
+ const age = Math.floor((Date.now() - t.createdAt) / 1e3);
13771
+ const ageStr = age < 60 ? `${age}s ago` : `${Math.floor(age / 60)}m ago`;
13772
+ return `| ${t.taskId} | ${t.status} | ${ageStr} | ${t.description.substring(0, 80)} |`;
13773
+ });
13774
+ return [
13775
+ "| task_id | status | age | description |",
13776
+ "|---------|--------|-----|-------------|",
13777
+ ...lines
13778
+ ].join("\n");
13779
+ },
13780
+ {
13781
+ name: "list_async_tasks",
13782
+ description: "List all async background tasks with their current status. Use this before reporting task status to the user. Statuses in conversation history may be stale.",
13783
+ schema: import_v32.z.object({})
13784
+ }
13785
+ );
13786
+ }
13787
+ function createCancelAsyncTaskTool() {
13788
+ return (0, import_langchain57.tool)(
13789
+ async (input, config) => {
13790
+ const { task_id } = input;
13791
+ const mainAgent = getMainAgentFromConfig(config);
13792
+ if (!mainAgent) {
13793
+ return "Cannot access main agent state.";
13794
+ }
13795
+ const cached = mainAgent.getAsyncTask(task_id);
13796
+ if (!cached) {
13797
+ return `Task ${task_id} not found.`;
13798
+ }
13799
+ try {
13800
+ const subAgentExists = agentInstanceManager.hasAgent({
13801
+ assistant_id: cached.assistantId,
13802
+ thread_id: task_id,
13803
+ tenant_id: mainAgent.tenant_id
13804
+ });
13805
+ if (subAgentExists) {
13806
+ const subAgent = agentInstanceManager.getAgent({
13807
+ assistant_id: cached.assistantId,
13808
+ thread_id: task_id,
13809
+ tenant_id: mainAgent.tenant_id
13810
+ });
13811
+ await subAgent.abort();
13812
+ agentInstanceManager.removeAgent({
13813
+ assistant_id: cached.assistantId,
13814
+ thread_id: task_id,
13815
+ tenant_id: mainAgent.tenant_id
13816
+ });
13817
+ }
13818
+ } catch (err) {
13819
+ return `Failed to cancel task ${task_id}: ${err instanceof Error ? err.message : String(err)}`;
13820
+ }
13821
+ mainAgent.updateAsyncTaskStatus(task_id, "cancelled");
13822
+ return `Task ${task_id} cancelled.`;
13823
+ },
13824
+ {
13825
+ name: "cancel_async_task",
13826
+ description: "Cancel a running async background task.",
13827
+ schema: import_v32.z.object({
13828
+ task_id: import_v32.z.string().describe("The task ID to cancel")
13435
13829
  })
13436
13830
  }
13437
13831
  );
@@ -13445,7 +13839,8 @@ function createSubAgentMiddleware(options) {
13445
13839
  subagents = [],
13446
13840
  systemPrompt = TASK_SYSTEM_PROMPT,
13447
13841
  generalPurposeAgent = true,
13448
- taskDescription = null
13842
+ taskDescription = null,
13843
+ allowAsync = true
13449
13844
  } = options;
13450
13845
  const taskTool = createTaskTool({
13451
13846
  defaultModel,
@@ -13454,17 +13849,27 @@ function createSubAgentMiddleware(options) {
13454
13849
  defaultInterruptOn,
13455
13850
  subagents,
13456
13851
  generalPurposeAgent,
13457
- taskDescription
13852
+ taskDescription,
13853
+ allowAsync
13458
13854
  });
13855
+ const allTools = [taskTool];
13856
+ if (allowAsync) {
13857
+ allTools.push(
13858
+ createCheckAsyncTaskTool(),
13859
+ createListAsyncTasksTool(),
13860
+ createCancelAsyncTaskTool()
13861
+ );
13862
+ }
13863
+ const effectiveSystemPrompt = allowAsync ? systemPrompt + getAsyncPromptText() : systemPrompt;
13459
13864
  return (0, import_langchain57.createMiddleware)({
13460
13865
  name: "subAgentMiddleware",
13461
- tools: [taskTool],
13866
+ tools: allTools,
13462
13867
  wrapModelCall: async (request, handler) => {
13463
- if (systemPrompt !== null) {
13868
+ if (effectiveSystemPrompt !== null) {
13464
13869
  const currentPrompt = request.systemPrompt || "";
13465
13870
  const newPrompt = currentPrompt ? `${currentPrompt}
13466
13871
 
13467
- ${systemPrompt}` : systemPrompt;
13872
+ ${effectiveSystemPrompt}` : effectiveSystemPrompt;
13468
13873
  return handler({
13469
13874
  ...request,
13470
13875
  systemPrompt: newPrompt
@@ -14995,7 +15400,7 @@ var DeepAgentGraphBuilder = class {
14995
15400
  const tools = params.tools.map((t) => {
14996
15401
  const toolClient = getToolClient(t.key);
14997
15402
  return toolClient;
14998
- }).filter((tool50) => tool50 !== void 0);
15403
+ }).filter((tool51) => tool51 !== void 0);
14999
15404
  const subagents = await Promise.all(params.subAgents.map(async (sa) => {
15000
15405
  if (sa.client) {
15001
15406
  return {
@@ -16620,7 +17025,7 @@ var TeamAgentGraphBuilder = class {
16620
17025
  const tools = params.tools.map((t) => {
16621
17026
  const toolClient = getToolClient(t.key);
16622
17027
  return toolClient;
16623
- }).filter((tool50) => tool50 !== void 0);
17028
+ }).filter((tool51) => tool51 !== void 0);
16624
17029
  const teammates = params.subAgents.map((sa) => {
16625
17030
  const baseConfig = sa.config;
16626
17031
  return {
@@ -16657,128 +17062,551 @@ var TeamAgentGraphBuilder = class {
16657
17062
  }
16658
17063
  };
16659
17064
 
16660
- // src/agent_lattice/builders/AgentGraphBuilderFactory.ts
16661
- var AgentGraphBuilderFactory = class _AgentGraphBuilderFactory {
16662
- constructor() {
16663
- this.builders = /* @__PURE__ */ new Map();
16664
- this.registerDefaultBuilders();
16665
- }
16666
- /**
16667
- * 获取单例实例
16668
- */
16669
- static getInstance() {
16670
- if (!_AgentGraphBuilderFactory.instance) {
16671
- _AgentGraphBuilderFactory.instance = new _AgentGraphBuilderFactory();
16672
- }
16673
- return _AgentGraphBuilderFactory.instance;
16674
- }
16675
- /**
16676
- * 注册默认的Builder
16677
- */
16678
- registerDefaultBuilders() {
16679
- this.builders.set(import_protocols.AgentType.REACT, new ReActAgentGraphBuilder());
16680
- this.builders.set(import_protocols.AgentType.DEEP_AGENT, new DeepAgentGraphBuilder());
16681
- this.builders.set(import_protocols.AgentType.TEAM, new TeamAgentGraphBuilder());
16682
- }
16683
- /**
16684
- * 注册自定义Builder
16685
- *
16686
- * @param type Agent类型
16687
- * @param builder Builder实例
16688
- */
16689
- registerBuilder(type, builder) {
16690
- this.builders.set(type, builder);
16691
- }
16692
- /**
16693
- * 获取Builder
16694
- *
16695
- * @param type Agent类型
16696
- * @returns 返回对应的Builder
16697
- */
16698
- getBuilder(type) {
16699
- const builder = this.builders.get(type);
16700
- if (!builder) {
16701
- throw new Error(`\u4E0D\u652F\u6301\u7684Agent\u7C7B\u578B: ${type}`);
16702
- }
16703
- return builder;
16704
- }
16705
- };
17065
+ // src/deep_agent_new/processing_agent.ts
17066
+ var import_langchain66 = require("langchain");
16706
17067
 
16707
- // src/agent_lattice/builders/AgentParamsBuilder.ts
16708
- var import_protocols9 = require("@axiom-lattice/protocols");
16709
- var AgentParamsBuilder = class {
16710
- /**
16711
- * constructor
16712
- *
16713
- * @param getAgentLatticeFunc get Agent Lattice function
16714
- */
16715
- constructor(getAgentLatticeFunc) {
16716
- this.getAgentLatticeFunc = getAgentLatticeFunc;
16717
- }
16718
- /**
16719
- * build Agent parameters
16720
- *
16721
- * @param agentLattice Agent Lattice object
16722
- * @param options build options
16723
- * @returns Agent build parameters
16724
- */
16725
- async buildParams(agentLattice, options) {
16726
- const skills = (0, import_protocols9.isDeepAgentConfig)(agentLattice.config) ? agentLattice.config.skillCategories : void 0;
16727
- const toolKeys = options?.overrideTools || (0, import_protocols9.getToolsFromConfig)(agentLattice.config);
16728
- const tools = toolKeys.map((toolKey) => {
16729
- const toolLattice = toolLatticeManager.getToolLattice(toolKey);
16730
- if (!toolLattice) {
16731
- throw new Error(`Tool "${toolKey}" does not exist`);
17068
+ // src/middlewares/topologyMiddleware.ts
17069
+ var import_langchain64 = require("langchain");
17070
+ var import_messages4 = require("@langchain/core/messages");
17071
+ var import_langchain65 = require("langchain");
17072
+ var import_zod51 = require("zod");
17073
+ var import_langgraph13 = require("@langchain/langgraph");
17074
+ var CompletedEdgeSchema = import_zod51.z.object({
17075
+ to: import_zod51.z.string(),
17076
+ purpose: import_zod51.z.string()
17077
+ });
17078
+ function deriveCompletedEdges(messages, edges) {
17079
+ const completedToolCallIds = /* @__PURE__ */ new Set();
17080
+ for (const msg of messages) {
17081
+ if (msg.name === "task" && msg.tool_call_id && msg.status !== "error") {
17082
+ completedToolCallIds.add(msg.tool_call_id);
17083
+ }
17084
+ }
17085
+ const completed = [];
17086
+ for (const msg of messages) {
17087
+ if (!msg.tool_calls) continue;
17088
+ for (const tc of msg.tool_calls) {
17089
+ if (tc.name !== "task" || !completedToolCallIds.has(tc.id)) continue;
17090
+ const targetAgent = tc.args?.subagent_type;
17091
+ const edge = edges.find(
17092
+ (e) => e.to === targetAgent
17093
+ );
17094
+ if (edge && !completed.some((e) => e.to === edge.to)) {
17095
+ completed.push({ to: edge.to, purpose: edge.purpose });
16732
17096
  }
16733
- return {
16734
- key: toolKey,
16735
- definition: toolLattice.config,
16736
- executor: toolLattice.client
16737
- };
16738
- });
16739
- const modelKey = options?.overrideModel || agentLattice.config.modelKey;
16740
- const model = modelKey ? modelLatticeManager.getModelLattice(modelKey).client : modelLatticeManager.getModelLattice("default").client;
16741
- if (!model) {
16742
- throw new Error(`Model "${modelKey}" does not exist`);
16743
17097
  }
16744
- const subAgentKeys = (0, import_protocols9.getSubAgentsFromConfig)(agentLattice.config);
16745
- const subAgents = await Promise.all(subAgentKeys.map(async (agentKey) => {
16746
- const subAgentLattice = await this.getAgentLatticeFunc(agentKey);
16747
- if (!subAgentLattice) {
16748
- throw new Error(`SubAgent "${agentKey}" does not exist`);
17098
+ }
17099
+ return completed;
17100
+ }
17101
+ function createTopologyMiddleware(options) {
17102
+ const { edges, trackingStore } = options;
17103
+ return (0, import_langchain64.createMiddleware)({
17104
+ name: "TopologyMiddleware",
17105
+ contextSchema: import_zod51.z.object({
17106
+ runConfig: import_zod51.z.any()
17107
+ }),
17108
+ stateSchema: import_zod51.z.object({
17109
+ currentAgentId: import_zod51.z.string().default(""),
17110
+ completedEdges: import_zod51.z.array(CompletedEdgeSchema).default([]),
17111
+ runId: import_zod51.z.string().default(""),
17112
+ stepIdMap: import_zod51.z.record(import_zod51.z.string()).default({})
17113
+ }),
17114
+ beforeAgent: async (state, runtime) => {
17115
+ const runConfig = runtime.context?.runConfig ?? {};
17116
+ const startingNode = edges[0]?.from ?? runConfig.assistant_id ?? "";
17117
+ let runId = "";
17118
+ if (trackingStore) {
17119
+ try {
17120
+ const run = await trackingStore.createWorkflowRun({
17121
+ tenantId: runConfig.tenantId || "default",
17122
+ assistantId: runConfig.assistant_id ?? "",
17123
+ threadId: runConfig.thread_id ?? "",
17124
+ topologyEdges: edges
17125
+ });
17126
+ runId = run.id;
17127
+ } catch (err) {
17128
+ console.error("[topologyMiddleware] Failed to create WorkflowRun:", err);
17129
+ }
16749
17130
  }
16750
17131
  return {
16751
- key: agentKey,
16752
- config: subAgentLattice.config,
16753
- client: subAgentLattice.client
17132
+ currentAgentId: startingNode,
17133
+ completedEdges: [],
17134
+ runId,
17135
+ stepIdMap: {}
16754
17136
  };
16755
- }));
16756
- let internalSubAgents = [];
16757
- if ((0, import_protocols9.isDeepAgentConfig)(agentLattice.config)) {
16758
- internalSubAgents = agentLattice.config.internalSubAgents?.map((i) => ({
16759
- key: i.key,
16760
- config: i
16761
- })) || [];
16762
- }
16763
- return {
16764
- tools,
16765
- model,
16766
- subAgents: [...subAgents, ...internalSubAgents],
16767
- prompt: agentLattice.config.prompt,
16768
- stateSchema: agentLattice.config.schema,
16769
- skillCategories: skills,
16770
- middleware: agentLattice.config.middleware,
16771
- tenantId: agentLattice.config.tenantId
16772
- };
16773
- }
16774
- };
17137
+ },
17138
+ wrapModelCall: async (request, handler) => {
17139
+ const steps = edges.map((e, i) => `${i + 1}. \`${e.from}\` \u2192 \`${e.to}\` \u2014 ${e.purpose}`).join("\n");
17140
+ const topologyPrompt = `## Workflow Execution Plan
16775
17141
 
16776
- // src/agent_lattice/utils/mergeAgentConfig.ts
16777
- var NON_INHERITABLE_FIELDS = /* @__PURE__ */ new Set([
16778
- "key",
16779
- "extendsAgent"
16780
- ]);
16781
- function mergeAgentConfig(parent, child) {
17142
+ Your job is to execute this workflow by delegating each step to the specialized agent
17143
+ shown below. This is your core execution process \u2014 it is not optional.
17144
+
17145
+ ${steps || "(no workflow steps defined)"}
17146
+
17147
+ Use the \`task\` tool to delegate work to each agent. Call \`read_topo_progress\` to
17148
+ see which steps are done and which are still pending.
17149
+
17150
+ Do NOT delegate to any agent outside the current node's allowed paths \u2014 such attempts
17151
+ will be blocked.`;
17152
+ const newSystemPrompt = request.systemPrompt ? `${topologyPrompt}
17153
+
17154
+ ---
17155
+
17156
+ ${request.systemPrompt}` : topologyPrompt;
17157
+ return handler({ ...request, systemPrompt: newSystemPrompt });
17158
+ },
17159
+ tools: [
17160
+ (0, import_langchain65.tool)(
17161
+ async (_input) => {
17162
+ return "placeholder";
17163
+ },
17164
+ {
17165
+ name: "read_topo_progress",
17166
+ description: "Check the current progress of the workflow execution plan. Returns which steps have been completed and which are still pending.",
17167
+ schema: import_zod51.z.object({})
17168
+ }
17169
+ )
17170
+ ],
17171
+ wrapToolCall: async (request, handler) => {
17172
+ if (request.toolCall?.name === "read_topo_progress") {
17173
+ const currentAgentId = request.state?.currentAgentId || "";
17174
+ const completedEdges = request.state?.completedEdges || [];
17175
+ const doneSet = new Set(completedEdges.map((e) => e.to));
17176
+ const progress = edges.map((e) => ({
17177
+ agent: e.to,
17178
+ purpose: e.purpose,
17179
+ status: doneSet.has(e.to) ? "done" : "pending"
17180
+ }));
17181
+ const doneCount = completedEdges.length;
17182
+ return new import_messages4.ToolMessage({
17183
+ content: JSON.stringify(
17184
+ {
17185
+ currentAgentId,
17186
+ progress: `${doneCount}/${edges.length} edges completed`,
17187
+ steps: progress,
17188
+ nextPending: progress.filter((s) => s.status === "pending").map((s) => s.agent)
17189
+ },
17190
+ null,
17191
+ 2
17192
+ ),
17193
+ name: "read_topo_progress",
17194
+ tool_call_id: request.toolCall.id
17195
+ });
17196
+ }
17197
+ try {
17198
+ return await handler(request);
17199
+ } catch (error) {
17200
+ if (error instanceof import_langgraph13.GraphInterrupt) {
17201
+ throw error;
17202
+ }
17203
+ throw error;
17204
+ }
17205
+ },
17206
+ afterModel: {
17207
+ canJumpTo: ["model"],
17208
+ hook: async (state, runtime) => {
17209
+ const { messages, runId, stepIdMap: prevStepIdMap } = state;
17210
+ let { currentAgentId } = state;
17211
+ const runConfig = runtime.context?.runConfig ?? {};
17212
+ const stepIdMap = { ...prevStepIdMap };
17213
+ if (!messages || messages.length === 0) return;
17214
+ const lastMessage = messages[messages.length - 1];
17215
+ if ("tool_calls" in lastMessage) {
17216
+ for (const tc of lastMessage.tool_calls) {
17217
+ if (tc.name !== "task") continue;
17218
+ const targetAgent = tc.args?.subagent_type;
17219
+ const edge = edges.find(
17220
+ (e) => e.from === currentAgentId && e.to === targetAgent
17221
+ );
17222
+ if (!edge) {
17223
+ const myEdges = edges.filter(
17224
+ (e) => e.from === currentAgentId
17225
+ );
17226
+ console.warn(
17227
+ JSON.stringify({
17228
+ event: "topology_violation",
17229
+ currentAgentId,
17230
+ targetAgent,
17231
+ description: tc.args?.description,
17232
+ allowedTargets: myEdges.map((e) => e.to),
17233
+ threadId: runtime.configurable?.thread_id,
17234
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
17235
+ })
17236
+ );
17237
+ const allowedList = myEdges.length > 0 ? [
17238
+ `Agent \`${currentAgentId}\` may only delegate to:`,
17239
+ ...myEdges.map(
17240
+ (e) => `- \`${e.to}\` \u2014 ${e.purpose}`
17241
+ )
17242
+ ] : [
17243
+ `Agent \`${currentAgentId}\` has no outgoing delegation edges configured.`
17244
+ ];
17245
+ return {
17246
+ messages: [
17247
+ new import_messages4.AIMessage({
17248
+ content: [
17249
+ `Task rejected: topology violation.`,
17250
+ `Agent "${currentAgentId}" is not allowed to delegate to "${targetAgent}".`,
17251
+ ...allowedList,
17252
+ `Please delegate to one of the allowed agents above or handle the task yourself.`
17253
+ ].join("\n")
17254
+ })
17255
+ ],
17256
+ jumpTo: "model"
17257
+ };
17258
+ }
17259
+ currentAgentId = edge.to;
17260
+ if (trackingStore && runId) {
17261
+ try {
17262
+ const step = await trackingStore.createRunStep({
17263
+ runId,
17264
+ tenantId: runConfig.tenantId || "default",
17265
+ stepType: "task_delegation",
17266
+ stepName: targetAgent,
17267
+ edgeFrom: edge.from,
17268
+ edgeTo: edge.to,
17269
+ edgePurpose: edge.purpose,
17270
+ input: { description: tc.args?.description }
17271
+ });
17272
+ stepIdMap[edge.to] = step.id;
17273
+ } catch (err) {
17274
+ console.error("[topologyMiddleware] Failed to create RunStep:", err);
17275
+ }
17276
+ }
17277
+ }
17278
+ }
17279
+ const completedEdges = deriveCompletedEdges(
17280
+ messages,
17281
+ edges
17282
+ );
17283
+ if (trackingStore && runId) {
17284
+ for (const ce of completedEdges) {
17285
+ const stepId = stepIdMap[ce.to];
17286
+ if (!stepId) continue;
17287
+ let output;
17288
+ for (const msg of messages) {
17289
+ if (msg.name === "task" && msg.tool_call_id) {
17290
+ for (const tc of messages.find(
17291
+ (m) => m.tool_calls?.some((c) => c.id === msg.tool_call_id)
17292
+ )?.tool_calls || []) {
17293
+ if (tc.id === msg.tool_call_id && tc.args?.subagent_type === ce.to) {
17294
+ output = msg.content;
17295
+ break;
17296
+ }
17297
+ }
17298
+ if (output) break;
17299
+ }
17300
+ }
17301
+ if (output) {
17302
+ try {
17303
+ await trackingStore.updateRunStep(runId, stepId, {
17304
+ status: "completed",
17305
+ output: { result: output },
17306
+ completedAt: /* @__PURE__ */ new Date()
17307
+ });
17308
+ } catch (err) {
17309
+ console.error("[topologyMiddleware] Failed to update RunStep output:", err);
17310
+ }
17311
+ }
17312
+ }
17313
+ }
17314
+ if (trackingStore && runId) {
17315
+ try {
17316
+ await trackingStore.updateWorkflowRun(runId, {
17317
+ completedEdges: completedEdges.length
17318
+ });
17319
+ } catch (err) {
17320
+ console.error("[topologyMiddleware] Failed to update WorkflowRun completedEdges:", err);
17321
+ }
17322
+ }
17323
+ return { currentAgentId, completedEdges, stepIdMap };
17324
+ }
17325
+ },
17326
+ afterAgent: async (state, runtime) => {
17327
+ const { runId, completedEdges } = state;
17328
+ if (!trackingStore || !runId) return;
17329
+ const allDone = completedEdges && completedEdges.length >= edges.length;
17330
+ if (!allDone) return;
17331
+ try {
17332
+ await trackingStore.updateWorkflowRun(runId, {
17333
+ status: "completed",
17334
+ completedAt: /* @__PURE__ */ new Date()
17335
+ });
17336
+ } catch (err) {
17337
+ console.error("[topologyMiddleware] Failed to finalize WorkflowRun:", err);
17338
+ }
17339
+ }
17340
+ });
17341
+ }
17342
+
17343
+ // src/deep_agent_new/processing_agent.ts
17344
+ var BASE_PROMPT2 = `In order to complete the objective that the user asks of you, you have access to a number of standard tools.`;
17345
+ function createProcessingAgent(params) {
17346
+ const {
17347
+ model = "claude-sonnet-4-5-20250929",
17348
+ tools = [],
17349
+ systemPrompt,
17350
+ middleware: customMiddleware = [],
17351
+ subagents = [],
17352
+ responseFormat,
17353
+ contextSchema: contextSchema2,
17354
+ checkpointer,
17355
+ store,
17356
+ backend,
17357
+ interruptOn,
17358
+ name,
17359
+ skills,
17360
+ topologyEdges
17361
+ } = params;
17362
+ const finalSystemPrompt = systemPrompt ? `${systemPrompt}
17363
+
17364
+ ${BASE_PROMPT2}` : BASE_PROMPT2;
17365
+ const filesystemBackend = backend ? backend : async (config) => new StateBackend(config);
17366
+ let trackingStore;
17367
+ try {
17368
+ const storeLattice = getStoreLattice("default", "workflowTracking");
17369
+ trackingStore = storeLattice.store;
17370
+ } catch {
17371
+ }
17372
+ const middleware = [
17373
+ // Workflow topology enforcement — replaces todoListMiddleware
17374
+ createTopologyMiddleware({ edges: topologyEdges, trackingStore }),
17375
+ // Enables filesystem operations and optional long-term memory storage
17376
+ createFilesystemMiddleware({ backend: filesystemBackend }),
17377
+ // Enables delegation to specialized subagents for complex tasks
17378
+ createSubAgentMiddleware({
17379
+ defaultModel: model,
17380
+ defaultTools: tools,
17381
+ defaultMiddleware: [
17382
+ // Subagent middleware: Todo list management (subagents get todo, not topology)
17383
+ todoListMiddleware(),
17384
+ // Subagent middleware: Filesystem operations
17385
+ createFilesystemMiddleware({
17386
+ backend: filesystemBackend
17387
+ }),
17388
+ // Subagent middleware: Automatic conversation summarization
17389
+ (0, import_langchain66.summarizationMiddleware)({
17390
+ model,
17391
+ trigger: { tokens: 17e4 },
17392
+ keep: { messages: 6 }
17393
+ }),
17394
+ // Subagent middleware: Anthropic prompt caching
17395
+ (0, import_langchain66.anthropicPromptCachingMiddleware)({
17396
+ unsupportedModelBehavior: "ignore"
17397
+ }),
17398
+ // Subagent middleware: Patches tool calls
17399
+ createPatchToolCallsMiddleware(),
17400
+ ...customMiddleware
17401
+ ],
17402
+ defaultInterruptOn: interruptOn,
17403
+ subagents,
17404
+ generalPurposeAgent: true,
17405
+ allowAsync: false
17406
+ }),
17407
+ // Automatically summarizes conversation history
17408
+ (0, import_langchain66.summarizationMiddleware)({
17409
+ model,
17410
+ trigger: { tokens: 17e4 },
17411
+ keep: { messages: 6 }
17412
+ }),
17413
+ // Enables Anthropic prompt caching
17414
+ (0, import_langchain66.anthropicPromptCachingMiddleware)({
17415
+ unsupportedModelBehavior: "ignore"
17416
+ }),
17417
+ // Patches tool calls
17418
+ createPatchToolCallsMiddleware()
17419
+ ];
17420
+ if (interruptOn) {
17421
+ middleware.push((0, import_langchain66.humanInTheLoopMiddleware)({ interruptOn }));
17422
+ }
17423
+ middleware.push(...customMiddleware);
17424
+ return (0, import_langchain66.createAgent)({
17425
+ model,
17426
+ systemPrompt: finalSystemPrompt,
17427
+ tools,
17428
+ middleware,
17429
+ responseFormat,
17430
+ contextSchema: contextSchema2,
17431
+ checkpointer,
17432
+ store,
17433
+ name
17434
+ });
17435
+ }
17436
+
17437
+ // src/agent_lattice/builders/ProcessingAgentGraphBuilder.ts
17438
+ var ProcessingAgentGraphBuilder = class {
17439
+ async build(agentLattice, params) {
17440
+ const tools = params.tools.map((t) => {
17441
+ const toolClient = getToolClient(t.key);
17442
+ return toolClient;
17443
+ }).filter((tool51) => tool51 !== void 0);
17444
+ const subagents = await Promise.all(params.subAgents.map(async (sa) => {
17445
+ if (sa.client) {
17446
+ return {
17447
+ key: sa.config.key,
17448
+ name: sa.config.name,
17449
+ description: sa.config.description,
17450
+ runnable: sa.client
17451
+ };
17452
+ } else {
17453
+ const subagentClient = await createAgentClientFromAgentLattice({
17454
+ config: sa.config
17455
+ });
17456
+ return {
17457
+ key: sa.config.key,
17458
+ name: sa.config.name,
17459
+ description: sa.config.description,
17460
+ runnable: subagentClient
17461
+ };
17462
+ }
17463
+ }));
17464
+ const middlewareConfigs = params.middleware || [];
17465
+ const filesystemBackend = createFilesystemBackendFactory(middlewareConfigs);
17466
+ const middlewares = await createCommonMiddlewares(middlewareConfigs, filesystemBackend, true);
17467
+ const topologyConfig = middlewareConfigs.find(
17468
+ (m) => m.type === "topology" && m.enabled
17469
+ );
17470
+ const topologyEdges = topologyConfig?.config?.edges || [];
17471
+ const processingAgent = createProcessingAgent({
17472
+ tools,
17473
+ model: params.model,
17474
+ contextSchema: params.stateSchema,
17475
+ systemPrompt: params.prompt,
17476
+ subagents,
17477
+ checkpointer: getCheckpointSaver("default"),
17478
+ skills: params.skillCategories,
17479
+ backend: filesystemBackend,
17480
+ middleware: middlewares,
17481
+ topologyEdges
17482
+ });
17483
+ return processingAgent;
17484
+ }
17485
+ };
17486
+
17487
+ // src/agent_lattice/builders/AgentGraphBuilderFactory.ts
17488
+ var AgentGraphBuilderFactory = class _AgentGraphBuilderFactory {
17489
+ constructor() {
17490
+ this.builders = /* @__PURE__ */ new Map();
17491
+ this.registerDefaultBuilders();
17492
+ }
17493
+ /**
17494
+ * 获取单例实例
17495
+ */
17496
+ static getInstance() {
17497
+ if (!_AgentGraphBuilderFactory.instance) {
17498
+ _AgentGraphBuilderFactory.instance = new _AgentGraphBuilderFactory();
17499
+ }
17500
+ return _AgentGraphBuilderFactory.instance;
17501
+ }
17502
+ /**
17503
+ * 注册默认的Builder
17504
+ */
17505
+ registerDefaultBuilders() {
17506
+ this.builders.set(import_protocols.AgentType.REACT, new ReActAgentGraphBuilder());
17507
+ this.builders.set(import_protocols.AgentType.DEEP_AGENT, new DeepAgentGraphBuilder());
17508
+ this.builders.set(import_protocols.AgentType.TEAM, new TeamAgentGraphBuilder());
17509
+ this.builders.set(import_protocols.AgentType.PROCESSING, new ProcessingAgentGraphBuilder());
17510
+ }
17511
+ /**
17512
+ * 注册自定义Builder
17513
+ *
17514
+ * @param type Agent类型
17515
+ * @param builder Builder实例
17516
+ */
17517
+ registerBuilder(type, builder) {
17518
+ this.builders.set(type, builder);
17519
+ }
17520
+ /**
17521
+ * 获取Builder
17522
+ *
17523
+ * @param type Agent类型
17524
+ * @returns 返回对应的Builder
17525
+ */
17526
+ getBuilder(type) {
17527
+ const builder = this.builders.get(type);
17528
+ if (!builder) {
17529
+ throw new Error(`\u4E0D\u652F\u6301\u7684Agent\u7C7B\u578B: ${type}`);
17530
+ }
17531
+ return builder;
17532
+ }
17533
+ };
17534
+
17535
+ // src/agent_lattice/builders/AgentParamsBuilder.ts
17536
+ var import_protocols9 = require("@axiom-lattice/protocols");
17537
+ var AgentParamsBuilder = class {
17538
+ /**
17539
+ * constructor
17540
+ *
17541
+ * @param getAgentLatticeFunc get Agent Lattice function
17542
+ */
17543
+ constructor(getAgentLatticeFunc) {
17544
+ this.getAgentLatticeFunc = getAgentLatticeFunc;
17545
+ }
17546
+ /**
17547
+ * build Agent parameters
17548
+ *
17549
+ * @param agentLattice Agent Lattice object
17550
+ * @param options build options
17551
+ * @returns Agent build parameters
17552
+ */
17553
+ async buildParams(agentLattice, options) {
17554
+ const skills = (0, import_protocols9.isDeepAgentConfig)(agentLattice.config) || (0, import_protocols9.isProcessingAgentConfig)(agentLattice.config) ? agentLattice.config.skillCategories : void 0;
17555
+ const toolKeys = options?.overrideTools || (0, import_protocols9.getToolsFromConfig)(agentLattice.config);
17556
+ const tools = toolKeys.map((toolKey) => {
17557
+ const toolLattice = toolLatticeManager.getToolLattice(toolKey);
17558
+ if (!toolLattice) {
17559
+ throw new Error(`Tool "${toolKey}" does not exist`);
17560
+ }
17561
+ return {
17562
+ key: toolKey,
17563
+ definition: toolLattice.config,
17564
+ executor: toolLattice.client
17565
+ };
17566
+ });
17567
+ const modelKey = options?.overrideModel || agentLattice.config.modelKey;
17568
+ const model = modelKey ? modelLatticeManager.getModelLattice(modelKey).client : modelLatticeManager.getModelLattice("default").client;
17569
+ if (!model) {
17570
+ throw new Error(`Model "${modelKey}" does not exist`);
17571
+ }
17572
+ const subAgentKeys = (0, import_protocols9.getSubAgentsFromConfig)(agentLattice.config);
17573
+ const subAgents = await Promise.all(subAgentKeys.map(async (agentKey) => {
17574
+ const subAgentLattice = await this.getAgentLatticeFunc(agentKey);
17575
+ if (!subAgentLattice) {
17576
+ throw new Error(`SubAgent "${agentKey}" does not exist`);
17577
+ }
17578
+ return {
17579
+ key: agentKey,
17580
+ config: subAgentLattice.config,
17581
+ client: subAgentLattice.client
17582
+ };
17583
+ }));
17584
+ let internalSubAgents = [];
17585
+ if ((0, import_protocols9.isDeepAgentConfig)(agentLattice.config) || (0, import_protocols9.isProcessingAgentConfig)(agentLattice.config)) {
17586
+ internalSubAgents = agentLattice.config.internalSubAgents?.map((i) => ({
17587
+ key: i.key,
17588
+ config: i
17589
+ })) || [];
17590
+ }
17591
+ return {
17592
+ tools,
17593
+ model,
17594
+ subAgents: [...subAgents, ...internalSubAgents],
17595
+ prompt: agentLattice.config.prompt,
17596
+ stateSchema: agentLattice.config.schema,
17597
+ skillCategories: skills,
17598
+ middleware: agentLattice.config.middleware,
17599
+ tenantId: agentLattice.config.tenantId
17600
+ };
17601
+ }
17602
+ };
17603
+
17604
+ // src/agent_lattice/utils/mergeAgentConfig.ts
17605
+ var NON_INHERITABLE_FIELDS = /* @__PURE__ */ new Set([
17606
+ "key",
17607
+ "extendsAgent"
17608
+ ]);
17609
+ function mergeAgentConfig(parent, child) {
16782
17610
  const merged = { ...parent };
16783
17611
  for (const [key, value] of Object.entries(child)) {
16784
17612
  if (NON_INHERITABLE_FIELDS.has(key)) {
@@ -17193,98 +18021,1105 @@ ${body}` : `${frontmatter}
17193
18021
  subSkills: updates.subSkills !== void 0 ? updates.subSkills : skill.subSkills,
17194
18022
  updatedAt: /* @__PURE__ */ new Date()
17195
18023
  };
17196
- await this.writeSkillFile(newSkill, context);
17197
- await this.deleteSkill(tenantId, id, context);
17198
- return newSkill;
18024
+ await this.writeSkillFile(newSkill, context);
18025
+ await this.deleteSkill(tenantId, id, context);
18026
+ return newSkill;
18027
+ }
18028
+ }
18029
+ const updatedSkill = {
18030
+ ...skill,
18031
+ name: updates.name ?? skill.name,
18032
+ description: updates.description ?? skill.description,
18033
+ license: updates.license ?? skill.license,
18034
+ compatibility: updates.compatibility ?? skill.compatibility,
18035
+ metadata: updates.metadata ?? skill.metadata,
18036
+ content: updates.content !== void 0 ? updates.content : skill.content,
18037
+ subSkills: updates.subSkills !== void 0 ? updates.subSkills : skill.subSkills,
18038
+ updatedAt: /* @__PURE__ */ new Date()
18039
+ };
18040
+ await this.writeSkillFile(updatedSkill, context);
18041
+ return updatedSkill;
18042
+ }
18043
+ /**
18044
+ * Delete a skill by ID
18045
+ */
18046
+ async deleteSkill(tenantId, id, context) {
18047
+ if (isBuiltInSkill(id)) {
18048
+ throw new Error(
18049
+ `Skill "${id}" is a built-in skill and cannot be deleted`
18050
+ );
18051
+ }
18052
+ try {
18053
+ const sandbox = await this.getSandbox(tenantId, context);
18054
+ const dirPath = this.getSkillDirectoryPath(tenantId, id);
18055
+ const deleteResult = await sandbox.shell.execCommand({
18056
+ command: `rm -rf ${dirPath}`
18057
+ });
18058
+ if (deleteResult.exit_code !== 0) {
18059
+ return false;
18060
+ }
18061
+ return true;
18062
+ } catch (error) {
18063
+ console.error(`Error deleting skill ${id}:`, error);
18064
+ return false;
18065
+ }
18066
+ }
18067
+ /**
18068
+ * Check if skill exists
18069
+ */
18070
+ async hasSkill(tenantId, id, context) {
18071
+ if (isBuiltInSkill(id)) return true;
18072
+ const skill = await this.getSkillById(tenantId, id, context);
18073
+ return skill !== null;
18074
+ }
18075
+ /**
18076
+ * Search skills by metadata within a tenant
18077
+ */
18078
+ async searchByMetadata(tenantId, metadataKey, metadataValue, context) {
18079
+ const allSkills = await this.getAllSkills(tenantId, context);
18080
+ return allSkills.filter(
18081
+ (skill) => skill.metadata && skill.metadata[metadataKey] === metadataValue
18082
+ );
18083
+ }
18084
+ /**
18085
+ * Filter skills by compatibility within a tenant
18086
+ */
18087
+ async filterByCompatibility(tenantId, compatibility, context) {
18088
+ const allSkills = await this.getAllSkills(tenantId, context);
18089
+ return allSkills.filter((skill) => skill.compatibility === compatibility);
18090
+ }
18091
+ /**
18092
+ * Filter skills by license within a tenant
18093
+ */
18094
+ async filterByLicense(tenantId, license, context) {
18095
+ const allSkills = await this.getAllSkills(tenantId, context);
18096
+ return allSkills.filter((skill) => skill.license === license);
18097
+ }
18098
+ /**
18099
+ * Get sub-skills of a parent skill within a tenant
18100
+ */
18101
+ async getSubSkills(tenantId, parentSkillName, context) {
18102
+ const parentSkill = await this.getSkillById(tenantId, parentSkillName, context);
18103
+ if (!parentSkill || !parentSkill.subSkills || parentSkill.subSkills.length === 0) {
18104
+ return [];
18105
+ }
18106
+ const subSkills = [];
18107
+ for (const subSkillName of parentSkill.subSkills) {
18108
+ const subSkill = await this.getSkillById(tenantId, subSkillName, context);
18109
+ if (subSkill) {
18110
+ subSkills.push(subSkill);
18111
+ }
18112
+ }
18113
+ return subSkills;
18114
+ }
18115
+ };
18116
+
18117
+ // src/agent_lattice/agentArchitectTools.ts
18118
+ var import_zod52 = __toESM(require("zod"));
18119
+ var import_uuid4 = require("uuid");
18120
+ var import_protocols10 = require("@axiom-lattice/protocols");
18121
+ function getTenantId(exeConfig) {
18122
+ const runConfig = exeConfig?.configurable?.runConfig || {};
18123
+ return runConfig.tenantId || "default";
18124
+ }
18125
+ function getAssistStore() {
18126
+ return getStoreLattice("default", "assistant").store;
18127
+ }
18128
+ function slugify(name) {
18129
+ return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").replace(/-+/g, "-") || "agent";
18130
+ }
18131
+ async function generateAgentId(tenantId, name) {
18132
+ const store = getAssistStore();
18133
+ const base = slugify(name);
18134
+ let id = base;
18135
+ let counter = 2;
18136
+ while (true) {
18137
+ const existing = await store.getAssistantById(tenantId, id);
18138
+ if (!existing) return id;
18139
+ id = `${base}-${counter}`;
18140
+ counter++;
18141
+ }
18142
+ }
18143
+ registerToolLattice(
18144
+ "list_agents",
18145
+ {
18146
+ name: "list_agents",
18147
+ description: "List all agents for the current workspace. Returns a summary with id, name, description, and type for each agent.",
18148
+ schema: import_zod52.default.object({})
18149
+ },
18150
+ async (_input, exeConfig) => {
18151
+ try {
18152
+ const tenantId = getTenantId(exeConfig);
18153
+ const store = getAssistStore();
18154
+ const agents = await store.getAllAssistants(tenantId);
18155
+ return JSON.stringify({
18156
+ agents: agents.map((a) => ({
18157
+ id: a.id,
18158
+ name: a.name,
18159
+ description: a.description || "",
18160
+ type: a.graphDefinition?.type || "react",
18161
+ createdAt: a.createdAt,
18162
+ updatedAt: a.updatedAt
18163
+ }))
18164
+ });
18165
+ } catch (error) {
18166
+ return JSON.stringify({ error: `Failed to list agents: ${error.message}` });
18167
+ }
18168
+ }
18169
+ );
18170
+ registerToolLattice(
18171
+ "get_agent",
18172
+ {
18173
+ name: "get_agent",
18174
+ description: "Get the full configuration of a specific agent by its ID. Returns the complete AgentConfig including prompt, middleware, tools, and sub-agents.",
18175
+ schema: import_zod52.default.object({
18176
+ id: import_zod52.default.string().describe("The agent ID to retrieve")
18177
+ })
18178
+ },
18179
+ async (input, exeConfig) => {
18180
+ try {
18181
+ const tenantId = getTenantId(exeConfig);
18182
+ const store = getAssistStore();
18183
+ const agent = await store.getAssistantById(tenantId, input.id);
18184
+ if (!agent) {
18185
+ return JSON.stringify({ error: `Agent '${input.id}' not found` });
18186
+ }
18187
+ return JSON.stringify(agent.graphDefinition);
18188
+ } catch (error) {
18189
+ return JSON.stringify({ error: `Failed to get agent: ${error.message}` });
18190
+ }
18191
+ }
18192
+ );
18193
+ var middlewareConfigSchema = import_zod52.default.object({
18194
+ id: import_zod52.default.string(),
18195
+ type: import_zod52.default.string(),
18196
+ name: import_zod52.default.string(),
18197
+ description: import_zod52.default.string(),
18198
+ enabled: import_zod52.default.boolean(),
18199
+ config: import_zod52.default.record(import_zod52.default.any()).optional()
18200
+ });
18201
+ var createAgentSchema = import_zod52.default.object({
18202
+ name: import_zod52.default.string().describe("Human-friendly display name for the agent. The machine ID (used in other tools) is auto-generated as a slug from this name (e.g. 'My Cool Agent' \u2192 'my-cool-agent')."),
18203
+ description: import_zod52.default.string().optional().describe("Short description"),
18204
+ type: import_zod52.default.enum(["react", "deep_agent"]).describe("Agent type. Use 'react' for simple single-responsibility agents, 'deep_agent' for complex open-ended agents. For PROCESSING agents (workflow orchestration), use create_processing_agent instead."),
18205
+ prompt: import_zod52.default.string().describe("System prompt for the agent"),
18206
+ tools: import_zod52.default.array(import_zod52.default.string()).optional().describe("Tool keys (strings) to assign. Call list_tools first to see available keys. Each element is a plain string like 'sap_api_search'. IMPORTANT: tools is a FLAT string array of tool names. Do NOT put middleware-like objects here \u2014 middleware goes in the separate 'middleware' field."),
18207
+ middleware: import_zod52.default.array(middlewareConfigSchema).optional().describe("Middleware configuration objects. Each has {id, type, name, description, enabled, config}. IMPORTANT: middleware objects are NOT tools. Do NOT put tool keys (strings) here \u2014 tool names go in the separate 'tools' array. For user approval/confirmation scenarios, use type: 'ask_user_to_clarify' with config: {}."),
18208
+ subAgents: import_zod52.default.array(import_zod52.default.string()).optional().describe("Sub-agent IDs (deep_agent only)"),
18209
+ internalSubAgents: import_zod52.default.array(import_zod52.default.any()).optional().describe("Inline sub-agent configs (deep_agent only)"),
18210
+ modelKey: import_zod52.default.string().optional().describe("Model key to use")
18211
+ });
18212
+ registerToolLattice(
18213
+ "create_agent",
18214
+ {
18215
+ name: "create_agent",
18216
+ description: "Create and save a new REACT or DEEP_AGENT. For PROCESSING agents, use create_processing_agent instead. Returns the new agent's ID and name. NOTE: 'tools' is a string array of tool names, 'middleware' is an object array of middleware configs \u2014 they are separate fields and must not be mixed. IMPORTANT: If the agent needs user confirmation, approval, or must ask clarifying questions, include the 'ask_user_to_clarify' middleware (type: 'ask_user_to_clarify', no config required).",
18217
+ schema: createAgentSchema
18218
+ },
18219
+ async (input, exeConfig) => {
18220
+ try {
18221
+ const tenantId = getTenantId(exeConfig);
18222
+ const store = getAssistStore();
18223
+ const id = await generateAgentId(tenantId, input.name);
18224
+ const config = {
18225
+ key: id,
18226
+ name: input.name,
18227
+ description: input.description || "",
18228
+ type: input.type === "deep_agent" ? import_protocols10.AgentType.DEEP_AGENT : import_protocols10.AgentType.REACT,
18229
+ prompt: input.prompt,
18230
+ ...input.tools && input.tools.length > 0 ? { tools: input.tools } : {},
18231
+ ...input.middleware && input.middleware.length > 0 ? { middleware: input.middleware } : {},
18232
+ ...input.subAgents && input.subAgents.length > 0 ? { subAgents: input.subAgents } : {},
18233
+ ...input.internalSubAgents ? { internalSubAgents: input.internalSubAgents } : {},
18234
+ ...input.modelKey ? { modelKey: input.modelKey } : {}
18235
+ };
18236
+ await store.createAssistant(tenantId, id, {
18237
+ name: input.name,
18238
+ description: input.description,
18239
+ graphDefinition: config
18240
+ });
18241
+ return JSON.stringify({ id, name: input.name, type: input.type });
18242
+ } catch (error) {
18243
+ return JSON.stringify({ error: `Failed to create agent: ${error.message}` });
18244
+ }
18245
+ }
18246
+ );
18247
+ var topologyEdgeSchema = import_zod52.default.object({
18248
+ from: import_zod52.default.string().describe("Source agent ID. For the first edge, this is the orchestrator (use the orchestrator's name as a placeholder \u2014 the tool will replace it with the actual ID). For subsequent chained edges, this is the previous stage's sub-agent ID."),
18249
+ to: import_zod52.default.string().describe("Target agent ID (the sub-agent to delegate to)"),
18250
+ purpose: import_zod52.default.string().describe("Business purpose of this delegation step \u2014 what the sub-agent should accomplish")
18251
+ });
18252
+ var createProcessingAgentSchema = import_zod52.default.object({
18253
+ name: import_zod52.default.string().describe("Display name for the processing agent"),
18254
+ description: import_zod52.default.string().optional().describe("Short description"),
18255
+ prompt: import_zod52.default.string().describe("System prompt for the orchestrator. Should describe how to route tasks through the topology."),
18256
+ edges: import_zod52.default.array(topologyEdgeSchema).min(1).describe("Topology edges defining the workflow. Each edge describes a delegation step with its business purpose. The orchestrator will follow this topology to delegate tasks to sub-agents."),
18257
+ tools: import_zod52.default.array(import_zod52.default.string()).optional().describe("Tool keys (strings) to assign to the orchestrator. Call list_tools first to see available keys. Each element is a plain string like 'sap_api_search'. IMPORTANT: tools is a FLAT string array. Do NOT put middleware-like objects here \u2014 middleware goes in the separate 'middleware' field."),
18258
+ subAgents: import_zod52.default.array(import_zod52.default.string()).describe("IDs of sub-agents that form the workflow pipeline. These must be created first via create_agent."),
18259
+ internalSubAgents: import_zod52.default.array(import_zod52.default.any()).optional().describe("Inline sub-agent configs (alternative to pre-created sub-agents)"),
18260
+ middleware: import_zod52.default.array(middlewareConfigSchema).optional().describe("Additional middleware config objects beyond the auto-managed topology middleware. Each has {id, type, name, description, enabled, config}. IMPORTANT: middleware objects are NOT tools. Do NOT put tool keys (strings) here. For user approval/confirmation scenarios, use type: 'ask_user_to_clarify' with config: {}."),
18261
+ modelKey: import_zod52.default.string().optional().describe("Model key to use")
18262
+ }).refine(
18263
+ (data) => {
18264
+ const edgeTargets = new Set(data.edges.map((e) => e.to));
18265
+ const subAgentIds = new Set(data.subAgents);
18266
+ for (const target of edgeTargets) {
18267
+ if (!subAgentIds.has(target)) {
18268
+ return false;
18269
+ }
18270
+ }
18271
+ return true;
18272
+ },
18273
+ { message: "All edge targets (to) must be included in the subAgents list" }
18274
+ );
18275
+ registerToolLattice(
18276
+ "create_processing_agent",
18277
+ {
18278
+ name: "create_processing_agent",
18279
+ description: "Create a PROCESSING agent with a business-defined workflow topology. The edges define a serial delegation chain: the first edge starts from the orchestrator (use its name as placeholder), then each subsequent edge chains from the previous stage's sub-agent. Sub-agents must be created first via create_agent. NOTE: 'tools' is a string array of tool names, 'middleware' is an object array \u2014 they are separate fields and must not be mixed. IMPORTANT: If any sub-agent or the orchestrator needs user confirmation/approval, include the 'ask_user_to_clarify' middleware on that specific agent.",
18280
+ schema: createProcessingAgentSchema
18281
+ },
18282
+ async (input, exeConfig) => {
18283
+ try {
18284
+ const tenantId = getTenantId(exeConfig);
18285
+ const store = getAssistStore();
18286
+ const id = await generateAgentId(tenantId, input.name);
18287
+ const normalize = (s) => s.toLowerCase().replace(/[_\-\s]/g, "");
18288
+ const resolveFrom = (rawFrom) => {
18289
+ const fromLower = rawFrom.toLowerCase();
18290
+ const nameLower = input.name.toLowerCase();
18291
+ if (fromLower === nameLower || fromLower === "orchestrator" || fromLower === "orchestrator-id" || normalize(rawFrom) === normalize(input.name)) {
18292
+ return id;
18293
+ }
18294
+ return rawFrom;
18295
+ };
18296
+ const topologyMiddleware = {
18297
+ id: "topology",
18298
+ type: "topology",
18299
+ name: "Topology",
18300
+ description: `Enforce ${input.edges.length}-step workflow topology`,
18301
+ enabled: true,
18302
+ config: {
18303
+ edges: input.edges.map((e) => ({
18304
+ from: resolveFrom(e.from),
18305
+ to: e.to,
18306
+ purpose: e.purpose
18307
+ }))
18308
+ }
18309
+ };
18310
+ const additionalMiddleware = input.middleware || [];
18311
+ const middleware = [topologyMiddleware, ...additionalMiddleware];
18312
+ const config = {
18313
+ key: id,
18314
+ name: input.name,
18315
+ description: input.description || "",
18316
+ type: import_protocols10.AgentType.PROCESSING,
18317
+ prompt: input.prompt,
18318
+ ...input.tools && input.tools.length > 0 ? { tools: input.tools } : {},
18319
+ middleware,
18320
+ subAgents: input.subAgents,
18321
+ ...input.internalSubAgents ? { internalSubAgents: input.internalSubAgents } : {},
18322
+ ...input.modelKey ? { modelKey: input.modelKey } : {}
18323
+ };
18324
+ await store.createAssistant(tenantId, id, {
18325
+ name: input.name,
18326
+ description: input.description,
18327
+ graphDefinition: config
18328
+ });
18329
+ return JSON.stringify({
18330
+ id,
18331
+ name: input.name,
18332
+ type: "processing",
18333
+ topology: {
18334
+ edges: input.edges.map((e) => ({ from: resolveFrom(e.from), to: e.to, purpose: e.purpose }))
18335
+ }
18336
+ });
18337
+ } catch (error) {
18338
+ return JSON.stringify({ error: `Failed to create processing agent: ${error.message}` });
18339
+ }
18340
+ }
18341
+ );
18342
+ var updateProcessingAgentSchema = import_zod52.default.object({
18343
+ id: import_zod52.default.string().describe("The PROCESSING agent ID to update"),
18344
+ name: import_zod52.default.string().optional().describe("New display name for the orchestrator"),
18345
+ description: import_zod52.default.string().optional().describe("New short description"),
18346
+ prompt: import_zod52.default.string().optional().describe("New system prompt for the orchestrator"),
18347
+ edges: import_zod52.default.array(topologyEdgeSchema).min(1).optional().describe("New topology edges. First edge's from must reference the orchestrator by name (the tool replaces it). Subsequent edges chain from previous sub-agent IDs."),
18348
+ tools: import_zod52.default.array(import_zod52.default.string()).optional().describe("Tool keys (strings) to assign to the orchestrator. Each element is a plain string like 'sap_api_search'. IMPORTANT: tools is a FLAT string array \u2014 do NOT put middleware-like objects here."),
18349
+ subAgents: import_zod52.default.array(import_zod52.default.string()).optional().describe("New IDs of sub-agents in the workflow pipeline"),
18350
+ middleware: import_zod52.default.array(middlewareConfigSchema).optional().describe("Additional middleware config objects (topology middleware is auto-managed, do not include it). Each has {id, type, name, description, enabled, config}. IMPORTANT: middleware objects are NOT tools. Do NOT put tool keys (strings) here. For user approval/confirmation scenarios, use type: 'ask_user_to_clarify' with config: {}."),
18351
+ modelKey: import_zod52.default.string().optional().describe("New model key")
18352
+ }).refine(
18353
+ (data) => {
18354
+ if (!data.edges) return true;
18355
+ const subAgentIds = new Set(data.subAgents || []);
18356
+ if (subAgentIds.size === 0) return true;
18357
+ const edgeTargets = new Set(data.edges.map((e) => e.to));
18358
+ for (const target of edgeTargets) {
18359
+ if (!subAgentIds.has(target)) {
18360
+ return false;
18361
+ }
18362
+ }
18363
+ return true;
18364
+ },
18365
+ { message: "All edge targets (to) must be included in the subAgents list" }
18366
+ );
18367
+ registerToolLattice(
18368
+ "update_processing_agent",
18369
+ {
18370
+ name: "update_processing_agent",
18371
+ description: "Update an existing PROCESSING agent's topology edges, name, prompt, tools, or sub-agents. Use this instead of update_agent for PROCESSING agents because edges require proper placeholder resolution and topology middleware management. NOTE: 'tools' is a string array of tool names, 'middleware' is an object array \u2014 they are separate fields and must not be mixed. For user approval/confirmation scenarios, add middleware with type: 'ask_user_to_clarify'.",
18372
+ schema: updateProcessingAgentSchema
18373
+ },
18374
+ async (input, exeConfig) => {
18375
+ try {
18376
+ const tenantId = getTenantId(exeConfig);
18377
+ const store = getAssistStore();
18378
+ const existing = await store.getAssistantById(tenantId, input.id);
18379
+ if (!existing) {
18380
+ return JSON.stringify({ error: `Agent '${input.id}' not found` });
18381
+ }
18382
+ const existingConfig = existing.graphDefinition || {};
18383
+ if (existingConfig.type !== import_protocols10.AgentType.PROCESSING) {
18384
+ return JSON.stringify({ error: `Agent '${input.id}' is not a PROCESSING agent (type: ${existingConfig.type})` });
18385
+ }
18386
+ const normalize = (s) => s.toLowerCase().replace(/[_\-\s]/g, "");
18387
+ const orchestratorName = input.name || existingConfig.name || existing.name || "";
18388
+ const resolveFrom = (rawFrom) => {
18389
+ const fromLower = rawFrom.toLowerCase();
18390
+ const nameLower = orchestratorName.toLowerCase();
18391
+ if (fromLower === nameLower || fromLower === "orchestrator" || fromLower === "orchestrator-id" || normalize(rawFrom) === normalize(orchestratorName)) {
18392
+ return input.id;
18393
+ }
18394
+ return rawFrom;
18395
+ };
18396
+ let middleware = existingConfig.middleware || [];
18397
+ let resolvedEdges;
18398
+ if (input.edges) {
18399
+ resolvedEdges = input.edges.map((e) => ({
18400
+ from: resolveFrom(e.from),
18401
+ to: e.to,
18402
+ purpose: e.purpose
18403
+ }));
18404
+ const topoIndex = middleware.findIndex(
18405
+ (m) => m.type === "topology"
18406
+ );
18407
+ const topoMiddleware = {
18408
+ id: "topology",
18409
+ type: "topology",
18410
+ name: "Topology",
18411
+ description: `Enforce ${resolvedEdges.length}-step workflow topology`,
18412
+ enabled: true,
18413
+ config: { edges: resolvedEdges }
18414
+ };
18415
+ if (topoIndex >= 0) {
18416
+ middleware = [...middleware];
18417
+ middleware[topoIndex] = topoMiddleware;
18418
+ } else {
18419
+ middleware = [topoMiddleware, ...middleware];
18420
+ }
18421
+ if (input.middleware) {
18422
+ const nonTopo = input.middleware.filter(
18423
+ (m) => m.type !== "topology"
18424
+ );
18425
+ const topoIdx = middleware.findIndex(
18426
+ (m) => m.type === "topology"
18427
+ );
18428
+ const prefix = middleware.slice(0, topoIdx + 1);
18429
+ const suffix = middleware.slice(topoIdx + 1);
18430
+ middleware = [...prefix, ...nonTopo];
18431
+ }
18432
+ } else if (input.middleware) {
18433
+ const nonTopo = input.middleware.filter(
18434
+ (m) => m.type !== "topology"
18435
+ );
18436
+ const topoIdx = middleware.findIndex(
18437
+ (m) => m.type === "topology"
18438
+ );
18439
+ if (topoIdx >= 0) {
18440
+ middleware = [...middleware.slice(0, topoIdx + 1), ...nonTopo];
18441
+ } else {
18442
+ middleware = [...middleware, ...nonTopo];
18443
+ }
17199
18444
  }
17200
- }
17201
- const updatedSkill = {
17202
- ...skill,
17203
- name: updates.name ?? skill.name,
17204
- description: updates.description ?? skill.description,
17205
- license: updates.license ?? skill.license,
17206
- compatibility: updates.compatibility ?? skill.compatibility,
17207
- metadata: updates.metadata ?? skill.metadata,
17208
- content: updates.content !== void 0 ? updates.content : skill.content,
17209
- subSkills: updates.subSkills !== void 0 ? updates.subSkills : skill.subSkills,
17210
- updatedAt: /* @__PURE__ */ new Date()
17211
- };
17212
- await this.writeSkillFile(updatedSkill, context);
17213
- return updatedSkill;
17214
- }
17215
- /**
17216
- * Delete a skill by ID
17217
- */
17218
- async deleteSkill(tenantId, id, context) {
17219
- if (isBuiltInSkill(id)) {
17220
- throw new Error(
17221
- `Skill "${id}" is a built-in skill and cannot be deleted`
18445
+ const mergedConfig = {
18446
+ ...existingConfig,
18447
+ ...input.name !== void 0 ? { name: input.name } : {},
18448
+ ...input.description !== void 0 ? { description: input.description } : {},
18449
+ ...input.prompt !== void 0 ? { prompt: input.prompt } : {},
18450
+ ...input.tools !== void 0 ? { tools: input.tools } : {},
18451
+ ...input.subAgents !== void 0 ? { subAgents: input.subAgents } : {},
18452
+ ...input.modelKey !== void 0 ? { modelKey: input.modelKey } : {},
18453
+ middleware,
18454
+ key: input.id
18455
+ };
18456
+ const newName = input.name || existing.name;
18457
+ await store.updateAssistant(tenantId, input.id, {
18458
+ name: newName,
18459
+ description: input.description !== void 0 ? input.description : existing.description,
18460
+ graphDefinition: mergedConfig
18461
+ });
18462
+ const topoConfig = middleware.find(
18463
+ (m) => m.type === "topology"
17222
18464
  );
18465
+ return JSON.stringify({
18466
+ id: input.id,
18467
+ name: newName,
18468
+ type: "processing",
18469
+ topology: {
18470
+ edges: topoConfig?.config?.edges || resolvedEdges || []
18471
+ }
18472
+ });
18473
+ } catch (error) {
18474
+ return JSON.stringify({ error: `Failed to update processing agent: ${error.message}` });
17223
18475
  }
18476
+ }
18477
+ );
18478
+ var updateAgentSchema = import_zod52.default.object({
18479
+ id: import_zod52.default.string().describe("The agent ID to update"),
18480
+ config: import_zod52.default.object({
18481
+ name: import_zod52.default.string().optional().describe("New display name for the agent"),
18482
+ description: import_zod52.default.string().optional().describe("New short description"),
18483
+ type: import_zod52.default.enum(["react", "deep_agent"]).optional().describe("Agent type"),
18484
+ prompt: import_zod52.default.string().optional().describe("New system prompt for the agent"),
18485
+ tools: import_zod52.default.array(import_zod52.default.string()).optional().describe("Tool keys to assign to this agent. These are registered tool names (strings), NOT middleware objects."),
18486
+ middleware: import_zod52.default.array(middlewareConfigSchema).optional().describe("Middleware configurations. NOTE: middleware objects have type/name/description/enabled/config fields and are NOT the same as tools. Tool keys go in the 'tools' array. For user approval/confirmation scenarios, use type: 'ask_user_to_clarify' with config: {}."),
18487
+ subAgents: import_zod52.default.array(import_zod52.default.string()).optional().describe("Sub-agent IDs (deep_agent only)"),
18488
+ internalSubAgents: import_zod52.default.array(import_zod52.default.any()).optional().describe("Inline sub-agent configs (deep_agent only)"),
18489
+ modelKey: import_zod52.default.string().optional().describe("Model key to use")
18490
+ }).describe("Configuration fields to update. Only include the fields you want to change.")
18491
+ });
18492
+ registerToolLattice(
18493
+ "update_agent",
18494
+ {
18495
+ name: "update_agent",
18496
+ description: "Update an existing agent's configuration. Provide the agent ID and the fields to change. Returns the updated agent's ID and name. NOTE: For user approval/confirmation scenarios, add middleware with type: 'ask_user_to_clarify'.",
18497
+ schema: updateAgentSchema
18498
+ },
18499
+ async (input, exeConfig) => {
17224
18500
  try {
17225
- const sandbox = await this.getSandbox(tenantId, context);
17226
- const dirPath = this.getSkillDirectoryPath(tenantId, id);
17227
- const deleteResult = await sandbox.shell.execCommand({
17228
- command: `rm -rf ${dirPath}`
18501
+ const tenantId = getTenantId(exeConfig);
18502
+ const store = getAssistStore();
18503
+ const existing = await store.getAssistantById(tenantId, input.id);
18504
+ if (!existing) {
18505
+ return JSON.stringify({ error: `Agent '${input.id}' not found` });
18506
+ }
18507
+ const existingConfig = existing.graphDefinition || {};
18508
+ const mergedConfig = { ...existingConfig, ...input.config };
18509
+ const newName = input.config.name || existing.name;
18510
+ await store.updateAssistant(tenantId, input.id, {
18511
+ name: newName,
18512
+ description: input.config.description !== void 0 ? input.config.description : existing.description,
18513
+ graphDefinition: mergedConfig
17229
18514
  });
17230
- if (deleteResult.exit_code !== 0) {
17231
- return false;
17232
- }
17233
- return true;
18515
+ return JSON.stringify({ id: input.id, name: newName });
17234
18516
  } catch (error) {
17235
- console.error(`Error deleting skill ${id}:`, error);
17236
- return false;
18517
+ return JSON.stringify({ error: `Failed to update agent: ${error.message}` });
17237
18518
  }
17238
18519
  }
17239
- /**
17240
- * Check if skill exists
17241
- */
17242
- async hasSkill(tenantId, id, context) {
17243
- if (isBuiltInSkill(id)) return true;
17244
- const skill = await this.getSkillById(tenantId, id, context);
17245
- return skill !== null;
18520
+ );
18521
+ registerToolLattice(
18522
+ "delete_agent",
18523
+ {
18524
+ name: "delete_agent",
18525
+ description: "Permanently delete an agent by its ID. This action cannot be undone.",
18526
+ schema: import_zod52.default.object({
18527
+ id: import_zod52.default.string().describe("The agent ID to delete")
18528
+ })
18529
+ },
18530
+ async (input, exeConfig) => {
18531
+ try {
18532
+ const tenantId = getTenantId(exeConfig);
18533
+ const store = getAssistStore();
18534
+ const existing = await store.getAssistantById(tenantId, input.id);
18535
+ if (!existing) {
18536
+ return JSON.stringify({ error: `Agent '${input.id}' not found`, success: false });
18537
+ }
18538
+ const success = await store.deleteAssistant(tenantId, input.id);
18539
+ return JSON.stringify({ success, id: input.id });
18540
+ } catch (error) {
18541
+ return JSON.stringify({ error: `Failed to delete agent: ${error.message}` });
18542
+ }
17246
18543
  }
17247
- /**
17248
- * Search skills by metadata within a tenant
17249
- */
17250
- async searchByMetadata(tenantId, metadataKey, metadataValue, context) {
17251
- const allSkills = await this.getAllSkills(tenantId, context);
17252
- return allSkills.filter(
17253
- (skill) => skill.metadata && skill.metadata[metadataKey] === metadataValue
17254
- );
18544
+ );
18545
+ registerToolLattice(
18546
+ "list_tools",
18547
+ {
18548
+ name: "list_tools",
18549
+ description: "List all available tools that can be assigned to agents. Returns each tool's name (use this string value in the 'tools' array), description, and whether it requires user approval. The tool names from this list are what you pass as strings in the 'tools' field of create_agent or update_agent.",
18550
+ schema: import_zod52.default.object({})
18551
+ },
18552
+ async (_input, _exeConfig) => {
18553
+ try {
18554
+ const lattices = toolLatticeManager.getAllLattices();
18555
+ return JSON.stringify({
18556
+ tools: lattices.map((l) => ({
18557
+ name: l.config.name,
18558
+ description: l.config.description,
18559
+ needUserApprove: l.config.needUserApprove ?? false
18560
+ }))
18561
+ });
18562
+ } catch (error) {
18563
+ return JSON.stringify({ error: `Failed to list tools: ${error.message}` });
18564
+ }
17255
18565
  }
17256
- /**
17257
- * Filter skills by compatibility within a tenant
17258
- */
17259
- async filterByCompatibility(tenantId, compatibility, context) {
17260
- const allSkills = await this.getAllSkills(tenantId, context);
17261
- return allSkills.filter((skill) => skill.compatibility === compatibility);
18566
+ );
18567
+ registerToolLattice(
18568
+ "invoke_agent",
18569
+ {
18570
+ name: "invoke_agent",
18571
+ description: "Invoke an agent with a test message and return its response. Use this to verify an agent works correctly after creating or modifying it. The agent must be compiled (already created and valid).",
18572
+ schema: import_zod52.default.object({
18573
+ id: import_zod52.default.string().describe("The agent ID to invoke"),
18574
+ message: import_zod52.default.string().describe("The test message to send to the agent")
18575
+ })
18576
+ },
18577
+ async (input, exeConfig) => {
18578
+ try {
18579
+ const tenantId = getTenantId(exeConfig);
18580
+ const { id, message } = input;
18581
+ const store = getAssistStore();
18582
+ const existing = await store.getAssistantById(tenantId, id);
18583
+ if (!existing) {
18584
+ return JSON.stringify({ error: `Agent '${id}' not found` });
18585
+ }
18586
+ const threadId = (0, import_uuid4.v4)();
18587
+ const agent = new Agent({
18588
+ tenant_id: tenantId,
18589
+ assistant_id: id,
18590
+ thread_id: threadId
18591
+ });
18592
+ const result = await agent.invoke({ input: { message } });
18593
+ const messages = result?.messages || [];
18594
+ const lastAi = [...messages].reverse().find(
18595
+ (m) => m.role === "ai" || m.type === "ai"
18596
+ );
18597
+ const content = lastAi?.content ?? "(no response)";
18598
+ return JSON.stringify({
18599
+ agentId: id,
18600
+ threadId,
18601
+ response: typeof content === "string" ? content : JSON.stringify(content)
18602
+ });
18603
+ } catch (error) {
18604
+ return JSON.stringify({ error: `Failed to invoke agent: ${error.message}` });
18605
+ }
17262
18606
  }
17263
- /**
17264
- * Filter skills by license within a tenant
17265
- */
17266
- async filterByLicense(tenantId, license, context) {
17267
- const allSkills = await this.getAllSkills(tenantId, context);
17268
- return allSkills.filter((skill) => skill.license === license);
18607
+ );
18608
+
18609
+ // src/agent_lattice/agentArchitectConfig.ts
18610
+ var import_protocols11 = require("@axiom-lattice/protocols");
18611
+
18612
+ // src/agent_lattice/agentArchitectPrompt.ts
18613
+ var AGENT_ARCHITECT_PROMPT = `# Agent Architect
18614
+
18615
+ You are an **Agent Architect** \u2014 an expert AI system designer. You help users transform natural language requirements into working AI agents.
18616
+
18617
+ ## Your Tools
18618
+
18619
+ You have nine tools:
18620
+ - **list_agents** \u2014 See all existing agents for this workspace
18621
+ - **list_tools** \u2014 See all available tools that can be assigned to agents
18622
+ - **get_agent** \u2014 View the full configuration of a specific agent
18623
+ - **create_agent** \u2014 Create a REACT or DEEP_AGENT agent
18624
+ - **create_processing_agent** \u2014 Create a PROCESSING agent with business-defined workflow topology
18625
+ - **update_processing_agent** \u2014 Modify a PROCESSING agent's topology edges, name, prompt, or sub-agents
18626
+ - **update_agent** \u2014 Modify an existing REACT or DEEP_AGENT agent's configuration
18627
+ - **delete_agent** \u2014 Remove an agent permanently
18628
+ - **invoke_agent** \u2014 Test an agent by sending a message and getting its response
18629
+
18630
+ ## Global Interaction Rules
18631
+
18632
+ 1. **One question at a time.** Never overwhelm the user. Each message should ask exactly one question or present exactly one decision.
18633
+ 2. **Confirm before creating.** Always present your design to the user and get explicit approval before calling create_agent or update_agent.
18634
+ 3. **Be concise.** Show configs clearly but briefly. Use structured formats when presenting designs.
18635
+ 4. **Use kebab-case for agent names.** E.g., "code-reviewer", "data-analyzer".
18636
+
18637
+ ---
18638
+
18639
+ ## Agent Types Overview
18640
+
18641
+ | Type | Best for | Execution Model |
18642
+ |------|----------|----------------|
18643
+ | **react** | Simple, single-responsibility tasks | Classic ReAct loop (think \u2192 act \u2192 observe) |
18644
+ | **processing** | Standard BPO workflows, preset process orchestration | Topology-driven: predefined agent topology with reliable multi-agent coordination |
18645
+ | **deep_agent** | Complex, open-ended tasks requiring dynamic decomposition | Self-generating dynamic todos: agent analyzes the task and creates its own execution plan at runtime |
18646
+
18647
+ ---
18648
+
18649
+ ## Workflow A: Simple Agent (REACT type)
18650
+
18651
+ Use this for straightforward tasks \u2014 a single agent with a single responsibility, no sub-agent decomposition needed. The classic ReAct pattern: the agent reasons, acts, and observes in a loop.
18652
+
18653
+ ### Step 1: Understand the Goal
18654
+ Ask: What should this agent do? Who will use it? What are the inputs and outputs?
18655
+
18656
+ ### Step 2: Choose Middleware
18657
+ Based on the goal, recommend which middleware the agent needs. Call **list_tools** first to verify what's available, then consult the **Middleware Config Reference** at the bottom of this prompt for exact config shapes.
18658
+
18659
+ **IMPORTANT:** If the agent needs user confirmation, approval, or must ask the user clarifying questions, you MUST include the **ask_user_to_clarify** middleware. Do NOT assume the user will be available to answer in chat \u2014 the ask_user_to_clarify tool is the only way for the agent to pause and request input.
18660
+
18661
+ ### Step 3: Write the System Prompt
18662
+ Craft the agent's system prompt with:
18663
+ 1. **Role definition** \u2014 Who the agent is and what it does
18664
+ 2. **Workflow** \u2014 Step-by-step instructions
18665
+ 3. **Constraints** \u2014 Boundaries, quality standards, forbidden actions
18666
+
18667
+ Present the prompt. Get user confirmation.
18668
+
18669
+ ### Step 4: Create
18670
+ Call create_agent with the agreed configuration.
18671
+
18672
+ ---
18673
+
18674
+ ## Workflow B: Workflow Agent (PROCESSING type)
18675
+
18676
+ Use this when the task follows a standard BPO (Business Process Orchestration) pattern \u2014 a predefined topology of sub-agents working through a preset pipeline or process. The topology is designed upfront and sub-agents coordinate according to the defined flow. This is the most reliable type for multi-agent workflows where the process is well-understood.
18677
+
18678
+ ### Phase 1: Process Analysis
18679
+
18680
+ Ask: What is the end-to-end process we need to automate? What are the stages?
18681
+
18682
+ Based on the answer, identify the processing stages. Output a **pipeline**:
18683
+
18684
+ \`\`\`
18685
+ I see the following processing stages:
18686
+ \u251C\u2500\u2500 Input Intake: [what happens]
18687
+ \u251C\u2500\u2500 Stage 1: [processing step]
18688
+ \u251C\u2500\u2500 Stage 2: [processing step]
18689
+ \u2514\u2500\u2500 Output: [final deliverable]
18690
+
18691
+ Do these stages look right?
18692
+ \`\`\`
18693
+
18694
+ ### Phase 2: Topology Design
18695
+
18696
+ Define the agent topology. Each stage may be handled by a dedicated sub-agent. Create a **topology diagram**:
18697
+
18698
+ \`\`\`
18699
+ \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510 \u250C\u2500\u2500\u2500\u2500\u2510 \u250C\u2500\u2500\u2500\u2500\u2510 \u250C\u2500\u2500\u2500\u2500\u2510
18700
+ \u2502 Orchestrator \u2502 \u2500\u2500\u25BA \u2502Stage\u2502 \u2500\u2500\u25BA \u2502Stage\u2502 \u2500\u2500\u25BA \u2502Stage\u2502
18701
+ \u2502 \u2502 \u2502 1 \u2502 \u2502 2 \u2502 \u2502 3 \u2502
18702
+ \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518 \u2514\u2500\u2500\u2500\u2500\u2518 \u2514\u2500\u2500\u2500\u2500\u2518 \u2514\u2500\u2500\u2500\u2500\u2518
18703
+
18704
+ Flow: Orchestrator \u2192 Stage 1 \u2192 Stage 2 \u2192 Stage 3 \u2192 Output
18705
+
18706
+ Each edge chains from the previous node:
18707
+ Orchestrator \u2500\u2500\u25BA Stage 1 \u2500\u2500\u25BA Stage 2 \u2500\u2500\u25BA Stage 3
18708
+ \`\`\`
18709
+
18710
+ **Design checks:**
18711
+ - Each stage has exactly one responsibility
18712
+ - The flow between stages is a serial chain \u2014 each stage processes output from the previous one
18713
+ - The orchestrator directs the first stage, then each stage hands off to the next
18714
+ - The orchestrator enforces the topology \u2014 it does NOT improvise
18715
+ - Error handling per stage: retry, skip, or escalate
18716
+
18717
+ ### Phase 3: Design Each Sub-Agent
18718
+
18719
+ For each sub-agent, one at a time:
18720
+
18721
+ 1. **Responsibility** \u2014 One sentence
18722
+ 2. **System Prompt** \u2014 Role + workflow + constraints
18723
+ 3. **Middleware** \u2014 Which middleware, and why (include ask_user_to_clarify if this sub-agent needs user approval)
18724
+ 4. **Input/Output contract** \u2014 What it receives, what it returns
18725
+
18726
+ Present each sub-agent design. Get user confirmation before moving to the next.
18727
+
18728
+ ### Phase 4: Design the Orchestrator
18729
+
18730
+ The orchestrator is the parent PROCESSING agent. Use **create_processing_agent** (NOT create_agent):
18731
+
18732
+ 1. **Responsibility** \u2014 Receive user request, route through the pipeline stages, enforce topology
18733
+ 2. **System Prompt** \u2014 The defined topology, when to call which sub-agent, error handling
18734
+ 3. **Topology edges** \u2014 One edge per pipeline stage with a business-meaningful purpose
18735
+ 4. **Sub-agent list** \u2014 All sub-agents with their role in the pipeline
18736
+
18737
+ ### Phase 5: Final Review
18738
+
18739
+ Before creating, check:
18740
+ 1. **Completeness** \u2014 Is every stage of the process covered by an edge?
18741
+ 2. **Purposes** \u2014 Does each edge's purpose clearly describe the business intent?
18742
+ 3. **Order** \u2014 Is the edge sequence correct?
18743
+ 4. **Handoffs** \u2014 Is data passed correctly between stages?
18744
+ 5. **Edge cases** \u2014 What happens on invalid input, stage failure, timeout?
18745
+
18746
+ ### Creation Order
18747
+
18748
+ Always create sub-agents FIRST (via create_agent as react agents), then the orchestrator via create_processing_agent.
18749
+
18750
+ \`\`\`
18751
+ Creating:
18752
+ 1. create_agent(name: "stage-1", type: "react", ...)
18753
+ 2. create_agent(name: "stage-2", type: "react", ...)
18754
+ 3. create_agent(name: "stage-3", type: "react", ...)
18755
+ 4. create_processing_agent(
18756
+ name: "orchestrator",
18757
+ prompt: "...",
18758
+ edges: [
18759
+ { from: "orchestrator", to: "stage-1-id", purpose: "Validate and normalize input data" },
18760
+ { from: "stage-1-id", to: "stage-2-id", purpose: "Transform data into target format" },
18761
+ { from: "stage-2-id", to: "stage-3-id", purpose: "Generate final output report" },
18762
+ ],
18763
+ subAgents: ["stage-1-id", "stage-2-id", "stage-3-id"],
18764
+ )
18765
+ \`\`\`
18766
+
18767
+ **Why serial?** The topology is a chain: Orchestrator \u2192 Stage 1 \u2192 Stage 2 \u2192 Stage 3. Only the first edge's \`from\` references the orchestrator (by name). Subsequent edges chain from the previous sub-agent's ID. The tool automatically replaces the orchestrator name placeholder with the actual generated ID.
18768
+
18769
+ ---
18770
+
18771
+ ## Workflow C: Dynamic Agent (DEEP_AGENT type)
18772
+
18773
+ Use this for complex, open-ended tasks where the execution path cannot be fully predetermined. The DEEP_AGENT analyzes the user's intent, self-generates a dynamic todo list, and iteratively works through it \u2014 creating, updating, and completing todos as understanding evolves. This is ideal when the task requires exploration, research, or creative problem-solving where the steps emerge during execution.
18774
+
18775
+ ### Phase 1: Domain Analysis
18776
+
18777
+ Ask: What is the overall goal? What makes this complex or open-ended?
18778
+
18779
+ Explain why a DEEP_AGENT is the right choice (dynamic decomposition, exploration-driven, adaptive planning).
18780
+
18781
+ ### Phase 2: Identify Capabilities
18782
+
18783
+ Instead of designing a fixed topology, identify what capabilities the agent needs:
18784
+
18785
+ \`\`\`
18786
+ The agent will need:
18787
+ \u251C\u2500\u2500 Capability A: [what the agent must be able to do]
18788
+ \u251C\u2500\u2500 Capability B: [what the agent must be able to do]
18789
+ \u2514\u2500\u2500 Capability C: [what the agent must be able to do]
18790
+ \`\`\`
18791
+
18792
+ Each capability maps to middleware or a sub-agent tool.
18793
+
18794
+ ### Phase 3: Design the Agent
18795
+
18796
+ 1. **System Prompt** \u2014 Emphasize the dynamic todo-driven workflow. The agent should:
18797
+ - Analyze the user's request and break it into a todo list
18798
+ - Work through todos one at a time
18799
+ - Update and refine the todo list as understanding deepens
18800
+ - Self-correct and adapt based on intermediate findings
18801
+
18802
+ 2. **Middleware** \u2014 Tools the agent needs:
18803
+ - **filesystem** \u2014 Essential for persistent work
18804
+ - **code_eval** \u2014 If computation or data analysis is needed
18805
+ - **browser** \u2014 If research or web access is needed
18806
+ - **skill** \u2014 If domain-specific workflows are available
18807
+ - **widget** \u2014 If visual output (diagrams, interactive content) is beneficial
18808
+ - **ask_user_to_clarify** \u2014 If the agent needs to confirm actions or ask clarifying questions
18809
+
18810
+ 3. **Sub-agents** (optional) \u2014 Specialized agents the deep agent can delegate to for specific capabilities
18811
+
18812
+ ### Phase 4: Final Review
18813
+
18814
+ Before creating, check:
18815
+ 1. **Autonomy** \u2014 Can the agent operate independently?
18816
+ 2. **Tools** \u2014 Does it have everything needed to self-decompose tasks?
18817
+ 3. **Guardrails** \u2014 Are there clear boundaries on what the agent should NOT do?
18818
+
18819
+ ### Creation
18820
+
18821
+ \`\`\`
18822
+ create_agent(
18823
+ name: "research-agent",
18824
+ type: "deep_agent",
18825
+ prompt: "...",
18826
+ middleware: [...],
18827
+ subAgents: [...] // optional
18828
+ )
18829
+ \`\`\`
18830
+
18831
+ ---
18832
+
18833
+ ## Editing Existing Agents
18834
+
18835
+ When the user wants to modify an agent:
18836
+ 1. Call **get_agent** to see the current config
18837
+ 2. Understand what the user wants to change
18838
+ 3. Present the proposed changes
18839
+ 4. Call **update_agent** to apply
18840
+
18841
+ ## Deleting Agents
18842
+
18843
+ When the user wants to delete an agent:
18844
+ 1. Call **get_agent** to show what will be deleted
18845
+ 2. Warn if this agent is referenced as a sub-agent by others
18846
+ 3. Ask for explicit confirmation
18847
+ 4. Call **delete_agent**
18848
+
18849
+ ## Agent Configuration Reference
18850
+
18851
+ ### create_agent (REACT and DEEP_AGENT)
18852
+
18853
+ All fields except name, type, and prompt are optional.
18854
+
18855
+ \`\`\`typescript
18856
+ {
18857
+ name: string, // Required. Display name
18858
+ description?: string, // Optional. Short description
18859
+ type: "react" | "deep_agent", // Required
18860
+ prompt: string, // Required. System prompt
18861
+ tools?: string[], // Optional. Tool keys from list_tools
18862
+ middleware?: MiddlewareConfig[], // Optional. See middleware reference below
18863
+ subAgents?: string[], // DEEP_AGENT only. IDs of sub-agents
18864
+ internalSubAgents?: AgentConfig[], // DEEP_AGENT only. Inline sub-agent configs
18865
+ modelKey?: string, // Optional. Model to use
18866
+ }
18867
+ \`\`\`
18868
+
18869
+ ### create_processing_agent (PROCESSING)
18870
+
18871
+ Creates a PROCESSING agent with a business-defined workflow topology. Sub-agents must already exist.
18872
+
18873
+ \`\`\`typescript
18874
+ {
18875
+ name: string, // Required. Display name for the orchestrator
18876
+ description?: string, // Optional. Short description
18877
+ prompt: string, // Required. System prompt \u2014 how to route through the topology
18878
+ edges: [{ // Required. At least 1 edge defining the workflow
18879
+ from: string, // Orchestrator's ID (use placeholder name; tool auto-replaces)
18880
+ to: string, // Sub-agent ID to delegate to
18881
+ purpose: string, // Business purpose \u2014 what this step accomplishes
18882
+ }],
18883
+ tools?: string[], // Optional. Tool keys from list_tools
18884
+ subAgents: string[], // Required. IDs of sub-agents in the pipeline
18885
+ internalSubAgents?: AgentConfig[], // Optional. Inline sub-agent configs
18886
+ middleware?: MiddlewareConfig[], // Optional. Additional middleware (topology is auto-added)
18887
+ modelKey?: string, // Optional. Model to use
18888
+ }
18889
+ \`\`\`
18890
+
18891
+ ### create_processing_agent (PROCESSING)
18892
+
18893
+ Creates a PROCESSING agent with a business-defined workflow topology. Sub-agents must already exist.
18894
+
18895
+ \`\`\`typescript
18896
+ {
18897
+ name: string, // Required. Display name for the orchestrator
18898
+ description?: string, // Optional. Short description
18899
+ prompt: string, // Required. System prompt \u2014 how to route through the topology
18900
+ edges: [{ // Required. At least 1 edge defining the serial workflow chain
18901
+ from: string, // Source agent ID. First edge: use orchestrator name as placeholder (tool auto-replaces). Subsequent edges: previous sub-agent ID
18902
+ to: string, // Sub-agent ID to delegate to
18903
+ purpose: string, // Business purpose \u2014 what this step accomplishes
18904
+ }],
18905
+ subAgents: string[], // Required. IDs of sub-agents in the pipeline
18906
+ internalSubAgents?: AgentConfig[], // Optional. Inline sub-agent configs
18907
+ middleware?: MiddlewareConfig[], // Optional. Additional middleware (topology is auto-added)
18908
+ modelKey?: string, // Optional. Model to use
18909
+ }
18910
+ \`\`\`
18911
+
18912
+ ### Middleware Config Reference
18913
+
18914
+ Each middleware entry uses this base shape:
18915
+
18916
+ \`\`\`typescript
18917
+ {
18918
+ id: string, // Unique ID, usually same as type
18919
+ type: string, // Middleware type from the table below
18920
+ name: string, // Display name
18921
+ description: string, // What this middleware provides
18922
+ enabled: true, // Always true for active middleware
18923
+ config: { ... } // Type-specific config (see table)
18924
+ }
18925
+ \`\`\`
18926
+
18927
+ #### filesystem
18928
+ Provides: \`ls\`, \`read_file\`, \`write_file\`, \`edit_file\`, \`glob\`, \`grep\`
18929
+ | config field | type | description |
18930
+ |-------------|------|-------------|
18931
+ | backend | string | Pluggable backend, usually omitted (uses default) |
18932
+ | systemPrompt | string? | Custom system prompt override for filesystem conventions |
18933
+
18934
+ #### code_eval
18935
+ Provides: \`run_code\` \u2014 execute Python/JavaScript in a sandbox
18936
+ | config field | type | description |
18937
+ |-------------|------|-------------|
18938
+ | vmIsolation | "agent" | "project" | "global" | Sandbox isolation level. Default recommended: \`"agent"\` |
18939
+ | timeout | number? | Execution timeout in milliseconds |
18940
+ | memoryLimit | number? | Memory limit in MB |
18941
+
18942
+ #### browser
18943
+ Provides: \`browser_navigate\`, \`browser_click\`, \`browser_screenshot\`, \`browser_get_markdown\`, etc. (21 tools)
18944
+ | config field | type | description |
18945
+ |-------------|------|-------------|
18946
+ | vmIsolation | "agent" | "project" | "global" | Sandbox isolation level. Default recommended: \`"agent"\` |
18947
+ | headless | boolean? | Whether to run in headless mode |
18948
+
18949
+ #### sql
18950
+ Provides: \`sql_list_tables\`, \`sql_table_info\`, \`sql_query_checker\`, \`sql_query\`
18951
+ | config field | type | description |
18952
+ |-------------|------|-------------|
18953
+ | databaseKeys | string[] | Array of database config keys to expose. Required. |
18954
+ | databaseDescriptions | Record<string,string>? | Optional human-readable descriptions keyed by database key |
18955
+
18956
+ #### skill
18957
+ Provides: \`load_skill_content\` \u2014 load and read detailed skill instructions
18958
+ | config field | type | description |
18959
+ |-------------|------|-------------|
18960
+ | skills | string[]? | List of specific skill IDs to expose |
18961
+ | readAll | boolean? | When \`true\`, all available skills are exposed (recommended) |
18962
+ | heading | string? | Optional heading for the skills section |
18963
+ | extraNote | string? | Optional extra note appended after skills list |
18964
+
18965
+ #### metrics
18966
+ Provides: \`list_datasources\`, \`query_metrics_list\`, \`query_semantic_metric_data\`, \`query_tables_list\`, \`execute_sql_query\`, etc. (7 tools)
18967
+ | config field | type | description |
18968
+ |-------------|------|-------------|
18969
+ | serverKeys | string[] | List of metrics server keys. Required. |
18970
+ | serverDescriptions | Record<string,string>? | Optional descriptions for each server |
18971
+ | connectAll | boolean? | When \`true\`, connects to all available metrics servers automatically |
18972
+
18973
+ #### ask_user_to_clarify
18974
+ Provides: \`ask_user_to_clarify\` \u2014 pause execution and present questions with predefined options to the user. The agent halts until the user responds, then receives the answers as structured data.
18975
+ **Use this when:** the agent needs to confirm an action, get user approval, ask "which one?", or gather missing parameters. Without this middleware, the agent CANNOT interact with the user mid-execution.
18976
+ Config: \`{}\` \u2014 no configuration needed.
18977
+
18978
+ #### widget
18979
+ Provides: \`load_guidelines\`, \`show_widget\` \u2014 render interactive HTML widgets and SVG diagrams
18980
+ Config: \`{}\` \u2014 no configuration needed.
18981
+
18982
+ #### claw
18983
+ Provides: bootstrap file management (AGENTS.md, SOUL.md, etc.) \u2014 injects project context into system prompt
18984
+ | config field | type | description |
18985
+ |-------------|------|-------------|
18986
+ | injectBootstrapFiles | boolean? | Whether to inject bootstrap files into system prompt. Default: \`true\` |
18987
+ | bootstrapFiles | object? | Custom content for each bootstrap file |
18988
+
18989
+ \`bootstrapFiles\` sub-fields: \`agents\`, \`soul\`, \`identity\`, \`user\`, \`tools\`, \`bootstrap\` \u2014 each is an optional string.
18990
+
18991
+ #### date
18992
+ Provides: \`get_current_date_time\` \u2014 get current date and time
18993
+ | config field | type | description |
18994
+ |-------------|------|-------------|
18995
+ | timezone | string? | IANA timezone like \`"Asia/Shanghai"\` or \`"America/New_York"\`. Default: \`"UTC"\` |
18996
+
18997
+ #### scheduler
18998
+ Provides: \`schedule_at\`, \`schedule_after\`, \`schedule_recurring\`, \`cancel_scheduled_task\`, \`list_scheduled_tasks\`
18999
+ | config field | type | description |
19000
+ |-------------|------|-------------|
19001
+ | defaultMaxRetries | number? | Default max retries for scheduled tasks. Default: \`0\` |
19002
+
19003
+ #### topology
19004
+ Provides: \`read_topo_progress\` \u2014 enforces multi-agent workflow topology. **Required for PROCESSING agents \u2014 auto-injected by create_processing_agent.**
19005
+ | config field | type | description |
19006
+ |-------------|------|-------------|
19007
+ | edges | TopologyEdge[] | **Required.** Directed edges: \`{ from: string, to: string, purpose: string }\`. The \`purpose\` must describe the business intent of this delegation step. |
19008
+ | trackingStore | object? | Optional persistence for workflow run tracking | |
19009
+
19010
+ ### When to use ask_user_to_clarify Middleware
19011
+
19012
+ **CRITICAL: Always add this middleware when the agent needs user confirmation, approval, or clarification.** Without it, the agent cannot interact with the user during execution.
19013
+
19014
+ **Required scenarios:**
19015
+ - Confirming irreversible actions (delete data, send emails, make purchases, modify production configs)
19016
+ - Asking the user to choose between options (e.g., "Which database?", "Which report format?")
19017
+ - Gathering missing parameters the user didn't provide upfront
19018
+ - Requesting user approval before proceeding to a critical step
19019
+ - Disambiguating vague user requests before acting
19020
+
19021
+ **Tool capabilities:**
19022
+ | Feature | Description |
19023
+ |---------|-------------|
19024
+ | Single choice | User picks ONE option from a list (e.g., "Choose environment: [production] [staging]") |
19025
+ | Multiple choice | User picks SEVERAL options (e.g., "Select reports: [sales] [inventory] [hr]") |
19026
+ | Required | Forces the user to answer before the agent continues |
19027
+ | allowOther | Lets the user type a custom answer beyond listed options |
19028
+
19029
+ **Design rule:** If your agent's system prompt says anything like "confirm with the user before...", "ask the user to choose...", or "get approval for...", you MUST include the \`ask_user_to_clarify\` middleware.
19030
+
19031
+ ### Quick Pick: Common Middleware Combos
19032
+
19033
+ | Agent Role | Recommended Middleware |
19034
+ |-----------|----------------------|
19035
+ | Code assistant | filesystem, code_eval, widget |
19036
+ | Data analyst | filesystem, sql, code_eval, widget |
19037
+ | Web researcher | browser, filesystem, widget |
19038
+ | Operations / SRE | metrics, sql, widget |
19039
+ | Process orchestrator | skill, date, scheduler, widget |
19040
+ | General assistant | filesystem, date, widget |
19041
+ | Approval-gated operations | ask_user_to_clarify, filesystem, widget |
19042
+ | Interactive Q&A | ask_user_to_clarify, date, widget |
19043
+
19044
+ ### update_processing_agent
19045
+
19046
+ Updates a PROCESSING agent's topology edges, name, prompt, or sub-agents. Unlike update_agent, this properly handles placeholder resolution for edge \`from\` values and manages the topology middleware correctly.
19047
+
19048
+ \`\`\`typescript
19049
+ {
19050
+ id: string, // Required. The PROCESSING agent ID to update
19051
+ name?: string, // Optional. New display name
19052
+ description?: string, // Optional. New short description
19053
+ prompt?: string, // Optional. New orchestrator system prompt
19054
+ edges?: [{ // Optional. New topology edges (serial chain)
19055
+ from: string, // First edge: orchestrator name placeholder. Subsequent: previous sub-agent ID
19056
+ to: string, // Sub-agent ID
19057
+ purpose: string, // Business purpose
19058
+ }],
19059
+ subAgents?: string[], // Optional. New sub-agent IDs
19060
+ middleware?: MiddlewareConfig[], // Optional. Additional middleware (topology auto-managed)
19061
+ modelKey?: string, // Optional. New model
19062
+ }
19063
+ \`\`\`
19064
+
19065
+ **When to use:** Use this whenever you need to change a PROCESSING agent's topology \u2014 adding/removing/recruiting pipeline stages, changing the flow order, or updating edge purposes. Use regular \`update_agent\` only for REACT and DEEP_AGENT agents.
19066
+
19067
+ ### update_agent parameters
19068
+
19069
+ \`\`\`typescript
19070
+ {
19071
+ id: string, // Required. Agent ID to update
19072
+ config: { // Required. Full or partial agent config
19073
+ name?: string,
19074
+ description?: string,
19075
+ prompt?: string,
19076
+ middleware?: [...],
19077
+ // ... any other fields
17269
19078
  }
17270
- /**
17271
- * Get sub-skills of a parent skill within a tenant
17272
- */
17273
- async getSubSkills(tenantId, parentSkillName, context) {
17274
- const parentSkill = await this.getSkillById(tenantId, parentSkillName, context);
17275
- if (!parentSkill || !parentSkill.subSkills || parentSkill.subSkills.length === 0) {
17276
- return [];
19079
+ }
19080
+ \`\`\`
19081
+ `;
19082
+
19083
+ // src/agent_lattice/agentArchitectConfig.ts
19084
+ var AGENT_ARCHITECT_KEY = "agent-architect";
19085
+ var agentArchitectConfig = {
19086
+ key: AGENT_ARCHITECT_KEY,
19087
+ name: "Agent Architect",
19088
+ description: "Design and manage AI agents through natural language conversation. Use this agent when you want to create a new agent, modify an existing agent, or manage your agent collection (list, view, update, delete).",
19089
+ type: import_protocols11.AgentType.DEEP_AGENT,
19090
+ prompt: AGENT_ARCHITECT_PROMPT,
19091
+ tools: [
19092
+ "list_agents",
19093
+ "list_tools",
19094
+ "get_agent",
19095
+ "create_agent",
19096
+ "create_processing_agent",
19097
+ "update_processing_agent",
19098
+ "update_agent",
19099
+ "delete_agent",
19100
+ "invoke_agent"
19101
+ ],
19102
+ middleware: [
19103
+ {
19104
+ id: "widget",
19105
+ type: "widget",
19106
+ name: "Widget",
19107
+ description: "Render interactive HTML widgets and SVG diagrams",
19108
+ enabled: true,
19109
+ config: {}
17277
19110
  }
17278
- const subSkills = [];
17279
- for (const subSkillName of parentSkill.subSkills) {
17280
- const subSkill = await this.getSkillById(tenantId, subSkillName, context);
17281
- if (subSkill) {
17282
- subSkills.push(subSkill);
17283
- }
19111
+ ]
19112
+ };
19113
+
19114
+ // src/agent_lattice/builtinAgents.ts
19115
+ var BUILTIN_AGENTS = [agentArchitectConfig];
19116
+ function ensureBuiltinAgentsForTenant(tenantId) {
19117
+ for (const config of BUILTIN_AGENTS) {
19118
+ if (!agentLatticeManager.hasWithTenant(tenantId, config.key)) {
19119
+ agentLatticeManager.registerLatticeWithTenant(tenantId, config);
17284
19120
  }
17285
- return subSkills;
17286
19121
  }
17287
- };
19122
+ }
17288
19123
 
17289
19124
  // src/agent_lattice/AgentLatticeManager.ts
17290
19125
  function assistantToConfig(assistant) {
@@ -17471,6 +19306,7 @@ var AgentLatticeManager = class _AgentLatticeManager extends BaseLatticeManager
17471
19306
  * @param tenantId 租户ID
17472
19307
  */
17473
19308
  async initializeStoredAssistantsForTenant(tenantId) {
19309
+ ensureBuiltinAgentsForTenant(tenantId);
17474
19310
  try {
17475
19311
  const storeLattice = getStoreLattice("default", "assistant");
17476
19312
  const assistants = await storeLattice.store.getAllAssistants(tenantId);
@@ -17915,7 +19751,7 @@ var getVectorStoreLattice = (key) => vectorStoreLatticeManager.getVectorStoreLat
17915
19751
  var getVectorStoreClient = (key) => vectorStoreLatticeManager.getVectorStoreClient(key);
17916
19752
 
17917
19753
  // src/logger_lattice/LoggerLatticeManager.ts
17918
- var import_protocols10 = require("@axiom-lattice/protocols");
19754
+ var import_protocols12 = require("@axiom-lattice/protocols");
17919
19755
 
17920
19756
  // src/logger_lattice/PinoLoggerClient.ts
17921
19757
  var import_pino = __toESM(require("pino"));
@@ -18137,11 +19973,11 @@ var LoggerLatticeManager = class _LoggerLatticeManager extends BaseLatticeManage
18137
19973
  if (client) {
18138
19974
  loggerClient = client;
18139
19975
  } else {
18140
- if (config.type === import_protocols10.LoggerType.PINO) {
19976
+ if (config.type === import_protocols12.LoggerType.PINO) {
18141
19977
  loggerClient = new PinoLoggerClient(config);
18142
- } else if (config.type === import_protocols10.LoggerType.CONSOLE) {
19978
+ } else if (config.type === import_protocols12.LoggerType.CONSOLE) {
18143
19979
  loggerClient = new ConsoleLoggerClient(config);
18144
- } else if (config.type === import_protocols10.LoggerType.CUSTOM) {
19980
+ } else if (config.type === import_protocols12.LoggerType.CUSTOM) {
18145
19981
  throw new Error(
18146
19982
  `Custom logger client must be provided. Please pass the client to registerLattice.`
18147
19983
  );
@@ -18688,10 +20524,10 @@ var McpLatticeManager = class _McpLatticeManager extends BaseLatticeManager {
18688
20524
  }
18689
20525
  const tools = await this.getAllTools();
18690
20526
  console.log(`[MCP] Registering ${tools.length} tools to Tool Lattice...`);
18691
- for (const tool50 of tools) {
18692
- const toolKey = prefix ? `${prefix}_${tool50.name}` : tool50.name;
18693
- tool50.name = toolKey;
18694
- toolLatticeManager.registerExistingTool(toolKey, tool50);
20527
+ for (const tool51 of tools) {
20528
+ const toolKey = prefix ? `${prefix}_${tool51.name}` : tool51.name;
20529
+ tool51.name = toolKey;
20530
+ toolLatticeManager.registerExistingTool(toolKey, tool51);
18695
20531
  console.log(`[MCP] Registered tool: ${toolKey}`);
18696
20532
  }
18697
20533
  console.log(`[MCP] Successfully registered ${tools.length} tools to Tool Lattice`);
@@ -18989,7 +20825,7 @@ function parseOptionalNumberEnv(name, fallback) {
18989
20825
  }
18990
20826
  function getDefaultMicrosandboxRemoteConfig() {
18991
20827
  return {
18992
- image: process.env.MICROSANDBOX_IMAGE ?? "daytona-cn-shanghai.cr.volces.com/daytona/sandbox:0.0.4",
20828
+ image: process.env.MICROSANDBOX_IMAGE ?? "daytona-cn-shanghai.cr.volces.com/daytona/sandbox:0.0.5",
18993
20829
  //"daytonaio/sandbox:0.6.0",
18994
20830
  cpus: parseOptionalNumberEnv("MICROSANDBOX_CPUS", 1),
18995
20831
  memoryMib: parseOptionalNumberEnv("MICROSANDBOX_MEMORY", 512),
@@ -19939,6 +21775,7 @@ function clearEncryptionKeyCache() {
19939
21775
  createListMetricsServersTool,
19940
21776
  createListTablesSqlTool,
19941
21777
  createModelSelectorMiddleware,
21778
+ createProcessingAgent,
19942
21779
  createQueryCheckerSqlTool,
19943
21780
  createQueryMetricDefinitionTool,
19944
21781
  createQueryMetricsListTool,