@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 +41 -0
- package/lib/cjs/orchestrator/index.d.ts +2 -0
- package/lib/cjs/orchestrator/index.js +60 -24
- package/lib/cjs/orchestrator/prompt.d.ts +1 -1
- package/lib/cjs/orchestrator/prompt.js +44 -13
- package/lib/cjs/orchestrator/type.d.ts +8 -4
- package/lib/cjs/orchestrator/type.js +13 -4
- package/lib/dts/orchestrator/index.d.ts +2 -0
- package/lib/dts/orchestrator/prompt.d.ts +1 -1
- package/lib/dts/orchestrator/type.d.ts +8 -4
- package/lib/esm/orchestrator/index.d.ts +2 -0
- package/lib/esm/orchestrator/index.js +27 -24
- package/lib/esm/orchestrator/prompt.d.ts +1 -1
- package/lib/esm/orchestrator/prompt.js +44 -13
- package/lib/esm/orchestrator/type.d.ts +8 -4
- package/lib/esm/orchestrator/type.js +13 -4
- package/package.json +4 -4
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.
|
|
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
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
...taskResult,
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
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
|
|
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
|
|
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 "
|
|
41
|
-
2. **Worker** executes the
|
|
42
|
-
3. **Loop back to step 1**, Planner plans the next
|
|
43
|
-
4. **Repeat steps 1-3** until Planner determines the
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
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
|
-
-
|
|
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
|
-
|
|
139
|
-
|
|
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
|
-
|
|
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
|
-
|
|
179
|
+
nextTasks?: string[];
|
|
180
|
+
parallelTasks?: boolean;
|
|
180
181
|
finished?: boolean;
|
|
181
182
|
}
|
|
182
183
|
export declare const plannerOutputSchema: z.ZodObject<{
|
|
183
|
-
|
|
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
|
-
|
|
188
|
+
nextTasks?: string[] | undefined;
|
|
189
|
+
parallelTasks?: boolean | undefined;
|
|
187
190
|
finished?: boolean | undefined;
|
|
188
191
|
}, {
|
|
189
|
-
|
|
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
|
-
|
|
35
|
-
.string()
|
|
34
|
+
nextTasks: zod_1.default
|
|
35
|
+
.array(zod_1.default.string())
|
|
36
36
|
.optional()
|
|
37
37
|
.describe(`\
|
|
38
|
-
The next
|
|
39
|
-
Provide
|
|
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
|
|
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
|
-
|
|
179
|
+
nextTasks?: string[];
|
|
180
|
+
parallelTasks?: boolean;
|
|
180
181
|
finished?: boolean;
|
|
181
182
|
}
|
|
182
183
|
export declare const plannerOutputSchema: z.ZodObject<{
|
|
183
|
-
|
|
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
|
-
|
|
188
|
+
nextTasks?: string[] | undefined;
|
|
189
|
+
parallelTasks?: boolean | undefined;
|
|
187
190
|
finished?: boolean | undefined;
|
|
188
191
|
}, {
|
|
189
|
-
|
|
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.
|
|
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
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
...taskResult,
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
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
|
|
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
|
|
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 "
|
|
38
|
-
2. **Worker** executes the
|
|
39
|
-
3. **Loop back to step 1**, Planner plans the next
|
|
40
|
-
4. **Repeat steps 1-3** until Planner determines the
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
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
|
-
-
|
|
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
|
-
|
|
136
|
-
|
|
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
|
-
|
|
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
|
-
|
|
179
|
+
nextTasks?: string[];
|
|
180
|
+
parallelTasks?: boolean;
|
|
180
181
|
finished?: boolean;
|
|
181
182
|
}
|
|
182
183
|
export declare const plannerOutputSchema: z.ZodObject<{
|
|
183
|
-
|
|
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
|
-
|
|
188
|
+
nextTasks?: string[] | undefined;
|
|
189
|
+
parallelTasks?: boolean | undefined;
|
|
187
190
|
finished?: boolean | undefined;
|
|
188
191
|
}, {
|
|
189
|
-
|
|
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
|
-
|
|
29
|
-
.string()
|
|
28
|
+
nextTasks: z
|
|
29
|
+
.array(z.string())
|
|
30
30
|
.optional()
|
|
31
31
|
.describe(`\
|
|
32
|
-
The next
|
|
33
|
-
Provide
|
|
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.
|
|
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/
|
|
61
|
-
"@aigne/
|
|
62
|
-
"@aigne/
|
|
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",
|