modular-agent-examples 0.0.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/chunking-demo.ts +339 -0
- package/cleanup-duplicates.ts +142 -0
- package/data/flower.jpg +0 -0
- package/generative.ts +128 -0
- package/graph/context-example.ts +209 -0
- package/graph/data-pipeline/agents.ts +60 -0
- package/graph/data-pipeline/fetchers.ts +166 -0
- package/graph/data-pipeline/index.ts +282 -0
- package/graph/index.ts +154 -0
- package/graph/map-example.ts +227 -0
- package/graph/metrics-example.ts +238 -0
- package/graph/parallel-example.ts +167 -0
- package/graph/pipeline-example.ts +225 -0
- package/graph/planning-example.ts +406 -0
- package/graph/router-example.ts +226 -0
- package/graph/sequential-example.ts +141 -0
- package/graph/voting-example.ts +159 -0
- package/graph-rag/docker-compose.yaml +14 -0
- package/graph-rag/index.js +99 -0
- package/graph-rag/init-db.sh +7 -0
- package/graph-rag/package.json +15 -0
- package/history-compression-example.ts +163 -0
- package/history-persistence.ts +347 -0
- package/index.ts +175 -0
- package/ingestion-pipeline.ts +353 -0
- package/mcp-airbnb-example.ts +69 -0
- package/mcp-http-example.ts +70 -0
- package/mcp-stdio-example.ts +63 -0
- package/multimodal.ts +144 -0
- package/ollama.ts +148 -0
- package/openai-compatible.ts +141 -0
- package/opensearch-vector-store.ts +342 -0
- package/package.json +24 -0
- package/pubmed.ts +289 -0
- package/reasoning-with-sub-agent.ts +311 -0
- package/synchronous/index.ts +48 -0
- package/tsconfig.json +8 -0
- package/vector-store-filtering.ts +303 -0
- package/vector-store.ts +210 -0
- package/vectorstore/index.ts +0 -0
- package/vectorstore/store/dbService.ts +80 -0
- package/voyage-embeddings.ts +99 -0
- package/weather-with-sub-agent.ts +276 -0
- package/weather.ts +389 -0
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Metrics and Observability Example
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates how to track timing, token usage, and pipeline structure
|
|
5
|
+
* for analysis and visualization.
|
|
6
|
+
*/
|
|
7
|
+
import "dotenv/config";
|
|
8
|
+
import { ClaudeAgent } from "../../lib/agents/anthropic/ClaudeAgent";
|
|
9
|
+
import {
|
|
10
|
+
AgentGraph,
|
|
11
|
+
createMetricsCollector,
|
|
12
|
+
VotingInput,
|
|
13
|
+
GraphNode,
|
|
14
|
+
} from "../../lib/graph/AgentGraph";
|
|
15
|
+
|
|
16
|
+
const apiKey = process.env.ANTHROPIC_API_KEY as string;
|
|
17
|
+
|
|
18
|
+
// Create some agents for demonstration
|
|
19
|
+
const researchAgent = new ClaudeAgent({
|
|
20
|
+
id: "researcher",
|
|
21
|
+
name: "Researcher",
|
|
22
|
+
description:
|
|
23
|
+
"Research the given topic briefly. Keep response under 50 words.",
|
|
24
|
+
apiKey,
|
|
25
|
+
maxTokens: 128,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const optimistAgent = new ClaudeAgent({
|
|
29
|
+
id: "optimist",
|
|
30
|
+
name: "Optimist",
|
|
31
|
+
description: "Give a brief optimistic perspective. Under 30 words.",
|
|
32
|
+
apiKey,
|
|
33
|
+
maxTokens: 64,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const pessimistAgent = new ClaudeAgent({
|
|
37
|
+
id: "pessimist",
|
|
38
|
+
name: "Pessimist",
|
|
39
|
+
description: "Give a brief pessimistic perspective. Under 30 words.",
|
|
40
|
+
apiKey,
|
|
41
|
+
maxTokens: 64,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const judgeAgent = new ClaudeAgent({
|
|
45
|
+
id: "judge",
|
|
46
|
+
name: "Judge",
|
|
47
|
+
description:
|
|
48
|
+
"Pick the better perspective. Say 'Optimist' or 'Pessimist' only.",
|
|
49
|
+
apiKey,
|
|
50
|
+
maxTokens: 16,
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
async function runMetricsExample() {
|
|
54
|
+
console.log("╔══════════════════════════════════════════════╗");
|
|
55
|
+
console.log("║ Graph Metrics & Observability Demo ║");
|
|
56
|
+
console.log("╚══════════════════════════════════════════════╝\n");
|
|
57
|
+
|
|
58
|
+
// Create a metrics collector
|
|
59
|
+
const metrics = createMetricsCollector();
|
|
60
|
+
|
|
61
|
+
// Build a pipeline with metrics enabled
|
|
62
|
+
const pipeline = AgentGraph.pipeline<string, string>(
|
|
63
|
+
// Stage 1: Research
|
|
64
|
+
AgentGraph.sequential({ wrapInput: false }, researchAgent),
|
|
65
|
+
|
|
66
|
+
// Stage 2: Parallel perspectives
|
|
67
|
+
AgentGraph.parallel({ wrapInput: false }, optimistAgent, pessimistAgent),
|
|
68
|
+
|
|
69
|
+
// Stage 3: Transform for voting
|
|
70
|
+
{
|
|
71
|
+
name: "TransformForVoting",
|
|
72
|
+
execute: async (results: string[]) => ({
|
|
73
|
+
originalInput: "Which perspective is better?",
|
|
74
|
+
solutions: results,
|
|
75
|
+
}),
|
|
76
|
+
} as GraphNode<string[], VotingInput>,
|
|
77
|
+
|
|
78
|
+
// Stage 4: Judge votes
|
|
79
|
+
AgentGraph.votingSystem(judgeAgent)
|
|
80
|
+
).withMetrics(metrics);
|
|
81
|
+
|
|
82
|
+
console.log("Running pipeline with metrics collection...\n");
|
|
83
|
+
const startTime = Date.now();
|
|
84
|
+
|
|
85
|
+
try {
|
|
86
|
+
const result = await pipeline.execute("The future of renewable energy");
|
|
87
|
+
const totalTime = Date.now() - startTime;
|
|
88
|
+
|
|
89
|
+
console.log("\n════════════════════════════════════════════════");
|
|
90
|
+
console.log("RESULT:", result);
|
|
91
|
+
console.log("════════════════════════════════════════════════\n");
|
|
92
|
+
|
|
93
|
+
// Display metrics
|
|
94
|
+
console.log("📊 EXECUTION METRICS\n");
|
|
95
|
+
console.log(metrics.toTextVisualization());
|
|
96
|
+
|
|
97
|
+
// Get aggregate metrics
|
|
98
|
+
const aggregate = metrics.getAggregateMetrics();
|
|
99
|
+
|
|
100
|
+
console.log("\n────────────────────────────────────────────────");
|
|
101
|
+
console.log("📈 AGGREGATE STATISTICS\n");
|
|
102
|
+
console.log(`Total Duration: ${aggregate.totalDurationMs}ms`);
|
|
103
|
+
console.log(`Nodes Executed: ${aggregate.nodeCount}`);
|
|
104
|
+
console.log(`Successful: ${aggregate.successCount}`);
|
|
105
|
+
console.log(`Failed: ${aggregate.failureCount}`);
|
|
106
|
+
console.log(`Total Tokens: ${aggregate.totalTokens.totalTokens}`);
|
|
107
|
+
console.log(` - Input Tokens: ${aggregate.totalTokens.inputTokens}`);
|
|
108
|
+
console.log(` - Output Tokens: ${aggregate.totalTokens.outputTokens}`);
|
|
109
|
+
|
|
110
|
+
// Display pipeline structure
|
|
111
|
+
console.log("\n────────────────────────────────────────────────");
|
|
112
|
+
console.log("🏗️ PIPELINE STRUCTURE\n");
|
|
113
|
+
displayStructure(aggregate.structure);
|
|
114
|
+
|
|
115
|
+
// Show JSON output (for external tools)
|
|
116
|
+
console.log("\n────────────────────────────────────────────────");
|
|
117
|
+
console.log("📄 JSON OUTPUT (for visualization tools)\n");
|
|
118
|
+
console.log(metrics.toJSON());
|
|
119
|
+
} catch (error) {
|
|
120
|
+
console.error("Pipeline failed:", error);
|
|
121
|
+
|
|
122
|
+
// Even on failure, we can see what executed
|
|
123
|
+
console.log("\n📊 PARTIAL EXECUTION METRICS\n");
|
|
124
|
+
console.log(metrics.toTextVisualization());
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Display pipeline structure as ASCII tree
|
|
130
|
+
*/
|
|
131
|
+
function displayStructure(
|
|
132
|
+
structure: { type: string; name: string; children?: any[] },
|
|
133
|
+
indent = 0
|
|
134
|
+
): void {
|
|
135
|
+
const prefix = indent === 0 ? "" : " ".repeat(indent - 1) + "├─ ";
|
|
136
|
+
console.log(`${prefix}[${structure.type}] ${structure.name}`);
|
|
137
|
+
|
|
138
|
+
if (structure.children) {
|
|
139
|
+
for (const child of structure.children) {
|
|
140
|
+
displayStructure(child, indent + 1);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Example: Comparing execution times
|
|
147
|
+
*/
|
|
148
|
+
async function runTimingComparison() {
|
|
149
|
+
console.log("\n╔══════════════════════════════════════════════╗");
|
|
150
|
+
console.log("║ Timing Comparison Example ║");
|
|
151
|
+
console.log("╚══════════════════════════════════════════════╝\n");
|
|
152
|
+
|
|
153
|
+
const quickAgent = new ClaudeAgent({
|
|
154
|
+
id: "quick",
|
|
155
|
+
name: "Quick Agent",
|
|
156
|
+
description: "Say 'Hello' only.",
|
|
157
|
+
apiKey,
|
|
158
|
+
maxTokens: 8,
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// Sequential execution
|
|
162
|
+
const seqMetrics = createMetricsCollector();
|
|
163
|
+
const sequential = AgentGraph.sequential(
|
|
164
|
+
{ wrapInput: false },
|
|
165
|
+
quickAgent,
|
|
166
|
+
quickAgent,
|
|
167
|
+
quickAgent
|
|
168
|
+
).withMetrics(seqMetrics);
|
|
169
|
+
|
|
170
|
+
console.log("Running 3 agents SEQUENTIALLY...");
|
|
171
|
+
await sequential.execute("test");
|
|
172
|
+
const seqAggregate = seqMetrics.getAggregateMetrics();
|
|
173
|
+
console.log(`Sequential time: ${seqAggregate.totalDurationMs}ms\n`);
|
|
174
|
+
|
|
175
|
+
// Parallel execution
|
|
176
|
+
const parMetrics = createMetricsCollector();
|
|
177
|
+
const parallel = AgentGraph.parallel(
|
|
178
|
+
{ wrapInput: false },
|
|
179
|
+
quickAgent,
|
|
180
|
+
quickAgent,
|
|
181
|
+
quickAgent
|
|
182
|
+
).withMetrics(parMetrics);
|
|
183
|
+
|
|
184
|
+
console.log("Running 3 agents in PARALLEL...");
|
|
185
|
+
await parallel.execute("test");
|
|
186
|
+
const parAggregate = parMetrics.getAggregateMetrics();
|
|
187
|
+
console.log(`Parallel time: ${parAggregate.totalDurationMs}ms\n`);
|
|
188
|
+
|
|
189
|
+
const speedup = seqAggregate.totalDurationMs / parAggregate.totalDurationMs;
|
|
190
|
+
console.log(`Speedup: ${speedup.toFixed(2)}x faster with parallel execution`);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Example: Error tracking
|
|
195
|
+
*/
|
|
196
|
+
async function runErrorTrackingExample() {
|
|
197
|
+
console.log("\n╔══════════════════════════════════════════════╗");
|
|
198
|
+
console.log("║ Error Tracking Example ║");
|
|
199
|
+
console.log("╚══════════════════════════════════════════════╝\n");
|
|
200
|
+
|
|
201
|
+
const failingNode: GraphNode<string, string> = {
|
|
202
|
+
name: "FailingNode",
|
|
203
|
+
execute: async () => {
|
|
204
|
+
throw new Error("Simulated failure!");
|
|
205
|
+
},
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
const metrics = createMetricsCollector();
|
|
209
|
+
const pipeline = AgentGraph.pipeline(
|
|
210
|
+
AgentGraph.sequential({ wrapInput: false }, researchAgent),
|
|
211
|
+
failingNode
|
|
212
|
+
).withMetrics(metrics);
|
|
213
|
+
|
|
214
|
+
console.log("Running pipeline with a failing stage...\n");
|
|
215
|
+
|
|
216
|
+
try {
|
|
217
|
+
await pipeline.execute("test topic");
|
|
218
|
+
} catch (error) {
|
|
219
|
+
console.log("Pipeline failed as expected.\n");
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
console.log("📊 METRICS (showing failure):\n");
|
|
223
|
+
console.log(metrics.toTextVisualization());
|
|
224
|
+
|
|
225
|
+
const aggregate = metrics.getAggregateMetrics();
|
|
226
|
+
console.log(
|
|
227
|
+
`\nSuccess rate: ${aggregate.successCount}/${aggregate.nodeCount}`
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Run all examples
|
|
232
|
+
async function main() {
|
|
233
|
+
await runMetricsExample();
|
|
234
|
+
await runTimingComparison();
|
|
235
|
+
await runErrorTrackingExample();
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
main().catch(console.error);
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parallel Executor Example
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates running multiple agents concurrently on the same input.
|
|
5
|
+
* Each agent provides their unique perspective simultaneously.
|
|
6
|
+
*
|
|
7
|
+
* Use case: Getting multiple expert opinions on a topic
|
|
8
|
+
*/
|
|
9
|
+
import "dotenv/config";
|
|
10
|
+
import { ClaudeAgent } from "../../lib/agents/anthropic/ClaudeAgent";
|
|
11
|
+
import { AgentGraph } from "../../lib/graph/AgentGraph";
|
|
12
|
+
import { AgentEvent } from "../../lib/agents/AgentEvent";
|
|
13
|
+
|
|
14
|
+
const apiKey = process.env.ANTHROPIC_API_KEY as string;
|
|
15
|
+
console.log("apiKey", apiKey);
|
|
16
|
+
if (!apiKey) {
|
|
17
|
+
console.error("Please set ANTHROPIC_API_KEY environment variable");
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Expert 1: Technical perspective
|
|
22
|
+
const technicalExpert = new ClaudeAgent({
|
|
23
|
+
id: "tech-expert",
|
|
24
|
+
name: "Technical Expert",
|
|
25
|
+
description: `You are a technical expert specializing in technology and engineering.
|
|
26
|
+
Analyze topics from a technical feasibility and implementation perspective.
|
|
27
|
+
Focus on: technical challenges, solutions, innovations, and practical considerations.
|
|
28
|
+
Keep your analysis concise (under 150 words).`,
|
|
29
|
+
apiKey,
|
|
30
|
+
maxTokens: 512,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// Expert 2: Economic perspective
|
|
34
|
+
const economicExpert = new ClaudeAgent({
|
|
35
|
+
id: "econ-expert",
|
|
36
|
+
name: "Economic Expert",
|
|
37
|
+
description: `You are an economic expert specializing in markets and business.
|
|
38
|
+
Analyze topics from an economic and business perspective.
|
|
39
|
+
Focus on: costs, benefits, market impact, investment potential, and economic trends.
|
|
40
|
+
Keep your analysis concise (under 150 words).`,
|
|
41
|
+
apiKey,
|
|
42
|
+
maxTokens: 512,
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// Expert 3: Social perspective
|
|
46
|
+
const socialExpert = new ClaudeAgent({
|
|
47
|
+
id: "social-expert",
|
|
48
|
+
name: "Social Expert",
|
|
49
|
+
description: `You are a social scientist specializing in societal impact.
|
|
50
|
+
Analyze topics from a social and human perspective.
|
|
51
|
+
Focus on: social implications, ethical considerations, human behavior, and cultural impact.
|
|
52
|
+
Keep your analysis concise (under 150 words).`,
|
|
53
|
+
apiKey,
|
|
54
|
+
maxTokens: 512,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// Expert 4: Environmental perspective
|
|
58
|
+
const environmentalExpert = new ClaudeAgent({
|
|
59
|
+
id: "env-expert",
|
|
60
|
+
name: "Environmental Expert",
|
|
61
|
+
description: `You are an environmental scientist.
|
|
62
|
+
Analyze topics from an environmental and sustainability perspective.
|
|
63
|
+
Focus on: environmental impact, sustainability, resource usage, and ecological considerations.
|
|
64
|
+
Keep your analysis concise (under 150 words).`,
|
|
65
|
+
apiKey,
|
|
66
|
+
maxTokens: 512,
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
async function runParallelExample() {
|
|
70
|
+
console.log("=== Parallel Executor Example ===\n");
|
|
71
|
+
console.log("Running 4 experts in parallel to analyze a topic\n");
|
|
72
|
+
|
|
73
|
+
// Create parallel executor with all experts
|
|
74
|
+
const expertPanel = AgentGraph.parallel(
|
|
75
|
+
{ wrapInput: false }, // Pass raw input to each expert
|
|
76
|
+
technicalExpert,
|
|
77
|
+
economicExpert,
|
|
78
|
+
socialExpert,
|
|
79
|
+
environmentalExpert
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
// Track timing
|
|
83
|
+
const experts = [
|
|
84
|
+
technicalExpert,
|
|
85
|
+
economicExpert,
|
|
86
|
+
socialExpert,
|
|
87
|
+
environmentalExpert,
|
|
88
|
+
];
|
|
89
|
+
const startTimes: Record<string, number> = {};
|
|
90
|
+
|
|
91
|
+
experts.forEach((expert) => {
|
|
92
|
+
expert.addListener(AgentEvent.BEFORE_EXECUTE, () => {
|
|
93
|
+
startTimes[expert.getId()] = Date.now();
|
|
94
|
+
console.log(`>>> ${expert.getName()} starting analysis...`);
|
|
95
|
+
});
|
|
96
|
+
expert.addListener(AgentEvent.DONE, () => {
|
|
97
|
+
const elapsed = Date.now() - startTimes[expert.getId()];
|
|
98
|
+
console.log(`<<< ${expert.getName()} completed (${elapsed}ms)`);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
const topic = "The rise of electric vehicles and autonomous driving";
|
|
103
|
+
console.log(`Topic: "${topic}"\n`);
|
|
104
|
+
|
|
105
|
+
const overallStart = Date.now();
|
|
106
|
+
|
|
107
|
+
try {
|
|
108
|
+
const results = await expertPanel.execute(topic);
|
|
109
|
+
const totalTime = Date.now() - overallStart;
|
|
110
|
+
|
|
111
|
+
console.log("\n=== Expert Opinions ===\n");
|
|
112
|
+
|
|
113
|
+
const expertNames = ["Technical", "Economic", "Social", "Environmental"];
|
|
114
|
+
results.forEach((result, index) => {
|
|
115
|
+
console.log(`--- ${expertNames[index]} Perspective ---`);
|
|
116
|
+
console.log(result);
|
|
117
|
+
console.log();
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
console.log(`Total time: ${totalTime}ms (parallel execution)`);
|
|
121
|
+
console.log("Note: Sequential execution would take ~4x longer\n");
|
|
122
|
+
} catch (error) {
|
|
123
|
+
console.error("Expert panel failed:", error);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Demonstrate isolated vs shared execution
|
|
128
|
+
async function runIsolationExample() {
|
|
129
|
+
console.log("\n=== Isolation Modes ===\n");
|
|
130
|
+
|
|
131
|
+
const analyst1 = new ClaudeAgent({
|
|
132
|
+
id: "analyst-1",
|
|
133
|
+
name: "Analyst 1",
|
|
134
|
+
description: `Provide a brief one-sentence analysis of the topic.`,
|
|
135
|
+
apiKey,
|
|
136
|
+
maxTokens: 100,
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
const analyst2 = new ClaudeAgent({
|
|
140
|
+
id: "analyst-2",
|
|
141
|
+
name: "Analyst 2",
|
|
142
|
+
description: `Provide a brief one-sentence analysis of the topic.`,
|
|
143
|
+
apiKey,
|
|
144
|
+
maxTokens: 100,
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// Isolated execution - each agent works independently
|
|
148
|
+
const isolatedPanel = AgentGraph.parallel(
|
|
149
|
+
{ isolatedExecution: true, wrapInput: false },
|
|
150
|
+
analyst1,
|
|
151
|
+
analyst2
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
console.log("Running with isolated execution...");
|
|
155
|
+
const results = await isolatedPanel.execute("Climate change");
|
|
156
|
+
|
|
157
|
+
console.log("\nAnalyst 1:", results[0]);
|
|
158
|
+
console.log("Analyst 2:", results[1]);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Run examples
|
|
162
|
+
async function main() {
|
|
163
|
+
await runParallelExample();
|
|
164
|
+
await runIsolationExample();
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
main().catch(console.error);
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pipeline Example
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates building complex multi-stage workflows by composing
|
|
5
|
+
* different executor types together.
|
|
6
|
+
*
|
|
7
|
+
* Use case: Complete research workflow with parallel experts and voting
|
|
8
|
+
*/
|
|
9
|
+
import "dotenv/config";
|
|
10
|
+
import { ClaudeAgent } from "../../lib/agents/anthropic/ClaudeAgent";
|
|
11
|
+
import { AgentGraph, GraphNode, VotingInput } from "../../lib/graph/AgentGraph";
|
|
12
|
+
import { AgentEvent } from "../../lib/agents/AgentEvent";
|
|
13
|
+
|
|
14
|
+
const apiKey = process.env.ANTHROPIC_API_KEY as string;
|
|
15
|
+
|
|
16
|
+
if (!apiKey) {
|
|
17
|
+
console.error("Please set ANTHROPIC_API_KEY environment variable");
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Stage 1: Research Agent
|
|
22
|
+
const researchAgent = new ClaudeAgent({
|
|
23
|
+
id: "researcher",
|
|
24
|
+
name: "Researcher",
|
|
25
|
+
description: `You are a research assistant. Given a topic, provide a clear, factual overview.
|
|
26
|
+
Focus on the most important and interesting aspects.
|
|
27
|
+
Keep your response under 200 words.`,
|
|
28
|
+
apiKey,
|
|
29
|
+
maxTokens: 512,
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
// Stage 2: Parallel Experts
|
|
33
|
+
const optimistExpert = new ClaudeAgent({
|
|
34
|
+
id: "optimist",
|
|
35
|
+
name: "Optimist",
|
|
36
|
+
description: `You analyze research findings with an optimistic lens.
|
|
37
|
+
Highlight opportunities, positive developments, and potential benefits.
|
|
38
|
+
Keep your analysis under 100 words.`,
|
|
39
|
+
apiKey,
|
|
40
|
+
maxTokens: 256,
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const pessimistExpert = new ClaudeAgent({
|
|
44
|
+
id: "pessimist",
|
|
45
|
+
name: "Pessimist",
|
|
46
|
+
description: `You analyze research findings with a critical lens.
|
|
47
|
+
Highlight risks, challenges, and potential problems.
|
|
48
|
+
Keep your analysis under 100 words.`,
|
|
49
|
+
apiKey,
|
|
50
|
+
maxTokens: 256,
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const realistExpert = new ClaudeAgent({
|
|
54
|
+
id: "realist",
|
|
55
|
+
name: "Realist",
|
|
56
|
+
description: `You analyze research findings with a balanced, realistic lens.
|
|
57
|
+
Present both opportunities and challenges objectively.
|
|
58
|
+
Keep your analysis under 100 words.`,
|
|
59
|
+
apiKey,
|
|
60
|
+
maxTokens: 256,
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// Stage 3: Judge
|
|
64
|
+
const judgeAgent = new ClaudeAgent({
|
|
65
|
+
id: "judge",
|
|
66
|
+
name: "Judge",
|
|
67
|
+
description: `You synthesize multiple expert perspectives into a final, balanced conclusion.
|
|
68
|
+
Combine the best insights from each perspective.
|
|
69
|
+
Provide actionable takeaways.
|
|
70
|
+
Keep your synthesis under 150 words.`,
|
|
71
|
+
apiKey,
|
|
72
|
+
maxTokens: 384,
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// Custom transformer node to prepare data for voting
|
|
76
|
+
const prepareForVoting: GraphNode<string[], VotingInput> = {
|
|
77
|
+
execute: async (expertResults: string[]) => {
|
|
78
|
+
// Store the original question for later (in real use, you'd pass this through context)
|
|
79
|
+
return {
|
|
80
|
+
originalInput:
|
|
81
|
+
"Synthesize these expert analyses into a balanced conclusion",
|
|
82
|
+
solutions: expertResults,
|
|
83
|
+
};
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
async function runFullPipelineExample() {
|
|
88
|
+
console.log("=== Full Pipeline Example ===\n");
|
|
89
|
+
console.log(
|
|
90
|
+
"Pipeline: Research -> Parallel Experts -> Transform -> Voting\n"
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
// Build the complete pipeline
|
|
94
|
+
const analysisPipeline = AgentGraph.pipeline(
|
|
95
|
+
// Stage 1: Initial research (sequential with single agent)
|
|
96
|
+
AgentGraph.sequential({ wrapInput: false }, researchAgent),
|
|
97
|
+
|
|
98
|
+
// Stage 2: Parallel expert analysis
|
|
99
|
+
AgentGraph.parallel(
|
|
100
|
+
{ wrapInput: false },
|
|
101
|
+
optimistExpert,
|
|
102
|
+
pessimistExpert,
|
|
103
|
+
realistExpert
|
|
104
|
+
),
|
|
105
|
+
|
|
106
|
+
// Stage 3: Transform results for voting
|
|
107
|
+
prepareForVoting,
|
|
108
|
+
|
|
109
|
+
// Stage 4: Judge synthesizes final answer
|
|
110
|
+
AgentGraph.votingSystem(judgeAgent)
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
// Add logging
|
|
114
|
+
const allAgents = [
|
|
115
|
+
researchAgent,
|
|
116
|
+
optimistExpert,
|
|
117
|
+
pessimistExpert,
|
|
118
|
+
realistExpert,
|
|
119
|
+
judgeAgent,
|
|
120
|
+
];
|
|
121
|
+
allAgents.forEach((agent) => {
|
|
122
|
+
agent.addListener(AgentEvent.BEFORE_EXECUTE, () => {
|
|
123
|
+
console.log(` > ${agent.getName()} working...`);
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
const topic = "The future of remote work";
|
|
128
|
+
console.log(`Topic: "${topic}"\n`);
|
|
129
|
+
console.log("Running pipeline...\n");
|
|
130
|
+
|
|
131
|
+
const startTime = Date.now();
|
|
132
|
+
|
|
133
|
+
try {
|
|
134
|
+
const result = await analysisPipeline.execute(topic);
|
|
135
|
+
const elapsed = Date.now() - startTime;
|
|
136
|
+
|
|
137
|
+
console.log("\n=== Final Synthesized Analysis ===\n");
|
|
138
|
+
console.log(result);
|
|
139
|
+
console.log(`\nCompleted in ${elapsed}ms`);
|
|
140
|
+
} catch (error) {
|
|
141
|
+
console.error("Pipeline failed:", error);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Demonstrate pipeline with custom intermediate stages
|
|
146
|
+
async function runCustomStagesPipeline() {
|
|
147
|
+
console.log("\n=== Pipeline with Custom Stages ===\n");
|
|
148
|
+
|
|
149
|
+
const writer = new ClaudeAgent({
|
|
150
|
+
id: "writer",
|
|
151
|
+
name: "Writer",
|
|
152
|
+
description: `Write a short paragraph about the given topic. Keep it under 50 words.`,
|
|
153
|
+
apiKey,
|
|
154
|
+
maxTokens: 128,
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
// Build pipeline with custom transformation stages
|
|
158
|
+
const textPipeline = AgentGraph.pipeline<string, string>(
|
|
159
|
+
// Stage 1: Write initial content
|
|
160
|
+
AgentGraph.sequential({ wrapInput: false }, writer),
|
|
161
|
+
|
|
162
|
+
// Stage 2: Custom transformation - convert to uppercase
|
|
163
|
+
{
|
|
164
|
+
execute: async (text: string) => {
|
|
165
|
+
console.log(" > Transforming to uppercase...");
|
|
166
|
+
return text.toUpperCase();
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
|
|
170
|
+
// Stage 3: Custom transformation - add decoration
|
|
171
|
+
{
|
|
172
|
+
execute: async (text: string) => {
|
|
173
|
+
console.log(" > Adding decoration...");
|
|
174
|
+
return `✨ ${text} ✨`;
|
|
175
|
+
},
|
|
176
|
+
}
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
const result = await textPipeline.execute("The beauty of nature");
|
|
180
|
+
console.log("\nResult:");
|
|
181
|
+
console.log(result);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Demonstrate building pipeline incrementally
|
|
185
|
+
async function runIncrementalPipeline() {
|
|
186
|
+
console.log("\n=== Incremental Pipeline Building ===\n");
|
|
187
|
+
|
|
188
|
+
// Build pipeline with explicit stages using AgentGraph.pipeline
|
|
189
|
+
// Each stage transforms the data: number -> number -> number -> string
|
|
190
|
+
const pipeline = AgentGraph.pipeline<number, string>(
|
|
191
|
+
{
|
|
192
|
+
execute: async (n: number) => {
|
|
193
|
+
console.log(` > Doubling ${n}...`);
|
|
194
|
+
return n * 2;
|
|
195
|
+
},
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
execute: async (n: number) => {
|
|
199
|
+
console.log(` > Adding 10 to ${n}...`);
|
|
200
|
+
return n + 10;
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
execute: async (n: number) => {
|
|
205
|
+
console.log(` > Converting ${n} to string...`);
|
|
206
|
+
return `The result is: ${n}`;
|
|
207
|
+
},
|
|
208
|
+
}
|
|
209
|
+
);
|
|
210
|
+
|
|
211
|
+
console.log("Pipeline stages:", pipeline.length);
|
|
212
|
+
console.log("Input: 5\n");
|
|
213
|
+
|
|
214
|
+
const result = await pipeline.execute(5);
|
|
215
|
+
console.log("\nOutput:", result);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Run all examples
|
|
219
|
+
async function main() {
|
|
220
|
+
await runFullPipelineExample();
|
|
221
|
+
await runCustomStagesPipeline();
|
|
222
|
+
await runIncrementalPipeline();
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
main().catch(console.error);
|