@aigne/example-workflow-orchestrator 1.13.87 → 1.14.0-beta

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/README.md CHANGED
@@ -8,43 +8,38 @@
8
8
  </picture>
9
9
  </p>
10
10
 
11
- This is a demonstration of using [AIGNE Framework](https://github.com/AIGNE-io/aigne-framework) to build an orchestrator workflow. The example now supports both one-shot and interactive chat modes, along with customizable model settings and pipeline input/output.
11
+ This is a demonstration of using [AIGNE Framework](https://github.com/AIGNE-io/aigne-framework) to build an orchestrator workflow using YAML configuration. The orchestrator pattern enables autonomous task planning and execution through a planner-worker-completer architecture.
12
+
13
+ ## Architecture
14
+
15
+ The orchestrator follows a three-phase workflow:
12
16
 
13
17
  ```mermaid
14
18
  flowchart LR
15
-
16
- in(In)
17
- out(Out)
18
- orchestrator(Orchestrator)
19
- synthesizer(Synthesizer)
20
- finder(Finder)
21
- writer(Writer)
22
- proofreader(Proofreader)
23
- fact_checker(Fact Checker)
24
- style_enforcer(Style Enforcer)
25
-
26
- in ==> orchestrator
27
- orchestrator -.-> finder -.-> synthesizer
28
- orchestrator -.-> writer -.-> synthesizer
29
- orchestrator -.-> proofreader -.-> synthesizer
30
- orchestrator -.-> fact_checker -.-> synthesizer
31
- orchestrator -.-> style_enforcer -.-> synthesizer
32
- synthesizer ==> out
33
-
34
- classDef inputOutput fill:#f9f0ed,stroke:#debbae,stroke-width:2px,color:#b35b39,font-weight:bolder;
35
- classDef processing fill:#F0F4EB,stroke:#C2D7A7,stroke-width:2px,color:#6B8F3C,font-weight:bolder;
36
-
37
- class in inputOutput
38
- class out inputOutput
39
- class orchestrator processing
40
- class synthesizer processing
41
- class finder processing
42
- class writer processing
43
- class proofreader processing
44
- class fact_checker processing
45
- class style_enforcer processing
19
+ Input([User Objective]) --> Planner
20
+ Planner -->|Next Task| Worker
21
+ Worker -->|Task Result| State[Execution State]
22
+ State --> Planner
23
+ Planner -->|Finished| Completer
24
+ Completer --> Output([Final Response])
25
+
26
+ Skills[Skills/Tools] -.->|Available to| Worker
27
+
28
+ classDef inputOutput fill:#f9f0ed,stroke:#debbae,stroke-width:2px,color:#b35b39,font-weight:bolder
29
+ classDef agent fill:#F0F4EB,stroke:#C2D7A7,stroke-width:2px,color:#6B8F3C,font-weight:bolder
30
+ classDef resource fill:#E8F4F8,stroke:#4A9EBF,stroke-width:2px,color:#2B5F75,font-weight:bolder
31
+
32
+ class Input,Output inputOutput
33
+ class Planner,Worker,Completer agent
34
+ class State,Skills resource
46
35
  ```
47
36
 
37
+ **Components:**
38
+ - **Planner**: Analyzes the objective and execution state to determine the next task
39
+ - **Worker**: Executes assigned tasks using available skills and tools
40
+ - **Completer**: Synthesizes all results and provides the final response
41
+ - **Execution State**: Tracks task history, results, and progress
42
+
48
43
  ## Prerequisites
49
44
 
50
45
  * [Node.js](https://nodejs.org) (>=20.0) and npm installed on your machine
@@ -53,19 +48,22 @@ class style_enforcer processing
53
48
  * [Bun](https://bun.sh) for running unit tests & examples
54
49
  * [Pnpm](https://pnpm.io) for package management
55
50
 
56
- ## Quick Start (No Installation Required)
51
+ ## Quick Start
57
52
 
58
- ```bash
59
- export OPENAI_API_KEY=YOUR_OPENAI_API_KEY # Set your OpenAI API key
53
+ The orchestrator is configured using YAML files. This example uses:
54
+ - [aigne.yaml](./aigne.yaml) - Main configuration file
55
+ - [agents/orchestrator.yaml](./agents/orchestrator.yaml) - Orchestrator agent definition
56
+ - [agents/objective.md](./agents/objective.md) - Objective prompt template
57
+ - [agents/planner.md](./agents/planner.md) - Custom planner instructions
60
58
 
61
- # Run in one-shot mode (default)
62
- npx -y @aigne/example-workflow-orchestrator
59
+ ### Run with npx (No Installation Required)
63
60
 
64
- # Run in interactive chat mode
65
- npx -y @aigne/example-workflow-orchestrator --chat
61
+ ```bash
62
+ export OPENAI_API_KEY=YOUR_OPENAI_API_KEY # Set your API key
63
+ export GEMINI_API_KEY=YOUR_GEMINI_API_KEY # Or use Gemini
66
64
 
67
- # Use pipeline input
68
- echo "Research ArcBlock and compile a report about their products and architecture" | npx -y @aigne/example-workflow-orchestrator
65
+ # Run the orchestrator
66
+ npx -y @aigne/example-workflow-orchestrator
69
67
  ```
70
68
 
71
69
  ## Installation
@@ -115,126 +113,112 @@ You can use different AI models by setting the `MODEL` environment variable alon
115
113
 
116
114
  For detailed configuration examples, please refer to the `.env.local.example` file in this directory.
117
115
 
118
- ### Run the Example
116
+ ### Run from Source
119
117
 
120
118
  ```bash
121
- pnpm start # Run in one-shot mode (default)
119
+ cd examples/workflow-orchestrator
120
+ pnpm start
121
+ ```
122
+
123
+ You can pass custom messages to the orchestrator:
122
124
 
123
- # Run in interactive chat mode
124
- pnpm start -- --chat
125
+ ```bash
126
+ # Pass message via command line
127
+ pnpm start -- -m "Analyze the project structure"
125
128
 
126
- # Use pipeline input
127
- echo "Research ArcBlock and compile a report about their products and architecture" | pnpm start
129
+ # Or use YAML input
130
+ pnpm start -- --input-yaml '{ message: "Generate a README for this project" }'
128
131
  ```
129
132
 
130
- ### Run Options
133
+ ## Configuration
131
134
 
132
- The example supports the following command-line parameters:
135
+ ### Main Configuration (aigne.yaml)
133
136
 
134
- | Parameter | Description | Default |
135
- |-----------|-------------|---------|
136
- | `--chat` | Run in interactive chat mode | Disabled (one-shot mode) |
137
- | `--model <provider[:model]>` | AI model to use in format 'provider\[:model]' where model is optional. Examples: 'openai' or 'openai:gpt-4o-mini' | openai |
138
- | `--temperature <value>` | Temperature for model generation | Provider default |
139
- | `--top-p <value>` | Top-p sampling value | Provider default |
140
- | `--presence-penalty <value>` | Presence penalty value | Provider default |
141
- | `--frequency-penalty <value>` | Frequency penalty value | Provider default |
142
- | `--log-level <level>` | Set logging level (ERROR, WARN, INFO, DEBUG, TRACE) | INFO |
143
- | `--input`, `-i <input>` | Specify input directly | None |
137
+ ```yaml
138
+ #!/usr/bin/env aigne
144
139
 
145
- #### Examples
140
+ model: aignehub/google/gemini-2.5-pro
141
+ agents:
142
+ - agents/orchestrator.yaml
143
+ ```
146
144
 
147
- ```bash
148
- # Run in chat mode (interactive)
149
- pnpm start -- --chat
145
+ ### Orchestrator Configuration (agents/orchestrator.yaml)
146
+
147
+ ```yaml
148
+ type: "@aigne/agent-library/orchestrator"
149
+ name: orchestrator
150
+ input_schema:
151
+ type: object
152
+ properties:
153
+ message:
154
+ type: string
155
+ description: (Optional) User's instruction
156
+ required: []
157
+
158
+ # Specify the objective for the orchestrator agent
159
+ objective:
160
+ url: objective.md
161
+
162
+ # Custom planner agent can be defined here
163
+ planner:
164
+ type: ai
165
+ instructions:
166
+ url: planner.md
167
+
168
+ # Custom worker agent (optional)
169
+ # worker:
170
+ # type: ai
171
+ # instructions:
172
+ # url: path/to/worker_instructions.md
173
+
174
+ # Custom completer agent (optional)
175
+ # completer:
176
+ # type: ai
177
+ # instructions:
178
+ # url: path/to/completer_instructions.md
179
+
180
+ # State management configuration
181
+ state_management:
182
+ max_iterations: 5 # Maximum planning-execution iterations
183
+ max_tokens: 100000 # Optional: limit total tokens for state management
184
+ keep_recent: 20 # Optional: keep only N most recent states in memory
185
+
186
+ # Agent File System configuration
187
+ afs:
188
+ modules:
189
+ - module: local-fs
190
+ options:
191
+ name: workspace
192
+ localPath: .
193
+ description: Workspace directory for the orchestrator agent.
194
+ ```
150
195
 
151
- # Set logging level
152
- pnpm start -- --log-level DEBUG
196
+ ### Objective Template (agents/objective.md)
153
197
 
154
- # Use pipeline input
155
- echo "Research ArcBlock and compile a report about their products and architecture" | pnpm start
156
- ```
198
+ ```markdown
199
+ Explore the project directory `/modules/workspace/` structure and generate a project summary report in Markdown format.
157
200
 
158
- ## Example
159
-
160
- The following example demonstrates how to build a orchestrator workflow:
161
-
162
- Here is the generated report for this example: [arcblock-deep-research.md](./generated-report-arcblock.md)
163
-
164
- ```typescript
165
- import { OrchestratorAgent } from "@aigne/agent-library/orchestrator/index.js";
166
- import { AIAgent, AIGNE, MCPAgent } from "@aigne/core";
167
- import { OpenAIChatModel } from "@aigne/core/models/openai-chat-model.js";
168
-
169
- const { OPENAI_API_KEY } = process.env;
170
-
171
- const model = new OpenAIChatModel({
172
- apiKey: OPENAI_API_KEY,
173
- modelOptions: {
174
- parallelToolCalls: false, // puppeteer can only run one task at a time
175
- },
176
- });
177
-
178
- const puppeteer = await MCPAgent.from({
179
- command: "npx",
180
- args: ["-y", "@modelcontextprotocol/server-puppeteer"],
181
- env: process.env as Record<string, string>,
182
- });
183
-
184
- const filesystem = await MCPAgent.from({
185
- command: "npx",
186
- args: ["-y", "@modelcontextprotocol/server-filesystem", import.meta.dir],
187
- });
188
-
189
- const finder = AIAgent.from({
190
- name: "finder",
191
- description: "Find the closest match to a user's request",
192
- instructions: `You are an agent that can find information on the web.
193
- You are tasked with finding the closest match to the user's request.
194
- You can use puppeteer to scrape the web for information.
195
- You can also use the filesystem to save the information you find.
196
-
197
- Rules:
198
- - do not use screenshot of puppeteer
199
- - use document.body.innerText to get the text content of a page
200
- - if you want a url to some page, you should get all link and it's title of current(home) page,
201
- then you can use the title to search the url of the page you want to visit.
202
- `,
203
- skills: [puppeteer, filesystem],
204
- });
205
-
206
- const writer = AIAgent.from({
207
- name: "writer",
208
- description: "Write to the filesystem",
209
- instructions: `You are an agent that can write to the filesystem.
210
- You are tasked with taking the user's input, addressing it, and
211
- writing the result to disk in the appropriate location.`,
212
- skills: [filesystem],
213
- });
214
-
215
- const agent = OrchestratorAgent.from({
216
- skills: [finder, writer],
217
- maxIterations: 3,
218
- tasksConcurrency: 1, // puppeteer can only run one task at a time
219
- });
220
-
221
- const aigne = new AIGNE({ model });
222
-
223
- const result = await aigne.invoke(
224
- agent,
225
- `\
226
- Conduct an in-depth research on ArcBlock using only the official website\
227
- (avoid search engines or third-party sources) and compile a detailed report saved as arcblock.md. \
228
- The report should include comprehensive insights into the company's products \
229
- (with detailed research findings and links), technical architecture, and future plans.`,
230
- );
231
- console.log(result);
232
- // Output:
233
- // {
234
- // $message: "The objective of conducting in-depth research on ArcBlock using only the official website has been successfully completed...",
235
- // }
201
+ - Ignore directories like node_modules, .git, dist, build, etc.
202
+ - Provide accurate information based on actual file contents
203
+
204
+ {% if message %}
205
+ ## User Instructions
206
+ {{ message }}
207
+ {% endif %}
236
208
  ```
237
209
 
210
+ ### Custom Planner Instructions (agents/planner.md)
211
+
212
+ The planner is responsible for iterative task planning. See [agents/planner.md](./agents/planner.md) for the full custom planner prompt that enables autonomous exploration and task decomposition.
213
+
214
+ ### Key Features
215
+
216
+ 1. **YAML-based Configuration**: Define your orchestrator workflow declaratively
217
+ 2. **Customizable Components**: Override planner, worker, or completer with custom instructions
218
+ 3. **State Management**: Control iteration limits and memory usage
219
+ 4. **Agent File System**: Shared storage accessible to all agent components
220
+ 5. **Template Support**: Use Jinja2-style templates in objective prompts
221
+
238
222
  ## License
239
223
 
240
224
  This project is licensed under the MIT License.
package/aigne.yaml ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env aigne
2
+
3
+ model: aignehub/google/gemini-2.5-pro
4
+ agents:
5
+ - agents/orchestrator.yaml
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aigne/example-workflow-orchestrator",
3
- "version": "1.13.87",
3
+ "version": "1.14.0-beta",
4
4
  "description": "A demonstration of using AIGNE Framework to build a orchestrator workflow",
5
5
  "author": "Arcblock <blocklet@arcblock.io> https://github.com/blocklet",
6
6
  "homepage": "https://github.com/AIGNE-io/aigne-framework/tree/main/examples/workflow-orchestrator",
@@ -9,24 +9,21 @@
9
9
  "type": "git",
10
10
  "url": "git+https://github.com/AIGNE-io/aigne-framework"
11
11
  },
12
- "bin": "index.ts",
12
+ "bin": "aigne.yaml",
13
13
  "files": [
14
14
  ".env.local.example",
15
15
  "*.ts",
16
16
  "README.md"
17
17
  ],
18
18
  "dependencies": {
19
- "@aigne/agent-library": "^1.22.4",
20
- "@aigne/openai": "^0.16.14",
21
- "@aigne/core": "^1.70.1",
22
- "@aigne/cli": "^1.57.3"
19
+ "@aigne/agent-library": "^1.23.0-beta",
20
+ "@aigne/cli": "^1.58.0-beta"
23
21
  },
24
22
  "devDependencies": {
25
23
  "@types/bun": "^1.2.22",
26
- "@aigne/test-utils": "^0.5.67"
24
+ "@aigne/test-utils": "^0.5.68-beta"
27
25
  },
28
26
  "scripts": {
29
- "start": "bun run index.ts",
30
- "lint": "tsc --noEmit"
27
+ "start": "aigne run ."
31
28
  }
32
29
  }
package/index.ts DELETED
@@ -1,64 +0,0 @@
1
- #!/usr/bin/env bunwrapper
2
-
3
- import { OrchestratorAgent } from "@aigne/agent-library/orchestrator/index.js";
4
- import { runWithAIGNE } from "@aigne/cli/utils/run-with-aigne.js";
5
- import { AIAgent, MCPAgent } from "@aigne/core";
6
-
7
- const puppeteer = await MCPAgent.from({
8
- command: "npx",
9
- args: ["-y", "@modelcontextprotocol/server-puppeteer"],
10
- env: process.env as Record<string, string>,
11
- });
12
-
13
- const filesystem = await MCPAgent.from({
14
- command: "npx",
15
- args: ["-y", "@modelcontextprotocol/server-filesystem", import.meta.dir],
16
- });
17
-
18
- const finder = AIAgent.from({
19
- name: "finder",
20
- description: "Find the closest match to a user's request",
21
- instructions: `You are an agent that can find information on the web.
22
- You are tasked with finding the closest match to the user's request.
23
- You can use puppeteer to scrape the web for information.
24
- You can also use the filesystem to save the information you find.
25
-
26
- Rules:
27
- - do not use screenshot of puppeteer
28
- - use document.body.innerText to get the text content of a page
29
- - if you want a url to some page, you should get all link and it's title of current(home) page,
30
- then you can use the title to search the url of the page you want to visit.
31
- `,
32
- skills: [puppeteer, filesystem],
33
- });
34
-
35
- const writer = AIAgent.from({
36
- name: "writer",
37
- description: "Write to the filesystem",
38
- instructions: `You are an agent that can write to the filesystem.
39
- You are tasked with taking the user's input, addressing it, and
40
- writing the result to disk in the appropriate location.`,
41
- skills: [filesystem],
42
- });
43
-
44
- const agent = OrchestratorAgent.from({
45
- skills: [finder, writer],
46
- maxIterations: 3,
47
- tasksConcurrency: 1, // puppeteer can only run one task at a time
48
- inputKey: "message",
49
- });
50
-
51
- await runWithAIGNE(agent, {
52
- modelOptions: { parallelToolCalls: false },
53
- chatLoopOptions: {
54
- welcome: "Welcome to the Orchestrator Agent!",
55
- inputKey: "message",
56
- defaultQuestion: `\
57
- Conduct an in-depth research on ArcBlock using only the official website\
58
- (avoid search engines or third-party sources) and compile a detailed report saved as arcblock.md. \
59
- The report should include comprehensive insights into the company's products \
60
- (with detailed research findings and links), technical architecture, and future plans.`,
61
- },
62
- });
63
-
64
- process.exit(0);
package/usage.ts DELETED
@@ -1,73 +0,0 @@
1
- import assert from "node:assert";
2
- import { OrchestratorAgent } from "@aigne/agent-library/orchestrator/index.js";
3
- import { AIAgent, AIGNE, MCPAgent } from "@aigne/core";
4
- import { OpenAIChatModel } from "@aigne/openai";
5
-
6
- const { OPENAI_API_KEY } = process.env;
7
- assert(OPENAI_API_KEY, "Please set the OPENAI_API_KEY environment variable");
8
-
9
- const model = new OpenAIChatModel({
10
- apiKey: OPENAI_API_KEY,
11
- modelOptions: {
12
- parallelToolCalls: false, // puppeteer can only run one task at a time
13
- },
14
- });
15
-
16
- const puppeteer = await MCPAgent.from({
17
- command: "npx",
18
- args: ["-y", "@modelcontextprotocol/server-puppeteer"],
19
- env: process.env as Record<string, string>,
20
- });
21
-
22
- const filesystem = await MCPAgent.from({
23
- command: "npx",
24
- args: ["-y", "@modelcontextprotocol/server-filesystem", import.meta.dir],
25
- });
26
-
27
- const finder = AIAgent.from({
28
- name: "finder",
29
- description: "Find the closest match to a user's request",
30
- instructions: `You are an agent that can find information on the web.
31
- You are tasked with finding the closest match to the user's request.
32
- You can use puppeteer to scrape the web for information.
33
- You can also use the filesystem to save the information you find.
34
-
35
- Rules:
36
- - do not use screenshot of puppeteer
37
- - use document.body.innerText to get the text content of a page
38
- - if you want a url to some page, you should get all link and it's title of current(home) page,
39
- then you can use the title to search the url of the page you want to visit.
40
- `,
41
- skills: [puppeteer, filesystem],
42
- });
43
-
44
- const writer = AIAgent.from({
45
- name: "writer",
46
- description: "Write to the filesystem",
47
- instructions: `You are an agent that can write to the filesystem.
48
- You are tasked with taking the user's input, addressing it, and
49
- writing the result to disk in the appropriate location.`,
50
- skills: [filesystem],
51
- });
52
-
53
- const agent = OrchestratorAgent.from({
54
- skills: [finder, writer],
55
- maxIterations: 3,
56
- tasksConcurrency: 1, // puppeteer can only run one task at a time
57
- inputKey: "message",
58
- });
59
-
60
- const aigne = new AIGNE({ model });
61
-
62
- const result = await aigne.invoke(agent, {
63
- message: `\
64
- Conduct an in-depth research on ArcBlock using only the official website\
65
- (avoid search engines or third-party sources) and compile a detailed report saved as arcblock.md. \
66
- The report should include comprehensive insights into the company's products \
67
- (with detailed research findings and links), technical architecture, and future plans.`,
68
- });
69
- console.log(result);
70
- // Output:
71
- // {
72
- // message: "The objective of conducting in-depth research on ArcBlock using only the official website has been successfully completed...",
73
- // }