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.
Files changed (44) hide show
  1. package/chunking-demo.ts +339 -0
  2. package/cleanup-duplicates.ts +142 -0
  3. package/data/flower.jpg +0 -0
  4. package/generative.ts +128 -0
  5. package/graph/context-example.ts +209 -0
  6. package/graph/data-pipeline/agents.ts +60 -0
  7. package/graph/data-pipeline/fetchers.ts +166 -0
  8. package/graph/data-pipeline/index.ts +282 -0
  9. package/graph/index.ts +154 -0
  10. package/graph/map-example.ts +227 -0
  11. package/graph/metrics-example.ts +238 -0
  12. package/graph/parallel-example.ts +167 -0
  13. package/graph/pipeline-example.ts +225 -0
  14. package/graph/planning-example.ts +406 -0
  15. package/graph/router-example.ts +226 -0
  16. package/graph/sequential-example.ts +141 -0
  17. package/graph/voting-example.ts +159 -0
  18. package/graph-rag/docker-compose.yaml +14 -0
  19. package/graph-rag/index.js +99 -0
  20. package/graph-rag/init-db.sh +7 -0
  21. package/graph-rag/package.json +15 -0
  22. package/history-compression-example.ts +163 -0
  23. package/history-persistence.ts +347 -0
  24. package/index.ts +175 -0
  25. package/ingestion-pipeline.ts +353 -0
  26. package/mcp-airbnb-example.ts +69 -0
  27. package/mcp-http-example.ts +70 -0
  28. package/mcp-stdio-example.ts +63 -0
  29. package/multimodal.ts +144 -0
  30. package/ollama.ts +148 -0
  31. package/openai-compatible.ts +141 -0
  32. package/opensearch-vector-store.ts +342 -0
  33. package/package.json +24 -0
  34. package/pubmed.ts +289 -0
  35. package/reasoning-with-sub-agent.ts +311 -0
  36. package/synchronous/index.ts +48 -0
  37. package/tsconfig.json +8 -0
  38. package/vector-store-filtering.ts +303 -0
  39. package/vector-store.ts +210 -0
  40. package/vectorstore/index.ts +0 -0
  41. package/vectorstore/store/dbService.ts +80 -0
  42. package/voyage-embeddings.ts +99 -0
  43. package/weather-with-sub-agent.ts +276 -0
  44. package/weather.ts +389 -0
@@ -0,0 +1,282 @@
1
+ /**
2
+ * Data Pipeline Example
3
+ *
4
+ * Demonstrates the factory pattern for creating data-fetching pipelines.
5
+ *
6
+ * Key concepts:
7
+ * - Factories capture context (user, config) at creation time
8
+ * - Pipeline data flow stays simple (string -> string)
9
+ * - Security/permissions are handled at the factory level
10
+ * - Easy to compose different fetchers for different use cases
11
+ *
12
+ * Run with: npx ts-node examples/graph/data-pipeline/index.ts
13
+ */
14
+
15
+ import "dotenv/config";
16
+ import {
17
+ AgentGraph,
18
+ GraphNode,
19
+ createMetricsCollector,
20
+ } from "../../../lib/graph/AgentGraph";
21
+ import {
22
+ createDatabaseFetcher,
23
+ createWebFetcher,
24
+ createVectorDbFetcher,
25
+ UserContext,
26
+ } from "./fetchers";
27
+ import { createPipelineAgents } from "./agents";
28
+
29
+ const apiKey = process.env.ANTHROPIC_API_KEY;
30
+
31
+ if (!apiKey) {
32
+ console.error("Please set ANTHROPIC_API_KEY environment variable");
33
+ process.exit(1);
34
+ }
35
+
36
+ // ============================================================================
37
+ // Helper: Combine Multiple Data Sources
38
+ // ============================================================================
39
+
40
+ /**
41
+ * Creates a node that combines results from multiple fetchers.
42
+ * Each fetcher runs in parallel, results are concatenated.
43
+ */
44
+ function createDataCombiner(
45
+ ...fetchers: GraphNode<string, string>[]
46
+ ): GraphNode<string, string> {
47
+ return {
48
+ name: "DataCombiner",
49
+ nodeType: "custom",
50
+ execute: async (topic: string) => {
51
+ console.log(`\n [COMBINE] Fetching from ${fetchers.length} sources in parallel...`);
52
+
53
+ // Run all fetchers in parallel
54
+ const results = await Promise.all(
55
+ fetchers.map((f) => f.execute(topic))
56
+ );
57
+
58
+ // Combine results with clear separation
59
+ return results.join("\n\n");
60
+ },
61
+ };
62
+ }
63
+
64
+ // ============================================================================
65
+ // Example 1: Basic Data Pipeline with Permissions
66
+ // ============================================================================
67
+
68
+ async function runBasicPipeline() {
69
+ console.log("╔══════════════════════════════════════════════════════════════╗");
70
+ console.log("║ Example 1: Basic Data Pipeline with Permissions ║");
71
+ console.log("╚══════════════════════════════════════════════════════════════╝\n");
72
+
73
+ // Simulate a user with limited permissions
74
+ const regularUser: UserContext = {
75
+ userId: "user-123",
76
+ tenantId: "acme-corp",
77
+ permissions: ["read:tech", "read:research"],
78
+ };
79
+
80
+ // Create fetchers with user context baked in
81
+ const dbFetcher = createDatabaseFetcher(regularUser);
82
+ const webFetcher = createWebFetcher();
83
+
84
+ // Create agents
85
+ const { summarizerAgent } = createPipelineAgents(apiKey);
86
+
87
+ // Build pipeline: Combine sources -> Summarize
88
+ const pipeline = AgentGraph.pipeline<string, string>(
89
+ createDataCombiner(dbFetcher, webFetcher),
90
+ AgentGraph.sequential({ wrapInput: false }, summarizerAgent)
91
+ );
92
+
93
+ console.log("User:", regularUser.userId);
94
+ console.log("Permissions:", regularUser.permissions.join(", "));
95
+ console.log("\n--- Running pipeline for 'quantum computing' ---\n");
96
+
97
+ const result = await pipeline.execute("quantum computing");
98
+
99
+ console.log("\n=== Result ===\n");
100
+ console.log(result);
101
+ }
102
+
103
+ // ============================================================================
104
+ // Example 2: Access Denied Scenario
105
+ // ============================================================================
106
+
107
+ async function runAccessDeniedExample() {
108
+ console.log("\n╔══════════════════════════════════════════════════════════════╗");
109
+ console.log("║ Example 2: Access Denied Scenario ║");
110
+ console.log("╚══════════════════════════════════════════════════════════════╝\n");
111
+
112
+ // User without finance permissions
113
+ const limitedUser: UserContext = {
114
+ userId: "intern-456",
115
+ tenantId: "acme-corp",
116
+ permissions: ["read:research"], // No finance access
117
+ };
118
+
119
+ const dbFetcher = createDatabaseFetcher(limitedUser);
120
+ const { summarizerAgent } = createPipelineAgents(apiKey);
121
+
122
+ const pipeline = AgentGraph.pipeline<string, string>(
123
+ dbFetcher,
124
+ AgentGraph.sequential({ wrapInput: false }, summarizerAgent)
125
+ );
126
+
127
+ console.log("User:", limitedUser.userId);
128
+ console.log("Permissions:", limitedUser.permissions.join(", "));
129
+ console.log("\n--- Attempting to access 'financials' ---\n");
130
+
131
+ const result = await pipeline.execute("financials");
132
+
133
+ console.log("\n=== Result ===\n");
134
+ console.log(result);
135
+ }
136
+
137
+ // ============================================================================
138
+ // Example 3: Multi-Source Research Pipeline
139
+ // ============================================================================
140
+
141
+ async function runMultiSourcePipeline() {
142
+ console.log("\n╔══════════════════════════════════════════════════════════════╗");
143
+ console.log("║ Example 3: Multi-Source Research Pipeline ║");
144
+ console.log("╚══════════════════════════════════════════════════════════════╝\n");
145
+
146
+ // Admin user with full access
147
+ const adminUser: UserContext = {
148
+ userId: "admin-001",
149
+ tenantId: "acme-corp",
150
+ permissions: ["read:tech", "read:research", "read:medical", "read:finance"],
151
+ };
152
+
153
+ // Create multiple fetchers
154
+ const dbFetcher = createDatabaseFetcher(adminUser);
155
+ const webFetcher = createWebFetcher();
156
+ const vectorFetcher = createVectorDbFetcher(adminUser, {
157
+ collection: "research-papers",
158
+ topK: 3
159
+ });
160
+
161
+ // Create agents
162
+ const { analyzerAgent, summarizerAgent } = createPipelineAgents(apiKey);
163
+
164
+ // Create metrics collector
165
+ const metrics = createMetricsCollector();
166
+
167
+ // Build comprehensive research pipeline
168
+ const researchPipeline = AgentGraph.pipeline<string, string>(
169
+ // Stage 1: Fetch from all sources in parallel
170
+ createDataCombiner(dbFetcher, webFetcher, vectorFetcher),
171
+
172
+ // Stage 2: Deep analysis
173
+ AgentGraph.sequential({ wrapInput: false }, analyzerAgent),
174
+
175
+ // Stage 3: Executive summary
176
+ AgentGraph.sequential({ wrapInput: false }, summarizerAgent)
177
+ ).withMetrics(metrics);
178
+
179
+ console.log("User:", adminUser.userId);
180
+ console.log("Data sources: Database, Web, VectorDB");
181
+ console.log("\n--- Running comprehensive research on 'penicillin' ---\n");
182
+
183
+ const result = await researchPipeline.execute("penicillin");
184
+
185
+ console.log("\n=== Executive Summary ===\n");
186
+ console.log(result);
187
+
188
+ // Show metrics
189
+ console.log("\n=== Pipeline Metrics ===\n");
190
+ console.log(metrics.toTextVisualization());
191
+
192
+ const aggregate = metrics.getAggregateMetrics();
193
+ console.log(`\nTotal duration: ${aggregate.totalDurationMs}ms`);
194
+ console.log(`Total tokens: ${aggregate.totalTokens.totalTokens}`);
195
+ }
196
+
197
+ // ============================================================================
198
+ // Example 4: Dynamic Pipeline Based on User Role
199
+ // ============================================================================
200
+
201
+ async function runRoleBasedPipeline() {
202
+ console.log("\n╔══════════════════════════════════════════════════════════════╗");
203
+ console.log("║ Example 4: Dynamic Pipeline Based on User Role ║");
204
+ console.log("╚══════════════════════════════════════════════════════════════╝\n");
205
+
206
+ /**
207
+ * Factory that creates different pipelines based on user role.
208
+ * Demonstrates how to compose pipelines dynamically.
209
+ */
210
+ function createPipelineForUser(
211
+ user: UserContext & { role: "basic" | "researcher" | "admin" }
212
+ ): GraphNode<string, string> {
213
+ const { summarizerAgent, analyzerAgent } = createPipelineAgents(apiKey);
214
+
215
+ switch (user.role) {
216
+ case "basic":
217
+ // Basic users only get web data
218
+ console.log(`Creating basic pipeline for ${user.userId}`);
219
+ return AgentGraph.pipeline(
220
+ createWebFetcher(),
221
+ AgentGraph.sequential({ wrapInput: false }, summarizerAgent)
222
+ );
223
+
224
+ case "researcher":
225
+ // Researchers get DB + web
226
+ console.log(`Creating researcher pipeline for ${user.userId}`);
227
+ return AgentGraph.pipeline(
228
+ createDataCombiner(
229
+ createDatabaseFetcher(user),
230
+ createWebFetcher()
231
+ ),
232
+ AgentGraph.sequential({ wrapInput: false }, analyzerAgent),
233
+ AgentGraph.sequential({ wrapInput: false }, summarizerAgent)
234
+ );
235
+
236
+ case "admin":
237
+ // Admins get everything
238
+ console.log(`Creating admin pipeline for ${user.userId}`);
239
+ return AgentGraph.pipeline(
240
+ createDataCombiner(
241
+ createDatabaseFetcher(user),
242
+ createWebFetcher(),
243
+ createVectorDbFetcher(user)
244
+ ),
245
+ AgentGraph.sequential({ wrapInput: false }, analyzerAgent),
246
+ AgentGraph.sequential({ wrapInput: false }, summarizerAgent)
247
+ );
248
+ }
249
+ }
250
+
251
+ // Test with different roles
252
+ const basicUser = {
253
+ userId: "basic-user",
254
+ tenantId: "acme-corp",
255
+ permissions: [],
256
+ role: "basic" as const,
257
+ };
258
+
259
+ const pipeline = createPipelineForUser(basicUser);
260
+
261
+ console.log("\n--- Running with basic user role ---\n");
262
+
263
+ const result = await pipeline.execute("climate change");
264
+
265
+ console.log("\n=== Result ===\n");
266
+ console.log(result);
267
+ }
268
+
269
+ // ============================================================================
270
+ // Main
271
+ // ============================================================================
272
+
273
+ async function main() {
274
+ await runBasicPipeline();
275
+ await runAccessDeniedExample();
276
+ await runMultiSourcePipeline();
277
+ await runRoleBasedPipeline();
278
+
279
+ console.log("\n✓ All examples completed");
280
+ }
281
+
282
+ main().catch(console.error);
package/graph/index.ts ADDED
@@ -0,0 +1,154 @@
1
+ /**
2
+ * Graph Examples Index
3
+ *
4
+ * Run individual examples:
5
+ * npx ts-node examples/graph/sequential-example.ts
6
+ * npx ts-node examples/graph/parallel-example.ts
7
+ * npx ts-node examples/graph/voting-example.ts
8
+ * npx ts-node examples/graph/pipeline-example.ts
9
+ * npx ts-node examples/graph/map-example.ts
10
+ * npx ts-node examples/graph/router-example.ts
11
+ *
12
+ * Or run this file for a quick demo:
13
+ * npx ts-node examples/graph/index.ts
14
+ */
15
+ import "dotenv/config";
16
+ import { ClaudeAgent } from "../../lib/agents/anthropic/ClaudeAgent";
17
+ import { AgentGraph, VotingInput, GraphNode } from "../../lib/graph/AgentGraph";
18
+
19
+ const apiKey = process.env.ANTHROPIC_API_KEY;
20
+
21
+ if (!apiKey) {
22
+ console.error("Please set ANTHROPIC_API_KEY environment variable");
23
+ process.exit(1);
24
+ }
25
+
26
+ /**
27
+ * Quick demo showcasing all graph executor types
28
+ */
29
+ async function quickDemo() {
30
+ console.log("╔══════════════════════════════════════════╗");
31
+ console.log("║ Agention Graph System Quick Demo ║");
32
+ console.log("╚══════════════════════════════════════════╝\n");
33
+
34
+ // Create some simple agents for demonstration
35
+ const uppercaseAgent = new ClaudeAgent({
36
+ id: "uppercase",
37
+ name: "Uppercase Agent",
38
+ description:
39
+ "Convert the input to uppercase. Output only the uppercase text.",
40
+ apiKey,
41
+ maxTokens: 100,
42
+ });
43
+
44
+ const excitedAgent = new ClaudeAgent({
45
+ id: "excited",
46
+ name: "Excited Agent",
47
+ description:
48
+ "Add excitement to the text by adding exclamation marks and enthusiastic words. Keep it short.",
49
+ apiKey,
50
+ maxTokens: 100,
51
+ });
52
+
53
+ const calmAgent = new ClaudeAgent({
54
+ id: "calm",
55
+ name: "Calm Agent",
56
+ description:
57
+ "Make the text calmer and more relaxed. Use peaceful language. Keep it short.",
58
+ apiKey,
59
+ maxTokens: 100,
60
+ });
61
+
62
+ const judgeAgent = new ClaudeAgent({
63
+ id: "judge",
64
+ name: "Judge Agent",
65
+ description:
66
+ "You receive two versions of text. Pick the better one. Output only 'Version 1' or 'Version 2'.",
67
+ apiKey,
68
+ maxTokens: 20,
69
+ });
70
+
71
+ // 1. Sequential Example
72
+ console.log("1. SEQUENTIAL EXECUTOR");
73
+ console.log(" Chain: Input -> Uppercase -> Excited\n");
74
+
75
+ const sequential = AgentGraph.sequential(
76
+ { wrapInput: false },
77
+ uppercaseAgent,
78
+ excitedAgent
79
+ );
80
+
81
+ const seqResult = await sequential.execute("hello world");
82
+ console.log(` Input: "hello world"`);
83
+ console.log(` Output: "${seqResult}"\n`);
84
+
85
+ // 2. Parallel Example
86
+ console.log("2. PARALLEL EXECUTOR");
87
+ console.log(" Running Excited and Calm agents in parallel\n");
88
+
89
+ const parallel = AgentGraph.parallel(
90
+ { wrapInput: false },
91
+ excitedAgent,
92
+ calmAgent
93
+ );
94
+
95
+ const parResults = await parallel.execute("The sun is shining");
96
+ console.log(` Input: "The sun is shining"`);
97
+ console.log(` Excited: "${parResults[0]}"`);
98
+ console.log(` Calm: "${parResults[1]}"\n`);
99
+
100
+ // 3. Voting Example
101
+ console.log("3. VOTING SYSTEM");
102
+ console.log(" Judge picks between excited and calm versions\n");
103
+
104
+ const voting = AgentGraph.votingSystem(judgeAgent);
105
+ const votingInput: VotingInput = {
106
+ originalInput: "Pick the better version",
107
+ solutions: parResults,
108
+ };
109
+
110
+ const verdict = await voting.execute(votingInput);
111
+ console.log(` Verdict: ${verdict}\n`);
112
+
113
+ // 4. Map Example
114
+ console.log("4. MAP EXECUTOR");
115
+ console.log(" Processing array of items in parallel\n");
116
+
117
+ const mapper = AgentGraph.map(
118
+ AgentGraph.sequential({ wrapInput: false }, uppercaseAgent)
119
+ );
120
+
121
+ const mapResults = await mapper.execute(["one", "two", "three"]);
122
+ console.log(` Input: ["one", "two", "three"]`);
123
+ console.log(` Output: ${JSON.stringify(mapResults)}\n`);
124
+
125
+ // 5. Pipeline Example
126
+ console.log("5. PIPELINE");
127
+ console.log(" Complex workflow combining multiple executor types\n");
128
+
129
+ const pipeline = AgentGraph.pipeline<string, string>(
130
+ // Stage 1: Get two versions in parallel
131
+ AgentGraph.parallel({ wrapInput: false }, excitedAgent, calmAgent),
132
+
133
+ // Stage 2: Transform for voting
134
+ {
135
+ execute: async (results: string[]) => ({
136
+ originalInput: "Which version is better?",
137
+ solutions: results,
138
+ }),
139
+ } as GraphNode<string[], VotingInput>,
140
+
141
+ // Stage 3: Vote
142
+ voting
143
+ );
144
+
145
+ const pipelineResult = await pipeline.execute("Good morning");
146
+ console.log(` Input: "Good morning"`);
147
+ console.log(` Output: "${pipelineResult}"`);
148
+
149
+ console.log("\n╔══════════════════════════════════════════╗");
150
+ console.log("║ Demo Complete! ║");
151
+ console.log("╚══════════════════════════════════════════╝");
152
+ }
153
+
154
+ quickDemo().catch(console.error);
@@ -0,0 +1,227 @@
1
+ /**
2
+ * Map Executor Example
3
+ *
4
+ * Demonstrates processing arrays of items in parallel using a processor agent.
5
+ *
6
+ * Use case: Batch processing documents, summarizing multiple articles, etc.
7
+ */
8
+ import "dotenv/config";
9
+ import { ClaudeAgent } from "../../lib/agents/anthropic/ClaudeAgent";
10
+ import { AgentGraph, GraphNode } from "../../lib/graph/AgentGraph";
11
+
12
+ const apiKey = process.env.ANTHROPIC_API_KEY;
13
+
14
+ if (!apiKey) {
15
+ console.error("Please set ANTHROPIC_API_KEY environment variable");
16
+ process.exit(1);
17
+ }
18
+
19
+ // Summarization agent for processing individual documents
20
+ const summarizerAgent = new ClaudeAgent({
21
+ id: "summarizer",
22
+ name: "Summarizer",
23
+ description: `You are a summarization agent. Given a text, provide a one-sentence summary.
24
+ Be concise and capture the main point. Output only the summary sentence.`,
25
+ apiKey,
26
+ maxTokens: 100,
27
+ });
28
+
29
+ // Sentiment analysis agent
30
+ const sentimentAgent = new ClaudeAgent({
31
+ id: "sentiment",
32
+ name: "Sentiment Analyzer",
33
+ description: `Analyze the sentiment of the given text.
34
+ Output exactly one word: POSITIVE, NEGATIVE, or NEUTRAL`,
35
+ apiKey,
36
+ maxTokens: 10,
37
+ });
38
+
39
+ // Translation agent
40
+ const translatorAgent = new ClaudeAgent({
41
+ id: "translator",
42
+ name: "Translator",
43
+ description: `Translate the given text to Spanish. Output only the translation.`,
44
+ apiKey,
45
+ maxTokens: 200,
46
+ });
47
+
48
+ async function runBatchSummarization() {
49
+ console.log("=== Batch Summarization Example ===\n");
50
+
51
+ const documents = [
52
+ "Artificial intelligence is transforming healthcare by enabling faster diagnosis and personalized treatment plans. Machine learning algorithms can now detect diseases from medical images with accuracy matching or exceeding human experts.",
53
+ "Climate change is causing unprecedented shifts in global weather patterns. Rising temperatures are leading to more frequent extreme weather events, including hurricanes, droughts, and wildfires.",
54
+ "The global economy is increasingly driven by digital services and remote work. Companies are adapting to hybrid work models, reshaping urban centers and suburban communities alike.",
55
+ "Space exploration has entered a new era with private companies launching missions alongside government agencies. Reusable rockets have dramatically reduced the cost of reaching orbit.",
56
+ ];
57
+
58
+ console.log(`Processing ${documents.length} documents in parallel...\n`);
59
+
60
+ // Create map executor with the summarizer
61
+ const batchSummarizer = AgentGraph.map(
62
+ AgentGraph.sequential({ wrapInput: false }, summarizerAgent)
63
+ );
64
+
65
+ const startTime = Date.now();
66
+ const summaries = await batchSummarizer.execute(documents);
67
+ const elapsed = Date.now() - startTime;
68
+
69
+ console.log("Summaries:");
70
+ summaries.forEach((summary, index) => {
71
+ console.log(`${index + 1}. ${summary}`);
72
+ });
73
+
74
+ console.log(`\nProcessed ${documents.length} documents in ${elapsed}ms`);
75
+ }
76
+
77
+ async function runBatchSentimentAnalysis() {
78
+ console.log("\n=== Batch Sentiment Analysis Example ===\n");
79
+
80
+ const reviews = [
81
+ "This product exceeded all my expectations! Best purchase ever.",
82
+ "Terrible quality. Broke after one day. Complete waste of money.",
83
+ "It's okay. Does what it's supposed to do, nothing special.",
84
+ "Absolutely love it! Would recommend to everyone.",
85
+ "Not great, not terrible. Average product for average price.",
86
+ ];
87
+
88
+ console.log("Analyzing sentiment of customer reviews...\n");
89
+
90
+ const sentimentAnalyzer = AgentGraph.map(
91
+ AgentGraph.sequential({ wrapInput: false }, sentimentAgent)
92
+ );
93
+
94
+ const sentiments = await sentimentAnalyzer.execute(reviews);
95
+
96
+ console.log("Results:");
97
+ reviews.forEach((review, index) => {
98
+ console.log(`"${review.substring(0, 50)}..." -> ${sentiments[index]}`);
99
+ });
100
+
101
+ // Count sentiments
102
+ const counts = sentiments.reduce(
103
+ (acc, s) => {
104
+ const key = s.trim().toUpperCase();
105
+ acc[key] = (acc[key] || 0) + 1;
106
+ return acc;
107
+ },
108
+ {} as Record<string, number>
109
+ );
110
+
111
+ console.log("\nSummary:", counts);
112
+ }
113
+
114
+ async function runBatchTranslation() {
115
+ console.log("\n=== Batch Translation Example ===\n");
116
+
117
+ const phrases = [
118
+ "Hello, how are you?",
119
+ "The weather is beautiful today.",
120
+ "I love programming.",
121
+ ];
122
+
123
+ console.log("Translating phrases to Spanish...\n");
124
+
125
+ const translator = AgentGraph.map(
126
+ AgentGraph.sequential({ wrapInput: false }, translatorAgent)
127
+ );
128
+
129
+ const translations = await translator.execute(phrases);
130
+
131
+ console.log("Translations:");
132
+ phrases.forEach((phrase, index) => {
133
+ console.log(`EN: "${phrase}"`);
134
+ console.log(`ES: "${translations[index]}"`);
135
+ console.log();
136
+ });
137
+ }
138
+
139
+ // Custom processor example (non-agent)
140
+ async function runCustomProcessor() {
141
+ console.log("=== Custom Processor Example ===\n");
142
+
143
+ // Custom processor that doesn't use an agent
144
+ const wordCounter: GraphNode<string, { text: string; wordCount: number }> = {
145
+ execute: async (text: string) => ({
146
+ text: text.substring(0, 30) + "...",
147
+ wordCount: text.split(/\s+/).length,
148
+ }),
149
+ };
150
+
151
+ const mapper = AgentGraph.map(wordCounter);
152
+
153
+ const texts = [
154
+ "This is a short sentence.",
155
+ "This is a much longer sentence with many more words in it.",
156
+ "One two three four five six seven eight nine ten eleven twelve.",
157
+ ];
158
+
159
+ const results = await mapper.execute(texts);
160
+
161
+ console.log("Word counts:");
162
+ results.forEach((result) => {
163
+ console.log(`"${result.text}" -> ${result.wordCount} words`);
164
+ });
165
+ }
166
+
167
+ // Pipeline with map example
168
+ async function runPipelineWithMap() {
169
+ console.log("\n=== Pipeline with Map Example ===\n");
170
+
171
+ const qualityChecker = new ClaudeAgent({
172
+ id: "quality",
173
+ name: "Quality Checker",
174
+ description: `Given multiple summaries, identify which one is the best quality.
175
+ Output only the number (1, 2, 3, etc.) of the best summary.`,
176
+ apiKey,
177
+ maxTokens: 10,
178
+ });
179
+
180
+ // Pipeline: Split -> Summarize Each -> Select Best
181
+ const pipeline = AgentGraph.pipeline(
182
+ // Split input into paragraphs
183
+ {
184
+ execute: async (text: string) => text.split("\n\n").filter((p) => p.trim()),
185
+ },
186
+
187
+ // Summarize each paragraph
188
+ AgentGraph.map(AgentGraph.sequential({ wrapInput: false }, summarizerAgent)),
189
+
190
+ // Combine summaries and select best
191
+ {
192
+ execute: async (summaries: string[]) => {
193
+ const numbered = summaries
194
+ .map((s, i) => `${i + 1}. ${s}`)
195
+ .join("\n");
196
+ return `Select the best summary:\n${numbered}`;
197
+ },
198
+ },
199
+
200
+ // Pick the best one
201
+ AgentGraph.sequential({ wrapInput: false }, qualityChecker)
202
+ );
203
+
204
+ const document = `
205
+ The ocean covers over 70% of Earth's surface. It regulates climate, produces oxygen, and supports countless species. Marine ecosystems are vital for human survival.
206
+
207
+ Technology has revolutionized communication. Smartphones connect billions of people worldwide. Social media platforms have transformed how we share information and interact.
208
+
209
+ Education is the foundation of progress. Schools prepare young minds for the future. Lifelong learning enables adaptation in a rapidly changing world.
210
+ `.trim();
211
+
212
+ console.log("Document has 3 paragraphs. Finding best summary...\n");
213
+
214
+ const result = await pipeline.execute(document);
215
+ console.log("Best summary number:", result);
216
+ }
217
+
218
+ // Run all examples
219
+ async function main() {
220
+ await runBatchSummarization();
221
+ await runBatchSentimentAnalysis();
222
+ await runBatchTranslation();
223
+ await runCustomProcessor();
224
+ await runPipelineWithMap();
225
+ }
226
+
227
+ main().catch(console.error);