@axiom-lattice/core 2.1.56 → 2.1.58

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.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, tool50) {
651
+ registerExistingTool(key, tool51) {
652
652
  const config = {
653
- name: tool50.name,
654
- description: tool50.description,
655
- schema: tool50.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: tool50
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, tool50) => toolLatticeManager.registerExistingTool(key, tool50);
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, getTenantId) {
1123
+ function getTenantIdFromConfig(exeConfig, getTenantId2) {
1124
1124
  const runConfig = exeConfig?.configurable?.runConfig || {};
1125
- return runConfig.tenantId || (getTenantId ? getTenantId() : "default");
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, getTenantId);
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, getTenantId);
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, getTenantId);
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, getTenantId);
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, getTenantId) {
1473
+ function getTenantIdFromConfig2(exeConfig, getTenantId2) {
1474
1474
  const runConfig = exeConfig?.configurable?.runConfig || {};
1475
- return runConfig.tenantId || (getTenantId ? getTenantId() : "default");
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, getTenantId);
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, getTenantId);
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, getTenantId);
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, getTenantId);
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, getTenantId);
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, getTenantId);
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, getTenantId);
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, getTenantId);
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
@@ -4837,6 +4838,285 @@ import { tool as tool38 } from "langchain";
4837
4838
  // src/tool_lattice/skill/load_skill_content.ts
4838
4839
  import z42 from "zod";
4839
4840
  import { tool as tool39 } from "langchain";
4841
+
4842
+ // src/skill_lattice/builtinSkills.ts
4843
+ var BUILTIN_SKILLS = {
4844
+ "create-skill": `---
4845
+ name: create-skill
4846
+ description: Create new skills, modify and improve existing skills. Use this skill whenever users mention creating a skill, wanting a new capability, asking to "make a skill for X", setting up automated workflows, or wanting to capture repeatable agent instructions \u2014 even if they don't use the word "skill."
4847
+ license: MIT
4848
+ metadata:
4849
+ category: meta
4850
+ version: "2.0"
4851
+ ---
4852
+
4853
+ # Skill Creator
4854
+
4855
+ This skill guides you through creating and improving agent skills. Your job is to figure out where the user is in the process and help them progress \u2014 whether they're starting from scratch, have a rough idea, or want to improve an existing skill.
4856
+
4857
+ At a high level, the process follows an iterative loop: **understand intent \u2192 interview \u2192 draft \u2192 test \u2192 review \u2192 improve \u2192 repeat** until satisfied. But always be flexible \u2014 if the user says "just vibe with me," do that instead.
4858
+
4859
+ ## Communicating With the User
4860
+
4861
+ Users range from deep technical experts to people who just learned what a terminal is. Pay attention to context cues:
4862
+ - "JSON" and "assertion" \u2014 only use without explanation if the user shows comfort with them
4863
+ - "evaluation" and "benchmark" \u2014 borderline, briefly define if unsure
4864
+ - When in doubt, briefly explain terms. Short parenthetical definitions are fine.
4865
+
4866
+ ---
4867
+
4868
+ ## Step 1: Capture Intent
4869
+
4870
+ Start by understanding what the user wants. The current conversation may already contain a workflow they want to capture (e.g., they say "turn this into a skill"). If so, extract answers from the conversation history first \u2014 the tools used, the sequence of steps, corrections made, input/output formats observed.
4871
+
4872
+ Ask yourself:
4873
+ 1. What capability does this skill enable?
4874
+ 2. When should this skill trigger? (what user phrases, contexts, keywords)
4875
+ 3. What is the expected output or behavior?
4876
+ 4. Does it coordinate other skills (subSkills)?
4877
+
4878
+ ## Step 2: Interview and Research
4879
+
4880
+ Proactively ask questions before writing anything:
4881
+ - **Edge cases**: What unusual inputs might arise? What should happen on failure?
4882
+ - **Input/output formats**: What formats are involved (files, data, text)?
4883
+ - **Dependencies**: Are specific tools, APIs, or data sources needed?
4884
+ - **Success criteria**: How will the user know the skill is working?
4885
+
4886
+ Don't start writing until you've got clear answers. If the user is vague, ask clarifying questions \u2014 you'll save time by not guessing wrong.
4887
+
4888
+ ---
4889
+
4890
+ ## Step 3: Write the SKILL.md
4891
+
4892
+ ### Skill Directory Structure
4893
+
4894
+ Skills use progressive disclosure \u2014 three levels of loading:
4895
+
4896
+ \`\`\`
4897
+ skill-name/
4898
+ \u251C\u2500\u2500 SKILL.md # Required \u2014 frontmatter + markdown body
4899
+ \u2514\u2500\u2500 resources/ # Optional \u2014 bundled files
4900
+ \u251C\u2500\u2500 scripts/ # Executable code for repetitive tasks
4901
+ \u251C\u2500\u2500 references/ # Docs loaded into context as needed
4902
+ \u2514\u2500\u2500 assets/ # Files used in output (templates, icons)
4903
+ \`\`\`
4904
+
4905
+ - **Metadata** (name + description) \u2014 always in context (~100 words)
4906
+ - **SKILL.md body** \u2014 loaded when skill triggers (aim for <500 lines)
4907
+ - **Bundled resources** \u2014 loaded as needed, unlimited
4908
+
4909
+ If SKILL.md approaches 500 lines, add hierarchy with clear pointers to reference files.
4910
+
4911
+ ### File Location
4912
+
4913
+ Write the skill to: \`/root/.agents/skills/{skill-name}/SKILL.md\`
4914
+
4915
+ Resources go in: \`/root/.agents/skills/{skill-name}/resources/\`
4916
+
4917
+ ### Naming Rules
4918
+
4919
+ Skill names (also the directory name) must follow these rules:
4920
+ - 1-64 characters, lowercase letters, digits, single hyphens
4921
+ - Pattern: \`^[a-z0-9]+(-[a-z0-9]+)*$\`
4922
+ - Cannot start or end with \`-\`, cannot contain consecutive \`--\`
4923
+
4924
+ **Good**: \`pdf-processor\`, \`sql-query\`, \`code-review\`, \`data-analytics\`
4925
+ **Bad**: \`PDF-Processor\`, \`sql__query\`, \`-test\`, \`a\`
4926
+
4927
+ ### Frontmatter Reference
4928
+
4929
+ \`\`\`yaml
4930
+ ---
4931
+ name: my-skill-name # Required \u2014 kebab-case identifier
4932
+ description: ... # Required \u2014 what AND when (this drives triggering)
4933
+ license: MIT # Optional
4934
+ compatibility: node # Optional \u2014 runtime/context requirement
4935
+ metadata: # Optional \u2014 key-value tags for search/filter
4936
+ category: tools
4937
+ version: "1.0"
4938
+ subSkills: # Optional \u2014 coordinated sub-skill names
4939
+ - sub-skill-1
4940
+ ---
4941
+
4942
+ # Markdown Body
4943
+
4944
+ Instructional content for the agent.
4945
+ \`\`\`
4946
+
4947
+ ---
4948
+
4949
+ ## Writing Guide
4950
+
4951
+ ### The Description Field
4952
+
4953
+ This is the most critical part. The description is the primary mechanism that determines whether an agent invokes your skill. Combine WHAT the skill does with specific contexts for WHEN to trigger.
4954
+
4955
+ Agents tend to **undertrigger** \u2014 to not use skills when they'd be useful. To combat this, make descriptions a little "pushy":
4956
+
4957
+ - Weak: "Helps with PDF files"
4958
+ - Better: "Extract text, tables, and metadata from PDF files. Use when users need to read, parse, or extract data from PDF documents."
4959
+ - Good: "Extract text, tables, and metadata from PDF files. Make sure to use this skill whenever the user mentions PDFs, extracting document data, or needs to read any kind of document file \u2014 even if they don't explicitly ask for 'PDF processing.'"
4960
+
4961
+ Include domain-specific trigger words: file extensions, tool names, common user phrases.
4962
+
4963
+ ### Writing the Body
4964
+
4965
+ Prefer **imperative form**. Write what the agent should DO, not what the skill IS:
4966
+ - "Check the database connection and verify table schemas" \u2014 good
4967
+ - "The database connection is checked and table schemas are verified" \u2014 weak
4968
+
4969
+ **Explain WHY**, not just what. Use theory of mind \u2014 help the model understand the reasoning behind instructions so it can generalize to novel situations. If you find yourself writing ALWAYS or NEVER in all caps, that's a yellow flag \u2014 reframe and explain the reasoning.
4970
+
4971
+ **Use examples** to ground abstract instructions:
4972
+
4973
+ \`\`\`markdown
4974
+ ## Commit message format
4975
+ **Example 1:**
4976
+ Input: Added user authentication with JWT tokens
4977
+ Output: feat(auth): implement JWT-based authentication
4978
+ \`\`\`
4979
+
4980
+ **Define output formats** explicitly when structure matters:
4981
+
4982
+ \`\`\`markdown
4983
+ ## Report structure
4984
+ ALWAYS use this exact template:
4985
+ # [Title]
4986
+ ## Executive summary
4987
+ ## Key findings
4988
+ ## Recommendations
4989
+ \`\`\`
4990
+
4991
+ ### Body Structure Checklist
4992
+
4993
+ A well-written skill body typically includes:
4994
+ - **Role definition**: What role does the agent play when executing this skill?
4995
+ - **Workflow**: Step-by-step process in a clear sequence
4996
+ - **Guidelines**: Rules, constraints, quality standards, and the WHY behind them
4997
+ - **Scenarios**: 2-3 common scenarios with concrete examples of inputs and expected outputs
4998
+ - **Edge cases**: What to do when things go wrong, when data is missing, etc.
4999
+
5000
+ ---
5001
+
5002
+ ## Step 4: Test and Iterate
5003
+
5004
+ After writing the draft, test it:
5005
+
5006
+ 1. **Create 2-3 test prompts** \u2014 the kind of thing a real user would actually say. Share them with the user: "Here are a few test cases I'd like to try. Do these look right?"
5007
+ 2. **Run the skill** against each test prompt to see what the agent produces
5008
+ 3. **Review outputs with the user**: evaluate both qualitatively (does the output look right?) and quantitatively (did it follow the workflow? use the right tools?)
5009
+ 4. **Collect feedback**: What worked? What didn't? What surprised the user?
5010
+
5011
+ ### Improving the Skill
5012
+
5013
+ When iterating based on feedback:
5014
+
5015
+ 1. **Generalize from feedback** \u2014 don't overfit to the test cases. The skill will be used across many different prompts. If a fix only helps one specific example, think bigger.
5016
+ 2. **Keep it lean** \u2014 remove instructions that aren't pulling their weight. Read the full transcripts, not just final outputs. If the skill makes the agent waste time, trim it.
5017
+ 3. **Look for repeated work** \u2014 if all test runs involved writing the same helper script, bundle that script into \`resources/scripts/\` and have the skill reference it instead.
5018
+ 4. **Explain the why** \u2014 if you're adding a constraint because of a failure, explain the context so the model understands when to apply it and when it's safe to deviate.
5019
+
5020
+ Repeat the test \u2192 review \u2192 improve loop until the user is satisfied.
5021
+
5022
+ ---
5023
+
5024
+ ## Step 5: Optimize the Description (Optional)
5025
+
5026
+ After the skill works well, offer to optimize the description for better triggering accuracy.
5027
+
5028
+ ### How Triggering Works
5029
+
5030
+ The agent sees skills as a list of name + description pairs. It decides whether to consult a skill based on that description. Important: agents only consult skills for tasks they can't easily handle on their own. Simple one-step queries may not trigger a skill even if the description matches \u2014 so make sure the description emphasizes the COMPLEX or SPECIALIZED nature of the task.
5031
+
5032
+ ### Optimization Approach
5033
+
5034
+ 1. Create 10-15 eval queries \u2014 a mix of should-trigger and should-not-trigger prompts
5035
+ 2. For **should-trigger** (6-8): different phrasings of the same intent \u2014 formal, casual, indirect. Include cases where the user doesn't explicitly name the skill but clearly needs it
5036
+ 3. For **should-not-trigger** (6-8): focus on near-misses \u2014 queries that share keywords but need something different. Don't make them obviously irrelevant
5037
+ 4. Test the description against these queries and adjust based on misfires
5038
+ 5. Show the user before/after and explain what changed
5039
+
5040
+ ---
5041
+
5042
+ ## Step 6: Package and Present
5043
+
5044
+ When the skill is ready:
5045
+ 1. Verify the SKILL.md is at \`/root/.agents/skills/{skill-name}/SKILL.md\` with correct frontmatter
5046
+ 2. Confirm all resource files are in place under \`resources/\`
5047
+ 3. Tell the user the skill is ready and available at its path
5048
+ 4. Remind them that the skill will now appear in the available skills list for any agent using the skill system
5049
+
5050
+ ## Updating Existing Skills
5051
+
5052
+ When the user wants to improve an existing skill:
5053
+ 1. Read the current SKILL.md from \`/root/.agents/skills/{skill-name}/SKILL.md\`
5054
+ 2. Understand what it currently does and where it falls short
5055
+ 3. Follow the same interview \u2192 draft \u2192 test \u2192 iterate loop
5056
+ 4. **Preserve the original name** \u2014 the directory name and \`name\` frontmatter field should stay the same
5057
+ 5. Write the updated version back to the same path
5058
+
5059
+ ---
5060
+
5061
+ ## Example Walkthrough
5062
+
5063
+ **User**: "I want a skill that helps me analyze CSV data"
5064
+
5065
+ **You** (interview):
5066
+ - "What kinds of analysis \u2014 summary stats, filtering, charting?"
5067
+ - "Are the CSVs always the same format or varied?"
5068
+ - "Should it output results as text, new CSV, or visualizations?"
5069
+
5070
+ **User**: "Mostly summary stats and filtering. The files vary but all have headers."
5071
+
5072
+ **You** (draft frontmatter):
5073
+ \`\`\`yaml
5074
+ ---
5075
+ name: csv-analyzer
5076
+ description: Analyze CSV data with statistical summaries, filtering, and aggregation. Use whenever users want to explore, summarize, or extract insights from CSV files \u2014 even if they don't say "analyze" explicitly.
5077
+ metadata:
5078
+ category: data
5079
+ version: "1.0"
5080
+ ---
5081
+ \`\`\`
5082
+
5083
+ **You** (draft body): Write a workflow that teaches the agent to:
5084
+ 1. Inspect the CSV structure and headers
5085
+ 2. Let the user choose analysis type (summary, filter, aggregate)
5086
+ 3. Execute the analysis and present results clearly
5087
+ 4. Handle edge cases: missing headers, empty files, mixed types
5088
+
5089
+ **You** (write): Create \`/root/.agents/skills/csv-analyzer/SKILL.md\`
5090
+
5091
+ **You** (test): "Here are 3 test cases \u2014 'summarize this sales CSV', 'filter rows where region is West', 'show monthly revenue trends'. Let me run these and we'll review."
5092
+
5093
+ Then iterate based on what the user says.
5094
+ `
5095
+ };
5096
+ function getBuiltInSkillMeta(name) {
5097
+ const content = BUILTIN_SKILLS[name];
5098
+ if (!content) return null;
5099
+ try {
5100
+ const { meta } = parseSkillFrontmatter(content);
5101
+ return meta;
5102
+ } catch {
5103
+ return null;
5104
+ }
5105
+ }
5106
+ function getBuiltInSkillContent(name) {
5107
+ return BUILTIN_SKILLS[name];
5108
+ }
5109
+ function getAllBuiltInSkillMetas() {
5110
+ return Object.keys(BUILTIN_SKILLS).map((name) => getBuiltInSkillMeta(name)).filter((meta) => meta !== null);
5111
+ }
5112
+ function getBuiltInSkillNames() {
5113
+ return Object.keys(BUILTIN_SKILLS);
5114
+ }
5115
+ function isBuiltInSkill(name) {
5116
+ return name in BUILTIN_SKILLS;
5117
+ }
5118
+
5119
+ // src/tool_lattice/skill/load_skill_content.ts
4840
5120
  var LOAD_SKILL_CONTENT_DESCRIPTION = `
4841
5121
  Execute a skill within the main conversation
4842
5122
 
@@ -4877,6 +5157,11 @@ var createLoadSkillContentTool = () => {
4877
5157
  return tool39(
4878
5158
  async (input, _exe_config) => {
4879
5159
  try {
5160
+ const builtInContent = getBuiltInSkillContent(input.skill_name);
5161
+ if (builtInContent) {
5162
+ const { meta: meta2, body: body2 } = parseSkillFrontmatter(builtInContent);
5163
+ return buildSkillFile(meta2, body2);
5164
+ }
4880
5165
  const sandbox = await getSandboxFromExeConfig(_exe_config);
4881
5166
  const filePath = `/root/.agents/skills/${input.skill_name}/SKILL.md`;
4882
5167
  let content;
@@ -4934,6 +5219,7 @@ function createSkillMiddleware(params = {}) {
4934
5219
  createLoadSkillContentTool()
4935
5220
  ],
4936
5221
  beforeAgent: async (state, runtime) => {
5222
+ let resolvedSkills = [];
4937
5223
  try {
4938
5224
  const runConfig = runtime?.context?.runConfig || {};
4939
5225
  const manager = getSandBoxManager();
@@ -4963,13 +5249,24 @@ function createSkillMiddleware(params = {}) {
4963
5249
  }
4964
5250
  }
4965
5251
  if (readAll) {
4966
- latestSkills = allSkills;
5252
+ resolvedSkills = allSkills;
4967
5253
  } else if (skills && skills.length > 0) {
4968
- latestSkills = allSkills.filter((skill) => skills.includes(skill.id));
5254
+ resolvedSkills = allSkills.filter((skill) => skills.includes(skill.id));
5255
+ } else {
5256
+ resolvedSkills = allSkills;
4969
5257
  }
4970
5258
  } catch (error) {
4971
5259
  console.error("Error fetching skills:", error);
4972
5260
  }
5261
+ const builtinMetas = getAllBuiltInSkillMetas();
5262
+ for (const meta of builtinMetas) {
5263
+ resolvedSkills.push({
5264
+ id: meta.name,
5265
+ name: meta.name,
5266
+ description: meta.description
5267
+ });
5268
+ }
5269
+ latestSkills = resolvedSkills;
4973
5270
  },
4974
5271
  wrapModelCall: (request, handler) => {
4975
5272
  const skillsPrompt = latestSkills.filter((skill) => !!skill.name).map((skill) => `## ${skill.name}
@@ -10533,6 +10830,125 @@ var InMemoryThreadMessageQueueStore = class {
10533
10830
  }
10534
10831
  };
10535
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
+
10536
10952
  // src/store_lattice/StoreLatticeManager.ts
10537
10953
  var StoreLatticeManager = class _StoreLatticeManager extends BaseLatticeManager {
10538
10954
  /**
@@ -10689,6 +11105,12 @@ storeLatticeManager.registerLattice(
10689
11105
  "threadMessageQueue",
10690
11106
  defaultThreadMessageQueueStore
10691
11107
  );
11108
+ var defaultWorkflowTrackingStore = new InMemoryWorkflowTrackingStore();
11109
+ storeLatticeManager.registerLattice(
11110
+ "default",
11111
+ "workflowTracking",
11112
+ defaultWorkflowTrackingStore
11113
+ );
10692
11114
 
10693
11115
  // src/services/Agent.ts
10694
11116
  import { Command as Command2 } from "@langchain/langgraph";
@@ -11031,6 +11453,7 @@ var Agent = class {
11031
11453
  this.abortController = null;
11032
11454
  this.queueMode = this.getDefaultQueueConfig();
11033
11455
  this.isWaitingForQueueEnd = false;
11456
+ this.asyncTasks = [];
11034
11457
  this.agentExecutor = async ({ input, command, custom_run_config }, signal) => {
11035
11458
  const { runnable_agent, runConfig } = await this.getLatticeClientAndRuntimeConfig(custom_run_config);
11036
11459
  const { messages, ...rest } = input;
@@ -11809,6 +12232,23 @@ var Agent = class {
11809
12232
  console.log(namespacedEvent);
11810
12233
  event_bus_default.publish(namespacedEvent, data);
11811
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
+ }
11812
12252
  };
11813
12253
 
11814
12254
  // src/services/AgentInstanceManager.ts
@@ -12434,9 +12874,9 @@ var ReActAgentGraphBuilder = class {
12434
12874
  */
12435
12875
  async build(agentLattice, params) {
12436
12876
  const tools = params.tools.map((t) => {
12437
- const tool50 = getToolClient(t.key);
12438
- return tool50;
12439
- }).filter((tool50) => tool50 !== void 0);
12877
+ const tool51 = getToolClient(t.key);
12878
+ return tool51;
12879
+ }).filter((tool51) => tool51 !== void 0);
12440
12880
  const stateSchema2 = createReactAgentSchema(params.stateSchema);
12441
12881
  const middlewareConfigs = params.middleware || [];
12442
12882
  const filesystemBackend = createFilesystemBackendFactory(middlewareConfigs);
@@ -12860,6 +13300,25 @@ function getSubagents(options) {
12860
13300
  }
12861
13301
  return { agents, descriptions: subagentDescriptions };
12862
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
+ }
12863
13322
  function createTaskTool(options) {
12864
13323
  const {
12865
13324
  defaultModel,
@@ -12868,7 +13327,8 @@ function createTaskTool(options) {
12868
13327
  defaultInterruptOn,
12869
13328
  subagents,
12870
13329
  generalPurposeAgent,
12871
- taskDescription
13330
+ taskDescription,
13331
+ allowAsync
12872
13332
  } = options;
12873
13333
  const { agents: subagentGraphs, descriptions: subagentDescriptions } = getSubagents({
12874
13334
  defaultModel,
@@ -12881,7 +13341,7 @@ function createTaskTool(options) {
12881
13341
  const finalTaskDescription = taskDescription ? taskDescription : getTaskToolDescription(subagentDescriptions);
12882
13342
  return tool46(
12883
13343
  async (input, config) => {
12884
- const { description, subagent_type } = input;
13344
+ const { description, subagent_type, async } = input;
12885
13345
  let assistant_id = subagent_type;
12886
13346
  if (subagent_type === "general-purpose") {
12887
13347
  assistant_id = config.configurable?.runConfig?.assistant_id + "-general-purpose";
@@ -12911,6 +13371,57 @@ function createTaskTool(options) {
12911
13371
  const subagentState = filterStateForSubagent(currentState);
12912
13372
  subagentState.messages = [new HumanMessage2({ content: description })];
12913
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
+ }
12914
13425
  const workerResult = await agentWorkerGraph.invoke({
12915
13426
  assistant_id,
12916
13427
  thread_id: subagent_thread_id,
@@ -12952,7 +13463,186 @@ function createTaskTool(options) {
12952
13463
  `Name of the agent to use. Available: ${Object.keys(
12953
13464
  subagentGraphs
12954
13465
  ).join(", ")}`
12955
- )
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")
12956
13646
  })
12957
13647
  }
12958
13648
  );
@@ -12966,7 +13656,8 @@ function createSubAgentMiddleware(options) {
12966
13656
  subagents = [],
12967
13657
  systemPrompt = TASK_SYSTEM_PROMPT,
12968
13658
  generalPurposeAgent = true,
12969
- taskDescription = null
13659
+ taskDescription = null,
13660
+ allowAsync = true
12970
13661
  } = options;
12971
13662
  const taskTool = createTaskTool({
12972
13663
  defaultModel,
@@ -12975,17 +13666,27 @@ function createSubAgentMiddleware(options) {
12975
13666
  defaultInterruptOn,
12976
13667
  subagents,
12977
13668
  generalPurposeAgent,
12978
- taskDescription
13669
+ taskDescription,
13670
+ allowAsync
12979
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;
12980
13681
  return createMiddleware14({
12981
13682
  name: "subAgentMiddleware",
12982
- tools: [taskTool],
13683
+ tools: allTools,
12983
13684
  wrapModelCall: async (request, handler) => {
12984
- if (systemPrompt !== null) {
13685
+ if (effectiveSystemPrompt !== null) {
12985
13686
  const currentPrompt = request.systemPrompt || "";
12986
13687
  const newPrompt = currentPrompt ? `${currentPrompt}
12987
13688
 
12988
- ${systemPrompt}` : systemPrompt;
13689
+ ${effectiveSystemPrompt}` : effectiveSystemPrompt;
12989
13690
  return handler({
12990
13691
  ...request,
12991
13692
  systemPrompt: newPrompt
@@ -14520,7 +15221,7 @@ var DeepAgentGraphBuilder = class {
14520
15221
  const tools = params.tools.map((t) => {
14521
15222
  const toolClient = getToolClient(t.key);
14522
15223
  return toolClient;
14523
- }).filter((tool50) => tool50 !== void 0);
15224
+ }).filter((tool51) => tool51 !== void 0);
14524
15225
  const subagents = await Promise.all(params.subAgents.map(async (sa) => {
14525
15226
  if (sa.client) {
14526
15227
  return {
@@ -16145,7 +16846,7 @@ var TeamAgentGraphBuilder = class {
16145
16846
  const tools = params.tools.map((t) => {
16146
16847
  const toolClient = getToolClient(t.key);
16147
16848
  return toolClient;
16148
- }).filter((tool50) => tool50 !== void 0);
16849
+ }).filter((tool51) => tool51 !== void 0);
16149
16850
  const teammates = params.subAgents.map((sa) => {
16150
16851
  const baseConfig = sa.config;
16151
16852
  return {
@@ -16182,17 +16883,444 @@ var TeamAgentGraphBuilder = class {
16182
16883
  }
16183
16884
  };
16184
16885
 
16185
- // src/agent_lattice/builders/AgentGraphBuilderFactory.ts
16186
- var AgentGraphBuilderFactory = class _AgentGraphBuilderFactory {
16187
- constructor() {
16188
- this.builders = /* @__PURE__ */ new Map();
16189
- this.registerDefaultBuilders();
16886
+ // src/deep_agent_new/processing_agent.ts
16887
+ import {
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 });
16922
+ }
16923
+ }
16190
16924
  }
16191
- /**
16192
- * 获取单例实例
16193
- */
16194
- static getInstance() {
16195
- if (!_AgentGraphBuilderFactory.instance) {
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
+ }
16956
+ }
16957
+ return {
16958
+ currentAgentId: startingNode,
16959
+ completedEdges: [],
16960
+ runId,
16961
+ stepIdMap: {}
16962
+ };
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
16967
+
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) {
16196
17324
  _AgentGraphBuilderFactory.instance = new _AgentGraphBuilderFactory();
16197
17325
  }
16198
17326
  return _AgentGraphBuilderFactory.instance;
@@ -16204,6 +17332,7 @@ var AgentGraphBuilderFactory = class _AgentGraphBuilderFactory {
16204
17332
  this.builders.set(AgentType.REACT, new ReActAgentGraphBuilder());
16205
17333
  this.builders.set(AgentType.DEEP_AGENT, new DeepAgentGraphBuilder());
16206
17334
  this.builders.set(AgentType.TEAM, new TeamAgentGraphBuilder());
17335
+ this.builders.set(AgentType.PROCESSING, new ProcessingAgentGraphBuilder());
16207
17336
  }
16208
17337
  /**
16209
17338
  * 注册自定义Builder
@@ -16233,7 +17362,8 @@ var AgentGraphBuilderFactory = class _AgentGraphBuilderFactory {
16233
17362
  import {
16234
17363
  getToolsFromConfig as getToolsFromConfig2,
16235
17364
  getSubAgentsFromConfig as getSubAgentsFromConfig2,
16236
- isDeepAgentConfig as isDeepAgentConfig2
17365
+ isDeepAgentConfig as isDeepAgentConfig2,
17366
+ isProcessingAgentConfig as isProcessingAgentConfig2
16237
17367
  } from "@axiom-lattice/protocols";
16238
17368
  var AgentParamsBuilder = class {
16239
17369
  /**
@@ -16252,7 +17382,7 @@ var AgentParamsBuilder = class {
16252
17382
  * @returns Agent build parameters
16253
17383
  */
16254
17384
  async buildParams(agentLattice, options) {
16255
- const skills = isDeepAgentConfig2(agentLattice.config) ? agentLattice.config.skillCategories : void 0;
17385
+ const skills = isDeepAgentConfig2(agentLattice.config) || isProcessingAgentConfig2(agentLattice.config) ? agentLattice.config.skillCategories : void 0;
16256
17386
  const toolKeys = options?.overrideTools || getToolsFromConfig2(agentLattice.config);
16257
17387
  const tools = toolKeys.map((toolKey) => {
16258
17388
  const toolLattice = toolLatticeManager.getToolLattice(toolKey);
@@ -16283,7 +17413,7 @@ var AgentParamsBuilder = class {
16283
17413
  };
16284
17414
  }));
16285
17415
  let internalSubAgents = [];
16286
- if (isDeepAgentConfig2(agentLattice.config)) {
17416
+ if (isDeepAgentConfig2(agentLattice.config) || isProcessingAgentConfig2(agentLattice.config)) {
16287
17417
  internalSubAgents = agentLattice.config.internalSubAgents?.map((i) => ({
16288
17418
  key: i.key,
16289
17419
  config: i
@@ -16468,6 +17598,39 @@ var SandboxSkillStore = class {
16468
17598
  projectId: options.projectId
16469
17599
  };
16470
17600
  }
17601
+ /**
17602
+ * Build a Skill object from a built-in skill definition.
17603
+ */
17604
+ _builtInSkill(name, tenantId) {
17605
+ const content = getBuiltInSkillContent(name);
17606
+ if (!content) return null;
17607
+ const { meta } = parseSkillFrontmatter(content);
17608
+ const now = /* @__PURE__ */ new Date();
17609
+ return {
17610
+ id: meta.name || name,
17611
+ tenantId,
17612
+ name: meta.name || name,
17613
+ description: meta.description || "",
17614
+ license: meta.license,
17615
+ compatibility: meta.compatibility,
17616
+ metadata: meta.metadata || {},
17617
+ content,
17618
+ subSkills: meta.subSkills,
17619
+ createdAt: now,
17620
+ updatedAt: now
17621
+ };
17622
+ }
17623
+ /**
17624
+ * Get all built-in skills as Skill objects for a tenant.
17625
+ */
17626
+ _allBuiltInSkills(tenantId) {
17627
+ const skills = [];
17628
+ for (const name of Object.keys(BUILTIN_SKILLS)) {
17629
+ const skill = this._builtInSkill(name, tenantId);
17630
+ if (skill) skills.push(skill);
17631
+ }
17632
+ return skills;
17633
+ }
16471
17634
  /**
16472
17635
  * Get sandbox manager
16473
17636
  */
@@ -16604,17 +17767,25 @@ ${body}` : `${frontmatter}
16604
17767
  }
16605
17768
  }
16606
17769
  }
17770
+ const builtInSkills = this._allBuiltInSkills(tenantId);
17771
+ for (const bis of builtInSkills) {
17772
+ if (!skills.some((s) => s.id === bis.id)) {
17773
+ skills.push(bis);
17774
+ }
17775
+ }
16607
17776
  console.log(`[SandboxSkillStore] Loaded ${skills.length} skills for tenant ${tenantId}`);
16608
17777
  return skills.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
16609
17778
  } catch (error) {
16610
17779
  console.error(`[SandboxSkillStore] Error listing skills for tenant ${tenantId}:`, error);
16611
- return [];
17780
+ return this._allBuiltInSkills(tenantId);
16612
17781
  }
16613
17782
  }
16614
17783
  /**
16615
17784
  * Get skill by ID
16616
17785
  */
16617
17786
  async getSkillById(tenantId, id, context) {
17787
+ const builtIn = this._builtInSkill(id, tenantId);
17788
+ if (builtIn) return builtIn;
16618
17789
  return this.readSkillFile(tenantId, id, context);
16619
17790
  }
16620
17791
  /**
@@ -16622,6 +17793,11 @@ ${body}` : `${frontmatter}
16622
17793
  */
16623
17794
  async createSkill(tenantId, id, data, context) {
16624
17795
  validateSkillName(data.name);
17796
+ if (isBuiltInSkill(data.name)) {
17797
+ throw new Error(
17798
+ `Skill "${data.name}" is a built-in skill and cannot be overwritten`
17799
+ );
17800
+ }
16625
17801
  if (id !== data.name) {
16626
17802
  throw new Error(
16627
17803
  `Skill id "${id}" must equal name "${data.name}" (name is used for path addressing)`
@@ -16652,6 +17828,11 @@ ${body}` : `${frontmatter}
16652
17828
  * Update an existing skill
16653
17829
  */
16654
17830
  async updateSkill(tenantId, id, updates, context) {
17831
+ if (isBuiltInSkill(id)) {
17832
+ throw new Error(
17833
+ `Skill "${id}" is a built-in skill and cannot be modified`
17834
+ );
17835
+ }
16655
17836
  const skill = await this.readSkillFile(tenantId, id, context);
16656
17837
  if (!skill) {
16657
17838
  return null;
@@ -16694,6 +17875,11 @@ ${body}` : `${frontmatter}
16694
17875
  * Delete a skill by ID
16695
17876
  */
16696
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
+ }
16697
17883
  try {
16698
17884
  const sandbox = await this.getSandbox(tenantId, context);
16699
17885
  const dirPath = this.getSkillDirectoryPath(tenantId, id);
@@ -16713,6 +17899,7 @@ ${body}` : `${frontmatter}
16713
17899
  * Check if skill exists
16714
17900
  */
16715
17901
  async hasSkill(tenantId, id, context) {
17902
+ if (isBuiltInSkill(id)) return true;
16716
17903
  const skill = await this.getSkillById(tenantId, id, context);
16717
17904
  return skill !== null;
16718
17905
  }
@@ -16758,6 +17945,1013 @@ ${body}` : `${frontmatter}
16758
17945
  }
16759
17946
  };
16760
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
+ }
18275
+ }
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"
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}` });
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) => {
18331
+ try {
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
18345
+ });
18346
+ return JSON.stringify({ id: input.id, name: newName });
18347
+ } catch (error) {
18348
+ return JSON.stringify({ error: `Failed to update agent: ${error.message}` });
18349
+ }
18350
+ }
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
+ }
18374
+ }
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
+ }
18396
+ }
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
+ }
18437
+ }
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
18909
+ }
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: {}
18941
+ }
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);
18951
+ }
18952
+ }
18953
+ }
18954
+
16761
18955
  // src/agent_lattice/AgentLatticeManager.ts
16762
18956
  function assistantToConfig(assistant) {
16763
18957
  const graphDef = typeof assistant.graphDefinition === "object" && assistant.graphDefinition !== null ? assistant.graphDefinition : {};
@@ -16943,6 +19137,7 @@ var AgentLatticeManager = class _AgentLatticeManager extends BaseLatticeManager
16943
19137
  * @param tenantId 租户ID
16944
19138
  */
16945
19139
  async initializeStoredAssistantsForTenant(tenantId) {
19140
+ ensureBuiltinAgentsForTenant(tenantId);
16946
19141
  try {
16947
19142
  const storeLattice = getStoreLattice("default", "assistant");
16948
19143
  const assistants = await storeLattice.store.getAllAssistants(tenantId);
@@ -18162,10 +20357,10 @@ var McpLatticeManager = class _McpLatticeManager extends BaseLatticeManager {
18162
20357
  }
18163
20358
  const tools = await this.getAllTools();
18164
20359
  console.log(`[MCP] Registering ${tools.length} tools to Tool Lattice...`);
18165
- for (const tool50 of tools) {
18166
- const toolKey = prefix ? `${prefix}_${tool50.name}` : tool50.name;
18167
- tool50.name = toolKey;
18168
- toolLatticeManager.registerExistingTool(toolKey, tool50);
20360
+ for (const tool51 of tools) {
20361
+ const toolKey = prefix ? `${prefix}_${tool51.name}` : tool51.name;
20362
+ tool51.name = toolKey;
20363
+ toolLatticeManager.registerExistingTool(toolKey, tool51);
18169
20364
  console.log(`[MCP] Registered tool: ${toolKey}`);
18170
20365
  }
18171
20366
  console.log(`[MCP] Successfully registered ${tools.length} tools to Tool Lattice`);
@@ -18463,7 +20658,7 @@ function parseOptionalNumberEnv(name, fallback) {
18463
20658
  }
18464
20659
  function getDefaultMicrosandboxRemoteConfig() {
18465
20660
  return {
18466
- image: process.env.MICROSANDBOX_IMAGE ?? "daytona-cn-shanghai.cr.volces.com/daytona/sandbox:0.0.4",
20661
+ image: process.env.MICROSANDBOX_IMAGE ?? "daytona-cn-shanghai.cr.volces.com/daytona/sandbox:0.0.5",
18467
20662
  //"daytonaio/sandbox:0.6.0",
18468
20663
  cpus: parseOptionalNumberEnv("MICROSANDBOX_CPUS", 1),
18469
20664
  memoryMib: parseOptionalNumberEnv("MICROSANDBOX_MEMORY", 512),
@@ -19328,6 +21523,7 @@ export {
19328
21523
  AgentLatticeManager,
19329
21524
  AgentManager,
19330
21525
  AgentType,
21526
+ BUILTIN_SKILLS,
19331
21527
  ChunkBuffer,
19332
21528
  ChunkBufferLatticeManager,
19333
21529
  CompositeBackend,
@@ -19411,6 +21607,7 @@ export {
19411
21607
  createListMetricsServersTool,
19412
21608
  createListTablesSqlTool,
19413
21609
  createModelSelectorMiddleware,
21610
+ createProcessingAgent,
19414
21611
  createQueryCheckerSqlTool,
19415
21612
  createQueryMetricDefinitionTool,
19416
21613
  createQueryMetricsListTool,
@@ -19438,7 +21635,11 @@ export {
19438
21635
  getAgentClient,
19439
21636
  getAgentConfig,
19440
21637
  getAllAgentConfigs,
21638
+ getAllBuiltInSkillMetas,
19441
21639
  getAllToolDefinitions,
21640
+ getBuiltInSkillContent,
21641
+ getBuiltInSkillMeta,
21642
+ getBuiltInSkillNames,
19442
21643
  getCheckpointSaver,
19443
21644
  getChunkBuffer,
19444
21645
  getEmbeddingsClient,
@@ -19460,6 +21661,7 @@ export {
19460
21661
  grepMatchesFromFiles,
19461
21662
  grepSearchFiles,
19462
21663
  hasChunkBuffer,
21664
+ isBuiltInSkill,
19463
21665
  isUsingDefaultKey,
19464
21666
  isValidCronExpression,
19465
21667
  isValidSandboxName,