@aigne/agent-library 1.23.0 → 1.24.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,47 @@
7
7
  * @aigne/core bumped to 1.22.0
8
8
  * @aigne/openai bumped to 0.3.4
9
9
 
10
+ ## [1.24.0-beta.2](https://github.com/AIGNE-io/aigne-framework/compare/agent-library-v1.24.0-beta.1...agent-library-v1.24.0-beta.2) (2025-12-19)
11
+
12
+
13
+ ### Dependencies
14
+
15
+ * The following workspace dependencies were updated
16
+ * dependencies
17
+ * @aigne/core bumped to 1.72.0-beta.2
18
+ * @aigne/openai bumped to 0.16.16-beta.2
19
+
20
+ ## [1.24.0-beta.1](https://github.com/AIGNE-io/aigne-framework/compare/agent-library-v1.24.0-beta...agent-library-v1.24.0-beta.1) (2025-12-17)
21
+
22
+
23
+ ### Bug Fixes
24
+
25
+ * bump version ([70d217c](https://github.com/AIGNE-io/aigne-framework/commit/70d217c8360dd0dda7f5f17011c4e92ec836e801))
26
+
27
+
28
+ ### Dependencies
29
+
30
+ * The following workspace dependencies were updated
31
+ * dependencies
32
+ * @aigne/core bumped to 1.72.0-beta.1
33
+ * @aigne/openai bumped to 0.16.16-beta.1
34
+ * @aigne/sqlite bumped to 0.4.9-beta
35
+
36
+ ## [1.24.0-beta](https://github.com/AIGNE-io/aigne-framework/compare/agent-library-v1.23.0...agent-library-v1.24.0-beta) (2025-12-17)
37
+
38
+
39
+ ### Features
40
+
41
+ * **agent-library:** add parallel tasks support for orchestrator agent ([#834](https://github.com/AIGNE-io/aigne-framework/issues/834)) ([7314eb1](https://github.com/AIGNE-io/aigne-framework/commit/7314eb1ef5f1eb4bf6f2b8160c61ef627a6aa3cc))
42
+
43
+
44
+ ### Dependencies
45
+
46
+ * The following workspace dependencies were updated
47
+ * dependencies
48
+ * @aigne/core bumped to 1.72.0-beta
49
+ * @aigne/openai bumped to 0.16.16-beta
50
+
10
51
  ## [1.23.0](https://github.com/AIGNE-io/aigne-framework/compare/agent-library-v1.23.0-beta.8...agent-library-v1.23.0) (2025-12-12)
11
52
 
12
53
 
@@ -15,6 +15,7 @@ export interface OrchestratorAgentOptions<I extends Message = Message, O extends
15
15
  * Prevents context overflow during long-running executions
16
16
  */
17
17
  stateManagement?: StateManagementOptions;
18
+ concurrency?: number;
18
19
  }
19
20
  export interface LoadOrchestratorAgentOptions<I extends Message = Message, O extends Message = Message> extends Omit<AIAgentOptions<I, O>, "instructions"> {
20
21
  objective?: string | PromptBuilder | Instructions;
@@ -67,6 +68,7 @@ export declare class OrchestratorAgent<I extends Message = Message, O extends Me
67
68
  private worker;
68
69
  private completer;
69
70
  private stateManagement?;
71
+ private concurrency;
70
72
  /**
71
73
  * Compress execution state to prevent context overflow
72
74
  * Uses reverse accumulation to efficiently find optimal task count
@@ -1,4 +1,37 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  Object.defineProperty(exports, "__esModule", { value: true });
3
36
  exports.OrchestratorAgent = void 0;
4
37
  const core_1 = require("@aigne/core");
@@ -6,6 +39,7 @@ const agent_yaml_js_1 = require("@aigne/core/loader/agent-yaml.js");
6
39
  const index_js_1 = require("@aigne/core/loader/index.js");
7
40
  const schema_js_1 = require("@aigne/core/loader/schema.js");
8
41
  const agent_utils_js_1 = require("@aigne/core/utils/agent-utils.js");
42
+ const fastq = __importStar(require("@aigne/core/utils/queue.js"));
9
43
  const token_estimator_js_1 = require("@aigne/core/utils/token-estimator.js");
10
44
  const type_utils_js_1 = require("@aigne/core/utils/type-utils.js");
11
45
  const zod_1 = require("zod");
@@ -38,6 +72,7 @@ const defaultCompleterOptions = {
38
72
  disabled: true,
39
73
  },
40
74
  };
75
+ const DEFAULT_CONCURRENCY = 5;
41
76
  /**
42
77
  * Orchestrator Agent Class
43
78
  *
@@ -123,12 +158,14 @@ class OrchestratorAgent extends core_1.AIAgent {
123
158
  });
124
159
  // Initialize state management config
125
160
  this.stateManagement = options.stateManagement;
161
+ this.concurrency = options.concurrency ?? DEFAULT_CONCURRENCY;
126
162
  }
127
163
  objective;
128
164
  planner;
129
165
  worker;
130
166
  completer;
131
167
  stateManagement;
168
+ concurrency;
132
169
  /**
133
170
  * Compress execution state to prevent context overflow
134
171
  * Uses reverse accumulation to efficiently find optimal task count
@@ -198,33 +235,31 @@ class OrchestratorAgent extends core_1.AIAgent {
198
235
  executionState: compressedState,
199
236
  ...(0, type_utils_js_1.pick)(input, this.planner.inputKeys),
200
237
  }, { ...options, model, streaming: false });
201
- if (plan.finished || !plan.nextTask) {
238
+ if (plan.finished || !plan.nextTasks?.length) {
202
239
  break;
203
240
  }
204
- const task = plan.nextTask;
205
241
  const createdAt = Date.now();
206
- const taskResult = await this.invokeChildAgent(this.worker, {
207
- objective,
208
- executionState: compressedState,
209
- task,
210
- ...(0, type_utils_js_1.pick)(input, this.worker.inputKeys),
211
- }, { ...options, model, streaming: false })
212
- .then((res) => {
213
- if (res.error || res.success === false) {
214
- return { status: "failed", result: res.result, error: res.error };
215
- }
216
- return { status: "completed", result: res.result };
217
- })
218
- .catch((error) => ({
219
- status: "failed",
220
- error: { message: error instanceof Error ? error.message : String(error) },
221
- }));
222
- executionState.tasks.push({
223
- ...taskResult,
224
- task: task,
225
- createdAt,
226
- completedAt: Date.now(),
227
- });
242
+ const queue = fastq.promise(async ({ task }) => {
243
+ const taskResult = await this.invokeChildAgent(this.worker, {
244
+ objective,
245
+ executionState: compressedState,
246
+ task,
247
+ ...(0, type_utils_js_1.pick)(input, this.worker.inputKeys),
248
+ }, { ...options, model, streaming: false })
249
+ .then((res) => {
250
+ if (res.error || res.success === false) {
251
+ return { status: "failed", result: res.result, error: res.error };
252
+ }
253
+ return { status: "completed", result: res.result };
254
+ })
255
+ .catch((error) => ({
256
+ status: "failed",
257
+ error: { message: error instanceof Error ? error.message : String(error) },
258
+ }));
259
+ return { ...taskResult, task, createdAt, completedAt: Date.now() };
260
+ }, plan.parallelTasks ? this.concurrency : 1);
261
+ const taskResults = await Promise.all(plan.nextTasks.map((task) => queue.push({ task })));
262
+ executionState.tasks.push(...taskResults);
228
263
  }
229
264
  // Compress state for completer input if needed
230
265
  const compressedState = this.compressState(executionState);
@@ -246,5 +281,6 @@ function getOrchestratorAgentSchema({ filepath }) {
246
281
  worker: (0, schema_js_1.optionalize)(nestAgentSchema),
247
282
  completer: (0, schema_js_1.optionalize)(nestAgentSchema),
248
283
  stateManagement: (0, schema_js_1.optionalize)((0, schema_js_1.camelizeSchema)(type_js_1.stateManagementOptionsSchema)),
284
+ concurrency: (0, schema_js_1.optionalize)(zod_1.z.number().int().min(1).default(DEFAULT_CONCURRENCY)),
249
285
  }));
250
286
  }
@@ -1,3 +1,3 @@
1
1
  export declare const ORCHESTRATOR_COMPLETE_PROMPT = "You are an intelligent assistant that synthesizes and presents the results of completed tasks.\n\n{% if $afs.enabled %}\n## Environment\n\n### AFS\n{{ $afs.description }}\n\n```yaml alt=\"The modules available in the AFS\"\n{{ $afs.modules | yaml.stringify }}\n```\n{% endif %}\n\n## User's Objective\n\n```txt alt=\"The user's latest objective you need to address\"\n{{ objective }}\n```\n\n## Current Execution State\n\n```yaml alt=\"The latest execution state\"\n{{ executionState | yaml.stringify }}\n```\n\n## Your Task\nBased on the execution results above, provide a comprehensive and helpful response to the user's objective.\n";
2
- export declare const TODO_PLANNER_PROMPT_TEMPLATE = "Your responsibility is to decide the next task based on the current execution state.\n\n## Responsibilities\n\nYou are the Planner in the Orchestrator. The entire Orchestrator completes tasks through collaboration of three roles:\n\n1. **Planner (you)** analyzes the current state and outputs \"nextTask\"\n2. **Worker** executes the task and updates the execution state\n3. **Loop back to step 1**, Planner plans the next task based on the new state\n4. **Repeat steps 1-3** until Planner determines the task is complete\n5. **Planner** sets \"finished: true\"\n6. **Completer** generates the final report and returns it to the user\n\n{% if $afs.enabled %}\n## Environment\n\n### AFS\n{{ $afs.description }}\n\n```yaml alt=\"The modules available in the AFS\"\n{{ $afs.modules | yaml.stringify }}\n```\n{% endif %}\n\n## User's Objective\n\n```txt alt=\"The user's next objective you need to plan for\"\n{{ objective }}\n```\n\n## Current Execution State\n\n```yaml alt=\"The latest execution state\"\n{{ executionState | yaml.stringify }}\n```\n\n## How to Plan the Next Task\n\n### 1. Determine if Tasks Are Needed\n\nFirst, assess whether the objective requires any tasks at all. Ask yourself:\n\n**Does this objective require tasks?**\n\nConsider if completing the objective needs:\n- **Information gathering**: Does it need to collect or retrieve information?\n- **Analysis or processing**: Does it need to analyze, process, or compute something?\n- **State dependency**: Does it depend on information not yet in the execution state?\n\n**Set \"finished: true\" immediately when:**\n- The objective requires no exploration, analysis, or information gathering\n- The current execution state already contains everything needed to respond\n- The objective is purely conversational without requiring any action\n\n**Plan tasks when:**\n- The objective requires gathering information from external sources\n- The objective requires analysis, processing, or computation to be performed\n- Additional information must be collected before a complete response can be given\n\n### 2. Analyze Information Requirements\n\nIf tasks are needed, think about the current state and objective:\n- What information is needed to complete the objective?\n- Where can this information be obtained from?\n- What information has already been collected? What is still missing?\n- Is deeper exploration needed, or is it ready to generate a summary?\n\n### 3. Decision Principles\n\n- **Plan only one specific task at a time**: Don't try to plan all steps at once\n- **Only decide, don't execute**: You only output task descriptions, actual execution is done by the Worker\n- **Trust the iterative process**: You will be called again after each task completes, allowing you to adjust the plan dynamically\n- **Avoid duplicate work**: Review the execution history to understand what has been completed\n- **Goal-oriented descriptions**: Task descriptions should state \"what to do\", not \"how to do it\"\n- **Handle failures appropriately**: If a previous task failed, decide whether to retry, skip, or use an alternative approach\n\n### 4. Decision Making at Different Stages\n\nFlexibly decide the next step based on current progress:\n\n**Exploration Stage**:\n- Plan exploration tasks to gather required information\n- Gradually collect information, focusing on one aspect at a time\n\n**Summary Stage**:\n- When sufficient information is collected, plan to generate a summary or report task\n\n**Completion Stage**:\n- Set \"finished: true\" when:\n - The objective doesn't require any tasks\n - All necessary tasks are completed\n - The objective is fully achieved\n- This will trigger the Completer to integrate all information and generate the final report\n\n## Understanding Task Status\n\nEach task in the execution state has a status:\n- **completed**: Task finished successfully, result is available\n- **failed**: Task encountered an error, check error field for details\n- **pending**: Task has not been executed yet\n\n## Output Format\n\n```yaml\nnextTask: \"[task description]\" # optional, describe the next task to be performed to achieve the objective, null if no further tasks are needed\nfinished: false # set to true if no further tasks are needed and the objective is achieved\n```\n\nNote: Task descriptions should be **goal-oriented**, not specifying concrete operations. Let the worker autonomously decide how to complete the task based on the task objective.\n";
2
+ export declare const TODO_PLANNER_PROMPT_TEMPLATE = "Your responsibility is to decide the next tasks based on the current execution state.\n\n## Responsibilities\n\nYou are the Planner in the Orchestrator. The entire Orchestrator completes tasks through collaboration of three roles:\n\n1. **Planner (you)** analyzes the current state and outputs \"nextTasks\" (one or more tasks)\n2. **Worker** executes the tasks and updates the execution state\n3. **Loop back to step 1**, Planner plans the next tasks based on the new state\n4. **Repeat steps 1-3** until Planner determines the objective is complete\n5. **Planner** sets \"finished: true\"\n6. **Completer** generates the final report and returns it to the user\n\n{% if $afs.enabled %}\n## Environment\n\n### AFS\n{{ $afs.description }}\n\n```yaml alt=\"The modules available in the AFS\"\n{{ $afs.modules | yaml.stringify }}\n```\n{% endif %}\n\n## User's Objective\n\n```txt alt=\"The user's next objective you need to plan for\"\n{{ objective }}\n```\n\n## Current Execution State\n\n```yaml alt=\"The latest execution state\"\n{{ executionState | yaml.stringify }}\n```\n\n## How to Plan Tasks\n\n### 1. Determine if Tasks Are Needed\n\nFirst, assess whether the objective requires any tasks at all. Ask yourself:\n\n**Does this objective require tasks?**\n\nConsider if completing the objective needs:\n- **Information gathering**: Does it need to collect or retrieve information?\n- **Analysis or processing**: Does it need to analyze, process, or compute something?\n- **State dependency**: Does it depend on information not yet in the execution state?\n\n**Set \"finished: true\" immediately when:**\n- The objective requires no exploration, analysis, or information gathering\n- The current execution state already contains everything needed to respond\n- The objective is purely conversational without requiring any action\n\n**Plan tasks when:**\n- The objective requires gathering information from external sources\n- The objective requires analysis, processing, or computation to be performed\n- Additional information must be collected before a complete response can be given\n\n### 2. Analyze Information Requirements\n\nIf tasks are needed, think about the current state and objective:\n- What information is needed to complete the objective?\n- Where can this information be obtained from?\n- What information has already been collected? What is still missing?\n- Is deeper exploration needed, or is it ready to generate a summary?\n\n### 3. Decision Principles\n\n- **Plan one or more tasks per iteration**: You can output multiple tasks when they are independent\n- **Only decide, don't execute**: You only output task descriptions, actual execution is done by the Worker\n- **Trust the iterative process**: You will be called again after tasks complete, allowing you to adjust the plan dynamically\n- **Avoid duplicate work**: Review the execution history to understand what has been completed\n- **Goal-oriented descriptions**: Task descriptions should state \"what to do\", not \"how to do it\"\n- **Handle failures appropriately**: If a previous task failed, decide whether to retry, skip, or use an alternative approach\n\n### 4. Parallel vs Sequential Execution\n\nYou can specify whether tasks should run in parallel or sequentially using `parallelTasks`.\n\n**IMPORTANT: When tasks run in parallel, they CANNOT see each other's results.** Each parallel task receives the same execution state snapshot from before this batch started.\n\n**Set `parallelTasks: true` ONLY when ALL conditions are met:**\n- Tasks operate on **completely independent** data sources or resources\n- Task results are **not needed by other tasks** in the same batch\n- Tasks have **no ordering requirements** between them\n- You are **100% certain** there are no dependencies\n\n**Set `parallelTasks: false` (default) when ANY of these apply:**\n- Any task needs results from another task in the same batch\n- Tasks must be executed in a specific order\n- Tasks operate on shared resources that could conflict\n- You are **uncertain** whether tasks are truly independent\n\n**When in doubt, use sequential execution.** It's safer to be slower than to produce incorrect results.\n\n### 5. Decision Making at Different Stages\n\nFlexibly decide the next step based on current progress:\n\n**Exploration Stage**:\n- Plan exploration tasks to gather required information\n- If exploring multiple independent sources, consider parallel execution\n\n**Processing Stage**:\n- Process gathered information\n- Use sequential execution when processing depends on previous results\n\n**Summary Stage**:\n- When sufficient information is collected, plan to generate a summary or report task\n\n**Completion Stage**:\n- Set \"finished: true\" when:\n - The objective doesn't require any tasks\n - All necessary tasks are completed\n - The objective is fully achieved\n- This will trigger the Completer to integrate all information and generate the final report\n\n## Understanding Task Status\n\nEach task in the execution state has a status:\n- **completed**: Task finished successfully, result is available\n- **failed**: Task encountered an error, check error field for details\n- **pending**: Task has not been executed yet\n\n## Output Format\n\n```yaml\nnextTasks: # List of tasks to execute (omit if finished)\n - \"task description 1\"\n - \"task description 2\"\nparallelTasks: false # true if tasks can run in parallel, false for sequential (default: false)\nfinished: false # true if objective is achieved and no more tasks needed\n```\n\n**Notes:**\n- Task descriptions should be **goal-oriented**, not specifying concrete operations\n- Let the worker autonomously decide how to complete each task\n- Default to sequential execution (`parallelTasks: false`) unless you're certain tasks are independent\n- When `finished: true`, omit `nextTasks`\n";
3
3
  export declare const TODO_WORKER_PROMPT_TEMPLATE = "You are a task execution agent. Your job is to execute the specific task assigned to you - nothing more, nothing less.\n\n{% if $afs.enabled %}\n## Environment\n\n### AFS\n{{ $afs.description }}\n\n```yaml alt=\"The modules available in the AFS\"\n{{ $afs.modules | yaml.stringify }}\n```\n{% endif %}\n\n## User's Objective\n\n```txt alt=\"The user's objective provide for context only\"\n{{ objective }}\n```\n\n**CRITICAL CONSTRAINT**: The objective above is provided ONLY for context. You must NOT attempt to:\n- Solve the entire objective\n- Plan additional steps beyond your current task\n- Make decisions about what should happen next\n- Execute any tasks other than the one explicitly assigned to you below\n\n## Latest Execution State\n\n```yaml alt=\"The latest execution state for your reference\"\n{{ executionState | yaml.stringify }}\n```\n\n## Your Current Task\n\n```txt alt=\"The specific task you need to execute now\"\n{{ task }}\n```\n\n## Important Instructions\n- Focus EXCLUSIVELY on completing the current task described above\n- The task is self-contained - execute it completely and accurately\n- Do NOT perform additional tasks beyond what is specified\n- Do NOT try to determine what should happen after this task\n- Use the available tools and skills to accomplish this specific task\n- Return a clear result that the planner can use to decide the next step\n\n## Output Format\nReturn your task execution result as a structured response. The output schema will guide you on the required fields.\n";
@@ -31,16 +31,16 @@ ${"```"}
31
31
  Based on the execution results above, provide a comprehensive and helpful response to the user's objective.
32
32
  `;
33
33
  exports.TODO_PLANNER_PROMPT_TEMPLATE = `\
34
- Your responsibility is to decide the next task based on the current execution state.
34
+ Your responsibility is to decide the next tasks based on the current execution state.
35
35
 
36
36
  ## Responsibilities
37
37
 
38
38
  You are the Planner in the Orchestrator. The entire Orchestrator completes tasks through collaboration of three roles:
39
39
 
40
- 1. **Planner (you)** analyzes the current state and outputs "nextTask"
41
- 2. **Worker** executes the task and updates the execution state
42
- 3. **Loop back to step 1**, Planner plans the next task based on the new state
43
- 4. **Repeat steps 1-3** until Planner determines the task is complete
40
+ 1. **Planner (you)** analyzes the current state and outputs "nextTasks" (one or more tasks)
41
+ 2. **Worker** executes the tasks and updates the execution state
42
+ 3. **Loop back to step 1**, Planner plans the next tasks based on the new state
43
+ 4. **Repeat steps 1-3** until Planner determines the objective is complete
44
44
  5. **Planner** sets "finished: true"
45
45
  6. **Completer** generates the final report and returns it to the user
46
46
 
@@ -67,7 +67,7 @@ ${"```"}yaml alt="The latest execution state"
67
67
  {{ executionState | yaml.stringify }}
68
68
  ${"```"}
69
69
 
70
- ## How to Plan the Next Task
70
+ ## How to Plan Tasks
71
71
 
72
72
  ### 1. Determine if Tasks Are Needed
73
73
 
@@ -100,20 +100,44 @@ If tasks are needed, think about the current state and objective:
100
100
 
101
101
  ### 3. Decision Principles
102
102
 
103
- - **Plan only one specific task at a time**: Don't try to plan all steps at once
103
+ - **Plan one or more tasks per iteration**: You can output multiple tasks when they are independent
104
104
  - **Only decide, don't execute**: You only output task descriptions, actual execution is done by the Worker
105
- - **Trust the iterative process**: You will be called again after each task completes, allowing you to adjust the plan dynamically
105
+ - **Trust the iterative process**: You will be called again after tasks complete, allowing you to adjust the plan dynamically
106
106
  - **Avoid duplicate work**: Review the execution history to understand what has been completed
107
107
  - **Goal-oriented descriptions**: Task descriptions should state "what to do", not "how to do it"
108
108
  - **Handle failures appropriately**: If a previous task failed, decide whether to retry, skip, or use an alternative approach
109
109
 
110
- ### 4. Decision Making at Different Stages
110
+ ### 4. Parallel vs Sequential Execution
111
+
112
+ You can specify whether tasks should run in parallel or sequentially using \`parallelTasks\`.
113
+
114
+ **IMPORTANT: When tasks run in parallel, they CANNOT see each other's results.** Each parallel task receives the same execution state snapshot from before this batch started.
115
+
116
+ **Set \`parallelTasks: true\` ONLY when ALL conditions are met:**
117
+ - Tasks operate on **completely independent** data sources or resources
118
+ - Task results are **not needed by other tasks** in the same batch
119
+ - Tasks have **no ordering requirements** between them
120
+ - You are **100% certain** there are no dependencies
121
+
122
+ **Set \`parallelTasks: false\` (default) when ANY of these apply:**
123
+ - Any task needs results from another task in the same batch
124
+ - Tasks must be executed in a specific order
125
+ - Tasks operate on shared resources that could conflict
126
+ - You are **uncertain** whether tasks are truly independent
127
+
128
+ **When in doubt, use sequential execution.** It's safer to be slower than to produce incorrect results.
129
+
130
+ ### 5. Decision Making at Different Stages
111
131
 
112
132
  Flexibly decide the next step based on current progress:
113
133
 
114
134
  **Exploration Stage**:
115
135
  - Plan exploration tasks to gather required information
116
- - Gradually collect information, focusing on one aspect at a time
136
+ - If exploring multiple independent sources, consider parallel execution
137
+
138
+ **Processing Stage**:
139
+ - Process gathered information
140
+ - Use sequential execution when processing depends on previous results
117
141
 
118
142
  **Summary Stage**:
119
143
  - When sufficient information is collected, plan to generate a summary or report task
@@ -135,11 +159,18 @@ Each task in the execution state has a status:
135
159
  ## Output Format
136
160
 
137
161
  ${"```"}yaml
138
- nextTask: "[task description]" # optional, describe the next task to be performed to achieve the objective, null if no further tasks are needed
139
- finished: false # set to true if no further tasks are needed and the objective is achieved
162
+ nextTasks: # List of tasks to execute (omit if finished)
163
+ - "task description 1"
164
+ - "task description 2"
165
+ parallelTasks: false # true if tasks can run in parallel, false for sequential (default: false)
166
+ finished: false # true if objective is achieved and no more tasks needed
140
167
  ${"```"}
141
168
 
142
- Note: Task descriptions should be **goal-oriented**, not specifying concrete operations. Let the worker autonomously decide how to complete the task based on the task objective.
169
+ **Notes:**
170
+ - Task descriptions should be **goal-oriented**, not specifying concrete operations
171
+ - Let the worker autonomously decide how to complete each task
172
+ - Default to sequential execution (\`parallelTasks: false\`) unless you're certain tasks are independent
173
+ - When \`finished: true\`, omit \`nextTasks\`
143
174
  `;
144
175
  exports.TODO_WORKER_PROMPT_TEMPLATE = `\
145
176
  You are a task execution agent. Your job is to execute the specific task assigned to you - nothing more, nothing less.
@@ -176,17 +176,21 @@ export declare const plannerInputSchema: z.ZodObject<{
176
176
  } | undefined;
177
177
  }>;
178
178
  export interface PlannerOutput extends Message {
179
- nextTask?: string;
179
+ nextTasks?: string[];
180
+ parallelTasks?: boolean;
180
181
  finished?: boolean;
181
182
  }
182
183
  export declare const plannerOutputSchema: z.ZodObject<{
183
- nextTask: z.ZodOptional<z.ZodString>;
184
+ nextTasks: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
185
+ parallelTasks: z.ZodOptional<z.ZodBoolean>;
184
186
  finished: z.ZodOptional<z.ZodBoolean>;
185
187
  }, "strip", z.ZodTypeAny, {
186
- nextTask?: string | undefined;
188
+ nextTasks?: string[] | undefined;
189
+ parallelTasks?: boolean | undefined;
187
190
  finished?: boolean | undefined;
188
191
  }, {
189
- nextTask?: string | undefined;
192
+ nextTasks?: string[] | undefined;
193
+ parallelTasks?: boolean | undefined;
190
194
  finished?: boolean | undefined;
191
195
  }>;
192
196
  export interface WorkerInput extends Message {
@@ -31,14 +31,23 @@ exports.plannerInputSchema = zod_1.default.object({
31
31
  executionState: (0, schema_js_1.optionalize)(exports.executionStateSchema),
32
32
  });
33
33
  exports.plannerOutputSchema = zod_1.default.object({
34
- nextTask: zod_1.default
35
- .string()
34
+ nextTasks: zod_1.default
35
+ .array(zod_1.default.string())
36
36
  .optional()
37
37
  .describe(`\
38
- The next task to be executed by the worker.
39
- Provide a clear, actionable task description that specifies what needs to be done.
38
+ The next tasks to be executed by the worker.
39
+ Provide clear, actionable task descriptions that specify what needs to be done.
40
40
  Include relevant context from previous task results if needed for execution.
41
41
  Omit this field when all necessary work has been completed.
42
+ `),
43
+ parallelTasks: zod_1.default
44
+ .boolean()
45
+ .optional()
46
+ .describe(`\
47
+ Indicates whether the next tasks can be executed in parallel.
48
+ Set to true if tasks are independent and can run simultaneously.
49
+ Set to false if tasks must be executed sequentially.
50
+ default is false.
42
51
  `),
43
52
  finished: zod_1.default
44
53
  .boolean()
@@ -15,6 +15,7 @@ export interface OrchestratorAgentOptions<I extends Message = Message, O extends
15
15
  * Prevents context overflow during long-running executions
16
16
  */
17
17
  stateManagement?: StateManagementOptions;
18
+ concurrency?: number;
18
19
  }
19
20
  export interface LoadOrchestratorAgentOptions<I extends Message = Message, O extends Message = Message> extends Omit<AIAgentOptions<I, O>, "instructions"> {
20
21
  objective?: string | PromptBuilder | Instructions;
@@ -67,6 +68,7 @@ export declare class OrchestratorAgent<I extends Message = Message, O extends Me
67
68
  private worker;
68
69
  private completer;
69
70
  private stateManagement?;
71
+ private concurrency;
70
72
  /**
71
73
  * Compress execution state to prevent context overflow
72
74
  * Uses reverse accumulation to efficiently find optimal task count
@@ -1,3 +1,3 @@
1
1
  export declare const ORCHESTRATOR_COMPLETE_PROMPT = "You are an intelligent assistant that synthesizes and presents the results of completed tasks.\n\n{% if $afs.enabled %}\n## Environment\n\n### AFS\n{{ $afs.description }}\n\n```yaml alt=\"The modules available in the AFS\"\n{{ $afs.modules | yaml.stringify }}\n```\n{% endif %}\n\n## User's Objective\n\n```txt alt=\"The user's latest objective you need to address\"\n{{ objective }}\n```\n\n## Current Execution State\n\n```yaml alt=\"The latest execution state\"\n{{ executionState | yaml.stringify }}\n```\n\n## Your Task\nBased on the execution results above, provide a comprehensive and helpful response to the user's objective.\n";
2
- export declare const TODO_PLANNER_PROMPT_TEMPLATE = "Your responsibility is to decide the next task based on the current execution state.\n\n## Responsibilities\n\nYou are the Planner in the Orchestrator. The entire Orchestrator completes tasks through collaboration of three roles:\n\n1. **Planner (you)** analyzes the current state and outputs \"nextTask\"\n2. **Worker** executes the task and updates the execution state\n3. **Loop back to step 1**, Planner plans the next task based on the new state\n4. **Repeat steps 1-3** until Planner determines the task is complete\n5. **Planner** sets \"finished: true\"\n6. **Completer** generates the final report and returns it to the user\n\n{% if $afs.enabled %}\n## Environment\n\n### AFS\n{{ $afs.description }}\n\n```yaml alt=\"The modules available in the AFS\"\n{{ $afs.modules | yaml.stringify }}\n```\n{% endif %}\n\n## User's Objective\n\n```txt alt=\"The user's next objective you need to plan for\"\n{{ objective }}\n```\n\n## Current Execution State\n\n```yaml alt=\"The latest execution state\"\n{{ executionState | yaml.stringify }}\n```\n\n## How to Plan the Next Task\n\n### 1. Determine if Tasks Are Needed\n\nFirst, assess whether the objective requires any tasks at all. Ask yourself:\n\n**Does this objective require tasks?**\n\nConsider if completing the objective needs:\n- **Information gathering**: Does it need to collect or retrieve information?\n- **Analysis or processing**: Does it need to analyze, process, or compute something?\n- **State dependency**: Does it depend on information not yet in the execution state?\n\n**Set \"finished: true\" immediately when:**\n- The objective requires no exploration, analysis, or information gathering\n- The current execution state already contains everything needed to respond\n- The objective is purely conversational without requiring any action\n\n**Plan tasks when:**\n- The objective requires gathering information from external sources\n- The objective requires analysis, processing, or computation to be performed\n- Additional information must be collected before a complete response can be given\n\n### 2. Analyze Information Requirements\n\nIf tasks are needed, think about the current state and objective:\n- What information is needed to complete the objective?\n- Where can this information be obtained from?\n- What information has already been collected? What is still missing?\n- Is deeper exploration needed, or is it ready to generate a summary?\n\n### 3. Decision Principles\n\n- **Plan only one specific task at a time**: Don't try to plan all steps at once\n- **Only decide, don't execute**: You only output task descriptions, actual execution is done by the Worker\n- **Trust the iterative process**: You will be called again after each task completes, allowing you to adjust the plan dynamically\n- **Avoid duplicate work**: Review the execution history to understand what has been completed\n- **Goal-oriented descriptions**: Task descriptions should state \"what to do\", not \"how to do it\"\n- **Handle failures appropriately**: If a previous task failed, decide whether to retry, skip, or use an alternative approach\n\n### 4. Decision Making at Different Stages\n\nFlexibly decide the next step based on current progress:\n\n**Exploration Stage**:\n- Plan exploration tasks to gather required information\n- Gradually collect information, focusing on one aspect at a time\n\n**Summary Stage**:\n- When sufficient information is collected, plan to generate a summary or report task\n\n**Completion Stage**:\n- Set \"finished: true\" when:\n - The objective doesn't require any tasks\n - All necessary tasks are completed\n - The objective is fully achieved\n- This will trigger the Completer to integrate all information and generate the final report\n\n## Understanding Task Status\n\nEach task in the execution state has a status:\n- **completed**: Task finished successfully, result is available\n- **failed**: Task encountered an error, check error field for details\n- **pending**: Task has not been executed yet\n\n## Output Format\n\n```yaml\nnextTask: \"[task description]\" # optional, describe the next task to be performed to achieve the objective, null if no further tasks are needed\nfinished: false # set to true if no further tasks are needed and the objective is achieved\n```\n\nNote: Task descriptions should be **goal-oriented**, not specifying concrete operations. Let the worker autonomously decide how to complete the task based on the task objective.\n";
2
+ export declare const TODO_PLANNER_PROMPT_TEMPLATE = "Your responsibility is to decide the next tasks based on the current execution state.\n\n## Responsibilities\n\nYou are the Planner in the Orchestrator. The entire Orchestrator completes tasks through collaboration of three roles:\n\n1. **Planner (you)** analyzes the current state and outputs \"nextTasks\" (one or more tasks)\n2. **Worker** executes the tasks and updates the execution state\n3. **Loop back to step 1**, Planner plans the next tasks based on the new state\n4. **Repeat steps 1-3** until Planner determines the objective is complete\n5. **Planner** sets \"finished: true\"\n6. **Completer** generates the final report and returns it to the user\n\n{% if $afs.enabled %}\n## Environment\n\n### AFS\n{{ $afs.description }}\n\n```yaml alt=\"The modules available in the AFS\"\n{{ $afs.modules | yaml.stringify }}\n```\n{% endif %}\n\n## User's Objective\n\n```txt alt=\"The user's next objective you need to plan for\"\n{{ objective }}\n```\n\n## Current Execution State\n\n```yaml alt=\"The latest execution state\"\n{{ executionState | yaml.stringify }}\n```\n\n## How to Plan Tasks\n\n### 1. Determine if Tasks Are Needed\n\nFirst, assess whether the objective requires any tasks at all. Ask yourself:\n\n**Does this objective require tasks?**\n\nConsider if completing the objective needs:\n- **Information gathering**: Does it need to collect or retrieve information?\n- **Analysis or processing**: Does it need to analyze, process, or compute something?\n- **State dependency**: Does it depend on information not yet in the execution state?\n\n**Set \"finished: true\" immediately when:**\n- The objective requires no exploration, analysis, or information gathering\n- The current execution state already contains everything needed to respond\n- The objective is purely conversational without requiring any action\n\n**Plan tasks when:**\n- The objective requires gathering information from external sources\n- The objective requires analysis, processing, or computation to be performed\n- Additional information must be collected before a complete response can be given\n\n### 2. Analyze Information Requirements\n\nIf tasks are needed, think about the current state and objective:\n- What information is needed to complete the objective?\n- Where can this information be obtained from?\n- What information has already been collected? What is still missing?\n- Is deeper exploration needed, or is it ready to generate a summary?\n\n### 3. Decision Principles\n\n- **Plan one or more tasks per iteration**: You can output multiple tasks when they are independent\n- **Only decide, don't execute**: You only output task descriptions, actual execution is done by the Worker\n- **Trust the iterative process**: You will be called again after tasks complete, allowing you to adjust the plan dynamically\n- **Avoid duplicate work**: Review the execution history to understand what has been completed\n- **Goal-oriented descriptions**: Task descriptions should state \"what to do\", not \"how to do it\"\n- **Handle failures appropriately**: If a previous task failed, decide whether to retry, skip, or use an alternative approach\n\n### 4. Parallel vs Sequential Execution\n\nYou can specify whether tasks should run in parallel or sequentially using `parallelTasks`.\n\n**IMPORTANT: When tasks run in parallel, they CANNOT see each other's results.** Each parallel task receives the same execution state snapshot from before this batch started.\n\n**Set `parallelTasks: true` ONLY when ALL conditions are met:**\n- Tasks operate on **completely independent** data sources or resources\n- Task results are **not needed by other tasks** in the same batch\n- Tasks have **no ordering requirements** between them\n- You are **100% certain** there are no dependencies\n\n**Set `parallelTasks: false` (default) when ANY of these apply:**\n- Any task needs results from another task in the same batch\n- Tasks must be executed in a specific order\n- Tasks operate on shared resources that could conflict\n- You are **uncertain** whether tasks are truly independent\n\n**When in doubt, use sequential execution.** It's safer to be slower than to produce incorrect results.\n\n### 5. Decision Making at Different Stages\n\nFlexibly decide the next step based on current progress:\n\n**Exploration Stage**:\n- Plan exploration tasks to gather required information\n- If exploring multiple independent sources, consider parallel execution\n\n**Processing Stage**:\n- Process gathered information\n- Use sequential execution when processing depends on previous results\n\n**Summary Stage**:\n- When sufficient information is collected, plan to generate a summary or report task\n\n**Completion Stage**:\n- Set \"finished: true\" when:\n - The objective doesn't require any tasks\n - All necessary tasks are completed\n - The objective is fully achieved\n- This will trigger the Completer to integrate all information and generate the final report\n\n## Understanding Task Status\n\nEach task in the execution state has a status:\n- **completed**: Task finished successfully, result is available\n- **failed**: Task encountered an error, check error field for details\n- **pending**: Task has not been executed yet\n\n## Output Format\n\n```yaml\nnextTasks: # List of tasks to execute (omit if finished)\n - \"task description 1\"\n - \"task description 2\"\nparallelTasks: false # true if tasks can run in parallel, false for sequential (default: false)\nfinished: false # true if objective is achieved and no more tasks needed\n```\n\n**Notes:**\n- Task descriptions should be **goal-oriented**, not specifying concrete operations\n- Let the worker autonomously decide how to complete each task\n- Default to sequential execution (`parallelTasks: false`) unless you're certain tasks are independent\n- When `finished: true`, omit `nextTasks`\n";
3
3
  export declare const TODO_WORKER_PROMPT_TEMPLATE = "You are a task execution agent. Your job is to execute the specific task assigned to you - nothing more, nothing less.\n\n{% if $afs.enabled %}\n## Environment\n\n### AFS\n{{ $afs.description }}\n\n```yaml alt=\"The modules available in the AFS\"\n{{ $afs.modules | yaml.stringify }}\n```\n{% endif %}\n\n## User's Objective\n\n```txt alt=\"The user's objective provide for context only\"\n{{ objective }}\n```\n\n**CRITICAL CONSTRAINT**: The objective above is provided ONLY for context. You must NOT attempt to:\n- Solve the entire objective\n- Plan additional steps beyond your current task\n- Make decisions about what should happen next\n- Execute any tasks other than the one explicitly assigned to you below\n\n## Latest Execution State\n\n```yaml alt=\"The latest execution state for your reference\"\n{{ executionState | yaml.stringify }}\n```\n\n## Your Current Task\n\n```txt alt=\"The specific task you need to execute now\"\n{{ task }}\n```\n\n## Important Instructions\n- Focus EXCLUSIVELY on completing the current task described above\n- The task is self-contained - execute it completely and accurately\n- Do NOT perform additional tasks beyond what is specified\n- Do NOT try to determine what should happen after this task\n- Use the available tools and skills to accomplish this specific task\n- Return a clear result that the planner can use to decide the next step\n\n## Output Format\nReturn your task execution result as a structured response. The output schema will guide you on the required fields.\n";
@@ -176,17 +176,21 @@ export declare const plannerInputSchema: z.ZodObject<{
176
176
  } | undefined;
177
177
  }>;
178
178
  export interface PlannerOutput extends Message {
179
- nextTask?: string;
179
+ nextTasks?: string[];
180
+ parallelTasks?: boolean;
180
181
  finished?: boolean;
181
182
  }
182
183
  export declare const plannerOutputSchema: z.ZodObject<{
183
- nextTask: z.ZodOptional<z.ZodString>;
184
+ nextTasks: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
185
+ parallelTasks: z.ZodOptional<z.ZodBoolean>;
184
186
  finished: z.ZodOptional<z.ZodBoolean>;
185
187
  }, "strip", z.ZodTypeAny, {
186
- nextTask?: string | undefined;
188
+ nextTasks?: string[] | undefined;
189
+ parallelTasks?: boolean | undefined;
187
190
  finished?: boolean | undefined;
188
191
  }, {
189
- nextTask?: string | undefined;
192
+ nextTasks?: string[] | undefined;
193
+ parallelTasks?: boolean | undefined;
190
194
  finished?: boolean | undefined;
191
195
  }>;
192
196
  export interface WorkerInput extends Message {
@@ -15,6 +15,7 @@ export interface OrchestratorAgentOptions<I extends Message = Message, O extends
15
15
  * Prevents context overflow during long-running executions
16
16
  */
17
17
  stateManagement?: StateManagementOptions;
18
+ concurrency?: number;
18
19
  }
19
20
  export interface LoadOrchestratorAgentOptions<I extends Message = Message, O extends Message = Message> extends Omit<AIAgentOptions<I, O>, "instructions"> {
20
21
  objective?: string | PromptBuilder | Instructions;
@@ -67,6 +68,7 @@ export declare class OrchestratorAgent<I extends Message = Message, O extends Me
67
68
  private worker;
68
69
  private completer;
69
70
  private stateManagement?;
71
+ private concurrency;
70
72
  /**
71
73
  * Compress execution state to prevent context overflow
72
74
  * Uses reverse accumulation to efficiently find optimal task count
@@ -3,6 +3,7 @@ import { getInstructionsSchema, getNestAgentSchema, } from "@aigne/core/loader/a
3
3
  import { instructionsToPromptBuilder, loadNestAgent, } from "@aigne/core/loader/index.js";
4
4
  import { camelizeSchema, optionalize } from "@aigne/core/loader/schema.js";
5
5
  import { isAgent } from "@aigne/core/utils/agent-utils.js";
6
+ import * as fastq from "@aigne/core/utils/queue.js";
6
7
  import { estimateTokens } from "@aigne/core/utils/token-estimator.js";
7
8
  import { omit, pick } from "@aigne/core/utils/type-utils.js";
8
9
  import { z } from "zod";
@@ -35,6 +36,7 @@ const defaultCompleterOptions = {
35
36
  disabled: true,
36
37
  },
37
38
  };
39
+ const DEFAULT_CONCURRENCY = 5;
38
40
  /**
39
41
  * Orchestrator Agent Class
40
42
  *
@@ -120,12 +122,14 @@ export class OrchestratorAgent extends AIAgent {
120
122
  });
121
123
  // Initialize state management config
122
124
  this.stateManagement = options.stateManagement;
125
+ this.concurrency = options.concurrency ?? DEFAULT_CONCURRENCY;
123
126
  }
124
127
  objective;
125
128
  planner;
126
129
  worker;
127
130
  completer;
128
131
  stateManagement;
132
+ concurrency;
129
133
  /**
130
134
  * Compress execution state to prevent context overflow
131
135
  * Uses reverse accumulation to efficiently find optimal task count
@@ -195,33 +199,31 @@ export class OrchestratorAgent extends AIAgent {
195
199
  executionState: compressedState,
196
200
  ...pick(input, this.planner.inputKeys),
197
201
  }, { ...options, model, streaming: false });
198
- if (plan.finished || !plan.nextTask) {
202
+ if (plan.finished || !plan.nextTasks?.length) {
199
203
  break;
200
204
  }
201
- const task = plan.nextTask;
202
205
  const createdAt = Date.now();
203
- const taskResult = await this.invokeChildAgent(this.worker, {
204
- objective,
205
- executionState: compressedState,
206
- task,
207
- ...pick(input, this.worker.inputKeys),
208
- }, { ...options, model, streaming: false })
209
- .then((res) => {
210
- if (res.error || res.success === false) {
211
- return { status: "failed", result: res.result, error: res.error };
212
- }
213
- return { status: "completed", result: res.result };
214
- })
215
- .catch((error) => ({
216
- status: "failed",
217
- error: { message: error instanceof Error ? error.message : String(error) },
218
- }));
219
- executionState.tasks.push({
220
- ...taskResult,
221
- task: task,
222
- createdAt,
223
- completedAt: Date.now(),
224
- });
206
+ const queue = fastq.promise(async ({ task }) => {
207
+ const taskResult = await this.invokeChildAgent(this.worker, {
208
+ objective,
209
+ executionState: compressedState,
210
+ task,
211
+ ...pick(input, this.worker.inputKeys),
212
+ }, { ...options, model, streaming: false })
213
+ .then((res) => {
214
+ if (res.error || res.success === false) {
215
+ return { status: "failed", result: res.result, error: res.error };
216
+ }
217
+ return { status: "completed", result: res.result };
218
+ })
219
+ .catch((error) => ({
220
+ status: "failed",
221
+ error: { message: error instanceof Error ? error.message : String(error) },
222
+ }));
223
+ return { ...taskResult, task, createdAt, completedAt: Date.now() };
224
+ }, plan.parallelTasks ? this.concurrency : 1);
225
+ const taskResults = await Promise.all(plan.nextTasks.map((task) => queue.push({ task })));
226
+ executionState.tasks.push(...taskResults);
225
227
  }
226
228
  // Compress state for completer input if needed
227
229
  const compressedState = this.compressState(executionState);
@@ -242,5 +244,6 @@ function getOrchestratorAgentSchema({ filepath }) {
242
244
  worker: optionalize(nestAgentSchema),
243
245
  completer: optionalize(nestAgentSchema),
244
246
  stateManagement: optionalize(camelizeSchema(stateManagementOptionsSchema)),
247
+ concurrency: optionalize(z.number().int().min(1).default(DEFAULT_CONCURRENCY)),
245
248
  }));
246
249
  }
@@ -1,3 +1,3 @@
1
1
  export declare const ORCHESTRATOR_COMPLETE_PROMPT = "You are an intelligent assistant that synthesizes and presents the results of completed tasks.\n\n{% if $afs.enabled %}\n## Environment\n\n### AFS\n{{ $afs.description }}\n\n```yaml alt=\"The modules available in the AFS\"\n{{ $afs.modules | yaml.stringify }}\n```\n{% endif %}\n\n## User's Objective\n\n```txt alt=\"The user's latest objective you need to address\"\n{{ objective }}\n```\n\n## Current Execution State\n\n```yaml alt=\"The latest execution state\"\n{{ executionState | yaml.stringify }}\n```\n\n## Your Task\nBased on the execution results above, provide a comprehensive and helpful response to the user's objective.\n";
2
- export declare const TODO_PLANNER_PROMPT_TEMPLATE = "Your responsibility is to decide the next task based on the current execution state.\n\n## Responsibilities\n\nYou are the Planner in the Orchestrator. The entire Orchestrator completes tasks through collaboration of three roles:\n\n1. **Planner (you)** analyzes the current state and outputs \"nextTask\"\n2. **Worker** executes the task and updates the execution state\n3. **Loop back to step 1**, Planner plans the next task based on the new state\n4. **Repeat steps 1-3** until Planner determines the task is complete\n5. **Planner** sets \"finished: true\"\n6. **Completer** generates the final report and returns it to the user\n\n{% if $afs.enabled %}\n## Environment\n\n### AFS\n{{ $afs.description }}\n\n```yaml alt=\"The modules available in the AFS\"\n{{ $afs.modules | yaml.stringify }}\n```\n{% endif %}\n\n## User's Objective\n\n```txt alt=\"The user's next objective you need to plan for\"\n{{ objective }}\n```\n\n## Current Execution State\n\n```yaml alt=\"The latest execution state\"\n{{ executionState | yaml.stringify }}\n```\n\n## How to Plan the Next Task\n\n### 1. Determine if Tasks Are Needed\n\nFirst, assess whether the objective requires any tasks at all. Ask yourself:\n\n**Does this objective require tasks?**\n\nConsider if completing the objective needs:\n- **Information gathering**: Does it need to collect or retrieve information?\n- **Analysis or processing**: Does it need to analyze, process, or compute something?\n- **State dependency**: Does it depend on information not yet in the execution state?\n\n**Set \"finished: true\" immediately when:**\n- The objective requires no exploration, analysis, or information gathering\n- The current execution state already contains everything needed to respond\n- The objective is purely conversational without requiring any action\n\n**Plan tasks when:**\n- The objective requires gathering information from external sources\n- The objective requires analysis, processing, or computation to be performed\n- Additional information must be collected before a complete response can be given\n\n### 2. Analyze Information Requirements\n\nIf tasks are needed, think about the current state and objective:\n- What information is needed to complete the objective?\n- Where can this information be obtained from?\n- What information has already been collected? What is still missing?\n- Is deeper exploration needed, or is it ready to generate a summary?\n\n### 3. Decision Principles\n\n- **Plan only one specific task at a time**: Don't try to plan all steps at once\n- **Only decide, don't execute**: You only output task descriptions, actual execution is done by the Worker\n- **Trust the iterative process**: You will be called again after each task completes, allowing you to adjust the plan dynamically\n- **Avoid duplicate work**: Review the execution history to understand what has been completed\n- **Goal-oriented descriptions**: Task descriptions should state \"what to do\", not \"how to do it\"\n- **Handle failures appropriately**: If a previous task failed, decide whether to retry, skip, or use an alternative approach\n\n### 4. Decision Making at Different Stages\n\nFlexibly decide the next step based on current progress:\n\n**Exploration Stage**:\n- Plan exploration tasks to gather required information\n- Gradually collect information, focusing on one aspect at a time\n\n**Summary Stage**:\n- When sufficient information is collected, plan to generate a summary or report task\n\n**Completion Stage**:\n- Set \"finished: true\" when:\n - The objective doesn't require any tasks\n - All necessary tasks are completed\n - The objective is fully achieved\n- This will trigger the Completer to integrate all information and generate the final report\n\n## Understanding Task Status\n\nEach task in the execution state has a status:\n- **completed**: Task finished successfully, result is available\n- **failed**: Task encountered an error, check error field for details\n- **pending**: Task has not been executed yet\n\n## Output Format\n\n```yaml\nnextTask: \"[task description]\" # optional, describe the next task to be performed to achieve the objective, null if no further tasks are needed\nfinished: false # set to true if no further tasks are needed and the objective is achieved\n```\n\nNote: Task descriptions should be **goal-oriented**, not specifying concrete operations. Let the worker autonomously decide how to complete the task based on the task objective.\n";
2
+ export declare const TODO_PLANNER_PROMPT_TEMPLATE = "Your responsibility is to decide the next tasks based on the current execution state.\n\n## Responsibilities\n\nYou are the Planner in the Orchestrator. The entire Orchestrator completes tasks through collaboration of three roles:\n\n1. **Planner (you)** analyzes the current state and outputs \"nextTasks\" (one or more tasks)\n2. **Worker** executes the tasks and updates the execution state\n3. **Loop back to step 1**, Planner plans the next tasks based on the new state\n4. **Repeat steps 1-3** until Planner determines the objective is complete\n5. **Planner** sets \"finished: true\"\n6. **Completer** generates the final report and returns it to the user\n\n{% if $afs.enabled %}\n## Environment\n\n### AFS\n{{ $afs.description }}\n\n```yaml alt=\"The modules available in the AFS\"\n{{ $afs.modules | yaml.stringify }}\n```\n{% endif %}\n\n## User's Objective\n\n```txt alt=\"The user's next objective you need to plan for\"\n{{ objective }}\n```\n\n## Current Execution State\n\n```yaml alt=\"The latest execution state\"\n{{ executionState | yaml.stringify }}\n```\n\n## How to Plan Tasks\n\n### 1. Determine if Tasks Are Needed\n\nFirst, assess whether the objective requires any tasks at all. Ask yourself:\n\n**Does this objective require tasks?**\n\nConsider if completing the objective needs:\n- **Information gathering**: Does it need to collect or retrieve information?\n- **Analysis or processing**: Does it need to analyze, process, or compute something?\n- **State dependency**: Does it depend on information not yet in the execution state?\n\n**Set \"finished: true\" immediately when:**\n- The objective requires no exploration, analysis, or information gathering\n- The current execution state already contains everything needed to respond\n- The objective is purely conversational without requiring any action\n\n**Plan tasks when:**\n- The objective requires gathering information from external sources\n- The objective requires analysis, processing, or computation to be performed\n- Additional information must be collected before a complete response can be given\n\n### 2. Analyze Information Requirements\n\nIf tasks are needed, think about the current state and objective:\n- What information is needed to complete the objective?\n- Where can this information be obtained from?\n- What information has already been collected? What is still missing?\n- Is deeper exploration needed, or is it ready to generate a summary?\n\n### 3. Decision Principles\n\n- **Plan one or more tasks per iteration**: You can output multiple tasks when they are independent\n- **Only decide, don't execute**: You only output task descriptions, actual execution is done by the Worker\n- **Trust the iterative process**: You will be called again after tasks complete, allowing you to adjust the plan dynamically\n- **Avoid duplicate work**: Review the execution history to understand what has been completed\n- **Goal-oriented descriptions**: Task descriptions should state \"what to do\", not \"how to do it\"\n- **Handle failures appropriately**: If a previous task failed, decide whether to retry, skip, or use an alternative approach\n\n### 4. Parallel vs Sequential Execution\n\nYou can specify whether tasks should run in parallel or sequentially using `parallelTasks`.\n\n**IMPORTANT: When tasks run in parallel, they CANNOT see each other's results.** Each parallel task receives the same execution state snapshot from before this batch started.\n\n**Set `parallelTasks: true` ONLY when ALL conditions are met:**\n- Tasks operate on **completely independent** data sources or resources\n- Task results are **not needed by other tasks** in the same batch\n- Tasks have **no ordering requirements** between them\n- You are **100% certain** there are no dependencies\n\n**Set `parallelTasks: false` (default) when ANY of these apply:**\n- Any task needs results from another task in the same batch\n- Tasks must be executed in a specific order\n- Tasks operate on shared resources that could conflict\n- You are **uncertain** whether tasks are truly independent\n\n**When in doubt, use sequential execution.** It's safer to be slower than to produce incorrect results.\n\n### 5. Decision Making at Different Stages\n\nFlexibly decide the next step based on current progress:\n\n**Exploration Stage**:\n- Plan exploration tasks to gather required information\n- If exploring multiple independent sources, consider parallel execution\n\n**Processing Stage**:\n- Process gathered information\n- Use sequential execution when processing depends on previous results\n\n**Summary Stage**:\n- When sufficient information is collected, plan to generate a summary or report task\n\n**Completion Stage**:\n- Set \"finished: true\" when:\n - The objective doesn't require any tasks\n - All necessary tasks are completed\n - The objective is fully achieved\n- This will trigger the Completer to integrate all information and generate the final report\n\n## Understanding Task Status\n\nEach task in the execution state has a status:\n- **completed**: Task finished successfully, result is available\n- **failed**: Task encountered an error, check error field for details\n- **pending**: Task has not been executed yet\n\n## Output Format\n\n```yaml\nnextTasks: # List of tasks to execute (omit if finished)\n - \"task description 1\"\n - \"task description 2\"\nparallelTasks: false # true if tasks can run in parallel, false for sequential (default: false)\nfinished: false # true if objective is achieved and no more tasks needed\n```\n\n**Notes:**\n- Task descriptions should be **goal-oriented**, not specifying concrete operations\n- Let the worker autonomously decide how to complete each task\n- Default to sequential execution (`parallelTasks: false`) unless you're certain tasks are independent\n- When `finished: true`, omit `nextTasks`\n";
3
3
  export declare const TODO_WORKER_PROMPT_TEMPLATE = "You are a task execution agent. Your job is to execute the specific task assigned to you - nothing more, nothing less.\n\n{% if $afs.enabled %}\n## Environment\n\n### AFS\n{{ $afs.description }}\n\n```yaml alt=\"The modules available in the AFS\"\n{{ $afs.modules | yaml.stringify }}\n```\n{% endif %}\n\n## User's Objective\n\n```txt alt=\"The user's objective provide for context only\"\n{{ objective }}\n```\n\n**CRITICAL CONSTRAINT**: The objective above is provided ONLY for context. You must NOT attempt to:\n- Solve the entire objective\n- Plan additional steps beyond your current task\n- Make decisions about what should happen next\n- Execute any tasks other than the one explicitly assigned to you below\n\n## Latest Execution State\n\n```yaml alt=\"The latest execution state for your reference\"\n{{ executionState | yaml.stringify }}\n```\n\n## Your Current Task\n\n```txt alt=\"The specific task you need to execute now\"\n{{ task }}\n```\n\n## Important Instructions\n- Focus EXCLUSIVELY on completing the current task described above\n- The task is self-contained - execute it completely and accurately\n- Do NOT perform additional tasks beyond what is specified\n- Do NOT try to determine what should happen after this task\n- Use the available tools and skills to accomplish this specific task\n- Return a clear result that the planner can use to decide the next step\n\n## Output Format\nReturn your task execution result as a structured response. The output schema will guide you on the required fields.\n";
@@ -28,16 +28,16 @@ ${"```"}
28
28
  Based on the execution results above, provide a comprehensive and helpful response to the user's objective.
29
29
  `;
30
30
  export const TODO_PLANNER_PROMPT_TEMPLATE = `\
31
- Your responsibility is to decide the next task based on the current execution state.
31
+ Your responsibility is to decide the next tasks based on the current execution state.
32
32
 
33
33
  ## Responsibilities
34
34
 
35
35
  You are the Planner in the Orchestrator. The entire Orchestrator completes tasks through collaboration of three roles:
36
36
 
37
- 1. **Planner (you)** analyzes the current state and outputs "nextTask"
38
- 2. **Worker** executes the task and updates the execution state
39
- 3. **Loop back to step 1**, Planner plans the next task based on the new state
40
- 4. **Repeat steps 1-3** until Planner determines the task is complete
37
+ 1. **Planner (you)** analyzes the current state and outputs "nextTasks" (one or more tasks)
38
+ 2. **Worker** executes the tasks and updates the execution state
39
+ 3. **Loop back to step 1**, Planner plans the next tasks based on the new state
40
+ 4. **Repeat steps 1-3** until Planner determines the objective is complete
41
41
  5. **Planner** sets "finished: true"
42
42
  6. **Completer** generates the final report and returns it to the user
43
43
 
@@ -64,7 +64,7 @@ ${"```"}yaml alt="The latest execution state"
64
64
  {{ executionState | yaml.stringify }}
65
65
  ${"```"}
66
66
 
67
- ## How to Plan the Next Task
67
+ ## How to Plan Tasks
68
68
 
69
69
  ### 1. Determine if Tasks Are Needed
70
70
 
@@ -97,20 +97,44 @@ If tasks are needed, think about the current state and objective:
97
97
 
98
98
  ### 3. Decision Principles
99
99
 
100
- - **Plan only one specific task at a time**: Don't try to plan all steps at once
100
+ - **Plan one or more tasks per iteration**: You can output multiple tasks when they are independent
101
101
  - **Only decide, don't execute**: You only output task descriptions, actual execution is done by the Worker
102
- - **Trust the iterative process**: You will be called again after each task completes, allowing you to adjust the plan dynamically
102
+ - **Trust the iterative process**: You will be called again after tasks complete, allowing you to adjust the plan dynamically
103
103
  - **Avoid duplicate work**: Review the execution history to understand what has been completed
104
104
  - **Goal-oriented descriptions**: Task descriptions should state "what to do", not "how to do it"
105
105
  - **Handle failures appropriately**: If a previous task failed, decide whether to retry, skip, or use an alternative approach
106
106
 
107
- ### 4. Decision Making at Different Stages
107
+ ### 4. Parallel vs Sequential Execution
108
+
109
+ You can specify whether tasks should run in parallel or sequentially using \`parallelTasks\`.
110
+
111
+ **IMPORTANT: When tasks run in parallel, they CANNOT see each other's results.** Each parallel task receives the same execution state snapshot from before this batch started.
112
+
113
+ **Set \`parallelTasks: true\` ONLY when ALL conditions are met:**
114
+ - Tasks operate on **completely independent** data sources or resources
115
+ - Task results are **not needed by other tasks** in the same batch
116
+ - Tasks have **no ordering requirements** between them
117
+ - You are **100% certain** there are no dependencies
118
+
119
+ **Set \`parallelTasks: false\` (default) when ANY of these apply:**
120
+ - Any task needs results from another task in the same batch
121
+ - Tasks must be executed in a specific order
122
+ - Tasks operate on shared resources that could conflict
123
+ - You are **uncertain** whether tasks are truly independent
124
+
125
+ **When in doubt, use sequential execution.** It's safer to be slower than to produce incorrect results.
126
+
127
+ ### 5. Decision Making at Different Stages
108
128
 
109
129
  Flexibly decide the next step based on current progress:
110
130
 
111
131
  **Exploration Stage**:
112
132
  - Plan exploration tasks to gather required information
113
- - Gradually collect information, focusing on one aspect at a time
133
+ - If exploring multiple independent sources, consider parallel execution
134
+
135
+ **Processing Stage**:
136
+ - Process gathered information
137
+ - Use sequential execution when processing depends on previous results
114
138
 
115
139
  **Summary Stage**:
116
140
  - When sufficient information is collected, plan to generate a summary or report task
@@ -132,11 +156,18 @@ Each task in the execution state has a status:
132
156
  ## Output Format
133
157
 
134
158
  ${"```"}yaml
135
- nextTask: "[task description]" # optional, describe the next task to be performed to achieve the objective, null if no further tasks are needed
136
- finished: false # set to true if no further tasks are needed and the objective is achieved
159
+ nextTasks: # List of tasks to execute (omit if finished)
160
+ - "task description 1"
161
+ - "task description 2"
162
+ parallelTasks: false # true if tasks can run in parallel, false for sequential (default: false)
163
+ finished: false # true if objective is achieved and no more tasks needed
137
164
  ${"```"}
138
165
 
139
- Note: Task descriptions should be **goal-oriented**, not specifying concrete operations. Let the worker autonomously decide how to complete the task based on the task objective.
166
+ **Notes:**
167
+ - Task descriptions should be **goal-oriented**, not specifying concrete operations
168
+ - Let the worker autonomously decide how to complete each task
169
+ - Default to sequential execution (\`parallelTasks: false\`) unless you're certain tasks are independent
170
+ - When \`finished: true\`, omit \`nextTasks\`
140
171
  `;
141
172
  export const TODO_WORKER_PROMPT_TEMPLATE = `\
142
173
  You are a task execution agent. Your job is to execute the specific task assigned to you - nothing more, nothing less.
@@ -176,17 +176,21 @@ export declare const plannerInputSchema: z.ZodObject<{
176
176
  } | undefined;
177
177
  }>;
178
178
  export interface PlannerOutput extends Message {
179
- nextTask?: string;
179
+ nextTasks?: string[];
180
+ parallelTasks?: boolean;
180
181
  finished?: boolean;
181
182
  }
182
183
  export declare const plannerOutputSchema: z.ZodObject<{
183
- nextTask: z.ZodOptional<z.ZodString>;
184
+ nextTasks: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
185
+ parallelTasks: z.ZodOptional<z.ZodBoolean>;
184
186
  finished: z.ZodOptional<z.ZodBoolean>;
185
187
  }, "strip", z.ZodTypeAny, {
186
- nextTask?: string | undefined;
188
+ nextTasks?: string[] | undefined;
189
+ parallelTasks?: boolean | undefined;
187
190
  finished?: boolean | undefined;
188
191
  }, {
189
- nextTask?: string | undefined;
192
+ nextTasks?: string[] | undefined;
193
+ parallelTasks?: boolean | undefined;
190
194
  finished?: boolean | undefined;
191
195
  }>;
192
196
  export interface WorkerInput extends Message {
@@ -25,14 +25,23 @@ export const plannerInputSchema = z.object({
25
25
  executionState: optionalize(executionStateSchema),
26
26
  });
27
27
  export const plannerOutputSchema = z.object({
28
- nextTask: z
29
- .string()
28
+ nextTasks: z
29
+ .array(z.string())
30
30
  .optional()
31
31
  .describe(`\
32
- The next task to be executed by the worker.
33
- Provide a clear, actionable task description that specifies what needs to be done.
32
+ The next tasks to be executed by the worker.
33
+ Provide clear, actionable task descriptions that specify what needs to be done.
34
34
  Include relevant context from previous task results if needed for execution.
35
35
  Omit this field when all necessary work has been completed.
36
+ `),
37
+ parallelTasks: z
38
+ .boolean()
39
+ .optional()
40
+ .describe(`\
41
+ Indicates whether the next tasks can be executed in parallel.
42
+ Set to true if tasks are independent and can run simultaneously.
43
+ Set to false if tasks must be executed sequentially.
44
+ default is false.
36
45
  `),
37
46
  finished: z
38
47
  .boolean()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aigne/agent-library",
3
- "version": "1.23.0",
3
+ "version": "1.24.0-beta.2",
4
4
  "description": "Collection of agent libraries for AIGNE framework",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -57,9 +57,9 @@
57
57
  "yaml": "^2.8.1",
58
58
  "zod": "^3.25.67",
59
59
  "zod-to-json-schema": "^3.24.6",
60
- "@aigne/openai": "^0.16.15",
61
- "@aigne/core": "^1.71.0",
62
- "@aigne/sqlite": "^0.4.8"
60
+ "@aigne/core": "^1.72.0-beta.2",
61
+ "@aigne/sqlite": "^0.4.9-beta",
62
+ "@aigne/openai": "^0.16.16-beta.2"
63
63
  },
64
64
  "devDependencies": {
65
65
  "@types/bun": "^1.2.22",