@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.d.mts +100 -10
- package/dist/index.d.ts +100 -10
- package/dist/index.js +2087 -250
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2088 -245
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -648,11 +648,11 @@ var ToolLatticeManager = class _ToolLatticeManager extends BaseLatticeManager {
|
|
|
648
648
|
* @param key Lattice键名
|
|
649
649
|
* @param tool 已有的StructuredTool实例
|
|
650
650
|
*/
|
|
651
|
-
registerExistingTool(key,
|
|
651
|
+
registerExistingTool(key, tool51) {
|
|
652
652
|
const config = {
|
|
653
|
-
name:
|
|
654
|
-
description:
|
|
655
|
-
schema:
|
|
653
|
+
name: tool51.name,
|
|
654
|
+
description: tool51.description,
|
|
655
|
+
schema: tool51.schema,
|
|
656
656
|
// StructuredTool的schema已经是Zod兼容的
|
|
657
657
|
needUserApprove: false
|
|
658
658
|
// MCP工具默认不需要用户批准
|
|
@@ -660,7 +660,7 @@ var ToolLatticeManager = class _ToolLatticeManager extends BaseLatticeManager {
|
|
|
660
660
|
const toolLattice = {
|
|
661
661
|
key,
|
|
662
662
|
config,
|
|
663
|
-
client:
|
|
663
|
+
client: tool51
|
|
664
664
|
};
|
|
665
665
|
this.register(key, toolLattice);
|
|
666
666
|
}
|
|
@@ -686,7 +686,7 @@ var ToolLatticeManager = class _ToolLatticeManager extends BaseLatticeManager {
|
|
|
686
686
|
};
|
|
687
687
|
var toolLatticeManager = ToolLatticeManager.getInstance();
|
|
688
688
|
var registerToolLattice = (key, config, executor) => toolLatticeManager.registerLattice(key, config, executor);
|
|
689
|
-
var registerExistingTool = (key,
|
|
689
|
+
var registerExistingTool = (key, tool51) => toolLatticeManager.registerExistingTool(key, tool51);
|
|
690
690
|
var getToolLattice = (key) => toolLatticeManager.getToolLattice(key);
|
|
691
691
|
var getToolDefinition = (key) => toolLatticeManager.getToolDefinition(key);
|
|
692
692
|
var getToolClient = (key) => toolLatticeManager.getToolClient(key);
|
|
@@ -1120,14 +1120,14 @@ import z3 from "zod";
|
|
|
1120
1120
|
import { tool as tool2 } from "langchain";
|
|
1121
1121
|
|
|
1122
1122
|
// src/tool_lattice/sql/utils.ts
|
|
1123
|
-
function getTenantIdFromConfig(exeConfig,
|
|
1123
|
+
function getTenantIdFromConfig(exeConfig, getTenantId2) {
|
|
1124
1124
|
const runConfig = exeConfig?.configurable?.runConfig || {};
|
|
1125
|
-
return runConfig.tenantId || (
|
|
1125
|
+
return runConfig.tenantId || (getTenantId2 ? getTenantId2() : "default");
|
|
1126
1126
|
}
|
|
1127
1127
|
|
|
1128
1128
|
// src/tool_lattice/sql/list_tables_sql.ts
|
|
1129
1129
|
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.`;
|
|
1130
|
-
var createListTablesSqlTool = ({ databaseKeys, databaseDescriptions, getTenantId }) => {
|
|
1130
|
+
var createListTablesSqlTool = ({ databaseKeys, databaseDescriptions, getTenantId: getTenantId2 }) => {
|
|
1131
1131
|
const availableDbsText = databaseKeys.length > 0 ? `
|
|
1132
1132
|
|
|
1133
1133
|
Available databases:
|
|
@@ -1137,7 +1137,7 @@ ${databaseKeys.map(
|
|
|
1137
1137
|
return tool2(
|
|
1138
1138
|
async ({ databaseKey }, _exeConfig) => {
|
|
1139
1139
|
try {
|
|
1140
|
-
const tenantId = getTenantIdFromConfig(_exeConfig,
|
|
1140
|
+
const tenantId = getTenantIdFromConfig(_exeConfig, getTenantId2);
|
|
1141
1141
|
if (!databaseKey) {
|
|
1142
1142
|
return "Error: databaseKey parameter is required. Available databases: " + databaseKeys.join(", ");
|
|
1143
1143
|
}
|
|
@@ -1171,7 +1171,7 @@ ${databaseKeys.map(
|
|
|
1171
1171
|
import z4 from "zod";
|
|
1172
1172
|
import { tool as tool3 } from "langchain";
|
|
1173
1173
|
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.`;
|
|
1174
|
-
var createInfoSqlTool = ({ databaseKeys, databaseDescriptions, getTenantId }) => {
|
|
1174
|
+
var createInfoSqlTool = ({ databaseKeys, databaseDescriptions, getTenantId: getTenantId2 }) => {
|
|
1175
1175
|
const availableDbsText = databaseKeys.length > 0 ? `
|
|
1176
1176
|
|
|
1177
1177
|
Available databases:
|
|
@@ -1184,7 +1184,7 @@ ${databaseKeys.map(
|
|
|
1184
1184
|
databaseKey
|
|
1185
1185
|
}, _exeConfig) => {
|
|
1186
1186
|
try {
|
|
1187
|
-
const tenantId = getTenantIdFromConfig(_exeConfig,
|
|
1187
|
+
const tenantId = getTenantIdFromConfig(_exeConfig, getTenantId2);
|
|
1188
1188
|
if (!databaseKey) {
|
|
1189
1189
|
return "Error: databaseKey parameter is required. Available databases: " + databaseKeys.join(", ");
|
|
1190
1190
|
}
|
|
@@ -1303,7 +1303,7 @@ function checkDangerousOperations(query) {
|
|
|
1303
1303
|
}
|
|
1304
1304
|
return warnings;
|
|
1305
1305
|
}
|
|
1306
|
-
var createQueryCheckerSqlTool = ({ databaseKeys, databaseDescriptions, getTenantId }) => {
|
|
1306
|
+
var createQueryCheckerSqlTool = ({ databaseKeys, databaseDescriptions, getTenantId: getTenantId2 }) => {
|
|
1307
1307
|
const availableDbsText = databaseKeys.length > 0 ? `
|
|
1308
1308
|
|
|
1309
1309
|
Available databases:
|
|
@@ -1316,7 +1316,7 @@ ${databaseKeys.map(
|
|
|
1316
1316
|
databaseKey
|
|
1317
1317
|
}, _exeConfig) => {
|
|
1318
1318
|
try {
|
|
1319
|
-
const tenantId = getTenantIdFromConfig(_exeConfig,
|
|
1319
|
+
const tenantId = getTenantIdFromConfig(_exeConfig, getTenantId2);
|
|
1320
1320
|
const trimmedQuery = query.trim();
|
|
1321
1321
|
if (!trimmedQuery) {
|
|
1322
1322
|
return "Error: Empty query provided. Please provide a SQL query to check.";
|
|
@@ -1425,7 +1425,7 @@ function formatQueryResult(rows, fields) {
|
|
|
1425
1425
|
Total rows: ${rows.length}`);
|
|
1426
1426
|
return lines.join("\n");
|
|
1427
1427
|
}
|
|
1428
|
-
var createQuerySqlTool = ({ databaseKeys, databaseDescriptions, getTenantId }) => {
|
|
1428
|
+
var createQuerySqlTool = ({ databaseKeys, databaseDescriptions, getTenantId: getTenantId2 }) => {
|
|
1429
1429
|
const availableDbsText = databaseKeys.length > 0 ? `
|
|
1430
1430
|
|
|
1431
1431
|
Available databases:
|
|
@@ -1438,7 +1438,7 @@ ${databaseKeys.map(
|
|
|
1438
1438
|
databaseKey
|
|
1439
1439
|
}, _exeConfig) => {
|
|
1440
1440
|
try {
|
|
1441
|
-
const tenantId = getTenantIdFromConfig(_exeConfig,
|
|
1441
|
+
const tenantId = getTenantIdFromConfig(_exeConfig, getTenantId2);
|
|
1442
1442
|
if (!databaseKey) {
|
|
1443
1443
|
return "Error: databaseKey parameter is required. Available databases: " + databaseKeys.join(", ");
|
|
1444
1444
|
}
|
|
@@ -1470,9 +1470,9 @@ ${databaseKeys.map(
|
|
|
1470
1470
|
};
|
|
1471
1471
|
|
|
1472
1472
|
// src/tool_lattice/metrics/utils.ts
|
|
1473
|
-
function getTenantIdFromConfig2(exeConfig,
|
|
1473
|
+
function getTenantIdFromConfig2(exeConfig, getTenantId2) {
|
|
1474
1474
|
const runConfig = exeConfig?.configurable?.runConfig || {};
|
|
1475
|
-
return runConfig.tenantId || (
|
|
1475
|
+
return runConfig.tenantId || (getTenantId2 ? getTenantId2() : "default");
|
|
1476
1476
|
}
|
|
1477
1477
|
function filterServerKeysByTenant(serverKeys, tenantId, manager = metricsServerManager) {
|
|
1478
1478
|
return serverKeys.filter((key) => {
|
|
@@ -2324,7 +2324,7 @@ var metricsServerManager = MetricsServerManager.getInstance();
|
|
|
2324
2324
|
import z7 from "zod";
|
|
2325
2325
|
import { tool as tool6 } from "langchain";
|
|
2326
2326
|
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.`;
|
|
2327
|
-
var createListMetricsServersTool = ({ serverKeys, serverDescriptions, getTenantId }) => {
|
|
2327
|
+
var createListMetricsServersTool = ({ serverKeys, serverDescriptions, getTenantId: getTenantId2 }) => {
|
|
2328
2328
|
const availableServersText = serverKeys.length > 0 ? `
|
|
2329
2329
|
|
|
2330
2330
|
Available metrics servers:
|
|
@@ -2334,7 +2334,7 @@ ${serverKeys.map(
|
|
|
2334
2334
|
return tool6(
|
|
2335
2335
|
async (_input, _exeConfig) => {
|
|
2336
2336
|
try {
|
|
2337
|
-
const tenantId = getTenantIdFromConfig2(_exeConfig,
|
|
2337
|
+
const tenantId = getTenantIdFromConfig2(_exeConfig, getTenantId2);
|
|
2338
2338
|
const servers = metricsServerManager.getServerKeys(tenantId);
|
|
2339
2339
|
if (servers.length === 0) {
|
|
2340
2340
|
return "No metrics servers registered.";
|
|
@@ -2361,7 +2361,7 @@ ${lines.join("\n")}`;
|
|
|
2361
2361
|
import z8 from "zod";
|
|
2362
2362
|
import { tool as tool7 } from "langchain";
|
|
2363
2363
|
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.`;
|
|
2364
|
-
var createListMetricsDataSourcesTool = ({ serverKeys, serverDescriptions, getTenantId, connectAll }) => {
|
|
2364
|
+
var createListMetricsDataSourcesTool = ({ serverKeys, serverDescriptions, getTenantId: getTenantId2, connectAll }) => {
|
|
2365
2365
|
const availableServersText = serverKeys.length > 0 ? `
|
|
2366
2366
|
|
|
2367
2367
|
Configured metrics servers:
|
|
@@ -2371,7 +2371,7 @@ ${serverKeys.map(
|
|
|
2371
2371
|
return tool7(
|
|
2372
2372
|
async (_input, _exeConfig) => {
|
|
2373
2373
|
try {
|
|
2374
|
-
const tenantId = getTenantIdFromConfig2(_exeConfig,
|
|
2374
|
+
const tenantId = getTenantIdFromConfig2(_exeConfig, getTenantId2);
|
|
2375
2375
|
let effectiveServerKeys = serverKeys;
|
|
2376
2376
|
if (connectAll) {
|
|
2377
2377
|
effectiveServerKeys = metricsServerManager.getServerKeys(tenantId).map((s) => s.key);
|
|
@@ -2477,7 +2477,7 @@ Response Fields Reference
|
|
|
2477
2477
|
|
|
2478
2478
|
Next Step
|
|
2479
2479
|
After finding relevant metrics, call query_metric_definition with the metricName to get detailed metadata including time dimensions and supported filters.`;
|
|
2480
|
-
var createQueryMetricsListTool = ({ serverKeys, serverDescriptions, getTenantId, connectAll }) => {
|
|
2480
|
+
var createQueryMetricsListTool = ({ serverKeys, serverDescriptions, getTenantId: getTenantId2, connectAll }) => {
|
|
2481
2481
|
const availableServersText = serverKeys.length > 0 ? `
|
|
2482
2482
|
|
|
2483
2483
|
Available metrics servers:
|
|
@@ -2490,7 +2490,7 @@ ${serverKeys.map(
|
|
|
2490
2490
|
datasourceIds
|
|
2491
2491
|
}, _exeConfig) => {
|
|
2492
2492
|
try {
|
|
2493
|
-
const tenantId = getTenantIdFromConfig2(_exeConfig,
|
|
2493
|
+
const tenantId = getTenantIdFromConfig2(_exeConfig, getTenantId2);
|
|
2494
2494
|
let effectiveServerKeys = serverKeys;
|
|
2495
2495
|
if (connectAll) {
|
|
2496
2496
|
effectiveServerKeys = metricsServerManager.getServerKeys(tenantId).map((s) => s.key);
|
|
@@ -2634,7 +2634,7 @@ Rules
|
|
|
2634
2634
|
|
|
2635
2635
|
Next Step
|
|
2636
2636
|
Call query_semantic_metric_data with parameters derived from this definition.`;
|
|
2637
|
-
var createQueryMetricDefinitionTool = ({ serverKeys, serverDescriptions, getTenantId, connectAll }) => {
|
|
2637
|
+
var createQueryMetricDefinitionTool = ({ serverKeys, serverDescriptions, getTenantId: getTenantId2, connectAll }) => {
|
|
2638
2638
|
const availableServersText = serverKeys.length > 0 ? `
|
|
2639
2639
|
|
|
2640
2640
|
Available metrics servers:
|
|
@@ -2648,7 +2648,7 @@ ${serverKeys.map(
|
|
|
2648
2648
|
datasourceId: inputDatasourceId
|
|
2649
2649
|
}, _exeConfig) => {
|
|
2650
2650
|
try {
|
|
2651
|
-
const tenantId = getTenantIdFromConfig2(_exeConfig,
|
|
2651
|
+
const tenantId = getTenantIdFromConfig2(_exeConfig, getTenantId2);
|
|
2652
2652
|
let effectiveServerKeys = serverKeys;
|
|
2653
2653
|
if (connectAll) {
|
|
2654
2654
|
effectiveServerKeys = metricsServerManager.getServerKeys(tenantId).map((s) => s.key);
|
|
@@ -2867,7 +2867,7 @@ Semantic Model: ${semanticModel}`;
|
|
|
2867
2867
|
`);
|
|
2868
2868
|
return lines.join("\n");
|
|
2869
2869
|
}
|
|
2870
|
-
var createQuerySemanticMetricDataTool = ({ serverKeys, serverDescriptions, getTenantId, connectAll }) => {
|
|
2870
|
+
var createQuerySemanticMetricDataTool = ({ serverKeys, serverDescriptions, getTenantId: getTenantId2, connectAll }) => {
|
|
2871
2871
|
const availableServersText = serverKeys.length > 0 ? `
|
|
2872
2872
|
|
|
2873
2873
|
Available metrics servers:
|
|
@@ -2884,7 +2884,7 @@ ${serverKeys.map(
|
|
|
2884
2884
|
limit
|
|
2885
2885
|
}, _exeConfig) => {
|
|
2886
2886
|
try {
|
|
2887
|
-
const tenantId = getTenantIdFromConfig2(_exeConfig,
|
|
2887
|
+
const tenantId = getTenantIdFromConfig2(_exeConfig, getTenantId2);
|
|
2888
2888
|
let effectiveServerKeys = serverKeys;
|
|
2889
2889
|
if (connectAll) {
|
|
2890
2890
|
effectiveServerKeys = metricsServerManager.getServerKeys(tenantId).map((s) => s.key);
|
|
@@ -2952,7 +2952,7 @@ ${serverKeys.map(
|
|
|
2952
2952
|
import z12 from "zod";
|
|
2953
2953
|
import { tool as tool11 } from "langchain";
|
|
2954
2954
|
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.`;
|
|
2955
|
-
var createQueryTablesListTool = ({ serverKeys, serverDescriptions, getTenantId, connectAll }) => {
|
|
2955
|
+
var createQueryTablesListTool = ({ serverKeys, serverDescriptions, getTenantId: getTenantId2, connectAll }) => {
|
|
2956
2956
|
const availableServersText = serverKeys.length > 0 ? `
|
|
2957
2957
|
|
|
2958
2958
|
Available metrics servers:
|
|
@@ -2965,7 +2965,7 @@ ${serverKeys.map(
|
|
|
2965
2965
|
datasourceIds
|
|
2966
2966
|
}, _exeConfig) => {
|
|
2967
2967
|
try {
|
|
2968
|
-
const tenantId = getTenantIdFromConfig2(_exeConfig,
|
|
2968
|
+
const tenantId = getTenantIdFromConfig2(_exeConfig, getTenantId2);
|
|
2969
2969
|
let effectiveServerKeys = serverKeys;
|
|
2970
2970
|
if (connectAll) {
|
|
2971
2971
|
effectiveServerKeys = metricsServerManager.getServerKeys(tenantId).map((s) => s.key);
|
|
@@ -3056,7 +3056,7 @@ ${serverKeys.map(
|
|
|
3056
3056
|
import z13 from "zod";
|
|
3057
3057
|
import { tool as tool12 } from "langchain";
|
|
3058
3058
|
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.`;
|
|
3059
|
-
var createQueryTableDefinitionTool = ({ serverKeys, serverDescriptions, getTenantId, connectAll }) => {
|
|
3059
|
+
var createQueryTableDefinitionTool = ({ serverKeys, serverDescriptions, getTenantId: getTenantId2, connectAll }) => {
|
|
3060
3060
|
const availableServersText = serverKeys.length > 0 ? `
|
|
3061
3061
|
|
|
3062
3062
|
Available metrics servers:
|
|
@@ -3070,7 +3070,7 @@ ${serverKeys.map(
|
|
|
3070
3070
|
datasourceId: inputDatasourceId
|
|
3071
3071
|
}, _exeConfig) => {
|
|
3072
3072
|
try {
|
|
3073
|
-
const tenantId = getTenantIdFromConfig2(_exeConfig,
|
|
3073
|
+
const tenantId = getTenantIdFromConfig2(_exeConfig, getTenantId2);
|
|
3074
3074
|
let effectiveServerKeys = serverKeys;
|
|
3075
3075
|
if (connectAll) {
|
|
3076
3076
|
effectiveServerKeys = metricsServerManager.getServerKeys(tenantId).map((s) => s.key);
|
|
@@ -3194,7 +3194,7 @@ Example:
|
|
|
3194
3194
|
},
|
|
3195
3195
|
"limit": 100
|
|
3196
3196
|
}`;
|
|
3197
|
-
var createExecuteSqlQueryTool = ({ serverKeys, serverDescriptions, getTenantId, connectAll }) => {
|
|
3197
|
+
var createExecuteSqlQueryTool = ({ serverKeys, serverDescriptions, getTenantId: getTenantId2, connectAll }) => {
|
|
3198
3198
|
const availableServersText = serverKeys.length > 0 ? `
|
|
3199
3199
|
|
|
3200
3200
|
Available metrics servers:
|
|
@@ -3210,7 +3210,7 @@ ${serverKeys.map(
|
|
|
3210
3210
|
limit
|
|
3211
3211
|
}, _exeConfig) => {
|
|
3212
3212
|
try {
|
|
3213
|
-
const tenantId = getTenantIdFromConfig2(_exeConfig,
|
|
3213
|
+
const tenantId = getTenantIdFromConfig2(_exeConfig, getTenantId2);
|
|
3214
3214
|
let effectiveServerKeys = serverKeys;
|
|
3215
3215
|
if (connectAll) {
|
|
3216
3216
|
effectiveServerKeys = metricsServerManager.getServerKeys(tenantId).map((s) => s.key);
|
|
@@ -4528,6 +4528,7 @@ import {
|
|
|
4528
4528
|
AgentType,
|
|
4529
4529
|
hasTools,
|
|
4530
4530
|
isDeepAgentConfig,
|
|
4531
|
+
isProcessingAgentConfig,
|
|
4531
4532
|
isTeamAgentConfig,
|
|
4532
4533
|
getToolsFromConfig,
|
|
4533
4534
|
getSubAgentsFromConfig
|
|
@@ -10829,6 +10830,125 @@ var InMemoryThreadMessageQueueStore = class {
|
|
|
10829
10830
|
}
|
|
10830
10831
|
};
|
|
10831
10832
|
|
|
10833
|
+
// src/store_lattice/InMemoryWorkflowTrackingStore.ts
|
|
10834
|
+
var InMemoryWorkflowTrackingStore = class {
|
|
10835
|
+
constructor() {
|
|
10836
|
+
this.runs = /* @__PURE__ */ new Map();
|
|
10837
|
+
this.steps = /* @__PURE__ */ new Map();
|
|
10838
|
+
}
|
|
10839
|
+
async createWorkflowRun(request) {
|
|
10840
|
+
const now = /* @__PURE__ */ new Date();
|
|
10841
|
+
const run = {
|
|
10842
|
+
id: `${request.threadId}_${Date.now()}`,
|
|
10843
|
+
tenantId: request.tenantId,
|
|
10844
|
+
assistantId: request.assistantId,
|
|
10845
|
+
threadId: request.threadId,
|
|
10846
|
+
status: "running",
|
|
10847
|
+
topologyEdges: request.topologyEdges,
|
|
10848
|
+
totalEdges: request.topologyEdges.length,
|
|
10849
|
+
completedEdges: 0,
|
|
10850
|
+
metadata: request.metadata || {},
|
|
10851
|
+
startedAt: now,
|
|
10852
|
+
createdAt: now,
|
|
10853
|
+
updatedAt: now
|
|
10854
|
+
};
|
|
10855
|
+
this.runs.set(run.id, run);
|
|
10856
|
+
this.steps.set(run.id, []);
|
|
10857
|
+
return run;
|
|
10858
|
+
}
|
|
10859
|
+
async getWorkflowRun(runId) {
|
|
10860
|
+
return this.runs.get(runId) || null;
|
|
10861
|
+
}
|
|
10862
|
+
async updateWorkflowRun(runId, updates) {
|
|
10863
|
+
const run = this.runs.get(runId);
|
|
10864
|
+
if (!run) return null;
|
|
10865
|
+
const updated = {
|
|
10866
|
+
...run,
|
|
10867
|
+
...updates,
|
|
10868
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
10869
|
+
};
|
|
10870
|
+
this.runs.set(runId, updated);
|
|
10871
|
+
return updated;
|
|
10872
|
+
}
|
|
10873
|
+
async getWorkflowRunsByThreadId(tenantId, threadId) {
|
|
10874
|
+
const results = [];
|
|
10875
|
+
for (const run of this.runs.values()) {
|
|
10876
|
+
if (run.tenantId === tenantId && run.threadId === threadId) {
|
|
10877
|
+
results.push(run);
|
|
10878
|
+
}
|
|
10879
|
+
}
|
|
10880
|
+
return results;
|
|
10881
|
+
}
|
|
10882
|
+
async getWorkflowRunsByAssistantId(tenantId, assistantId) {
|
|
10883
|
+
const results = [];
|
|
10884
|
+
for (const run of this.runs.values()) {
|
|
10885
|
+
if (run.tenantId === tenantId && run.assistantId === assistantId) {
|
|
10886
|
+
results.push(run);
|
|
10887
|
+
}
|
|
10888
|
+
}
|
|
10889
|
+
return results;
|
|
10890
|
+
}
|
|
10891
|
+
async getWorkflowRunsByTenantId(tenantId) {
|
|
10892
|
+
const results = [];
|
|
10893
|
+
for (const run of this.runs.values()) {
|
|
10894
|
+
if (run.tenantId === tenantId) {
|
|
10895
|
+
results.push(run);
|
|
10896
|
+
}
|
|
10897
|
+
}
|
|
10898
|
+
return results;
|
|
10899
|
+
}
|
|
10900
|
+
async createRunStep(request) {
|
|
10901
|
+
const now = /* @__PURE__ */ new Date();
|
|
10902
|
+
const step = {
|
|
10903
|
+
id: `step_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`,
|
|
10904
|
+
runId: request.runId,
|
|
10905
|
+
tenantId: request.tenantId,
|
|
10906
|
+
stepType: request.stepType,
|
|
10907
|
+
stepName: request.stepName,
|
|
10908
|
+
edgeFrom: request.edgeFrom,
|
|
10909
|
+
edgeTo: request.edgeTo,
|
|
10910
|
+
edgePurpose: request.edgePurpose,
|
|
10911
|
+
input: request.input,
|
|
10912
|
+
status: "running",
|
|
10913
|
+
startedAt: now,
|
|
10914
|
+
createdAt: now,
|
|
10915
|
+
updatedAt: now
|
|
10916
|
+
};
|
|
10917
|
+
const runSteps = this.steps.get(request.runId) || [];
|
|
10918
|
+
runSteps.push(step);
|
|
10919
|
+
this.steps.set(request.runId, runSteps);
|
|
10920
|
+
return step;
|
|
10921
|
+
}
|
|
10922
|
+
async updateRunStep(runId, stepId, updates) {
|
|
10923
|
+
const runSteps = this.steps.get(runId);
|
|
10924
|
+
if (!runSteps) return null;
|
|
10925
|
+
const idx = runSteps.findIndex((s) => s.id === stepId);
|
|
10926
|
+
if (idx === -1) return null;
|
|
10927
|
+
const now = /* @__PURE__ */ new Date();
|
|
10928
|
+
runSteps[idx] = {
|
|
10929
|
+
...runSteps[idx],
|
|
10930
|
+
...updates,
|
|
10931
|
+
updatedAt: now
|
|
10932
|
+
};
|
|
10933
|
+
return runSteps[idx];
|
|
10934
|
+
}
|
|
10935
|
+
async getRunSteps(runId) {
|
|
10936
|
+
return this.steps.get(runId) || [];
|
|
10937
|
+
}
|
|
10938
|
+
async getRunStepsByType(runId, stepType) {
|
|
10939
|
+
const runSteps = this.steps.get(runId) || [];
|
|
10940
|
+
return runSteps.filter((s) => s.stepType === stepType);
|
|
10941
|
+
}
|
|
10942
|
+
async getInterruptedSteps(runId) {
|
|
10943
|
+
const runSteps = this.steps.get(runId) || [];
|
|
10944
|
+
return runSteps.filter((s) => s.status === "interrupted");
|
|
10945
|
+
}
|
|
10946
|
+
clear() {
|
|
10947
|
+
this.runs.clear();
|
|
10948
|
+
this.steps.clear();
|
|
10949
|
+
}
|
|
10950
|
+
};
|
|
10951
|
+
|
|
10832
10952
|
// src/store_lattice/StoreLatticeManager.ts
|
|
10833
10953
|
var StoreLatticeManager = class _StoreLatticeManager extends BaseLatticeManager {
|
|
10834
10954
|
/**
|
|
@@ -10985,6 +11105,12 @@ storeLatticeManager.registerLattice(
|
|
|
10985
11105
|
"threadMessageQueue",
|
|
10986
11106
|
defaultThreadMessageQueueStore
|
|
10987
11107
|
);
|
|
11108
|
+
var defaultWorkflowTrackingStore = new InMemoryWorkflowTrackingStore();
|
|
11109
|
+
storeLatticeManager.registerLattice(
|
|
11110
|
+
"default",
|
|
11111
|
+
"workflowTracking",
|
|
11112
|
+
defaultWorkflowTrackingStore
|
|
11113
|
+
);
|
|
10988
11114
|
|
|
10989
11115
|
// src/services/Agent.ts
|
|
10990
11116
|
import { Command as Command2 } from "@langchain/langgraph";
|
|
@@ -11327,6 +11453,7 @@ var Agent = class {
|
|
|
11327
11453
|
this.abortController = null;
|
|
11328
11454
|
this.queueMode = this.getDefaultQueueConfig();
|
|
11329
11455
|
this.isWaitingForQueueEnd = false;
|
|
11456
|
+
this.asyncTasks = [];
|
|
11330
11457
|
this.agentExecutor = async ({ input, command, custom_run_config }, signal) => {
|
|
11331
11458
|
const { runnable_agent, runConfig } = await this.getLatticeClientAndRuntimeConfig(custom_run_config);
|
|
11332
11459
|
const { messages, ...rest } = input;
|
|
@@ -12105,6 +12232,23 @@ var Agent = class {
|
|
|
12105
12232
|
console.log(namespacedEvent);
|
|
12106
12233
|
event_bus_default.publish(namespacedEvent, data);
|
|
12107
12234
|
}
|
|
12235
|
+
addAsyncTask(task) {
|
|
12236
|
+
this.asyncTasks.push(task);
|
|
12237
|
+
}
|
|
12238
|
+
getAsyncTasks() {
|
|
12239
|
+
return this.asyncTasks;
|
|
12240
|
+
}
|
|
12241
|
+
getAsyncTask(taskId) {
|
|
12242
|
+
return this.asyncTasks.find((t) => t.taskId === taskId);
|
|
12243
|
+
}
|
|
12244
|
+
updateAsyncTaskStatus(taskId, status) {
|
|
12245
|
+
const task = this.getAsyncTask(taskId);
|
|
12246
|
+
if (!task) return;
|
|
12247
|
+
task.status = status;
|
|
12248
|
+
if (status === "completed" || status === "failed" || status === "cancelled") {
|
|
12249
|
+
task.completedAt = Date.now();
|
|
12250
|
+
}
|
|
12251
|
+
}
|
|
12108
12252
|
};
|
|
12109
12253
|
|
|
12110
12254
|
// src/services/AgentInstanceManager.ts
|
|
@@ -12730,9 +12874,9 @@ var ReActAgentGraphBuilder = class {
|
|
|
12730
12874
|
*/
|
|
12731
12875
|
async build(agentLattice, params) {
|
|
12732
12876
|
const tools = params.tools.map((t) => {
|
|
12733
|
-
const
|
|
12734
|
-
return
|
|
12735
|
-
}).filter((
|
|
12877
|
+
const tool51 = getToolClient(t.key);
|
|
12878
|
+
return tool51;
|
|
12879
|
+
}).filter((tool51) => tool51 !== void 0);
|
|
12736
12880
|
const stateSchema2 = createReactAgentSchema(params.stateSchema);
|
|
12737
12881
|
const middlewareConfigs = params.middleware || [];
|
|
12738
12882
|
const filesystemBackend = createFilesystemBackendFactory(middlewareConfigs);
|
|
@@ -13156,6 +13300,25 @@ function getSubagents(options) {
|
|
|
13156
13300
|
}
|
|
13157
13301
|
return { agents, descriptions: subagentDescriptions };
|
|
13158
13302
|
}
|
|
13303
|
+
function getAsyncPromptText() {
|
|
13304
|
+
return `
|
|
13305
|
+
|
|
13306
|
+
## Async Task Usage
|
|
13307
|
+
|
|
13308
|
+
When tasks are independent and can run in parallel, use \`async: true\` to launch
|
|
13309
|
+
background tasks. The task returns immediately with a task ID.
|
|
13310
|
+
|
|
13311
|
+
CRITICAL: After launching with \`async: true\`, move on immediately.
|
|
13312
|
+
- NEVER call check_async_task or list_async_tasks right after starting a task.
|
|
13313
|
+
- NEVER poll for task completion. The result will arrive as a notification.
|
|
13314
|
+
- Only check task status when the USER explicitly asks for an update.
|
|
13315
|
+
- If you receive an [Async task completed] notification, read it and incorporate
|
|
13316
|
+
the result into your next response. Do not then call check_async_task repeatedly.
|
|
13317
|
+
- Task statuses in conversation history are stale \u2014 always use fresh tool calls
|
|
13318
|
+
when the user asks.
|
|
13319
|
+
- Use cancel_async_task if the user wants to stop a running task.
|
|
13320
|
+
- Keep the full task_id: never truncate or abbreviate it.`;
|
|
13321
|
+
}
|
|
13159
13322
|
function createTaskTool(options) {
|
|
13160
13323
|
const {
|
|
13161
13324
|
defaultModel,
|
|
@@ -13164,7 +13327,8 @@ function createTaskTool(options) {
|
|
|
13164
13327
|
defaultInterruptOn,
|
|
13165
13328
|
subagents,
|
|
13166
13329
|
generalPurposeAgent,
|
|
13167
|
-
taskDescription
|
|
13330
|
+
taskDescription,
|
|
13331
|
+
allowAsync
|
|
13168
13332
|
} = options;
|
|
13169
13333
|
const { agents: subagentGraphs, descriptions: subagentDescriptions } = getSubagents({
|
|
13170
13334
|
defaultModel,
|
|
@@ -13177,7 +13341,7 @@ function createTaskTool(options) {
|
|
|
13177
13341
|
const finalTaskDescription = taskDescription ? taskDescription : getTaskToolDescription(subagentDescriptions);
|
|
13178
13342
|
return tool46(
|
|
13179
13343
|
async (input, config) => {
|
|
13180
|
-
const { description, subagent_type } = input;
|
|
13344
|
+
const { description, subagent_type, async } = input;
|
|
13181
13345
|
let assistant_id = subagent_type;
|
|
13182
13346
|
if (subagent_type === "general-purpose") {
|
|
13183
13347
|
assistant_id = config.configurable?.runConfig?.assistant_id + "-general-purpose";
|
|
@@ -13207,6 +13371,57 @@ function createTaskTool(options) {
|
|
|
13207
13371
|
const subagentState = filterStateForSubagent(currentState);
|
|
13208
13372
|
subagentState.messages = [new HumanMessage2({ content: description })];
|
|
13209
13373
|
const subagent_thread_id = config.configurable?.thread_id + "____" + assistant_id + "_" + config.toolCall.id;
|
|
13374
|
+
if (async) {
|
|
13375
|
+
const tenantId = config.configurable?.runConfig?.tenantId;
|
|
13376
|
+
const mainAssistantId = config.configurable?.runConfig?.assistant_id;
|
|
13377
|
+
const mainThreadId = config.configurable?.runConfig?.thread_id;
|
|
13378
|
+
const mainRuntimeAgent = agentInstanceManager.getAgent({
|
|
13379
|
+
assistant_id: mainAssistantId,
|
|
13380
|
+
thread_id: mainThreadId,
|
|
13381
|
+
tenant_id: tenantId
|
|
13382
|
+
});
|
|
13383
|
+
if (mainRuntimeAgent) {
|
|
13384
|
+
mainRuntimeAgent.addAsyncTask({
|
|
13385
|
+
taskId: subagent_thread_id,
|
|
13386
|
+
assistantId: assistant_id,
|
|
13387
|
+
description: description.substring(0, 200),
|
|
13388
|
+
status: "running",
|
|
13389
|
+
createdAt: Date.now()
|
|
13390
|
+
});
|
|
13391
|
+
}
|
|
13392
|
+
AgentManager.getInstance().callAgentInQueue({
|
|
13393
|
+
assistant_id,
|
|
13394
|
+
thread_id: subagent_thread_id,
|
|
13395
|
+
input: { ...subagentState, message: description },
|
|
13396
|
+
"x-tenant-id": tenantId,
|
|
13397
|
+
runConfig: {
|
|
13398
|
+
...config.configurable?.runConfig,
|
|
13399
|
+
assistant_id,
|
|
13400
|
+
thread_id: subagent_thread_id
|
|
13401
|
+
},
|
|
13402
|
+
main_thread_id: mainThreadId,
|
|
13403
|
+
main_tenant_id: tenantId,
|
|
13404
|
+
main_assistant_id: mainAssistantId
|
|
13405
|
+
}, false).catch((err) => {
|
|
13406
|
+
console.error(`Failed to start async subagent ${subagent_thread_id}:`, err);
|
|
13407
|
+
});
|
|
13408
|
+
if (!config.toolCall?.id) {
|
|
13409
|
+
throw new Error("Tool call ID is required for subagent invocation");
|
|
13410
|
+
}
|
|
13411
|
+
return new Command3({
|
|
13412
|
+
update: {
|
|
13413
|
+
messages: [
|
|
13414
|
+
new ToolMessage4({
|
|
13415
|
+
content: `Async task started: ${subagent_thread_id}
|
|
13416
|
+
${description}
|
|
13417
|
+
The result will be delivered as a notification when complete. Do not poll.`,
|
|
13418
|
+
tool_call_id: config.toolCall.id,
|
|
13419
|
+
name: "task"
|
|
13420
|
+
})
|
|
13421
|
+
]
|
|
13422
|
+
}
|
|
13423
|
+
});
|
|
13424
|
+
}
|
|
13210
13425
|
const workerResult = await agentWorkerGraph.invoke({
|
|
13211
13426
|
assistant_id,
|
|
13212
13427
|
thread_id: subagent_thread_id,
|
|
@@ -13248,7 +13463,186 @@ function createTaskTool(options) {
|
|
|
13248
13463
|
`Name of the agent to use. Available: ${Object.keys(
|
|
13249
13464
|
subagentGraphs
|
|
13250
13465
|
).join(", ")}`
|
|
13251
|
-
)
|
|
13466
|
+
),
|
|
13467
|
+
...allowAsync ? {
|
|
13468
|
+
async: z48.boolean().default(false).describe(
|
|
13469
|
+
"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."
|
|
13470
|
+
)
|
|
13471
|
+
} : {}
|
|
13472
|
+
})
|
|
13473
|
+
}
|
|
13474
|
+
);
|
|
13475
|
+
}
|
|
13476
|
+
function getMainAgentFromConfig(config) {
|
|
13477
|
+
const tenantId = config.configurable?.runConfig?.tenantId;
|
|
13478
|
+
const mainAssistantId = config.configurable?.runConfig?.assistant_id;
|
|
13479
|
+
const mainThreadId = config.configurable?.runConfig?.thread_id;
|
|
13480
|
+
return agentInstanceManager.getAgent({
|
|
13481
|
+
assistant_id: mainAssistantId,
|
|
13482
|
+
thread_id: mainThreadId,
|
|
13483
|
+
tenant_id: tenantId
|
|
13484
|
+
});
|
|
13485
|
+
}
|
|
13486
|
+
function createCheckAsyncTaskTool() {
|
|
13487
|
+
return tool46(
|
|
13488
|
+
async (input, config) => {
|
|
13489
|
+
const { task_id } = input;
|
|
13490
|
+
const mainAgent = getMainAgentFromConfig(config);
|
|
13491
|
+
if (!mainAgent) {
|
|
13492
|
+
return "Cannot access main agent state.";
|
|
13493
|
+
}
|
|
13494
|
+
const cached = mainAgent.getAsyncTask(task_id);
|
|
13495
|
+
if (!cached) {
|
|
13496
|
+
return `Task ${task_id} not found. Use list_async_tasks to see all tasks.`;
|
|
13497
|
+
}
|
|
13498
|
+
try {
|
|
13499
|
+
if (!agentInstanceManager.hasAgent({
|
|
13500
|
+
assistant_id: cached.assistantId,
|
|
13501
|
+
thread_id: task_id,
|
|
13502
|
+
tenant_id: mainAgent.tenant_id
|
|
13503
|
+
})) {
|
|
13504
|
+
return `Task ${task_id}: not found (may have been cleaned up). Status was: ${cached.status}`;
|
|
13505
|
+
}
|
|
13506
|
+
const subAgent = agentInstanceManager.getAgent({
|
|
13507
|
+
assistant_id: cached.assistantId,
|
|
13508
|
+
thread_id: task_id,
|
|
13509
|
+
tenant_id: mainAgent.tenant_id
|
|
13510
|
+
});
|
|
13511
|
+
const status = await subAgent.getRunStatus();
|
|
13512
|
+
if (status === "busy") {
|
|
13513
|
+
return `Task ${task_id}: still running.
|
|
13514
|
+
Description: ${cached.description}`;
|
|
13515
|
+
}
|
|
13516
|
+
if (status === "idle") {
|
|
13517
|
+
const state = await subAgent.getCurrentState();
|
|
13518
|
+
const messages = state.values.messages || [];
|
|
13519
|
+
const lastAI = [...messages].reverse().find(
|
|
13520
|
+
(m) => m.type === "ai" || m.getType?.() === "ai"
|
|
13521
|
+
);
|
|
13522
|
+
mainAgent.updateAsyncTaskStatus(task_id, "completed");
|
|
13523
|
+
const result = lastAI?.content ?? "(completed, no output)";
|
|
13524
|
+
return `Task ${task_id}: COMPLETED.
|
|
13525
|
+
Description: ${cached.description}
|
|
13526
|
+
Result:
|
|
13527
|
+
${result}`;
|
|
13528
|
+
}
|
|
13529
|
+
if (status === "error") {
|
|
13530
|
+
mainAgent.updateAsyncTaskStatus(task_id, "failed");
|
|
13531
|
+
return `Task ${task_id}: failed.
|
|
13532
|
+
Description: ${cached.description}`;
|
|
13533
|
+
}
|
|
13534
|
+
if (status === "interrupted") {
|
|
13535
|
+
return `Task ${task_id}: interrupted (waiting for input).
|
|
13536
|
+
Description: ${cached.description}`;
|
|
13537
|
+
}
|
|
13538
|
+
return `Task ${task_id}: ${status}.
|
|
13539
|
+
Description: ${cached.description}`;
|
|
13540
|
+
} catch (err) {
|
|
13541
|
+
return `Task ${task_id}: error checking status: ${err instanceof Error ? err.message : String(err)}`;
|
|
13542
|
+
}
|
|
13543
|
+
},
|
|
13544
|
+
{
|
|
13545
|
+
name: "check_async_task",
|
|
13546
|
+
description: "Get the current status and result of an async background task. Use this to check if a previously launched async task has completed.",
|
|
13547
|
+
schema: z48.object({
|
|
13548
|
+
task_id: z48.string().describe("The task ID returned when the async task was started")
|
|
13549
|
+
})
|
|
13550
|
+
}
|
|
13551
|
+
);
|
|
13552
|
+
}
|
|
13553
|
+
function createListAsyncTasksTool() {
|
|
13554
|
+
return tool46(
|
|
13555
|
+
async (_input, config) => {
|
|
13556
|
+
const mainAgent = getMainAgentFromConfig(config);
|
|
13557
|
+
if (!mainAgent) {
|
|
13558
|
+
return "Cannot access main agent state.";
|
|
13559
|
+
}
|
|
13560
|
+
const tasks = mainAgent.getAsyncTasks();
|
|
13561
|
+
if (tasks.length === 0) {
|
|
13562
|
+
return "No async tasks have been launched.";
|
|
13563
|
+
}
|
|
13564
|
+
for (const task of tasks) {
|
|
13565
|
+
if (task.status === "completed" || task.status === "failed" || task.status === "cancelled") continue;
|
|
13566
|
+
try {
|
|
13567
|
+
if (!agentInstanceManager.hasAgent({
|
|
13568
|
+
assistant_id: task.assistantId,
|
|
13569
|
+
thread_id: task.taskId,
|
|
13570
|
+
tenant_id: mainAgent.tenant_id
|
|
13571
|
+
})) continue;
|
|
13572
|
+
const subAgent = agentInstanceManager.getAgent({
|
|
13573
|
+
assistant_id: task.assistantId,
|
|
13574
|
+
thread_id: task.taskId,
|
|
13575
|
+
tenant_id: mainAgent.tenant_id
|
|
13576
|
+
});
|
|
13577
|
+
const status = await subAgent.getRunStatus();
|
|
13578
|
+
if (status === "idle") {
|
|
13579
|
+
mainAgent.updateAsyncTaskStatus(task.taskId, "completed");
|
|
13580
|
+
} else if (status === "error") {
|
|
13581
|
+
mainAgent.updateAsyncTaskStatus(task.taskId, "failed");
|
|
13582
|
+
}
|
|
13583
|
+
} catch {
|
|
13584
|
+
}
|
|
13585
|
+
}
|
|
13586
|
+
const lines = tasks.map((t) => {
|
|
13587
|
+
const age = Math.floor((Date.now() - t.createdAt) / 1e3);
|
|
13588
|
+
const ageStr = age < 60 ? `${age}s ago` : `${Math.floor(age / 60)}m ago`;
|
|
13589
|
+
return `| ${t.taskId} | ${t.status} | ${ageStr} | ${t.description.substring(0, 80)} |`;
|
|
13590
|
+
});
|
|
13591
|
+
return [
|
|
13592
|
+
"| task_id | status | age | description |",
|
|
13593
|
+
"|---------|--------|-----|-------------|",
|
|
13594
|
+
...lines
|
|
13595
|
+
].join("\n");
|
|
13596
|
+
},
|
|
13597
|
+
{
|
|
13598
|
+
name: "list_async_tasks",
|
|
13599
|
+
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.",
|
|
13600
|
+
schema: z48.object({})
|
|
13601
|
+
}
|
|
13602
|
+
);
|
|
13603
|
+
}
|
|
13604
|
+
function createCancelAsyncTaskTool() {
|
|
13605
|
+
return tool46(
|
|
13606
|
+
async (input, config) => {
|
|
13607
|
+
const { task_id } = input;
|
|
13608
|
+
const mainAgent = getMainAgentFromConfig(config);
|
|
13609
|
+
if (!mainAgent) {
|
|
13610
|
+
return "Cannot access main agent state.";
|
|
13611
|
+
}
|
|
13612
|
+
const cached = mainAgent.getAsyncTask(task_id);
|
|
13613
|
+
if (!cached) {
|
|
13614
|
+
return `Task ${task_id} not found.`;
|
|
13615
|
+
}
|
|
13616
|
+
try {
|
|
13617
|
+
const subAgentExists = agentInstanceManager.hasAgent({
|
|
13618
|
+
assistant_id: cached.assistantId,
|
|
13619
|
+
thread_id: task_id,
|
|
13620
|
+
tenant_id: mainAgent.tenant_id
|
|
13621
|
+
});
|
|
13622
|
+
if (subAgentExists) {
|
|
13623
|
+
const subAgent = agentInstanceManager.getAgent({
|
|
13624
|
+
assistant_id: cached.assistantId,
|
|
13625
|
+
thread_id: task_id,
|
|
13626
|
+
tenant_id: mainAgent.tenant_id
|
|
13627
|
+
});
|
|
13628
|
+
await subAgent.abort();
|
|
13629
|
+
agentInstanceManager.removeAgent({
|
|
13630
|
+
assistant_id: cached.assistantId,
|
|
13631
|
+
thread_id: task_id,
|
|
13632
|
+
tenant_id: mainAgent.tenant_id
|
|
13633
|
+
});
|
|
13634
|
+
}
|
|
13635
|
+
} catch (err) {
|
|
13636
|
+
return `Failed to cancel task ${task_id}: ${err instanceof Error ? err.message : String(err)}`;
|
|
13637
|
+
}
|
|
13638
|
+
mainAgent.updateAsyncTaskStatus(task_id, "cancelled");
|
|
13639
|
+
return `Task ${task_id} cancelled.`;
|
|
13640
|
+
},
|
|
13641
|
+
{
|
|
13642
|
+
name: "cancel_async_task",
|
|
13643
|
+
description: "Cancel a running async background task.",
|
|
13644
|
+
schema: z48.object({
|
|
13645
|
+
task_id: z48.string().describe("The task ID to cancel")
|
|
13252
13646
|
})
|
|
13253
13647
|
}
|
|
13254
13648
|
);
|
|
@@ -13262,7 +13656,8 @@ function createSubAgentMiddleware(options) {
|
|
|
13262
13656
|
subagents = [],
|
|
13263
13657
|
systemPrompt = TASK_SYSTEM_PROMPT,
|
|
13264
13658
|
generalPurposeAgent = true,
|
|
13265
|
-
taskDescription = null
|
|
13659
|
+
taskDescription = null,
|
|
13660
|
+
allowAsync = true
|
|
13266
13661
|
} = options;
|
|
13267
13662
|
const taskTool = createTaskTool({
|
|
13268
13663
|
defaultModel,
|
|
@@ -13271,17 +13666,27 @@ function createSubAgentMiddleware(options) {
|
|
|
13271
13666
|
defaultInterruptOn,
|
|
13272
13667
|
subagents,
|
|
13273
13668
|
generalPurposeAgent,
|
|
13274
|
-
taskDescription
|
|
13669
|
+
taskDescription,
|
|
13670
|
+
allowAsync
|
|
13275
13671
|
});
|
|
13672
|
+
const allTools = [taskTool];
|
|
13673
|
+
if (allowAsync) {
|
|
13674
|
+
allTools.push(
|
|
13675
|
+
createCheckAsyncTaskTool(),
|
|
13676
|
+
createListAsyncTasksTool(),
|
|
13677
|
+
createCancelAsyncTaskTool()
|
|
13678
|
+
);
|
|
13679
|
+
}
|
|
13680
|
+
const effectiveSystemPrompt = allowAsync ? systemPrompt + getAsyncPromptText() : systemPrompt;
|
|
13276
13681
|
return createMiddleware14({
|
|
13277
13682
|
name: "subAgentMiddleware",
|
|
13278
|
-
tools:
|
|
13683
|
+
tools: allTools,
|
|
13279
13684
|
wrapModelCall: async (request, handler) => {
|
|
13280
|
-
if (
|
|
13685
|
+
if (effectiveSystemPrompt !== null) {
|
|
13281
13686
|
const currentPrompt = request.systemPrompt || "";
|
|
13282
13687
|
const newPrompt = currentPrompt ? `${currentPrompt}
|
|
13283
13688
|
|
|
13284
|
-
${
|
|
13689
|
+
${effectiveSystemPrompt}` : effectiveSystemPrompt;
|
|
13285
13690
|
return handler({
|
|
13286
13691
|
...request,
|
|
13287
13692
|
systemPrompt: newPrompt
|
|
@@ -14816,7 +15221,7 @@ var DeepAgentGraphBuilder = class {
|
|
|
14816
15221
|
const tools = params.tools.map((t) => {
|
|
14817
15222
|
const toolClient = getToolClient(t.key);
|
|
14818
15223
|
return toolClient;
|
|
14819
|
-
}).filter((
|
|
15224
|
+
}).filter((tool51) => tool51 !== void 0);
|
|
14820
15225
|
const subagents = await Promise.all(params.subAgents.map(async (sa) => {
|
|
14821
15226
|
if (sa.client) {
|
|
14822
15227
|
return {
|
|
@@ -16441,7 +16846,7 @@ var TeamAgentGraphBuilder = class {
|
|
|
16441
16846
|
const tools = params.tools.map((t) => {
|
|
16442
16847
|
const toolClient = getToolClient(t.key);
|
|
16443
16848
|
return toolClient;
|
|
16444
|
-
}).filter((
|
|
16849
|
+
}).filter((tool51) => tool51 !== void 0);
|
|
16445
16850
|
const teammates = params.subAgents.map((sa) => {
|
|
16446
16851
|
const baseConfig = sa.config;
|
|
16447
16852
|
return {
|
|
@@ -16478,129 +16883,558 @@ var TeamAgentGraphBuilder = class {
|
|
|
16478
16883
|
}
|
|
16479
16884
|
};
|
|
16480
16885
|
|
|
16481
|
-
// src/
|
|
16482
|
-
var AgentGraphBuilderFactory = class _AgentGraphBuilderFactory {
|
|
16483
|
-
constructor() {
|
|
16484
|
-
this.builders = /* @__PURE__ */ new Map();
|
|
16485
|
-
this.registerDefaultBuilders();
|
|
16486
|
-
}
|
|
16487
|
-
/**
|
|
16488
|
-
* 获取单例实例
|
|
16489
|
-
*/
|
|
16490
|
-
static getInstance() {
|
|
16491
|
-
if (!_AgentGraphBuilderFactory.instance) {
|
|
16492
|
-
_AgentGraphBuilderFactory.instance = new _AgentGraphBuilderFactory();
|
|
16493
|
-
}
|
|
16494
|
-
return _AgentGraphBuilderFactory.instance;
|
|
16495
|
-
}
|
|
16496
|
-
/**
|
|
16497
|
-
* 注册默认的Builder
|
|
16498
|
-
*/
|
|
16499
|
-
registerDefaultBuilders() {
|
|
16500
|
-
this.builders.set(AgentType.REACT, new ReActAgentGraphBuilder());
|
|
16501
|
-
this.builders.set(AgentType.DEEP_AGENT, new DeepAgentGraphBuilder());
|
|
16502
|
-
this.builders.set(AgentType.TEAM, new TeamAgentGraphBuilder());
|
|
16503
|
-
}
|
|
16504
|
-
/**
|
|
16505
|
-
* 注册自定义Builder
|
|
16506
|
-
*
|
|
16507
|
-
* @param type Agent类型
|
|
16508
|
-
* @param builder Builder实例
|
|
16509
|
-
*/
|
|
16510
|
-
registerBuilder(type, builder) {
|
|
16511
|
-
this.builders.set(type, builder);
|
|
16512
|
-
}
|
|
16513
|
-
/**
|
|
16514
|
-
* 获取Builder
|
|
16515
|
-
*
|
|
16516
|
-
* @param type Agent类型
|
|
16517
|
-
* @returns 返回对应的Builder
|
|
16518
|
-
*/
|
|
16519
|
-
getBuilder(type) {
|
|
16520
|
-
const builder = this.builders.get(type);
|
|
16521
|
-
if (!builder) {
|
|
16522
|
-
throw new Error(`\u4E0D\u652F\u6301\u7684Agent\u7C7B\u578B: ${type}`);
|
|
16523
|
-
}
|
|
16524
|
-
return builder;
|
|
16525
|
-
}
|
|
16526
|
-
};
|
|
16527
|
-
|
|
16528
|
-
// src/agent_lattice/builders/AgentParamsBuilder.ts
|
|
16886
|
+
// src/deep_agent_new/processing_agent.ts
|
|
16529
16887
|
import {
|
|
16530
|
-
|
|
16531
|
-
|
|
16532
|
-
|
|
16533
|
-
|
|
16534
|
-
|
|
16535
|
-
|
|
16536
|
-
|
|
16537
|
-
|
|
16538
|
-
|
|
16539
|
-
|
|
16540
|
-
|
|
16541
|
-
|
|
16542
|
-
|
|
16543
|
-
|
|
16544
|
-
|
|
16545
|
-
|
|
16546
|
-
|
|
16547
|
-
|
|
16548
|
-
|
|
16549
|
-
|
|
16550
|
-
|
|
16551
|
-
|
|
16552
|
-
|
|
16553
|
-
|
|
16554
|
-
|
|
16555
|
-
|
|
16556
|
-
|
|
16888
|
+
createAgent as createAgent6,
|
|
16889
|
+
humanInTheLoopMiddleware as humanInTheLoopMiddleware3,
|
|
16890
|
+
anthropicPromptCachingMiddleware as anthropicPromptCachingMiddleware2,
|
|
16891
|
+
summarizationMiddleware as summarizationMiddleware2
|
|
16892
|
+
} from "langchain";
|
|
16893
|
+
|
|
16894
|
+
// src/middlewares/topologyMiddleware.ts
|
|
16895
|
+
import { createMiddleware as createMiddleware18 } from "langchain";
|
|
16896
|
+
import { AIMessage as AIMessage3, ToolMessage as ToolMessage9 } from "@langchain/core/messages";
|
|
16897
|
+
import { tool as tool50 } from "langchain";
|
|
16898
|
+
import { z as z53 } from "zod";
|
|
16899
|
+
import { GraphInterrupt as GraphInterrupt4 } from "@langchain/langgraph";
|
|
16900
|
+
var CompletedEdgeSchema = z53.object({
|
|
16901
|
+
to: z53.string(),
|
|
16902
|
+
purpose: z53.string()
|
|
16903
|
+
});
|
|
16904
|
+
function deriveCompletedEdges(messages, edges) {
|
|
16905
|
+
const completedToolCallIds = /* @__PURE__ */ new Set();
|
|
16906
|
+
for (const msg of messages) {
|
|
16907
|
+
if (msg.name === "task" && msg.tool_call_id && msg.status !== "error") {
|
|
16908
|
+
completedToolCallIds.add(msg.tool_call_id);
|
|
16909
|
+
}
|
|
16910
|
+
}
|
|
16911
|
+
const completed = [];
|
|
16912
|
+
for (const msg of messages) {
|
|
16913
|
+
if (!msg.tool_calls) continue;
|
|
16914
|
+
for (const tc of msg.tool_calls) {
|
|
16915
|
+
if (tc.name !== "task" || !completedToolCallIds.has(tc.id)) continue;
|
|
16916
|
+
const targetAgent = tc.args?.subagent_type;
|
|
16917
|
+
const edge = edges.find(
|
|
16918
|
+
(e) => e.to === targetAgent
|
|
16919
|
+
);
|
|
16920
|
+
if (edge && !completed.some((e) => e.to === edge.to)) {
|
|
16921
|
+
completed.push({ to: edge.to, purpose: edge.purpose });
|
|
16557
16922
|
}
|
|
16558
|
-
return {
|
|
16559
|
-
key: toolKey,
|
|
16560
|
-
definition: toolLattice.config,
|
|
16561
|
-
executor: toolLattice.client
|
|
16562
|
-
};
|
|
16563
|
-
});
|
|
16564
|
-
const modelKey = options?.overrideModel || agentLattice.config.modelKey;
|
|
16565
|
-
const model = modelKey ? modelLatticeManager.getModelLattice(modelKey).client : modelLatticeManager.getModelLattice("default").client;
|
|
16566
|
-
if (!model) {
|
|
16567
|
-
throw new Error(`Model "${modelKey}" does not exist`);
|
|
16568
16923
|
}
|
|
16569
|
-
|
|
16570
|
-
|
|
16571
|
-
|
|
16572
|
-
|
|
16573
|
-
|
|
16924
|
+
}
|
|
16925
|
+
return completed;
|
|
16926
|
+
}
|
|
16927
|
+
function createTopologyMiddleware(options) {
|
|
16928
|
+
const { edges, trackingStore } = options;
|
|
16929
|
+
return createMiddleware18({
|
|
16930
|
+
name: "TopologyMiddleware",
|
|
16931
|
+
contextSchema: z53.object({
|
|
16932
|
+
runConfig: z53.any()
|
|
16933
|
+
}),
|
|
16934
|
+
stateSchema: z53.object({
|
|
16935
|
+
currentAgentId: z53.string().default(""),
|
|
16936
|
+
completedEdges: z53.array(CompletedEdgeSchema).default([]),
|
|
16937
|
+
runId: z53.string().default(""),
|
|
16938
|
+
stepIdMap: z53.record(z53.string()).default({})
|
|
16939
|
+
}),
|
|
16940
|
+
beforeAgent: async (state, runtime) => {
|
|
16941
|
+
const runConfig = runtime.context?.runConfig ?? {};
|
|
16942
|
+
const startingNode = edges[0]?.from ?? runConfig.assistant_id ?? "";
|
|
16943
|
+
let runId = "";
|
|
16944
|
+
if (trackingStore) {
|
|
16945
|
+
try {
|
|
16946
|
+
const run = await trackingStore.createWorkflowRun({
|
|
16947
|
+
tenantId: runConfig.tenantId || "default",
|
|
16948
|
+
assistantId: runConfig.assistant_id ?? "",
|
|
16949
|
+
threadId: runConfig.thread_id ?? "",
|
|
16950
|
+
topologyEdges: edges
|
|
16951
|
+
});
|
|
16952
|
+
runId = run.id;
|
|
16953
|
+
} catch (err) {
|
|
16954
|
+
console.error("[topologyMiddleware] Failed to create WorkflowRun:", err);
|
|
16955
|
+
}
|
|
16574
16956
|
}
|
|
16575
16957
|
return {
|
|
16576
|
-
|
|
16577
|
-
|
|
16578
|
-
|
|
16958
|
+
currentAgentId: startingNode,
|
|
16959
|
+
completedEdges: [],
|
|
16960
|
+
runId,
|
|
16961
|
+
stepIdMap: {}
|
|
16579
16962
|
};
|
|
16580
|
-
}
|
|
16581
|
-
|
|
16582
|
-
|
|
16583
|
-
|
|
16584
|
-
key: i.key,
|
|
16585
|
-
config: i
|
|
16586
|
-
})) || [];
|
|
16587
|
-
}
|
|
16588
|
-
return {
|
|
16589
|
-
tools,
|
|
16590
|
-
model,
|
|
16591
|
-
subAgents: [...subAgents, ...internalSubAgents],
|
|
16592
|
-
prompt: agentLattice.config.prompt,
|
|
16593
|
-
stateSchema: agentLattice.config.schema,
|
|
16594
|
-
skillCategories: skills,
|
|
16595
|
-
middleware: agentLattice.config.middleware,
|
|
16596
|
-
tenantId: agentLattice.config.tenantId
|
|
16597
|
-
};
|
|
16598
|
-
}
|
|
16599
|
-
};
|
|
16963
|
+
},
|
|
16964
|
+
wrapModelCall: async (request, handler) => {
|
|
16965
|
+
const steps = edges.map((e, i) => `${i + 1}. \`${e.from}\` \u2192 \`${e.to}\` \u2014 ${e.purpose}`).join("\n");
|
|
16966
|
+
const topologyPrompt = `## Workflow Execution Plan
|
|
16600
16967
|
|
|
16601
|
-
|
|
16602
|
-
|
|
16603
|
-
|
|
16968
|
+
Your job is to execute this workflow by delegating each step to the specialized agent
|
|
16969
|
+
shown below. This is your core execution process \u2014 it is not optional.
|
|
16970
|
+
|
|
16971
|
+
${steps || "(no workflow steps defined)"}
|
|
16972
|
+
|
|
16973
|
+
Use the \`task\` tool to delegate work to each agent. Call \`read_topo_progress\` to
|
|
16974
|
+
see which steps are done and which are still pending.
|
|
16975
|
+
|
|
16976
|
+
Do NOT delegate to any agent outside the current node's allowed paths \u2014 such attempts
|
|
16977
|
+
will be blocked.`;
|
|
16978
|
+
const newSystemPrompt = request.systemPrompt ? `${topologyPrompt}
|
|
16979
|
+
|
|
16980
|
+
---
|
|
16981
|
+
|
|
16982
|
+
${request.systemPrompt}` : topologyPrompt;
|
|
16983
|
+
return handler({ ...request, systemPrompt: newSystemPrompt });
|
|
16984
|
+
},
|
|
16985
|
+
tools: [
|
|
16986
|
+
tool50(
|
|
16987
|
+
async (_input) => {
|
|
16988
|
+
return "placeholder";
|
|
16989
|
+
},
|
|
16990
|
+
{
|
|
16991
|
+
name: "read_topo_progress",
|
|
16992
|
+
description: "Check the current progress of the workflow execution plan. Returns which steps have been completed and which are still pending.",
|
|
16993
|
+
schema: z53.object({})
|
|
16994
|
+
}
|
|
16995
|
+
)
|
|
16996
|
+
],
|
|
16997
|
+
wrapToolCall: async (request, handler) => {
|
|
16998
|
+
if (request.toolCall?.name === "read_topo_progress") {
|
|
16999
|
+
const currentAgentId = request.state?.currentAgentId || "";
|
|
17000
|
+
const completedEdges = request.state?.completedEdges || [];
|
|
17001
|
+
const doneSet = new Set(completedEdges.map((e) => e.to));
|
|
17002
|
+
const progress = edges.map((e) => ({
|
|
17003
|
+
agent: e.to,
|
|
17004
|
+
purpose: e.purpose,
|
|
17005
|
+
status: doneSet.has(e.to) ? "done" : "pending"
|
|
17006
|
+
}));
|
|
17007
|
+
const doneCount = completedEdges.length;
|
|
17008
|
+
return new ToolMessage9({
|
|
17009
|
+
content: JSON.stringify(
|
|
17010
|
+
{
|
|
17011
|
+
currentAgentId,
|
|
17012
|
+
progress: `${doneCount}/${edges.length} edges completed`,
|
|
17013
|
+
steps: progress,
|
|
17014
|
+
nextPending: progress.filter((s) => s.status === "pending").map((s) => s.agent)
|
|
17015
|
+
},
|
|
17016
|
+
null,
|
|
17017
|
+
2
|
|
17018
|
+
),
|
|
17019
|
+
name: "read_topo_progress",
|
|
17020
|
+
tool_call_id: request.toolCall.id
|
|
17021
|
+
});
|
|
17022
|
+
}
|
|
17023
|
+
try {
|
|
17024
|
+
return await handler(request);
|
|
17025
|
+
} catch (error) {
|
|
17026
|
+
if (error instanceof GraphInterrupt4) {
|
|
17027
|
+
throw error;
|
|
17028
|
+
}
|
|
17029
|
+
throw error;
|
|
17030
|
+
}
|
|
17031
|
+
},
|
|
17032
|
+
afterModel: {
|
|
17033
|
+
canJumpTo: ["model"],
|
|
17034
|
+
hook: async (state, runtime) => {
|
|
17035
|
+
const { messages, runId, stepIdMap: prevStepIdMap } = state;
|
|
17036
|
+
let { currentAgentId } = state;
|
|
17037
|
+
const runConfig = runtime.context?.runConfig ?? {};
|
|
17038
|
+
const stepIdMap = { ...prevStepIdMap };
|
|
17039
|
+
if (!messages || messages.length === 0) return;
|
|
17040
|
+
const lastMessage = messages[messages.length - 1];
|
|
17041
|
+
if ("tool_calls" in lastMessage) {
|
|
17042
|
+
for (const tc of lastMessage.tool_calls) {
|
|
17043
|
+
if (tc.name !== "task") continue;
|
|
17044
|
+
const targetAgent = tc.args?.subagent_type;
|
|
17045
|
+
const edge = edges.find(
|
|
17046
|
+
(e) => e.from === currentAgentId && e.to === targetAgent
|
|
17047
|
+
);
|
|
17048
|
+
if (!edge) {
|
|
17049
|
+
const myEdges = edges.filter(
|
|
17050
|
+
(e) => e.from === currentAgentId
|
|
17051
|
+
);
|
|
17052
|
+
console.warn(
|
|
17053
|
+
JSON.stringify({
|
|
17054
|
+
event: "topology_violation",
|
|
17055
|
+
currentAgentId,
|
|
17056
|
+
targetAgent,
|
|
17057
|
+
description: tc.args?.description,
|
|
17058
|
+
allowedTargets: myEdges.map((e) => e.to),
|
|
17059
|
+
threadId: runtime.configurable?.thread_id,
|
|
17060
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
17061
|
+
})
|
|
17062
|
+
);
|
|
17063
|
+
const allowedList = myEdges.length > 0 ? [
|
|
17064
|
+
`Agent \`${currentAgentId}\` may only delegate to:`,
|
|
17065
|
+
...myEdges.map(
|
|
17066
|
+
(e) => `- \`${e.to}\` \u2014 ${e.purpose}`
|
|
17067
|
+
)
|
|
17068
|
+
] : [
|
|
17069
|
+
`Agent \`${currentAgentId}\` has no outgoing delegation edges configured.`
|
|
17070
|
+
];
|
|
17071
|
+
return {
|
|
17072
|
+
messages: [
|
|
17073
|
+
new AIMessage3({
|
|
17074
|
+
content: [
|
|
17075
|
+
`Task rejected: topology violation.`,
|
|
17076
|
+
`Agent "${currentAgentId}" is not allowed to delegate to "${targetAgent}".`,
|
|
17077
|
+
...allowedList,
|
|
17078
|
+
`Please delegate to one of the allowed agents above or handle the task yourself.`
|
|
17079
|
+
].join("\n")
|
|
17080
|
+
})
|
|
17081
|
+
],
|
|
17082
|
+
jumpTo: "model"
|
|
17083
|
+
};
|
|
17084
|
+
}
|
|
17085
|
+
currentAgentId = edge.to;
|
|
17086
|
+
if (trackingStore && runId) {
|
|
17087
|
+
try {
|
|
17088
|
+
const step = await trackingStore.createRunStep({
|
|
17089
|
+
runId,
|
|
17090
|
+
tenantId: runConfig.tenantId || "default",
|
|
17091
|
+
stepType: "task_delegation",
|
|
17092
|
+
stepName: targetAgent,
|
|
17093
|
+
edgeFrom: edge.from,
|
|
17094
|
+
edgeTo: edge.to,
|
|
17095
|
+
edgePurpose: edge.purpose,
|
|
17096
|
+
input: { description: tc.args?.description }
|
|
17097
|
+
});
|
|
17098
|
+
stepIdMap[edge.to] = step.id;
|
|
17099
|
+
} catch (err) {
|
|
17100
|
+
console.error("[topologyMiddleware] Failed to create RunStep:", err);
|
|
17101
|
+
}
|
|
17102
|
+
}
|
|
17103
|
+
}
|
|
17104
|
+
}
|
|
17105
|
+
const completedEdges = deriveCompletedEdges(
|
|
17106
|
+
messages,
|
|
17107
|
+
edges
|
|
17108
|
+
);
|
|
17109
|
+
if (trackingStore && runId) {
|
|
17110
|
+
for (const ce of completedEdges) {
|
|
17111
|
+
const stepId = stepIdMap[ce.to];
|
|
17112
|
+
if (!stepId) continue;
|
|
17113
|
+
let output;
|
|
17114
|
+
for (const msg of messages) {
|
|
17115
|
+
if (msg.name === "task" && msg.tool_call_id) {
|
|
17116
|
+
for (const tc of messages.find(
|
|
17117
|
+
(m) => m.tool_calls?.some((c) => c.id === msg.tool_call_id)
|
|
17118
|
+
)?.tool_calls || []) {
|
|
17119
|
+
if (tc.id === msg.tool_call_id && tc.args?.subagent_type === ce.to) {
|
|
17120
|
+
output = msg.content;
|
|
17121
|
+
break;
|
|
17122
|
+
}
|
|
17123
|
+
}
|
|
17124
|
+
if (output) break;
|
|
17125
|
+
}
|
|
17126
|
+
}
|
|
17127
|
+
if (output) {
|
|
17128
|
+
try {
|
|
17129
|
+
await trackingStore.updateRunStep(runId, stepId, {
|
|
17130
|
+
status: "completed",
|
|
17131
|
+
output: { result: output },
|
|
17132
|
+
completedAt: /* @__PURE__ */ new Date()
|
|
17133
|
+
});
|
|
17134
|
+
} catch (err) {
|
|
17135
|
+
console.error("[topologyMiddleware] Failed to update RunStep output:", err);
|
|
17136
|
+
}
|
|
17137
|
+
}
|
|
17138
|
+
}
|
|
17139
|
+
}
|
|
17140
|
+
if (trackingStore && runId) {
|
|
17141
|
+
try {
|
|
17142
|
+
await trackingStore.updateWorkflowRun(runId, {
|
|
17143
|
+
completedEdges: completedEdges.length
|
|
17144
|
+
});
|
|
17145
|
+
} catch (err) {
|
|
17146
|
+
console.error("[topologyMiddleware] Failed to update WorkflowRun completedEdges:", err);
|
|
17147
|
+
}
|
|
17148
|
+
}
|
|
17149
|
+
return { currentAgentId, completedEdges, stepIdMap };
|
|
17150
|
+
}
|
|
17151
|
+
},
|
|
17152
|
+
afterAgent: async (state, runtime) => {
|
|
17153
|
+
const { runId, completedEdges } = state;
|
|
17154
|
+
if (!trackingStore || !runId) return;
|
|
17155
|
+
const allDone = completedEdges && completedEdges.length >= edges.length;
|
|
17156
|
+
if (!allDone) return;
|
|
17157
|
+
try {
|
|
17158
|
+
await trackingStore.updateWorkflowRun(runId, {
|
|
17159
|
+
status: "completed",
|
|
17160
|
+
completedAt: /* @__PURE__ */ new Date()
|
|
17161
|
+
});
|
|
17162
|
+
} catch (err) {
|
|
17163
|
+
console.error("[topologyMiddleware] Failed to finalize WorkflowRun:", err);
|
|
17164
|
+
}
|
|
17165
|
+
}
|
|
17166
|
+
});
|
|
17167
|
+
}
|
|
17168
|
+
|
|
17169
|
+
// src/deep_agent_new/processing_agent.ts
|
|
17170
|
+
var BASE_PROMPT2 = `In order to complete the objective that the user asks of you, you have access to a number of standard tools.`;
|
|
17171
|
+
function createProcessingAgent(params) {
|
|
17172
|
+
const {
|
|
17173
|
+
model = "claude-sonnet-4-5-20250929",
|
|
17174
|
+
tools = [],
|
|
17175
|
+
systemPrompt,
|
|
17176
|
+
middleware: customMiddleware = [],
|
|
17177
|
+
subagents = [],
|
|
17178
|
+
responseFormat,
|
|
17179
|
+
contextSchema: contextSchema2,
|
|
17180
|
+
checkpointer,
|
|
17181
|
+
store,
|
|
17182
|
+
backend,
|
|
17183
|
+
interruptOn,
|
|
17184
|
+
name,
|
|
17185
|
+
skills,
|
|
17186
|
+
topologyEdges
|
|
17187
|
+
} = params;
|
|
17188
|
+
const finalSystemPrompt = systemPrompt ? `${systemPrompt}
|
|
17189
|
+
|
|
17190
|
+
${BASE_PROMPT2}` : BASE_PROMPT2;
|
|
17191
|
+
const filesystemBackend = backend ? backend : async (config) => new StateBackend(config);
|
|
17192
|
+
let trackingStore;
|
|
17193
|
+
try {
|
|
17194
|
+
const storeLattice = getStoreLattice("default", "workflowTracking");
|
|
17195
|
+
trackingStore = storeLattice.store;
|
|
17196
|
+
} catch {
|
|
17197
|
+
}
|
|
17198
|
+
const middleware = [
|
|
17199
|
+
// Workflow topology enforcement — replaces todoListMiddleware
|
|
17200
|
+
createTopologyMiddleware({ edges: topologyEdges, trackingStore }),
|
|
17201
|
+
// Enables filesystem operations and optional long-term memory storage
|
|
17202
|
+
createFilesystemMiddleware({ backend: filesystemBackend }),
|
|
17203
|
+
// Enables delegation to specialized subagents for complex tasks
|
|
17204
|
+
createSubAgentMiddleware({
|
|
17205
|
+
defaultModel: model,
|
|
17206
|
+
defaultTools: tools,
|
|
17207
|
+
defaultMiddleware: [
|
|
17208
|
+
// Subagent middleware: Todo list management (subagents get todo, not topology)
|
|
17209
|
+
todoListMiddleware(),
|
|
17210
|
+
// Subagent middleware: Filesystem operations
|
|
17211
|
+
createFilesystemMiddleware({
|
|
17212
|
+
backend: filesystemBackend
|
|
17213
|
+
}),
|
|
17214
|
+
// Subagent middleware: Automatic conversation summarization
|
|
17215
|
+
summarizationMiddleware2({
|
|
17216
|
+
model,
|
|
17217
|
+
trigger: { tokens: 17e4 },
|
|
17218
|
+
keep: { messages: 6 }
|
|
17219
|
+
}),
|
|
17220
|
+
// Subagent middleware: Anthropic prompt caching
|
|
17221
|
+
anthropicPromptCachingMiddleware2({
|
|
17222
|
+
unsupportedModelBehavior: "ignore"
|
|
17223
|
+
}),
|
|
17224
|
+
// Subagent middleware: Patches tool calls
|
|
17225
|
+
createPatchToolCallsMiddleware(),
|
|
17226
|
+
...customMiddleware
|
|
17227
|
+
],
|
|
17228
|
+
defaultInterruptOn: interruptOn,
|
|
17229
|
+
subagents,
|
|
17230
|
+
generalPurposeAgent: true,
|
|
17231
|
+
allowAsync: false
|
|
17232
|
+
}),
|
|
17233
|
+
// Automatically summarizes conversation history
|
|
17234
|
+
summarizationMiddleware2({
|
|
17235
|
+
model,
|
|
17236
|
+
trigger: { tokens: 17e4 },
|
|
17237
|
+
keep: { messages: 6 }
|
|
17238
|
+
}),
|
|
17239
|
+
// Enables Anthropic prompt caching
|
|
17240
|
+
anthropicPromptCachingMiddleware2({
|
|
17241
|
+
unsupportedModelBehavior: "ignore"
|
|
17242
|
+
}),
|
|
17243
|
+
// Patches tool calls
|
|
17244
|
+
createPatchToolCallsMiddleware()
|
|
17245
|
+
];
|
|
17246
|
+
if (interruptOn) {
|
|
17247
|
+
middleware.push(humanInTheLoopMiddleware3({ interruptOn }));
|
|
17248
|
+
}
|
|
17249
|
+
middleware.push(...customMiddleware);
|
|
17250
|
+
return createAgent6({
|
|
17251
|
+
model,
|
|
17252
|
+
systemPrompt: finalSystemPrompt,
|
|
17253
|
+
tools,
|
|
17254
|
+
middleware,
|
|
17255
|
+
responseFormat,
|
|
17256
|
+
contextSchema: contextSchema2,
|
|
17257
|
+
checkpointer,
|
|
17258
|
+
store,
|
|
17259
|
+
name
|
|
17260
|
+
});
|
|
17261
|
+
}
|
|
17262
|
+
|
|
17263
|
+
// src/agent_lattice/builders/ProcessingAgentGraphBuilder.ts
|
|
17264
|
+
var ProcessingAgentGraphBuilder = class {
|
|
17265
|
+
async build(agentLattice, params) {
|
|
17266
|
+
const tools = params.tools.map((t) => {
|
|
17267
|
+
const toolClient = getToolClient(t.key);
|
|
17268
|
+
return toolClient;
|
|
17269
|
+
}).filter((tool51) => tool51 !== void 0);
|
|
17270
|
+
const subagents = await Promise.all(params.subAgents.map(async (sa) => {
|
|
17271
|
+
if (sa.client) {
|
|
17272
|
+
return {
|
|
17273
|
+
key: sa.config.key,
|
|
17274
|
+
name: sa.config.name,
|
|
17275
|
+
description: sa.config.description,
|
|
17276
|
+
runnable: sa.client
|
|
17277
|
+
};
|
|
17278
|
+
} else {
|
|
17279
|
+
const subagentClient = await createAgentClientFromAgentLattice({
|
|
17280
|
+
config: sa.config
|
|
17281
|
+
});
|
|
17282
|
+
return {
|
|
17283
|
+
key: sa.config.key,
|
|
17284
|
+
name: sa.config.name,
|
|
17285
|
+
description: sa.config.description,
|
|
17286
|
+
runnable: subagentClient
|
|
17287
|
+
};
|
|
17288
|
+
}
|
|
17289
|
+
}));
|
|
17290
|
+
const middlewareConfigs = params.middleware || [];
|
|
17291
|
+
const filesystemBackend = createFilesystemBackendFactory(middlewareConfigs);
|
|
17292
|
+
const middlewares = await createCommonMiddlewares(middlewareConfigs, filesystemBackend, true);
|
|
17293
|
+
const topologyConfig = middlewareConfigs.find(
|
|
17294
|
+
(m) => m.type === "topology" && m.enabled
|
|
17295
|
+
);
|
|
17296
|
+
const topologyEdges = topologyConfig?.config?.edges || [];
|
|
17297
|
+
const processingAgent = createProcessingAgent({
|
|
17298
|
+
tools,
|
|
17299
|
+
model: params.model,
|
|
17300
|
+
contextSchema: params.stateSchema,
|
|
17301
|
+
systemPrompt: params.prompt,
|
|
17302
|
+
subagents,
|
|
17303
|
+
checkpointer: getCheckpointSaver("default"),
|
|
17304
|
+
skills: params.skillCategories,
|
|
17305
|
+
backend: filesystemBackend,
|
|
17306
|
+
middleware: middlewares,
|
|
17307
|
+
topologyEdges
|
|
17308
|
+
});
|
|
17309
|
+
return processingAgent;
|
|
17310
|
+
}
|
|
17311
|
+
};
|
|
17312
|
+
|
|
17313
|
+
// src/agent_lattice/builders/AgentGraphBuilderFactory.ts
|
|
17314
|
+
var AgentGraphBuilderFactory = class _AgentGraphBuilderFactory {
|
|
17315
|
+
constructor() {
|
|
17316
|
+
this.builders = /* @__PURE__ */ new Map();
|
|
17317
|
+
this.registerDefaultBuilders();
|
|
17318
|
+
}
|
|
17319
|
+
/**
|
|
17320
|
+
* 获取单例实例
|
|
17321
|
+
*/
|
|
17322
|
+
static getInstance() {
|
|
17323
|
+
if (!_AgentGraphBuilderFactory.instance) {
|
|
17324
|
+
_AgentGraphBuilderFactory.instance = new _AgentGraphBuilderFactory();
|
|
17325
|
+
}
|
|
17326
|
+
return _AgentGraphBuilderFactory.instance;
|
|
17327
|
+
}
|
|
17328
|
+
/**
|
|
17329
|
+
* 注册默认的Builder
|
|
17330
|
+
*/
|
|
17331
|
+
registerDefaultBuilders() {
|
|
17332
|
+
this.builders.set(AgentType.REACT, new ReActAgentGraphBuilder());
|
|
17333
|
+
this.builders.set(AgentType.DEEP_AGENT, new DeepAgentGraphBuilder());
|
|
17334
|
+
this.builders.set(AgentType.TEAM, new TeamAgentGraphBuilder());
|
|
17335
|
+
this.builders.set(AgentType.PROCESSING, new ProcessingAgentGraphBuilder());
|
|
17336
|
+
}
|
|
17337
|
+
/**
|
|
17338
|
+
* 注册自定义Builder
|
|
17339
|
+
*
|
|
17340
|
+
* @param type Agent类型
|
|
17341
|
+
* @param builder Builder实例
|
|
17342
|
+
*/
|
|
17343
|
+
registerBuilder(type, builder) {
|
|
17344
|
+
this.builders.set(type, builder);
|
|
17345
|
+
}
|
|
17346
|
+
/**
|
|
17347
|
+
* 获取Builder
|
|
17348
|
+
*
|
|
17349
|
+
* @param type Agent类型
|
|
17350
|
+
* @returns 返回对应的Builder
|
|
17351
|
+
*/
|
|
17352
|
+
getBuilder(type) {
|
|
17353
|
+
const builder = this.builders.get(type);
|
|
17354
|
+
if (!builder) {
|
|
17355
|
+
throw new Error(`\u4E0D\u652F\u6301\u7684Agent\u7C7B\u578B: ${type}`);
|
|
17356
|
+
}
|
|
17357
|
+
return builder;
|
|
17358
|
+
}
|
|
17359
|
+
};
|
|
17360
|
+
|
|
17361
|
+
// src/agent_lattice/builders/AgentParamsBuilder.ts
|
|
17362
|
+
import {
|
|
17363
|
+
getToolsFromConfig as getToolsFromConfig2,
|
|
17364
|
+
getSubAgentsFromConfig as getSubAgentsFromConfig2,
|
|
17365
|
+
isDeepAgentConfig as isDeepAgentConfig2,
|
|
17366
|
+
isProcessingAgentConfig as isProcessingAgentConfig2
|
|
17367
|
+
} from "@axiom-lattice/protocols";
|
|
17368
|
+
var AgentParamsBuilder = class {
|
|
17369
|
+
/**
|
|
17370
|
+
* constructor
|
|
17371
|
+
*
|
|
17372
|
+
* @param getAgentLatticeFunc get Agent Lattice function
|
|
17373
|
+
*/
|
|
17374
|
+
constructor(getAgentLatticeFunc) {
|
|
17375
|
+
this.getAgentLatticeFunc = getAgentLatticeFunc;
|
|
17376
|
+
}
|
|
17377
|
+
/**
|
|
17378
|
+
* build Agent parameters
|
|
17379
|
+
*
|
|
17380
|
+
* @param agentLattice Agent Lattice object
|
|
17381
|
+
* @param options build options
|
|
17382
|
+
* @returns Agent build parameters
|
|
17383
|
+
*/
|
|
17384
|
+
async buildParams(agentLattice, options) {
|
|
17385
|
+
const skills = isDeepAgentConfig2(agentLattice.config) || isProcessingAgentConfig2(agentLattice.config) ? agentLattice.config.skillCategories : void 0;
|
|
17386
|
+
const toolKeys = options?.overrideTools || getToolsFromConfig2(agentLattice.config);
|
|
17387
|
+
const tools = toolKeys.map((toolKey) => {
|
|
17388
|
+
const toolLattice = toolLatticeManager.getToolLattice(toolKey);
|
|
17389
|
+
if (!toolLattice) {
|
|
17390
|
+
throw new Error(`Tool "${toolKey}" does not exist`);
|
|
17391
|
+
}
|
|
17392
|
+
return {
|
|
17393
|
+
key: toolKey,
|
|
17394
|
+
definition: toolLattice.config,
|
|
17395
|
+
executor: toolLattice.client
|
|
17396
|
+
};
|
|
17397
|
+
});
|
|
17398
|
+
const modelKey = options?.overrideModel || agentLattice.config.modelKey;
|
|
17399
|
+
const model = modelKey ? modelLatticeManager.getModelLattice(modelKey).client : modelLatticeManager.getModelLattice("default").client;
|
|
17400
|
+
if (!model) {
|
|
17401
|
+
throw new Error(`Model "${modelKey}" does not exist`);
|
|
17402
|
+
}
|
|
17403
|
+
const subAgentKeys = getSubAgentsFromConfig2(agentLattice.config);
|
|
17404
|
+
const subAgents = await Promise.all(subAgentKeys.map(async (agentKey) => {
|
|
17405
|
+
const subAgentLattice = await this.getAgentLatticeFunc(agentKey);
|
|
17406
|
+
if (!subAgentLattice) {
|
|
17407
|
+
throw new Error(`SubAgent "${agentKey}" does not exist`);
|
|
17408
|
+
}
|
|
17409
|
+
return {
|
|
17410
|
+
key: agentKey,
|
|
17411
|
+
config: subAgentLattice.config,
|
|
17412
|
+
client: subAgentLattice.client
|
|
17413
|
+
};
|
|
17414
|
+
}));
|
|
17415
|
+
let internalSubAgents = [];
|
|
17416
|
+
if (isDeepAgentConfig2(agentLattice.config) || isProcessingAgentConfig2(agentLattice.config)) {
|
|
17417
|
+
internalSubAgents = agentLattice.config.internalSubAgents?.map((i) => ({
|
|
17418
|
+
key: i.key,
|
|
17419
|
+
config: i
|
|
17420
|
+
})) || [];
|
|
17421
|
+
}
|
|
17422
|
+
return {
|
|
17423
|
+
tools,
|
|
17424
|
+
model,
|
|
17425
|
+
subAgents: [...subAgents, ...internalSubAgents],
|
|
17426
|
+
prompt: agentLattice.config.prompt,
|
|
17427
|
+
stateSchema: agentLattice.config.schema,
|
|
17428
|
+
skillCategories: skills,
|
|
17429
|
+
middleware: agentLattice.config.middleware,
|
|
17430
|
+
tenantId: agentLattice.config.tenantId
|
|
17431
|
+
};
|
|
17432
|
+
}
|
|
17433
|
+
};
|
|
17434
|
+
|
|
17435
|
+
// src/agent_lattice/utils/mergeAgentConfig.ts
|
|
17436
|
+
var NON_INHERITABLE_FIELDS = /* @__PURE__ */ new Set([
|
|
17437
|
+
"key",
|
|
16604
17438
|
"extendsAgent"
|
|
16605
17439
|
]);
|
|
16606
17440
|
function mergeAgentConfig(parent, child) {
|
|
@@ -17018,98 +17852,1105 @@ ${body}` : `${frontmatter}
|
|
|
17018
17852
|
subSkills: updates.subSkills !== void 0 ? updates.subSkills : skill.subSkills,
|
|
17019
17853
|
updatedAt: /* @__PURE__ */ new Date()
|
|
17020
17854
|
};
|
|
17021
|
-
await this.writeSkillFile(newSkill, context);
|
|
17022
|
-
await this.deleteSkill(tenantId, id, context);
|
|
17023
|
-
return newSkill;
|
|
17855
|
+
await this.writeSkillFile(newSkill, context);
|
|
17856
|
+
await this.deleteSkill(tenantId, id, context);
|
|
17857
|
+
return newSkill;
|
|
17858
|
+
}
|
|
17859
|
+
}
|
|
17860
|
+
const updatedSkill = {
|
|
17861
|
+
...skill,
|
|
17862
|
+
name: updates.name ?? skill.name,
|
|
17863
|
+
description: updates.description ?? skill.description,
|
|
17864
|
+
license: updates.license ?? skill.license,
|
|
17865
|
+
compatibility: updates.compatibility ?? skill.compatibility,
|
|
17866
|
+
metadata: updates.metadata ?? skill.metadata,
|
|
17867
|
+
content: updates.content !== void 0 ? updates.content : skill.content,
|
|
17868
|
+
subSkills: updates.subSkills !== void 0 ? updates.subSkills : skill.subSkills,
|
|
17869
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
17870
|
+
};
|
|
17871
|
+
await this.writeSkillFile(updatedSkill, context);
|
|
17872
|
+
return updatedSkill;
|
|
17873
|
+
}
|
|
17874
|
+
/**
|
|
17875
|
+
* Delete a skill by ID
|
|
17876
|
+
*/
|
|
17877
|
+
async deleteSkill(tenantId, id, context) {
|
|
17878
|
+
if (isBuiltInSkill(id)) {
|
|
17879
|
+
throw new Error(
|
|
17880
|
+
`Skill "${id}" is a built-in skill and cannot be deleted`
|
|
17881
|
+
);
|
|
17882
|
+
}
|
|
17883
|
+
try {
|
|
17884
|
+
const sandbox = await this.getSandbox(tenantId, context);
|
|
17885
|
+
const dirPath = this.getSkillDirectoryPath(tenantId, id);
|
|
17886
|
+
const deleteResult = await sandbox.shell.execCommand({
|
|
17887
|
+
command: `rm -rf ${dirPath}`
|
|
17888
|
+
});
|
|
17889
|
+
if (deleteResult.exit_code !== 0) {
|
|
17890
|
+
return false;
|
|
17891
|
+
}
|
|
17892
|
+
return true;
|
|
17893
|
+
} catch (error) {
|
|
17894
|
+
console.error(`Error deleting skill ${id}:`, error);
|
|
17895
|
+
return false;
|
|
17896
|
+
}
|
|
17897
|
+
}
|
|
17898
|
+
/**
|
|
17899
|
+
* Check if skill exists
|
|
17900
|
+
*/
|
|
17901
|
+
async hasSkill(tenantId, id, context) {
|
|
17902
|
+
if (isBuiltInSkill(id)) return true;
|
|
17903
|
+
const skill = await this.getSkillById(tenantId, id, context);
|
|
17904
|
+
return skill !== null;
|
|
17905
|
+
}
|
|
17906
|
+
/**
|
|
17907
|
+
* Search skills by metadata within a tenant
|
|
17908
|
+
*/
|
|
17909
|
+
async searchByMetadata(tenantId, metadataKey, metadataValue, context) {
|
|
17910
|
+
const allSkills = await this.getAllSkills(tenantId, context);
|
|
17911
|
+
return allSkills.filter(
|
|
17912
|
+
(skill) => skill.metadata && skill.metadata[metadataKey] === metadataValue
|
|
17913
|
+
);
|
|
17914
|
+
}
|
|
17915
|
+
/**
|
|
17916
|
+
* Filter skills by compatibility within a tenant
|
|
17917
|
+
*/
|
|
17918
|
+
async filterByCompatibility(tenantId, compatibility, context) {
|
|
17919
|
+
const allSkills = await this.getAllSkills(tenantId, context);
|
|
17920
|
+
return allSkills.filter((skill) => skill.compatibility === compatibility);
|
|
17921
|
+
}
|
|
17922
|
+
/**
|
|
17923
|
+
* Filter skills by license within a tenant
|
|
17924
|
+
*/
|
|
17925
|
+
async filterByLicense(tenantId, license, context) {
|
|
17926
|
+
const allSkills = await this.getAllSkills(tenantId, context);
|
|
17927
|
+
return allSkills.filter((skill) => skill.license === license);
|
|
17928
|
+
}
|
|
17929
|
+
/**
|
|
17930
|
+
* Get sub-skills of a parent skill within a tenant
|
|
17931
|
+
*/
|
|
17932
|
+
async getSubSkills(tenantId, parentSkillName, context) {
|
|
17933
|
+
const parentSkill = await this.getSkillById(tenantId, parentSkillName, context);
|
|
17934
|
+
if (!parentSkill || !parentSkill.subSkills || parentSkill.subSkills.length === 0) {
|
|
17935
|
+
return [];
|
|
17936
|
+
}
|
|
17937
|
+
const subSkills = [];
|
|
17938
|
+
for (const subSkillName of parentSkill.subSkills) {
|
|
17939
|
+
const subSkill = await this.getSkillById(tenantId, subSkillName, context);
|
|
17940
|
+
if (subSkill) {
|
|
17941
|
+
subSkills.push(subSkill);
|
|
17942
|
+
}
|
|
17943
|
+
}
|
|
17944
|
+
return subSkills;
|
|
17945
|
+
}
|
|
17946
|
+
};
|
|
17947
|
+
|
|
17948
|
+
// src/agent_lattice/agentArchitectTools.ts
|
|
17949
|
+
import z54 from "zod";
|
|
17950
|
+
import { v4 as v42 } from "uuid";
|
|
17951
|
+
import { AgentType as AgentType2 } from "@axiom-lattice/protocols";
|
|
17952
|
+
function getTenantId(exeConfig) {
|
|
17953
|
+
const runConfig = exeConfig?.configurable?.runConfig || {};
|
|
17954
|
+
return runConfig.tenantId || "default";
|
|
17955
|
+
}
|
|
17956
|
+
function getAssistStore() {
|
|
17957
|
+
return getStoreLattice("default", "assistant").store;
|
|
17958
|
+
}
|
|
17959
|
+
function slugify(name) {
|
|
17960
|
+
return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").replace(/-+/g, "-") || "agent";
|
|
17961
|
+
}
|
|
17962
|
+
async function generateAgentId(tenantId, name) {
|
|
17963
|
+
const store = getAssistStore();
|
|
17964
|
+
const base = slugify(name);
|
|
17965
|
+
let id = base;
|
|
17966
|
+
let counter = 2;
|
|
17967
|
+
while (true) {
|
|
17968
|
+
const existing = await store.getAssistantById(tenantId, id);
|
|
17969
|
+
if (!existing) return id;
|
|
17970
|
+
id = `${base}-${counter}`;
|
|
17971
|
+
counter++;
|
|
17972
|
+
}
|
|
17973
|
+
}
|
|
17974
|
+
registerToolLattice(
|
|
17975
|
+
"list_agents",
|
|
17976
|
+
{
|
|
17977
|
+
name: "list_agents",
|
|
17978
|
+
description: "List all agents for the current workspace. Returns a summary with id, name, description, and type for each agent.",
|
|
17979
|
+
schema: z54.object({})
|
|
17980
|
+
},
|
|
17981
|
+
async (_input, exeConfig) => {
|
|
17982
|
+
try {
|
|
17983
|
+
const tenantId = getTenantId(exeConfig);
|
|
17984
|
+
const store = getAssistStore();
|
|
17985
|
+
const agents = await store.getAllAssistants(tenantId);
|
|
17986
|
+
return JSON.stringify({
|
|
17987
|
+
agents: agents.map((a) => ({
|
|
17988
|
+
id: a.id,
|
|
17989
|
+
name: a.name,
|
|
17990
|
+
description: a.description || "",
|
|
17991
|
+
type: a.graphDefinition?.type || "react",
|
|
17992
|
+
createdAt: a.createdAt,
|
|
17993
|
+
updatedAt: a.updatedAt
|
|
17994
|
+
}))
|
|
17995
|
+
});
|
|
17996
|
+
} catch (error) {
|
|
17997
|
+
return JSON.stringify({ error: `Failed to list agents: ${error.message}` });
|
|
17998
|
+
}
|
|
17999
|
+
}
|
|
18000
|
+
);
|
|
18001
|
+
registerToolLattice(
|
|
18002
|
+
"get_agent",
|
|
18003
|
+
{
|
|
18004
|
+
name: "get_agent",
|
|
18005
|
+
description: "Get the full configuration of a specific agent by its ID. Returns the complete AgentConfig including prompt, middleware, tools, and sub-agents.",
|
|
18006
|
+
schema: z54.object({
|
|
18007
|
+
id: z54.string().describe("The agent ID to retrieve")
|
|
18008
|
+
})
|
|
18009
|
+
},
|
|
18010
|
+
async (input, exeConfig) => {
|
|
18011
|
+
try {
|
|
18012
|
+
const tenantId = getTenantId(exeConfig);
|
|
18013
|
+
const store = getAssistStore();
|
|
18014
|
+
const agent = await store.getAssistantById(tenantId, input.id);
|
|
18015
|
+
if (!agent) {
|
|
18016
|
+
return JSON.stringify({ error: `Agent '${input.id}' not found` });
|
|
18017
|
+
}
|
|
18018
|
+
return JSON.stringify(agent.graphDefinition);
|
|
18019
|
+
} catch (error) {
|
|
18020
|
+
return JSON.stringify({ error: `Failed to get agent: ${error.message}` });
|
|
18021
|
+
}
|
|
18022
|
+
}
|
|
18023
|
+
);
|
|
18024
|
+
var middlewareConfigSchema = z54.object({
|
|
18025
|
+
id: z54.string(),
|
|
18026
|
+
type: z54.string(),
|
|
18027
|
+
name: z54.string(),
|
|
18028
|
+
description: z54.string(),
|
|
18029
|
+
enabled: z54.boolean(),
|
|
18030
|
+
config: z54.record(z54.any()).optional()
|
|
18031
|
+
});
|
|
18032
|
+
var createAgentSchema = z54.object({
|
|
18033
|
+
name: z54.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')."),
|
|
18034
|
+
description: z54.string().optional().describe("Short description"),
|
|
18035
|
+
type: z54.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."),
|
|
18036
|
+
prompt: z54.string().describe("System prompt for the agent"),
|
|
18037
|
+
tools: z54.array(z54.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."),
|
|
18038
|
+
middleware: z54.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: {}."),
|
|
18039
|
+
subAgents: z54.array(z54.string()).optional().describe("Sub-agent IDs (deep_agent only)"),
|
|
18040
|
+
internalSubAgents: z54.array(z54.any()).optional().describe("Inline sub-agent configs (deep_agent only)"),
|
|
18041
|
+
modelKey: z54.string().optional().describe("Model key to use")
|
|
18042
|
+
});
|
|
18043
|
+
registerToolLattice(
|
|
18044
|
+
"create_agent",
|
|
18045
|
+
{
|
|
18046
|
+
name: "create_agent",
|
|
18047
|
+
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).",
|
|
18048
|
+
schema: createAgentSchema
|
|
18049
|
+
},
|
|
18050
|
+
async (input, exeConfig) => {
|
|
18051
|
+
try {
|
|
18052
|
+
const tenantId = getTenantId(exeConfig);
|
|
18053
|
+
const store = getAssistStore();
|
|
18054
|
+
const id = await generateAgentId(tenantId, input.name);
|
|
18055
|
+
const config = {
|
|
18056
|
+
key: id,
|
|
18057
|
+
name: input.name,
|
|
18058
|
+
description: input.description || "",
|
|
18059
|
+
type: input.type === "deep_agent" ? AgentType2.DEEP_AGENT : AgentType2.REACT,
|
|
18060
|
+
prompt: input.prompt,
|
|
18061
|
+
...input.tools && input.tools.length > 0 ? { tools: input.tools } : {},
|
|
18062
|
+
...input.middleware && input.middleware.length > 0 ? { middleware: input.middleware } : {},
|
|
18063
|
+
...input.subAgents && input.subAgents.length > 0 ? { subAgents: input.subAgents } : {},
|
|
18064
|
+
...input.internalSubAgents ? { internalSubAgents: input.internalSubAgents } : {},
|
|
18065
|
+
...input.modelKey ? { modelKey: input.modelKey } : {}
|
|
18066
|
+
};
|
|
18067
|
+
await store.createAssistant(tenantId, id, {
|
|
18068
|
+
name: input.name,
|
|
18069
|
+
description: input.description,
|
|
18070
|
+
graphDefinition: config
|
|
18071
|
+
});
|
|
18072
|
+
return JSON.stringify({ id, name: input.name, type: input.type });
|
|
18073
|
+
} catch (error) {
|
|
18074
|
+
return JSON.stringify({ error: `Failed to create agent: ${error.message}` });
|
|
18075
|
+
}
|
|
18076
|
+
}
|
|
18077
|
+
);
|
|
18078
|
+
var topologyEdgeSchema = z54.object({
|
|
18079
|
+
from: z54.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."),
|
|
18080
|
+
to: z54.string().describe("Target agent ID (the sub-agent to delegate to)"),
|
|
18081
|
+
purpose: z54.string().describe("Business purpose of this delegation step \u2014 what the sub-agent should accomplish")
|
|
18082
|
+
});
|
|
18083
|
+
var createProcessingAgentSchema = z54.object({
|
|
18084
|
+
name: z54.string().describe("Display name for the processing agent"),
|
|
18085
|
+
description: z54.string().optional().describe("Short description"),
|
|
18086
|
+
prompt: z54.string().describe("System prompt for the orchestrator. Should describe how to route tasks through the topology."),
|
|
18087
|
+
edges: z54.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."),
|
|
18088
|
+
tools: z54.array(z54.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."),
|
|
18089
|
+
subAgents: z54.array(z54.string()).describe("IDs of sub-agents that form the workflow pipeline. These must be created first via create_agent."),
|
|
18090
|
+
internalSubAgents: z54.array(z54.any()).optional().describe("Inline sub-agent configs (alternative to pre-created sub-agents)"),
|
|
18091
|
+
middleware: z54.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: {}."),
|
|
18092
|
+
modelKey: z54.string().optional().describe("Model key to use")
|
|
18093
|
+
}).refine(
|
|
18094
|
+
(data) => {
|
|
18095
|
+
const edgeTargets = new Set(data.edges.map((e) => e.to));
|
|
18096
|
+
const subAgentIds = new Set(data.subAgents);
|
|
18097
|
+
for (const target of edgeTargets) {
|
|
18098
|
+
if (!subAgentIds.has(target)) {
|
|
18099
|
+
return false;
|
|
18100
|
+
}
|
|
18101
|
+
}
|
|
18102
|
+
return true;
|
|
18103
|
+
},
|
|
18104
|
+
{ message: "All edge targets (to) must be included in the subAgents list" }
|
|
18105
|
+
);
|
|
18106
|
+
registerToolLattice(
|
|
18107
|
+
"create_processing_agent",
|
|
18108
|
+
{
|
|
18109
|
+
name: "create_processing_agent",
|
|
18110
|
+
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.",
|
|
18111
|
+
schema: createProcessingAgentSchema
|
|
18112
|
+
},
|
|
18113
|
+
async (input, exeConfig) => {
|
|
18114
|
+
try {
|
|
18115
|
+
const tenantId = getTenantId(exeConfig);
|
|
18116
|
+
const store = getAssistStore();
|
|
18117
|
+
const id = await generateAgentId(tenantId, input.name);
|
|
18118
|
+
const normalize = (s) => s.toLowerCase().replace(/[_\-\s]/g, "");
|
|
18119
|
+
const resolveFrom = (rawFrom) => {
|
|
18120
|
+
const fromLower = rawFrom.toLowerCase();
|
|
18121
|
+
const nameLower = input.name.toLowerCase();
|
|
18122
|
+
if (fromLower === nameLower || fromLower === "orchestrator" || fromLower === "orchestrator-id" || normalize(rawFrom) === normalize(input.name)) {
|
|
18123
|
+
return id;
|
|
18124
|
+
}
|
|
18125
|
+
return rawFrom;
|
|
18126
|
+
};
|
|
18127
|
+
const topologyMiddleware = {
|
|
18128
|
+
id: "topology",
|
|
18129
|
+
type: "topology",
|
|
18130
|
+
name: "Topology",
|
|
18131
|
+
description: `Enforce ${input.edges.length}-step workflow topology`,
|
|
18132
|
+
enabled: true,
|
|
18133
|
+
config: {
|
|
18134
|
+
edges: input.edges.map((e) => ({
|
|
18135
|
+
from: resolveFrom(e.from),
|
|
18136
|
+
to: e.to,
|
|
18137
|
+
purpose: e.purpose
|
|
18138
|
+
}))
|
|
18139
|
+
}
|
|
18140
|
+
};
|
|
18141
|
+
const additionalMiddleware = input.middleware || [];
|
|
18142
|
+
const middleware = [topologyMiddleware, ...additionalMiddleware];
|
|
18143
|
+
const config = {
|
|
18144
|
+
key: id,
|
|
18145
|
+
name: input.name,
|
|
18146
|
+
description: input.description || "",
|
|
18147
|
+
type: AgentType2.PROCESSING,
|
|
18148
|
+
prompt: input.prompt,
|
|
18149
|
+
...input.tools && input.tools.length > 0 ? { tools: input.tools } : {},
|
|
18150
|
+
middleware,
|
|
18151
|
+
subAgents: input.subAgents,
|
|
18152
|
+
...input.internalSubAgents ? { internalSubAgents: input.internalSubAgents } : {},
|
|
18153
|
+
...input.modelKey ? { modelKey: input.modelKey } : {}
|
|
18154
|
+
};
|
|
18155
|
+
await store.createAssistant(tenantId, id, {
|
|
18156
|
+
name: input.name,
|
|
18157
|
+
description: input.description,
|
|
18158
|
+
graphDefinition: config
|
|
18159
|
+
});
|
|
18160
|
+
return JSON.stringify({
|
|
18161
|
+
id,
|
|
18162
|
+
name: input.name,
|
|
18163
|
+
type: "processing",
|
|
18164
|
+
topology: {
|
|
18165
|
+
edges: input.edges.map((e) => ({ from: resolveFrom(e.from), to: e.to, purpose: e.purpose }))
|
|
18166
|
+
}
|
|
18167
|
+
});
|
|
18168
|
+
} catch (error) {
|
|
18169
|
+
return JSON.stringify({ error: `Failed to create processing agent: ${error.message}` });
|
|
18170
|
+
}
|
|
18171
|
+
}
|
|
18172
|
+
);
|
|
18173
|
+
var updateProcessingAgentSchema = z54.object({
|
|
18174
|
+
id: z54.string().describe("The PROCESSING agent ID to update"),
|
|
18175
|
+
name: z54.string().optional().describe("New display name for the orchestrator"),
|
|
18176
|
+
description: z54.string().optional().describe("New short description"),
|
|
18177
|
+
prompt: z54.string().optional().describe("New system prompt for the orchestrator"),
|
|
18178
|
+
edges: z54.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."),
|
|
18179
|
+
tools: z54.array(z54.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."),
|
|
18180
|
+
subAgents: z54.array(z54.string()).optional().describe("New IDs of sub-agents in the workflow pipeline"),
|
|
18181
|
+
middleware: z54.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: {}."),
|
|
18182
|
+
modelKey: z54.string().optional().describe("New model key")
|
|
18183
|
+
}).refine(
|
|
18184
|
+
(data) => {
|
|
18185
|
+
if (!data.edges) return true;
|
|
18186
|
+
const subAgentIds = new Set(data.subAgents || []);
|
|
18187
|
+
if (subAgentIds.size === 0) return true;
|
|
18188
|
+
const edgeTargets = new Set(data.edges.map((e) => e.to));
|
|
18189
|
+
for (const target of edgeTargets) {
|
|
18190
|
+
if (!subAgentIds.has(target)) {
|
|
18191
|
+
return false;
|
|
18192
|
+
}
|
|
18193
|
+
}
|
|
18194
|
+
return true;
|
|
18195
|
+
},
|
|
18196
|
+
{ message: "All edge targets (to) must be included in the subAgents list" }
|
|
18197
|
+
);
|
|
18198
|
+
registerToolLattice(
|
|
18199
|
+
"update_processing_agent",
|
|
18200
|
+
{
|
|
18201
|
+
name: "update_processing_agent",
|
|
18202
|
+
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'.",
|
|
18203
|
+
schema: updateProcessingAgentSchema
|
|
18204
|
+
},
|
|
18205
|
+
async (input, exeConfig) => {
|
|
18206
|
+
try {
|
|
18207
|
+
const tenantId = getTenantId(exeConfig);
|
|
18208
|
+
const store = getAssistStore();
|
|
18209
|
+
const existing = await store.getAssistantById(tenantId, input.id);
|
|
18210
|
+
if (!existing) {
|
|
18211
|
+
return JSON.stringify({ error: `Agent '${input.id}' not found` });
|
|
18212
|
+
}
|
|
18213
|
+
const existingConfig = existing.graphDefinition || {};
|
|
18214
|
+
if (existingConfig.type !== AgentType2.PROCESSING) {
|
|
18215
|
+
return JSON.stringify({ error: `Agent '${input.id}' is not a PROCESSING agent (type: ${existingConfig.type})` });
|
|
18216
|
+
}
|
|
18217
|
+
const normalize = (s) => s.toLowerCase().replace(/[_\-\s]/g, "");
|
|
18218
|
+
const orchestratorName = input.name || existingConfig.name || existing.name || "";
|
|
18219
|
+
const resolveFrom = (rawFrom) => {
|
|
18220
|
+
const fromLower = rawFrom.toLowerCase();
|
|
18221
|
+
const nameLower = orchestratorName.toLowerCase();
|
|
18222
|
+
if (fromLower === nameLower || fromLower === "orchestrator" || fromLower === "orchestrator-id" || normalize(rawFrom) === normalize(orchestratorName)) {
|
|
18223
|
+
return input.id;
|
|
18224
|
+
}
|
|
18225
|
+
return rawFrom;
|
|
18226
|
+
};
|
|
18227
|
+
let middleware = existingConfig.middleware || [];
|
|
18228
|
+
let resolvedEdges;
|
|
18229
|
+
if (input.edges) {
|
|
18230
|
+
resolvedEdges = input.edges.map((e) => ({
|
|
18231
|
+
from: resolveFrom(e.from),
|
|
18232
|
+
to: e.to,
|
|
18233
|
+
purpose: e.purpose
|
|
18234
|
+
}));
|
|
18235
|
+
const topoIndex = middleware.findIndex(
|
|
18236
|
+
(m) => m.type === "topology"
|
|
18237
|
+
);
|
|
18238
|
+
const topoMiddleware = {
|
|
18239
|
+
id: "topology",
|
|
18240
|
+
type: "topology",
|
|
18241
|
+
name: "Topology",
|
|
18242
|
+
description: `Enforce ${resolvedEdges.length}-step workflow topology`,
|
|
18243
|
+
enabled: true,
|
|
18244
|
+
config: { edges: resolvedEdges }
|
|
18245
|
+
};
|
|
18246
|
+
if (topoIndex >= 0) {
|
|
18247
|
+
middleware = [...middleware];
|
|
18248
|
+
middleware[topoIndex] = topoMiddleware;
|
|
18249
|
+
} else {
|
|
18250
|
+
middleware = [topoMiddleware, ...middleware];
|
|
18251
|
+
}
|
|
18252
|
+
if (input.middleware) {
|
|
18253
|
+
const nonTopo = input.middleware.filter(
|
|
18254
|
+
(m) => m.type !== "topology"
|
|
18255
|
+
);
|
|
18256
|
+
const topoIdx = middleware.findIndex(
|
|
18257
|
+
(m) => m.type === "topology"
|
|
18258
|
+
);
|
|
18259
|
+
const prefix = middleware.slice(0, topoIdx + 1);
|
|
18260
|
+
const suffix = middleware.slice(topoIdx + 1);
|
|
18261
|
+
middleware = [...prefix, ...nonTopo];
|
|
18262
|
+
}
|
|
18263
|
+
} else if (input.middleware) {
|
|
18264
|
+
const nonTopo = input.middleware.filter(
|
|
18265
|
+
(m) => m.type !== "topology"
|
|
18266
|
+
);
|
|
18267
|
+
const topoIdx = middleware.findIndex(
|
|
18268
|
+
(m) => m.type === "topology"
|
|
18269
|
+
);
|
|
18270
|
+
if (topoIdx >= 0) {
|
|
18271
|
+
middleware = [...middleware.slice(0, topoIdx + 1), ...nonTopo];
|
|
18272
|
+
} else {
|
|
18273
|
+
middleware = [...middleware, ...nonTopo];
|
|
18274
|
+
}
|
|
17024
18275
|
}
|
|
17025
|
-
|
|
17026
|
-
|
|
17027
|
-
|
|
17028
|
-
|
|
17029
|
-
|
|
17030
|
-
|
|
17031
|
-
|
|
17032
|
-
|
|
17033
|
-
|
|
17034
|
-
|
|
17035
|
-
|
|
17036
|
-
|
|
17037
|
-
|
|
17038
|
-
|
|
17039
|
-
|
|
17040
|
-
|
|
17041
|
-
|
|
17042
|
-
|
|
17043
|
-
|
|
17044
|
-
if (isBuiltInSkill(id)) {
|
|
17045
|
-
throw new Error(
|
|
17046
|
-
`Skill "${id}" is a built-in skill and cannot be deleted`
|
|
18276
|
+
const mergedConfig = {
|
|
18277
|
+
...existingConfig,
|
|
18278
|
+
...input.name !== void 0 ? { name: input.name } : {},
|
|
18279
|
+
...input.description !== void 0 ? { description: input.description } : {},
|
|
18280
|
+
...input.prompt !== void 0 ? { prompt: input.prompt } : {},
|
|
18281
|
+
...input.tools !== void 0 ? { tools: input.tools } : {},
|
|
18282
|
+
...input.subAgents !== void 0 ? { subAgents: input.subAgents } : {},
|
|
18283
|
+
...input.modelKey !== void 0 ? { modelKey: input.modelKey } : {},
|
|
18284
|
+
middleware,
|
|
18285
|
+
key: input.id
|
|
18286
|
+
};
|
|
18287
|
+
const newName = input.name || existing.name;
|
|
18288
|
+
await store.updateAssistant(tenantId, input.id, {
|
|
18289
|
+
name: newName,
|
|
18290
|
+
description: input.description !== void 0 ? input.description : existing.description,
|
|
18291
|
+
graphDefinition: mergedConfig
|
|
18292
|
+
});
|
|
18293
|
+
const topoConfig = middleware.find(
|
|
18294
|
+
(m) => m.type === "topology"
|
|
17047
18295
|
);
|
|
18296
|
+
return JSON.stringify({
|
|
18297
|
+
id: input.id,
|
|
18298
|
+
name: newName,
|
|
18299
|
+
type: "processing",
|
|
18300
|
+
topology: {
|
|
18301
|
+
edges: topoConfig?.config?.edges || resolvedEdges || []
|
|
18302
|
+
}
|
|
18303
|
+
});
|
|
18304
|
+
} catch (error) {
|
|
18305
|
+
return JSON.stringify({ error: `Failed to update processing agent: ${error.message}` });
|
|
17048
18306
|
}
|
|
18307
|
+
}
|
|
18308
|
+
);
|
|
18309
|
+
var updateAgentSchema = z54.object({
|
|
18310
|
+
id: z54.string().describe("The agent ID to update"),
|
|
18311
|
+
config: z54.object({
|
|
18312
|
+
name: z54.string().optional().describe("New display name for the agent"),
|
|
18313
|
+
description: z54.string().optional().describe("New short description"),
|
|
18314
|
+
type: z54.enum(["react", "deep_agent"]).optional().describe("Agent type"),
|
|
18315
|
+
prompt: z54.string().optional().describe("New system prompt for the agent"),
|
|
18316
|
+
tools: z54.array(z54.string()).optional().describe("Tool keys to assign to this agent. These are registered tool names (strings), NOT middleware objects."),
|
|
18317
|
+
middleware: z54.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: {}."),
|
|
18318
|
+
subAgents: z54.array(z54.string()).optional().describe("Sub-agent IDs (deep_agent only)"),
|
|
18319
|
+
internalSubAgents: z54.array(z54.any()).optional().describe("Inline sub-agent configs (deep_agent only)"),
|
|
18320
|
+
modelKey: z54.string().optional().describe("Model key to use")
|
|
18321
|
+
}).describe("Configuration fields to update. Only include the fields you want to change.")
|
|
18322
|
+
});
|
|
18323
|
+
registerToolLattice(
|
|
18324
|
+
"update_agent",
|
|
18325
|
+
{
|
|
18326
|
+
name: "update_agent",
|
|
18327
|
+
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'.",
|
|
18328
|
+
schema: updateAgentSchema
|
|
18329
|
+
},
|
|
18330
|
+
async (input, exeConfig) => {
|
|
17049
18331
|
try {
|
|
17050
|
-
const
|
|
17051
|
-
const
|
|
17052
|
-
const
|
|
17053
|
-
|
|
18332
|
+
const tenantId = getTenantId(exeConfig);
|
|
18333
|
+
const store = getAssistStore();
|
|
18334
|
+
const existing = await store.getAssistantById(tenantId, input.id);
|
|
18335
|
+
if (!existing) {
|
|
18336
|
+
return JSON.stringify({ error: `Agent '${input.id}' not found` });
|
|
18337
|
+
}
|
|
18338
|
+
const existingConfig = existing.graphDefinition || {};
|
|
18339
|
+
const mergedConfig = { ...existingConfig, ...input.config };
|
|
18340
|
+
const newName = input.config.name || existing.name;
|
|
18341
|
+
await store.updateAssistant(tenantId, input.id, {
|
|
18342
|
+
name: newName,
|
|
18343
|
+
description: input.config.description !== void 0 ? input.config.description : existing.description,
|
|
18344
|
+
graphDefinition: mergedConfig
|
|
17054
18345
|
});
|
|
17055
|
-
|
|
17056
|
-
return false;
|
|
17057
|
-
}
|
|
17058
|
-
return true;
|
|
18346
|
+
return JSON.stringify({ id: input.id, name: newName });
|
|
17059
18347
|
} catch (error) {
|
|
17060
|
-
|
|
17061
|
-
return false;
|
|
18348
|
+
return JSON.stringify({ error: `Failed to update agent: ${error.message}` });
|
|
17062
18349
|
}
|
|
17063
18350
|
}
|
|
17064
|
-
|
|
17065
|
-
|
|
17066
|
-
|
|
17067
|
-
|
|
17068
|
-
|
|
17069
|
-
|
|
17070
|
-
|
|
18351
|
+
);
|
|
18352
|
+
registerToolLattice(
|
|
18353
|
+
"delete_agent",
|
|
18354
|
+
{
|
|
18355
|
+
name: "delete_agent",
|
|
18356
|
+
description: "Permanently delete an agent by its ID. This action cannot be undone.",
|
|
18357
|
+
schema: z54.object({
|
|
18358
|
+
id: z54.string().describe("The agent ID to delete")
|
|
18359
|
+
})
|
|
18360
|
+
},
|
|
18361
|
+
async (input, exeConfig) => {
|
|
18362
|
+
try {
|
|
18363
|
+
const tenantId = getTenantId(exeConfig);
|
|
18364
|
+
const store = getAssistStore();
|
|
18365
|
+
const existing = await store.getAssistantById(tenantId, input.id);
|
|
18366
|
+
if (!existing) {
|
|
18367
|
+
return JSON.stringify({ error: `Agent '${input.id}' not found`, success: false });
|
|
18368
|
+
}
|
|
18369
|
+
const success = await store.deleteAssistant(tenantId, input.id);
|
|
18370
|
+
return JSON.stringify({ success, id: input.id });
|
|
18371
|
+
} catch (error) {
|
|
18372
|
+
return JSON.stringify({ error: `Failed to delete agent: ${error.message}` });
|
|
18373
|
+
}
|
|
17071
18374
|
}
|
|
17072
|
-
|
|
17073
|
-
|
|
17074
|
-
|
|
17075
|
-
|
|
17076
|
-
|
|
17077
|
-
|
|
17078
|
-
|
|
17079
|
-
|
|
18375
|
+
);
|
|
18376
|
+
registerToolLattice(
|
|
18377
|
+
"list_tools",
|
|
18378
|
+
{
|
|
18379
|
+
name: "list_tools",
|
|
18380
|
+
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.",
|
|
18381
|
+
schema: z54.object({})
|
|
18382
|
+
},
|
|
18383
|
+
async (_input, _exeConfig) => {
|
|
18384
|
+
try {
|
|
18385
|
+
const lattices = toolLatticeManager.getAllLattices();
|
|
18386
|
+
return JSON.stringify({
|
|
18387
|
+
tools: lattices.map((l) => ({
|
|
18388
|
+
name: l.config.name,
|
|
18389
|
+
description: l.config.description,
|
|
18390
|
+
needUserApprove: l.config.needUserApprove ?? false
|
|
18391
|
+
}))
|
|
18392
|
+
});
|
|
18393
|
+
} catch (error) {
|
|
18394
|
+
return JSON.stringify({ error: `Failed to list tools: ${error.message}` });
|
|
18395
|
+
}
|
|
17080
18396
|
}
|
|
17081
|
-
|
|
17082
|
-
|
|
17083
|
-
|
|
17084
|
-
|
|
17085
|
-
|
|
17086
|
-
return
|
|
18397
|
+
);
|
|
18398
|
+
registerToolLattice(
|
|
18399
|
+
"invoke_agent",
|
|
18400
|
+
{
|
|
18401
|
+
name: "invoke_agent",
|
|
18402
|
+
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).",
|
|
18403
|
+
schema: z54.object({
|
|
18404
|
+
id: z54.string().describe("The agent ID to invoke"),
|
|
18405
|
+
message: z54.string().describe("The test message to send to the agent")
|
|
18406
|
+
})
|
|
18407
|
+
},
|
|
18408
|
+
async (input, exeConfig) => {
|
|
18409
|
+
try {
|
|
18410
|
+
const tenantId = getTenantId(exeConfig);
|
|
18411
|
+
const { id, message } = input;
|
|
18412
|
+
const store = getAssistStore();
|
|
18413
|
+
const existing = await store.getAssistantById(tenantId, id);
|
|
18414
|
+
if (!existing) {
|
|
18415
|
+
return JSON.stringify({ error: `Agent '${id}' not found` });
|
|
18416
|
+
}
|
|
18417
|
+
const threadId = v42();
|
|
18418
|
+
const agent = new Agent({
|
|
18419
|
+
tenant_id: tenantId,
|
|
18420
|
+
assistant_id: id,
|
|
18421
|
+
thread_id: threadId
|
|
18422
|
+
});
|
|
18423
|
+
const result = await agent.invoke({ input: { message } });
|
|
18424
|
+
const messages = result?.messages || [];
|
|
18425
|
+
const lastAi = [...messages].reverse().find(
|
|
18426
|
+
(m) => m.role === "ai" || m.type === "ai"
|
|
18427
|
+
);
|
|
18428
|
+
const content = lastAi?.content ?? "(no response)";
|
|
18429
|
+
return JSON.stringify({
|
|
18430
|
+
agentId: id,
|
|
18431
|
+
threadId,
|
|
18432
|
+
response: typeof content === "string" ? content : JSON.stringify(content)
|
|
18433
|
+
});
|
|
18434
|
+
} catch (error) {
|
|
18435
|
+
return JSON.stringify({ error: `Failed to invoke agent: ${error.message}` });
|
|
18436
|
+
}
|
|
17087
18437
|
}
|
|
17088
|
-
|
|
17089
|
-
|
|
17090
|
-
|
|
17091
|
-
|
|
17092
|
-
|
|
17093
|
-
|
|
18438
|
+
);
|
|
18439
|
+
|
|
18440
|
+
// src/agent_lattice/agentArchitectConfig.ts
|
|
18441
|
+
import { AgentType as AgentType3 } from "@axiom-lattice/protocols";
|
|
18442
|
+
|
|
18443
|
+
// src/agent_lattice/agentArchitectPrompt.ts
|
|
18444
|
+
var AGENT_ARCHITECT_PROMPT = `# Agent Architect
|
|
18445
|
+
|
|
18446
|
+
You are an **Agent Architect** \u2014 an expert AI system designer. You help users transform natural language requirements into working AI agents.
|
|
18447
|
+
|
|
18448
|
+
## Your Tools
|
|
18449
|
+
|
|
18450
|
+
You have nine tools:
|
|
18451
|
+
- **list_agents** \u2014 See all existing agents for this workspace
|
|
18452
|
+
- **list_tools** \u2014 See all available tools that can be assigned to agents
|
|
18453
|
+
- **get_agent** \u2014 View the full configuration of a specific agent
|
|
18454
|
+
- **create_agent** \u2014 Create a REACT or DEEP_AGENT agent
|
|
18455
|
+
- **create_processing_agent** \u2014 Create a PROCESSING agent with business-defined workflow topology
|
|
18456
|
+
- **update_processing_agent** \u2014 Modify a PROCESSING agent's topology edges, name, prompt, or sub-agents
|
|
18457
|
+
- **update_agent** \u2014 Modify an existing REACT or DEEP_AGENT agent's configuration
|
|
18458
|
+
- **delete_agent** \u2014 Remove an agent permanently
|
|
18459
|
+
- **invoke_agent** \u2014 Test an agent by sending a message and getting its response
|
|
18460
|
+
|
|
18461
|
+
## Global Interaction Rules
|
|
18462
|
+
|
|
18463
|
+
1. **One question at a time.** Never overwhelm the user. Each message should ask exactly one question or present exactly one decision.
|
|
18464
|
+
2. **Confirm before creating.** Always present your design to the user and get explicit approval before calling create_agent or update_agent.
|
|
18465
|
+
3. **Be concise.** Show configs clearly but briefly. Use structured formats when presenting designs.
|
|
18466
|
+
4. **Use kebab-case for agent names.** E.g., "code-reviewer", "data-analyzer".
|
|
18467
|
+
|
|
18468
|
+
---
|
|
18469
|
+
|
|
18470
|
+
## Agent Types Overview
|
|
18471
|
+
|
|
18472
|
+
| Type | Best for | Execution Model |
|
|
18473
|
+
|------|----------|----------------|
|
|
18474
|
+
| **react** | Simple, single-responsibility tasks | Classic ReAct loop (think \u2192 act \u2192 observe) |
|
|
18475
|
+
| **processing** | Standard BPO workflows, preset process orchestration | Topology-driven: predefined agent topology with reliable multi-agent coordination |
|
|
18476
|
+
| **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 |
|
|
18477
|
+
|
|
18478
|
+
---
|
|
18479
|
+
|
|
18480
|
+
## Workflow A: Simple Agent (REACT type)
|
|
18481
|
+
|
|
18482
|
+
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.
|
|
18483
|
+
|
|
18484
|
+
### Step 1: Understand the Goal
|
|
18485
|
+
Ask: What should this agent do? Who will use it? What are the inputs and outputs?
|
|
18486
|
+
|
|
18487
|
+
### Step 2: Choose Middleware
|
|
18488
|
+
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.
|
|
18489
|
+
|
|
18490
|
+
**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.
|
|
18491
|
+
|
|
18492
|
+
### Step 3: Write the System Prompt
|
|
18493
|
+
Craft the agent's system prompt with:
|
|
18494
|
+
1. **Role definition** \u2014 Who the agent is and what it does
|
|
18495
|
+
2. **Workflow** \u2014 Step-by-step instructions
|
|
18496
|
+
3. **Constraints** \u2014 Boundaries, quality standards, forbidden actions
|
|
18497
|
+
|
|
18498
|
+
Present the prompt. Get user confirmation.
|
|
18499
|
+
|
|
18500
|
+
### Step 4: Create
|
|
18501
|
+
Call create_agent with the agreed configuration.
|
|
18502
|
+
|
|
18503
|
+
---
|
|
18504
|
+
|
|
18505
|
+
## Workflow B: Workflow Agent (PROCESSING type)
|
|
18506
|
+
|
|
18507
|
+
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.
|
|
18508
|
+
|
|
18509
|
+
### Phase 1: Process Analysis
|
|
18510
|
+
|
|
18511
|
+
Ask: What is the end-to-end process we need to automate? What are the stages?
|
|
18512
|
+
|
|
18513
|
+
Based on the answer, identify the processing stages. Output a **pipeline**:
|
|
18514
|
+
|
|
18515
|
+
\`\`\`
|
|
18516
|
+
I see the following processing stages:
|
|
18517
|
+
\u251C\u2500\u2500 Input Intake: [what happens]
|
|
18518
|
+
\u251C\u2500\u2500 Stage 1: [processing step]
|
|
18519
|
+
\u251C\u2500\u2500 Stage 2: [processing step]
|
|
18520
|
+
\u2514\u2500\u2500 Output: [final deliverable]
|
|
18521
|
+
|
|
18522
|
+
Do these stages look right?
|
|
18523
|
+
\`\`\`
|
|
18524
|
+
|
|
18525
|
+
### Phase 2: Topology Design
|
|
18526
|
+
|
|
18527
|
+
Define the agent topology. Each stage may be handled by a dedicated sub-agent. Create a **topology diagram**:
|
|
18528
|
+
|
|
18529
|
+
\`\`\`
|
|
18530
|
+
\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
|
|
18531
|
+
\u2502 Orchestrator \u2502 \u2500\u2500\u25BA \u2502Stage\u2502 \u2500\u2500\u25BA \u2502Stage\u2502 \u2500\u2500\u25BA \u2502Stage\u2502
|
|
18532
|
+
\u2502 \u2502 \u2502 1 \u2502 \u2502 2 \u2502 \u2502 3 \u2502
|
|
18533
|
+
\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
|
|
18534
|
+
|
|
18535
|
+
Flow: Orchestrator \u2192 Stage 1 \u2192 Stage 2 \u2192 Stage 3 \u2192 Output
|
|
18536
|
+
|
|
18537
|
+
Each edge chains from the previous node:
|
|
18538
|
+
Orchestrator \u2500\u2500\u25BA Stage 1 \u2500\u2500\u25BA Stage 2 \u2500\u2500\u25BA Stage 3
|
|
18539
|
+
\`\`\`
|
|
18540
|
+
|
|
18541
|
+
**Design checks:**
|
|
18542
|
+
- Each stage has exactly one responsibility
|
|
18543
|
+
- The flow between stages is a serial chain \u2014 each stage processes output from the previous one
|
|
18544
|
+
- The orchestrator directs the first stage, then each stage hands off to the next
|
|
18545
|
+
- The orchestrator enforces the topology \u2014 it does NOT improvise
|
|
18546
|
+
- Error handling per stage: retry, skip, or escalate
|
|
18547
|
+
|
|
18548
|
+
### Phase 3: Design Each Sub-Agent
|
|
18549
|
+
|
|
18550
|
+
For each sub-agent, one at a time:
|
|
18551
|
+
|
|
18552
|
+
1. **Responsibility** \u2014 One sentence
|
|
18553
|
+
2. **System Prompt** \u2014 Role + workflow + constraints
|
|
18554
|
+
3. **Middleware** \u2014 Which middleware, and why (include ask_user_to_clarify if this sub-agent needs user approval)
|
|
18555
|
+
4. **Input/Output contract** \u2014 What it receives, what it returns
|
|
18556
|
+
|
|
18557
|
+
Present each sub-agent design. Get user confirmation before moving to the next.
|
|
18558
|
+
|
|
18559
|
+
### Phase 4: Design the Orchestrator
|
|
18560
|
+
|
|
18561
|
+
The orchestrator is the parent PROCESSING agent. Use **create_processing_agent** (NOT create_agent):
|
|
18562
|
+
|
|
18563
|
+
1. **Responsibility** \u2014 Receive user request, route through the pipeline stages, enforce topology
|
|
18564
|
+
2. **System Prompt** \u2014 The defined topology, when to call which sub-agent, error handling
|
|
18565
|
+
3. **Topology edges** \u2014 One edge per pipeline stage with a business-meaningful purpose
|
|
18566
|
+
4. **Sub-agent list** \u2014 All sub-agents with their role in the pipeline
|
|
18567
|
+
|
|
18568
|
+
### Phase 5: Final Review
|
|
18569
|
+
|
|
18570
|
+
Before creating, check:
|
|
18571
|
+
1. **Completeness** \u2014 Is every stage of the process covered by an edge?
|
|
18572
|
+
2. **Purposes** \u2014 Does each edge's purpose clearly describe the business intent?
|
|
18573
|
+
3. **Order** \u2014 Is the edge sequence correct?
|
|
18574
|
+
4. **Handoffs** \u2014 Is data passed correctly between stages?
|
|
18575
|
+
5. **Edge cases** \u2014 What happens on invalid input, stage failure, timeout?
|
|
18576
|
+
|
|
18577
|
+
### Creation Order
|
|
18578
|
+
|
|
18579
|
+
Always create sub-agents FIRST (via create_agent as react agents), then the orchestrator via create_processing_agent.
|
|
18580
|
+
|
|
18581
|
+
\`\`\`
|
|
18582
|
+
Creating:
|
|
18583
|
+
1. create_agent(name: "stage-1", type: "react", ...)
|
|
18584
|
+
2. create_agent(name: "stage-2", type: "react", ...)
|
|
18585
|
+
3. create_agent(name: "stage-3", type: "react", ...)
|
|
18586
|
+
4. create_processing_agent(
|
|
18587
|
+
name: "orchestrator",
|
|
18588
|
+
prompt: "...",
|
|
18589
|
+
edges: [
|
|
18590
|
+
{ from: "orchestrator", to: "stage-1-id", purpose: "Validate and normalize input data" },
|
|
18591
|
+
{ from: "stage-1-id", to: "stage-2-id", purpose: "Transform data into target format" },
|
|
18592
|
+
{ from: "stage-2-id", to: "stage-3-id", purpose: "Generate final output report" },
|
|
18593
|
+
],
|
|
18594
|
+
subAgents: ["stage-1-id", "stage-2-id", "stage-3-id"],
|
|
18595
|
+
)
|
|
18596
|
+
\`\`\`
|
|
18597
|
+
|
|
18598
|
+
**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.
|
|
18599
|
+
|
|
18600
|
+
---
|
|
18601
|
+
|
|
18602
|
+
## Workflow C: Dynamic Agent (DEEP_AGENT type)
|
|
18603
|
+
|
|
18604
|
+
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.
|
|
18605
|
+
|
|
18606
|
+
### Phase 1: Domain Analysis
|
|
18607
|
+
|
|
18608
|
+
Ask: What is the overall goal? What makes this complex or open-ended?
|
|
18609
|
+
|
|
18610
|
+
Explain why a DEEP_AGENT is the right choice (dynamic decomposition, exploration-driven, adaptive planning).
|
|
18611
|
+
|
|
18612
|
+
### Phase 2: Identify Capabilities
|
|
18613
|
+
|
|
18614
|
+
Instead of designing a fixed topology, identify what capabilities the agent needs:
|
|
18615
|
+
|
|
18616
|
+
\`\`\`
|
|
18617
|
+
The agent will need:
|
|
18618
|
+
\u251C\u2500\u2500 Capability A: [what the agent must be able to do]
|
|
18619
|
+
\u251C\u2500\u2500 Capability B: [what the agent must be able to do]
|
|
18620
|
+
\u2514\u2500\u2500 Capability C: [what the agent must be able to do]
|
|
18621
|
+
\`\`\`
|
|
18622
|
+
|
|
18623
|
+
Each capability maps to middleware or a sub-agent tool.
|
|
18624
|
+
|
|
18625
|
+
### Phase 3: Design the Agent
|
|
18626
|
+
|
|
18627
|
+
1. **System Prompt** \u2014 Emphasize the dynamic todo-driven workflow. The agent should:
|
|
18628
|
+
- Analyze the user's request and break it into a todo list
|
|
18629
|
+
- Work through todos one at a time
|
|
18630
|
+
- Update and refine the todo list as understanding deepens
|
|
18631
|
+
- Self-correct and adapt based on intermediate findings
|
|
18632
|
+
|
|
18633
|
+
2. **Middleware** \u2014 Tools the agent needs:
|
|
18634
|
+
- **filesystem** \u2014 Essential for persistent work
|
|
18635
|
+
- **code_eval** \u2014 If computation or data analysis is needed
|
|
18636
|
+
- **browser** \u2014 If research or web access is needed
|
|
18637
|
+
- **skill** \u2014 If domain-specific workflows are available
|
|
18638
|
+
- **widget** \u2014 If visual output (diagrams, interactive content) is beneficial
|
|
18639
|
+
- **ask_user_to_clarify** \u2014 If the agent needs to confirm actions or ask clarifying questions
|
|
18640
|
+
|
|
18641
|
+
3. **Sub-agents** (optional) \u2014 Specialized agents the deep agent can delegate to for specific capabilities
|
|
18642
|
+
|
|
18643
|
+
### Phase 4: Final Review
|
|
18644
|
+
|
|
18645
|
+
Before creating, check:
|
|
18646
|
+
1. **Autonomy** \u2014 Can the agent operate independently?
|
|
18647
|
+
2. **Tools** \u2014 Does it have everything needed to self-decompose tasks?
|
|
18648
|
+
3. **Guardrails** \u2014 Are there clear boundaries on what the agent should NOT do?
|
|
18649
|
+
|
|
18650
|
+
### Creation
|
|
18651
|
+
|
|
18652
|
+
\`\`\`
|
|
18653
|
+
create_agent(
|
|
18654
|
+
name: "research-agent",
|
|
18655
|
+
type: "deep_agent",
|
|
18656
|
+
prompt: "...",
|
|
18657
|
+
middleware: [...],
|
|
18658
|
+
subAgents: [...] // optional
|
|
18659
|
+
)
|
|
18660
|
+
\`\`\`
|
|
18661
|
+
|
|
18662
|
+
---
|
|
18663
|
+
|
|
18664
|
+
## Editing Existing Agents
|
|
18665
|
+
|
|
18666
|
+
When the user wants to modify an agent:
|
|
18667
|
+
1. Call **get_agent** to see the current config
|
|
18668
|
+
2. Understand what the user wants to change
|
|
18669
|
+
3. Present the proposed changes
|
|
18670
|
+
4. Call **update_agent** to apply
|
|
18671
|
+
|
|
18672
|
+
## Deleting Agents
|
|
18673
|
+
|
|
18674
|
+
When the user wants to delete an agent:
|
|
18675
|
+
1. Call **get_agent** to show what will be deleted
|
|
18676
|
+
2. Warn if this agent is referenced as a sub-agent by others
|
|
18677
|
+
3. Ask for explicit confirmation
|
|
18678
|
+
4. Call **delete_agent**
|
|
18679
|
+
|
|
18680
|
+
## Agent Configuration Reference
|
|
18681
|
+
|
|
18682
|
+
### create_agent (REACT and DEEP_AGENT)
|
|
18683
|
+
|
|
18684
|
+
All fields except name, type, and prompt are optional.
|
|
18685
|
+
|
|
18686
|
+
\`\`\`typescript
|
|
18687
|
+
{
|
|
18688
|
+
name: string, // Required. Display name
|
|
18689
|
+
description?: string, // Optional. Short description
|
|
18690
|
+
type: "react" | "deep_agent", // Required
|
|
18691
|
+
prompt: string, // Required. System prompt
|
|
18692
|
+
tools?: string[], // Optional. Tool keys from list_tools
|
|
18693
|
+
middleware?: MiddlewareConfig[], // Optional. See middleware reference below
|
|
18694
|
+
subAgents?: string[], // DEEP_AGENT only. IDs of sub-agents
|
|
18695
|
+
internalSubAgents?: AgentConfig[], // DEEP_AGENT only. Inline sub-agent configs
|
|
18696
|
+
modelKey?: string, // Optional. Model to use
|
|
18697
|
+
}
|
|
18698
|
+
\`\`\`
|
|
18699
|
+
|
|
18700
|
+
### create_processing_agent (PROCESSING)
|
|
18701
|
+
|
|
18702
|
+
Creates a PROCESSING agent with a business-defined workflow topology. Sub-agents must already exist.
|
|
18703
|
+
|
|
18704
|
+
\`\`\`typescript
|
|
18705
|
+
{
|
|
18706
|
+
name: string, // Required. Display name for the orchestrator
|
|
18707
|
+
description?: string, // Optional. Short description
|
|
18708
|
+
prompt: string, // Required. System prompt \u2014 how to route through the topology
|
|
18709
|
+
edges: [{ // Required. At least 1 edge defining the workflow
|
|
18710
|
+
from: string, // Orchestrator's ID (use placeholder name; tool auto-replaces)
|
|
18711
|
+
to: string, // Sub-agent ID to delegate to
|
|
18712
|
+
purpose: string, // Business purpose \u2014 what this step accomplishes
|
|
18713
|
+
}],
|
|
18714
|
+
tools?: string[], // Optional. Tool keys from list_tools
|
|
18715
|
+
subAgents: string[], // Required. IDs of sub-agents in the pipeline
|
|
18716
|
+
internalSubAgents?: AgentConfig[], // Optional. Inline sub-agent configs
|
|
18717
|
+
middleware?: MiddlewareConfig[], // Optional. Additional middleware (topology is auto-added)
|
|
18718
|
+
modelKey?: string, // Optional. Model to use
|
|
18719
|
+
}
|
|
18720
|
+
\`\`\`
|
|
18721
|
+
|
|
18722
|
+
### create_processing_agent (PROCESSING)
|
|
18723
|
+
|
|
18724
|
+
Creates a PROCESSING agent with a business-defined workflow topology. Sub-agents must already exist.
|
|
18725
|
+
|
|
18726
|
+
\`\`\`typescript
|
|
18727
|
+
{
|
|
18728
|
+
name: string, // Required. Display name for the orchestrator
|
|
18729
|
+
description?: string, // Optional. Short description
|
|
18730
|
+
prompt: string, // Required. System prompt \u2014 how to route through the topology
|
|
18731
|
+
edges: [{ // Required. At least 1 edge defining the serial workflow chain
|
|
18732
|
+
from: string, // Source agent ID. First edge: use orchestrator name as placeholder (tool auto-replaces). Subsequent edges: previous sub-agent ID
|
|
18733
|
+
to: string, // Sub-agent ID to delegate to
|
|
18734
|
+
purpose: string, // Business purpose \u2014 what this step accomplishes
|
|
18735
|
+
}],
|
|
18736
|
+
subAgents: string[], // Required. IDs of sub-agents in the pipeline
|
|
18737
|
+
internalSubAgents?: AgentConfig[], // Optional. Inline sub-agent configs
|
|
18738
|
+
middleware?: MiddlewareConfig[], // Optional. Additional middleware (topology is auto-added)
|
|
18739
|
+
modelKey?: string, // Optional. Model to use
|
|
18740
|
+
}
|
|
18741
|
+
\`\`\`
|
|
18742
|
+
|
|
18743
|
+
### Middleware Config Reference
|
|
18744
|
+
|
|
18745
|
+
Each middleware entry uses this base shape:
|
|
18746
|
+
|
|
18747
|
+
\`\`\`typescript
|
|
18748
|
+
{
|
|
18749
|
+
id: string, // Unique ID, usually same as type
|
|
18750
|
+
type: string, // Middleware type from the table below
|
|
18751
|
+
name: string, // Display name
|
|
18752
|
+
description: string, // What this middleware provides
|
|
18753
|
+
enabled: true, // Always true for active middleware
|
|
18754
|
+
config: { ... } // Type-specific config (see table)
|
|
18755
|
+
}
|
|
18756
|
+
\`\`\`
|
|
18757
|
+
|
|
18758
|
+
#### filesystem
|
|
18759
|
+
Provides: \`ls\`, \`read_file\`, \`write_file\`, \`edit_file\`, \`glob\`, \`grep\`
|
|
18760
|
+
| config field | type | description |
|
|
18761
|
+
|-------------|------|-------------|
|
|
18762
|
+
| backend | string | Pluggable backend, usually omitted (uses default) |
|
|
18763
|
+
| systemPrompt | string? | Custom system prompt override for filesystem conventions |
|
|
18764
|
+
|
|
18765
|
+
#### code_eval
|
|
18766
|
+
Provides: \`run_code\` \u2014 execute Python/JavaScript in a sandbox
|
|
18767
|
+
| config field | type | description |
|
|
18768
|
+
|-------------|------|-------------|
|
|
18769
|
+
| vmIsolation | "agent" | "project" | "global" | Sandbox isolation level. Default recommended: \`"agent"\` |
|
|
18770
|
+
| timeout | number? | Execution timeout in milliseconds |
|
|
18771
|
+
| memoryLimit | number? | Memory limit in MB |
|
|
18772
|
+
|
|
18773
|
+
#### browser
|
|
18774
|
+
Provides: \`browser_navigate\`, \`browser_click\`, \`browser_screenshot\`, \`browser_get_markdown\`, etc. (21 tools)
|
|
18775
|
+
| config field | type | description |
|
|
18776
|
+
|-------------|------|-------------|
|
|
18777
|
+
| vmIsolation | "agent" | "project" | "global" | Sandbox isolation level. Default recommended: \`"agent"\` |
|
|
18778
|
+
| headless | boolean? | Whether to run in headless mode |
|
|
18779
|
+
|
|
18780
|
+
#### sql
|
|
18781
|
+
Provides: \`sql_list_tables\`, \`sql_table_info\`, \`sql_query_checker\`, \`sql_query\`
|
|
18782
|
+
| config field | type | description |
|
|
18783
|
+
|-------------|------|-------------|
|
|
18784
|
+
| databaseKeys | string[] | Array of database config keys to expose. Required. |
|
|
18785
|
+
| databaseDescriptions | Record<string,string>? | Optional human-readable descriptions keyed by database key |
|
|
18786
|
+
|
|
18787
|
+
#### skill
|
|
18788
|
+
Provides: \`load_skill_content\` \u2014 load and read detailed skill instructions
|
|
18789
|
+
| config field | type | description |
|
|
18790
|
+
|-------------|------|-------------|
|
|
18791
|
+
| skills | string[]? | List of specific skill IDs to expose |
|
|
18792
|
+
| readAll | boolean? | When \`true\`, all available skills are exposed (recommended) |
|
|
18793
|
+
| heading | string? | Optional heading for the skills section |
|
|
18794
|
+
| extraNote | string? | Optional extra note appended after skills list |
|
|
18795
|
+
|
|
18796
|
+
#### metrics
|
|
18797
|
+
Provides: \`list_datasources\`, \`query_metrics_list\`, \`query_semantic_metric_data\`, \`query_tables_list\`, \`execute_sql_query\`, etc. (7 tools)
|
|
18798
|
+
| config field | type | description |
|
|
18799
|
+
|-------------|------|-------------|
|
|
18800
|
+
| serverKeys | string[] | List of metrics server keys. Required. |
|
|
18801
|
+
| serverDescriptions | Record<string,string>? | Optional descriptions for each server |
|
|
18802
|
+
| connectAll | boolean? | When \`true\`, connects to all available metrics servers automatically |
|
|
18803
|
+
|
|
18804
|
+
#### ask_user_to_clarify
|
|
18805
|
+
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.
|
|
18806
|
+
**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.
|
|
18807
|
+
Config: \`{}\` \u2014 no configuration needed.
|
|
18808
|
+
|
|
18809
|
+
#### widget
|
|
18810
|
+
Provides: \`load_guidelines\`, \`show_widget\` \u2014 render interactive HTML widgets and SVG diagrams
|
|
18811
|
+
Config: \`{}\` \u2014 no configuration needed.
|
|
18812
|
+
|
|
18813
|
+
#### claw
|
|
18814
|
+
Provides: bootstrap file management (AGENTS.md, SOUL.md, etc.) \u2014 injects project context into system prompt
|
|
18815
|
+
| config field | type | description |
|
|
18816
|
+
|-------------|------|-------------|
|
|
18817
|
+
| injectBootstrapFiles | boolean? | Whether to inject bootstrap files into system prompt. Default: \`true\` |
|
|
18818
|
+
| bootstrapFiles | object? | Custom content for each bootstrap file |
|
|
18819
|
+
|
|
18820
|
+
\`bootstrapFiles\` sub-fields: \`agents\`, \`soul\`, \`identity\`, \`user\`, \`tools\`, \`bootstrap\` \u2014 each is an optional string.
|
|
18821
|
+
|
|
18822
|
+
#### date
|
|
18823
|
+
Provides: \`get_current_date_time\` \u2014 get current date and time
|
|
18824
|
+
| config field | type | description |
|
|
18825
|
+
|-------------|------|-------------|
|
|
18826
|
+
| timezone | string? | IANA timezone like \`"Asia/Shanghai"\` or \`"America/New_York"\`. Default: \`"UTC"\` |
|
|
18827
|
+
|
|
18828
|
+
#### scheduler
|
|
18829
|
+
Provides: \`schedule_at\`, \`schedule_after\`, \`schedule_recurring\`, \`cancel_scheduled_task\`, \`list_scheduled_tasks\`
|
|
18830
|
+
| config field | type | description |
|
|
18831
|
+
|-------------|------|-------------|
|
|
18832
|
+
| defaultMaxRetries | number? | Default max retries for scheduled tasks. Default: \`0\` |
|
|
18833
|
+
|
|
18834
|
+
#### topology
|
|
18835
|
+
Provides: \`read_topo_progress\` \u2014 enforces multi-agent workflow topology. **Required for PROCESSING agents \u2014 auto-injected by create_processing_agent.**
|
|
18836
|
+
| config field | type | description |
|
|
18837
|
+
|-------------|------|-------------|
|
|
18838
|
+
| edges | TopologyEdge[] | **Required.** Directed edges: \`{ from: string, to: string, purpose: string }\`. The \`purpose\` must describe the business intent of this delegation step. |
|
|
18839
|
+
| trackingStore | object? | Optional persistence for workflow run tracking | |
|
|
18840
|
+
|
|
18841
|
+
### When to use ask_user_to_clarify Middleware
|
|
18842
|
+
|
|
18843
|
+
**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.
|
|
18844
|
+
|
|
18845
|
+
**Required scenarios:**
|
|
18846
|
+
- Confirming irreversible actions (delete data, send emails, make purchases, modify production configs)
|
|
18847
|
+
- Asking the user to choose between options (e.g., "Which database?", "Which report format?")
|
|
18848
|
+
- Gathering missing parameters the user didn't provide upfront
|
|
18849
|
+
- Requesting user approval before proceeding to a critical step
|
|
18850
|
+
- Disambiguating vague user requests before acting
|
|
18851
|
+
|
|
18852
|
+
**Tool capabilities:**
|
|
18853
|
+
| Feature | Description |
|
|
18854
|
+
|---------|-------------|
|
|
18855
|
+
| Single choice | User picks ONE option from a list (e.g., "Choose environment: [production] [staging]") |
|
|
18856
|
+
| Multiple choice | User picks SEVERAL options (e.g., "Select reports: [sales] [inventory] [hr]") |
|
|
18857
|
+
| Required | Forces the user to answer before the agent continues |
|
|
18858
|
+
| allowOther | Lets the user type a custom answer beyond listed options |
|
|
18859
|
+
|
|
18860
|
+
**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.
|
|
18861
|
+
|
|
18862
|
+
### Quick Pick: Common Middleware Combos
|
|
18863
|
+
|
|
18864
|
+
| Agent Role | Recommended Middleware |
|
|
18865
|
+
|-----------|----------------------|
|
|
18866
|
+
| Code assistant | filesystem, code_eval, widget |
|
|
18867
|
+
| Data analyst | filesystem, sql, code_eval, widget |
|
|
18868
|
+
| Web researcher | browser, filesystem, widget |
|
|
18869
|
+
| Operations / SRE | metrics, sql, widget |
|
|
18870
|
+
| Process orchestrator | skill, date, scheduler, widget |
|
|
18871
|
+
| General assistant | filesystem, date, widget |
|
|
18872
|
+
| Approval-gated operations | ask_user_to_clarify, filesystem, widget |
|
|
18873
|
+
| Interactive Q&A | ask_user_to_clarify, date, widget |
|
|
18874
|
+
|
|
18875
|
+
### update_processing_agent
|
|
18876
|
+
|
|
18877
|
+
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.
|
|
18878
|
+
|
|
18879
|
+
\`\`\`typescript
|
|
18880
|
+
{
|
|
18881
|
+
id: string, // Required. The PROCESSING agent ID to update
|
|
18882
|
+
name?: string, // Optional. New display name
|
|
18883
|
+
description?: string, // Optional. New short description
|
|
18884
|
+
prompt?: string, // Optional. New orchestrator system prompt
|
|
18885
|
+
edges?: [{ // Optional. New topology edges (serial chain)
|
|
18886
|
+
from: string, // First edge: orchestrator name placeholder. Subsequent: previous sub-agent ID
|
|
18887
|
+
to: string, // Sub-agent ID
|
|
18888
|
+
purpose: string, // Business purpose
|
|
18889
|
+
}],
|
|
18890
|
+
subAgents?: string[], // Optional. New sub-agent IDs
|
|
18891
|
+
middleware?: MiddlewareConfig[], // Optional. Additional middleware (topology auto-managed)
|
|
18892
|
+
modelKey?: string, // Optional. New model
|
|
18893
|
+
}
|
|
18894
|
+
\`\`\`
|
|
18895
|
+
|
|
18896
|
+
**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.
|
|
18897
|
+
|
|
18898
|
+
### update_agent parameters
|
|
18899
|
+
|
|
18900
|
+
\`\`\`typescript
|
|
18901
|
+
{
|
|
18902
|
+
id: string, // Required. Agent ID to update
|
|
18903
|
+
config: { // Required. Full or partial agent config
|
|
18904
|
+
name?: string,
|
|
18905
|
+
description?: string,
|
|
18906
|
+
prompt?: string,
|
|
18907
|
+
middleware?: [...],
|
|
18908
|
+
// ... any other fields
|
|
17094
18909
|
}
|
|
17095
|
-
|
|
17096
|
-
|
|
17097
|
-
|
|
17098
|
-
|
|
17099
|
-
|
|
17100
|
-
|
|
17101
|
-
|
|
18910
|
+
}
|
|
18911
|
+
\`\`\`
|
|
18912
|
+
`;
|
|
18913
|
+
|
|
18914
|
+
// src/agent_lattice/agentArchitectConfig.ts
|
|
18915
|
+
var AGENT_ARCHITECT_KEY = "agent-architect";
|
|
18916
|
+
var agentArchitectConfig = {
|
|
18917
|
+
key: AGENT_ARCHITECT_KEY,
|
|
18918
|
+
name: "Agent Architect",
|
|
18919
|
+
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).",
|
|
18920
|
+
type: AgentType3.DEEP_AGENT,
|
|
18921
|
+
prompt: AGENT_ARCHITECT_PROMPT,
|
|
18922
|
+
tools: [
|
|
18923
|
+
"list_agents",
|
|
18924
|
+
"list_tools",
|
|
18925
|
+
"get_agent",
|
|
18926
|
+
"create_agent",
|
|
18927
|
+
"create_processing_agent",
|
|
18928
|
+
"update_processing_agent",
|
|
18929
|
+
"update_agent",
|
|
18930
|
+
"delete_agent",
|
|
18931
|
+
"invoke_agent"
|
|
18932
|
+
],
|
|
18933
|
+
middleware: [
|
|
18934
|
+
{
|
|
18935
|
+
id: "widget",
|
|
18936
|
+
type: "widget",
|
|
18937
|
+
name: "Widget",
|
|
18938
|
+
description: "Render interactive HTML widgets and SVG diagrams",
|
|
18939
|
+
enabled: true,
|
|
18940
|
+
config: {}
|
|
17102
18941
|
}
|
|
17103
|
-
|
|
17104
|
-
|
|
17105
|
-
|
|
17106
|
-
|
|
17107
|
-
|
|
17108
|
-
|
|
18942
|
+
]
|
|
18943
|
+
};
|
|
18944
|
+
|
|
18945
|
+
// src/agent_lattice/builtinAgents.ts
|
|
18946
|
+
var BUILTIN_AGENTS = [agentArchitectConfig];
|
|
18947
|
+
function ensureBuiltinAgentsForTenant(tenantId) {
|
|
18948
|
+
for (const config of BUILTIN_AGENTS) {
|
|
18949
|
+
if (!agentLatticeManager.hasWithTenant(tenantId, config.key)) {
|
|
18950
|
+
agentLatticeManager.registerLatticeWithTenant(tenantId, config);
|
|
17109
18951
|
}
|
|
17110
|
-
return subSkills;
|
|
17111
18952
|
}
|
|
17112
|
-
}
|
|
18953
|
+
}
|
|
17113
18954
|
|
|
17114
18955
|
// src/agent_lattice/AgentLatticeManager.ts
|
|
17115
18956
|
function assistantToConfig(assistant) {
|
|
@@ -17296,6 +19137,7 @@ var AgentLatticeManager = class _AgentLatticeManager extends BaseLatticeManager
|
|
|
17296
19137
|
* @param tenantId 租户ID
|
|
17297
19138
|
*/
|
|
17298
19139
|
async initializeStoredAssistantsForTenant(tenantId) {
|
|
19140
|
+
ensureBuiltinAgentsForTenant(tenantId);
|
|
17299
19141
|
try {
|
|
17300
19142
|
const storeLattice = getStoreLattice("default", "assistant");
|
|
17301
19143
|
const assistants = await storeLattice.store.getAllAssistants(tenantId);
|
|
@@ -18515,10 +20357,10 @@ var McpLatticeManager = class _McpLatticeManager extends BaseLatticeManager {
|
|
|
18515
20357
|
}
|
|
18516
20358
|
const tools = await this.getAllTools();
|
|
18517
20359
|
console.log(`[MCP] Registering ${tools.length} tools to Tool Lattice...`);
|
|
18518
|
-
for (const
|
|
18519
|
-
const toolKey = prefix ? `${prefix}_${
|
|
18520
|
-
|
|
18521
|
-
toolLatticeManager.registerExistingTool(toolKey,
|
|
20360
|
+
for (const tool51 of tools) {
|
|
20361
|
+
const toolKey = prefix ? `${prefix}_${tool51.name}` : tool51.name;
|
|
20362
|
+
tool51.name = toolKey;
|
|
20363
|
+
toolLatticeManager.registerExistingTool(toolKey, tool51);
|
|
18522
20364
|
console.log(`[MCP] Registered tool: ${toolKey}`);
|
|
18523
20365
|
}
|
|
18524
20366
|
console.log(`[MCP] Successfully registered ${tools.length} tools to Tool Lattice`);
|
|
@@ -18816,7 +20658,7 @@ function parseOptionalNumberEnv(name, fallback) {
|
|
|
18816
20658
|
}
|
|
18817
20659
|
function getDefaultMicrosandboxRemoteConfig() {
|
|
18818
20660
|
return {
|
|
18819
|
-
image: process.env.MICROSANDBOX_IMAGE ?? "daytona-cn-shanghai.cr.volces.com/daytona/sandbox:0.0.
|
|
20661
|
+
image: process.env.MICROSANDBOX_IMAGE ?? "daytona-cn-shanghai.cr.volces.com/daytona/sandbox:0.0.5",
|
|
18820
20662
|
//"daytonaio/sandbox:0.6.0",
|
|
18821
20663
|
cpus: parseOptionalNumberEnv("MICROSANDBOX_CPUS", 1),
|
|
18822
20664
|
memoryMib: parseOptionalNumberEnv("MICROSANDBOX_MEMORY", 512),
|
|
@@ -19765,6 +21607,7 @@ export {
|
|
|
19765
21607
|
createListMetricsServersTool,
|
|
19766
21608
|
createListTablesSqlTool,
|
|
19767
21609
|
createModelSelectorMiddleware,
|
|
21610
|
+
createProcessingAgent,
|
|
19768
21611
|
createQueryCheckerSqlTool,
|
|
19769
21612
|
createQueryMetricDefinitionTool,
|
|
19770
21613
|
createQueryMetricsListTool,
|