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

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,20 +48,64 @@ 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
52
+
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
58
+
59
+ ### Run with npx (No Installation Required)
57
60
 
58
61
  ```bash
59
- export OPENAI_API_KEY=YOUR_OPENAI_API_KEY # Set your OpenAI API key
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
60
64
 
61
- # Run in one-shot mode (default)
65
+ # Run the orchestrator
62
66
  npx -y @aigne/example-workflow-orchestrator
67
+ ```
68
+
69
+ ### Connect to an AI Model
70
+
71
+ As an example, running `npx -y @aigne/example-workflow-orchestrator --chat` requires an AI model. If this is your first run, you need to connect one.
72
+
73
+ ![run example](./run-example.png)
63
74
 
64
- # Run in interactive chat mode
65
- npx -y @aigne/example-workflow-orchestrator --chat
75
+ - Connect via the official AIGNE Hub
66
76
 
67
- # Use pipeline input
68
- echo "Research ArcBlock and compile a report about their products and architecture" | npx -y @aigne/example-workflow-orchestrator
77
+ Choose the first option and your browser will open the official AIGNE Hub page. Follow the prompts to complete the connection. If you're a new user, the system automatically grants 400,000 tokens for you to use.
78
+
79
+ ![connect to official aigne hub](../images/connect-to-aigne-hub.png)
80
+
81
+ - Connect via a self-hosted AIGNE Hub
82
+
83
+ Choose the second option, enter the URL of your self-hosted AIGNE Hub, and follow the prompts to complete the connection. If you need to set up a self-hosted AIGNE Hub, visit the Blocklet Store to install and deploy it: [Blocklet Store](https://store.blocklet.dev/blocklets/z8ia3xzq2tMq8CRHfaXj1BTYJyYnEcHbqP8cJ?utm_source=www.arcblock.io&utm_medium=blog_link&utm_campaign=default&utm_content=store.blocklet.dev#:~:text=%F0%9F%9A%80%20Get%20Started%20in%20Minutes).
84
+
85
+ ![connect to self hosted aigne hub](../images/connect-to-self-hosted-aigne-hub.png)
86
+
87
+ - Connect via a third-party model provider
88
+
89
+ Using OpenAI as an example, you can configure the provider's API key via environment variables. After configuration, run the example again:
90
+
91
+ ```bash
92
+ export OPENAI_API_KEY="" # Set your OpenAI API key here
69
93
  ```
94
+ For more details on third-party model configuration (e.g., OpenAI, DeepSeek, Google Gemini), see [.env.local.example](./.env.local.example).
95
+
96
+ After configuration, run the example again.
97
+
98
+ ### Debugging
99
+
100
+ The `aigne observe` command starts a local web server to monitor and analyze agent execution data. It provides a user-friendly interface to inspect traces, view detailed call information, and understand your agent’s behavior during runtime. This tool is essential for debugging, performance tuning, and gaining insight into how your agent processes information and interacts with tools and models.
101
+
102
+ Start the observation server.
103
+
104
+ ![aigne-observe-execute](../images/aigne-observe-execute.png)
105
+
106
+ View a list of recent executions.
107
+
108
+ ![aigne-observe-list](../images/aigne-observe-list.png)
70
109
 
71
110
  ## Installation
72
111
 
@@ -115,126 +154,112 @@ You can use different AI models by setting the `MODEL` environment variable alon
115
154
 
116
155
  For detailed configuration examples, please refer to the `.env.local.example` file in this directory.
117
156
 
118
- ### Run the Example
157
+ ### Run from Source
119
158
 
120
159
  ```bash
121
- pnpm start # Run in one-shot mode (default)
160
+ cd examples/workflow-orchestrator
161
+ pnpm start
162
+ ```
122
163
 
123
- # Run in interactive chat mode
124
- pnpm start -- --chat
164
+ You can pass custom messages to the orchestrator:
165
+
166
+ ```bash
167
+ # Pass message via command line
168
+ pnpm start -- -m "Analyze the project structure"
125
169
 
126
- # Use pipeline input
127
- echo "Research ArcBlock and compile a report about their products and architecture" | pnpm start
170
+ # Or use YAML input
171
+ pnpm start -- --input-yaml '{ message: "Generate a README for this project" }'
128
172
  ```
129
173
 
130
- ### Run Options
174
+ ## Configuration
131
175
 
132
- The example supports the following command-line parameters:
176
+ ### Main Configuration (aigne.yaml)
133
177
 
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 |
178
+ ```yaml
179
+ #!/usr/bin/env aigne
144
180
 
145
- #### Examples
181
+ model: aignehub/google/gemini-2.5-pro
182
+ agents:
183
+ - agents/orchestrator.yaml
184
+ ```
146
185
 
147
- ```bash
148
- # Run in chat mode (interactive)
149
- pnpm start -- --chat
186
+ ### Orchestrator Configuration (agents/orchestrator.yaml)
187
+
188
+ ```yaml
189
+ type: "@aigne/agent-library/orchestrator"
190
+ name: orchestrator
191
+ input_schema:
192
+ type: object
193
+ properties:
194
+ message:
195
+ type: string
196
+ description: (Optional) User's instruction
197
+ required: []
198
+
199
+ # Specify the objective for the orchestrator agent
200
+ objective:
201
+ url: objective.md
202
+
203
+ # Custom planner agent can be defined here
204
+ planner:
205
+ type: ai
206
+ instructions:
207
+ url: planner.md
208
+
209
+ # Custom worker agent (optional)
210
+ # worker:
211
+ # type: ai
212
+ # instructions:
213
+ # url: path/to/worker_instructions.md
214
+
215
+ # Custom completer agent (optional)
216
+ # completer:
217
+ # type: ai
218
+ # instructions:
219
+ # url: path/to/completer_instructions.md
220
+
221
+ # State management configuration
222
+ state_management:
223
+ max_iterations: 5 # Maximum planning-execution iterations
224
+ max_tokens: 100000 # Optional: limit total tokens for state management
225
+ keep_recent: 20 # Optional: keep only N most recent states in memory
226
+
227
+ # Agent File System configuration
228
+ afs:
229
+ modules:
230
+ - module: local-fs
231
+ options:
232
+ name: workspace
233
+ localPath: .
234
+ description: Workspace directory for the orchestrator agent.
235
+ ```
150
236
 
151
- # Set logging level
152
- pnpm start -- --log-level DEBUG
237
+ ### Objective Template (agents/objective.md)
153
238
 
154
- # Use pipeline input
155
- echo "Research ArcBlock and compile a report about their products and architecture" | pnpm start
156
- ```
239
+ ```markdown
240
+ Explore the project directory `/modules/workspace/` structure and generate a project summary report in Markdown format.
241
+
242
+ - Ignore directories like node_modules, .git, dist, build, etc.
243
+ - Provide accurate information based on actual file contents
157
244
 
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
- // }
245
+ {% if message %}
246
+ ## User Instructions
247
+ {{ message }}
248
+ {% endif %}
236
249
  ```
237
250
 
251
+ ### Custom Planner Instructions (agents/planner.md)
252
+
253
+ 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.
254
+
255
+ ### Key Features
256
+
257
+ 1. **YAML-based Configuration**: Define your orchestrator workflow declaratively
258
+ 2. **Customizable Components**: Override planner, worker, or completer with custom instructions
259
+ 3. **State Management**: Control iteration limits and memory usage
260
+ 4. **Agent File System**: Shared storage accessible to all agent components
261
+ 5. **Template Support**: Use Jinja2-style templates in objective prompts
262
+
238
263
  ## License
239
264
 
240
265
  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.1",
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.1",
20
+ "@aigne/cli": "^1.58.0-beta.1"
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.1"
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
- // }