Skip to content

Commit a1ab720

Browse files
nirgaclaude
andauthored
fix(ai-sdk): add agent detection support for AI SDK (#830)
Co-authored-by: Claude <noreply@anthropic.com>
1 parent d6ebc23 commit a1ab720

File tree

10 files changed

+1188
-8
lines changed

10 files changed

+1188
-8
lines changed

packages/sample-app/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
"run:vercel": "npm run build && node dist/src/sample_vercel_ai.js",
2121
"run:vercel_object": "npm run build && node dist/src/sample_vercel_ai_object.js",
2222
"run:vercel_tools": "npm run build && node dist/src/sample_vercel_ai_tools.js",
23+
"run:vercel_agent": "npm run build && node dist/src/sample_vercel_ai_agent.js",
24+
"run:vercel_agent_simple": "npm run build && node dist/src/sample_vercel_ai_agent_simple.js",
2325
"run:sample_vision": "npm run build && node dist/src/sample_vision_prompt.js",
2426
"run:sample_azure": "npm run build && node dist/src/sample_azure.js",
2527
"run:openai_streaming": "npm run build && node dist/src/sample_openai_streaming.js",
Lines changed: 367 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,367 @@
1+
import * as traceloop from "@traceloop/node-server-sdk";
2+
import { openai } from "@ai-sdk/openai";
3+
import { generateText, tool, CoreMessage } from "ai";
4+
import { z } from "zod";
5+
6+
import "dotenv/config";
7+
8+
traceloop.initialize({
9+
appName: "sample_vercel_ai_agent",
10+
disableBatch: true,
11+
});
12+
13+
// Simulated knowledge base
14+
const knowledgeBase = new Map([
15+
[
16+
"javascript",
17+
{
18+
description: "A high-level programming language",
19+
popularity: "Very High",
20+
useCase: "Web development, server-side development, mobile apps",
21+
},
22+
],
23+
[
24+
"python",
25+
{
26+
description: "An interpreted high-level programming language",
27+
popularity: "Very High",
28+
useCase: "Data science, web development, automation, AI/ML",
29+
},
30+
],
31+
[
32+
"rust",
33+
{
34+
description: "A systems programming language",
35+
popularity: "Growing",
36+
useCase: "Systems programming, web assembly, blockchain",
37+
},
38+
],
39+
[
40+
"typescript",
41+
{
42+
description: "JavaScript with static type definitions",
43+
popularity: "High",
44+
useCase: "Large-scale JavaScript applications, enterprise development",
45+
},
46+
],
47+
]);
48+
49+
// Define agent tools
50+
const searchKnowledge = tool({
51+
description:
52+
"Search the knowledge base for information about programming languages and technologies",
53+
parameters: z.object({
54+
query: z.string().describe("The search term or technology to look up"),
55+
}),
56+
execute: async ({ query }) => {
57+
console.log(`🔍 Searching knowledge base for: ${query}`);
58+
59+
await new Promise((resolve) => setTimeout(resolve, 100));
60+
61+
const normalizedQuery = query.toLowerCase();
62+
const result = knowledgeBase.get(normalizedQuery);
63+
64+
if (result) {
65+
console.log(`✅ Found information for ${query}:`, result);
66+
return {
67+
found: true,
68+
technology: query,
69+
...result,
70+
};
71+
} else {
72+
console.log(`❌ No information found for: ${query}`);
73+
return {
74+
found: false,
75+
technology: query,
76+
message: "No information available in knowledge base",
77+
};
78+
}
79+
},
80+
});
81+
82+
const analyzeTrends = tool({
83+
description: "Analyze technology trends and compare popularity",
84+
parameters: z.object({
85+
technologies: z
86+
.array(z.string())
87+
.describe("Array of technologies to analyze"),
88+
}),
89+
execute: async ({ technologies }) => {
90+
console.log(`📊 Analyzing trends for technologies:`, technologies);
91+
92+
await new Promise((resolve) => setTimeout(resolve, 200));
93+
94+
const analysis = technologies.map((tech) => {
95+
const info = knowledgeBase.get(tech.toLowerCase());
96+
return {
97+
technology: tech,
98+
popularity: info?.popularity || "Unknown",
99+
trend: Math.random() > 0.5 ? "Growing" : "Stable",
100+
marketShare: Math.floor(Math.random() * 30) + 5, // 5-35%
101+
};
102+
});
103+
104+
console.log(`📈 Trend analysis complete:`, analysis);
105+
return {
106+
analysis,
107+
summary: `Analyzed ${technologies.length} technologies`,
108+
recommendation:
109+
analysis.find((a) => a.popularity === "Very High")?.technology ||
110+
technologies[0],
111+
};
112+
},
113+
});
114+
115+
const generateReport = tool({
116+
description: "Generate a detailed report based on research data",
117+
parameters: z.object({
118+
topic: z.string().describe("The main topic of the report"),
119+
data: z
120+
.array(z.string())
121+
.describe("Key data points to include in the report"),
122+
}),
123+
execute: async ({ topic, data }) => {
124+
console.log(`📝 Generating report on: ${topic}`);
125+
console.log(`📋 Including data points:`, data);
126+
127+
await new Promise((resolve) => setTimeout(resolve, 300));
128+
129+
const report = {
130+
title: `Research Report: ${topic}`,
131+
executiveSummary: `This report analyzes ${topic} based on available data and trends.`,
132+
keyFindings: data,
133+
methodology: "Knowledge base search and trend analysis",
134+
generatedAt: new Date().toISOString(),
135+
confidence: Math.floor(Math.random() * 30) + 70, // 70-100%
136+
};
137+
138+
console.log(`📊 Report generated successfully`);
139+
return report;
140+
},
141+
});
142+
143+
const saveToMemory = tool({
144+
description:
145+
"Save important information to agent memory for future reference",
146+
parameters: z.object({
147+
key: z.string().describe("Memory key identifier"),
148+
value: z.string().describe("Information to store"),
149+
}),
150+
execute: async ({ key, value }) => {
151+
console.log(`💾 Saving to memory - ${key}: ${value}`);
152+
153+
// In a real implementation, this would persist to a database
154+
// For demo purposes, we'll just log it
155+
agentMemory.set(key, {
156+
value,
157+
timestamp: new Date().toISOString(),
158+
accessCount: 0,
159+
});
160+
161+
console.log(`✅ Saved to memory successfully`);
162+
return {
163+
saved: true,
164+
key,
165+
value,
166+
totalMemoryItems: agentMemory.size,
167+
};
168+
},
169+
});
170+
171+
const recallFromMemory = tool({
172+
description: "Recall previously saved information from agent memory",
173+
parameters: z.object({
174+
key: z.string().describe("Memory key to recall"),
175+
}),
176+
execute: async ({ key }) => {
177+
console.log(`🧠 Recalling from memory: ${key}`);
178+
179+
const memory = agentMemory.get(key);
180+
if (memory) {
181+
memory.accessCount++;
182+
console.log(`✅ Memory recalled:`, memory);
183+
return {
184+
found: true,
185+
key,
186+
value: memory.value,
187+
timestamp: memory.timestamp,
188+
accessCount: memory.accessCount,
189+
};
190+
} else {
191+
console.log(`❌ No memory found for key: ${key}`);
192+
return {
193+
found: false,
194+
key,
195+
message: "No memory found for this key",
196+
};
197+
}
198+
},
199+
});
200+
201+
// Simple in-memory storage for agent memory
202+
const agentMemory = new Map<
203+
string,
204+
{
205+
value: string;
206+
timestamp: string;
207+
accessCount: number;
208+
}
209+
>();
210+
211+
class ResearchAgent {
212+
private conversationHistory: CoreMessage[] = [];
213+
private sessionId: string;
214+
private userId?: string;
215+
216+
constructor(userId?: string) {
217+
this.sessionId = `session_${Date.now()}_${crypto.randomUUID().substring(0, 8)}`;
218+
this.userId = userId;
219+
console.log(`🆔 Initialized agent with session: ${this.sessionId}`);
220+
}
221+
222+
async processRequest(userInput: string): Promise<string> {
223+
return await traceloop.withWorkflow(
224+
{ name: "research_agent_request" },
225+
async () => {
226+
console.log(`\n🤖 Research Agent processing: "${userInput}"`);
227+
console.log(
228+
`📋 Session: ${this.sessionId} | User: ${this.userId || "anonymous"} | Turn: ${this.conversationHistory.length / 2 + 1}\n`,
229+
);
230+
231+
// Add user message to conversation history
232+
this.conversationHistory.push({
233+
role: "user",
234+
content: userInput,
235+
});
236+
237+
const result = await generateText({
238+
model: openai("gpt-4o"),
239+
messages: [
240+
{
241+
role: "system",
242+
content: `You are a helpful research assistant agent. You have access to several tools:
243+
- searchKnowledge: Search for information about programming languages and technologies
244+
- analyzeTrends: Analyze and compare technology trends
245+
- generateReport: Create detailed reports from research data
246+
- saveToMemory: Save important information for future reference
247+
- recallFromMemory: Retrieve previously saved information
248+
249+
Your goal is to help users research technologies, analyze trends, and provide comprehensive information.
250+
You can maintain context across multiple interactions and remember important details.
251+
252+
Be proactive in using your tools to provide thorough and accurate responses. If you need to save important
253+
findings for future use, use saveToMemory. If the user refers to previous conversations, try recallFromMemory.
254+
255+
Agent Session: ${this.sessionId}
256+
User ID: ${this.userId || "anonymous"}
257+
Conversation Turn: ${this.conversationHistory.length / 2 + 1}`,
258+
},
259+
...this.conversationHistory,
260+
],
261+
tools: {
262+
searchKnowledge,
263+
analyzeTrends,
264+
generateReport,
265+
saveToMemory,
266+
recallFromMemory,
267+
},
268+
maxSteps: 10, // Allow multiple tool interactions
269+
experimental_telemetry: {
270+
isEnabled: true,
271+
// Metadata can be included in telemetry data
272+
functionId: `research_agent_${this.sessionId}`,
273+
metadata: {
274+
agent: "research_assistant",
275+
sessionId: this.sessionId,
276+
userId: this.userId || "anonymous",
277+
conversationTurn: this.conversationHistory.length / 2 + 1,
278+
timestamp: new Date().toISOString(),
279+
},
280+
},
281+
});
282+
283+
// Add assistant response to conversation history
284+
this.conversationHistory.push({
285+
role: "assistant",
286+
content: result.text,
287+
});
288+
289+
return result.text;
290+
},
291+
{ userInput },
292+
);
293+
}
294+
295+
getConversationHistory(): CoreMessage[] {
296+
return [...this.conversationHistory];
297+
}
298+
299+
clearMemory(): void {
300+
this.conversationHistory = [];
301+
agentMemory.clear();
302+
console.log("🧹 Agent memory cleared");
303+
}
304+
305+
getSessionId(): string {
306+
return this.sessionId;
307+
}
308+
309+
getUserId(): string | undefined {
310+
return this.userId;
311+
}
312+
}
313+
314+
async function demonstrateAgent() {
315+
// Initialize agent with user ID for metadata tracking
316+
const agent = new ResearchAgent("demo_user_123");
317+
318+
const queries = [
319+
"I'm starting a new project and need to choose between JavaScript and TypeScript. Can you help me research both?",
320+
"Based on your previous research, can you analyze the trends for JavaScript, TypeScript, Python, and Rust?",
321+
"Please generate a comprehensive report on the best language for web development based on our research",
322+
"Save the key finding from our research session for future reference",
323+
"What did we conclude about web development languages?",
324+
];
325+
326+
console.log(`🏷️ Agent Metadata:`);
327+
console.log(` Session ID: ${agent.getSessionId()}`);
328+
console.log(` User ID: ${agent.getUserId()}`);
329+
console.log(` Queries to process: ${queries.length}`);
330+
331+
for (let i = 0; i < queries.length; i++) {
332+
console.log(`\n${"=".repeat(80)}`);
333+
console.log(`🎯 QUERY ${i + 1}: ${queries[i]}`);
334+
console.log("=".repeat(80));
335+
336+
const response = await agent.processRequest(queries[i]);
337+
338+
console.log("\n🤖 AGENT RESPONSE:");
339+
console.log("-".repeat(40));
340+
console.log(response);
341+
342+
// Add delay between queries to simulate real conversation
343+
if (i < queries.length - 1) {
344+
console.log("\n⏳ Processing next query in 2 seconds...");
345+
await new Promise((resolve) => setTimeout(resolve, 2000));
346+
}
347+
}
348+
349+
console.log(`\n${"=".repeat(80)}`);
350+
console.log("📊 CONVERSATION SUMMARY");
351+
console.log("=".repeat(80));
352+
console.log(
353+
`Total messages in conversation: ${agent.getConversationHistory().length}`,
354+
);
355+
console.log(`Items saved in memory: ${agentMemory.size}`);
356+
console.log("=".repeat(80));
357+
}
358+
359+
async function main() {
360+
try {
361+
await demonstrateAgent();
362+
} catch (error) {
363+
console.error("❌ Error running agent demo:", error);
364+
}
365+
}
366+
367+
main().catch(console.error);

0 commit comments

Comments
 (0)