Skip to content

Commit 004df81

Browse files
authored
Feat/add langfuse exporter (#94)
* feat: add langfuse exporter * refactor: improve code formatting and organization in index.ts * refactor: streamline telemetry setup and improve code clarity in index.ts * feat(langfuse): update Langfuse exporter integration and improve telemetry handling * refactor: enhance OpenTelemetry span management and simplify related logic * refactor: remove commented-out sections for cleaner code in index.ts * docs: add usage instructions for LangfuseExporter in README.md * refactor: update error status handling and enhance telemetry metadata in Agent and LangfuseExporter * fix: implement error handling in weather tool and standardize error status in Agent * refactor: remove debug logging from OpenTelemetry span management and Langfuse integration * chore: remove unused LangfuseExporter entry from pnpm-lock.yaml * refactor: optimize LangfuseExporter integration and enhance error handling in telemetry
1 parent 3fbe80c commit 004df81

33 files changed

Lines changed: 2607 additions & 3888 deletions

File tree

.changeset/salty-kids-clap.md

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
---
2+
"@voltagent/langfuse-exporter": patch
3+
"@voltagent/core": patch
4+
---
5+
6+
feat: Add Langfuse Observability Exporter
7+
8+
This introduces a new package `@voltagent/langfuse-exporter` that allows you to export OpenTelemetry traces generated by `@voltagent/core` directly to Langfuse (https://langfuse.com/) for detailed observability into your agent's operations.
9+
10+
**How to Use:**
11+
12+
## Installation
13+
14+
Install the necessary packages:
15+
16+
```bash
17+
npm install @voltagent/core @voltagent/langfuse-exporter
18+
# or
19+
yarn add @voltagent/core @voltagent/langfuse-exporter
20+
```
21+
22+
## Configuration
23+
24+
Configure the `LangfuseExporter` and pass it to `VoltAgent`:
25+
26+
```typescript
27+
import { Agent, VoltAgent } from "@voltagent/core";
28+
import { LangfuseExporter } from "@voltagent/langfuse-exporter";
29+
// import { YourLLMProvider } from "./your-llm-provider"; // Replace with your provider
30+
// import { yourModel } from "./your-model"; // Replace with your model
31+
// import { yourTools } from "./your-tools"; // Replace with your tools
32+
33+
// Ensure LANGFUSE_SECRET_KEY and LANGFUSE_PUBLIC_KEY are set in your environment
34+
35+
// Define your agent(s)
36+
const agent = new Agent({
37+
name: "MyLangfuseAgent",
38+
// description: "...",
39+
// llm: new YourLLMProvider(),
40+
// model: yourModel,
41+
// tools: yourTools,
42+
});
43+
44+
// Configure the Langfuse Exporter
45+
const langfuseExporter = new LangfuseExporter({
46+
publicKey: process.env.LANGFUSE_PUBLIC_KEY,
47+
secretKey: process.env.LANGFUSE_SECRET_KEY,
48+
baseUrl: process.env.LANGFUSE_BASE_URL, // Optional: Defaults to Langfuse Cloud
49+
// debug: true // Optional: Enable exporter logging
50+
});
51+
52+
// Initialize VoltAgent with the exporter
53+
// This automatically sets up OpenTelemetry tracing
54+
new VoltAgent({
55+
agents: {
56+
agent, // Register your agent(s)
57+
},
58+
telemetryExporter: langfuseExporter, // Pass the exporter instance
59+
});
60+
61+
console.log("VoltAgent initialized with Langfuse exporter.");
62+
63+
// Now, any operations performed by 'agent' (e.g., agent.generateText(...))
64+
// will automatically generate traces and send them to Langfuse.
65+
```
66+
67+
By providing the `telemetryExporter` to `VoltAgent`, OpenTelemetry is automatically configured, and detailed traces including LLM interactions, tool usage, and agent metadata will appear in your Langfuse project.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
OPENAI_API_KEY=your_openai_api_key
2+
LANGFUSE_SECRET_KEY=your_langfuse_secret
3+
LANGFUSE_PUBLIC_KEY=your_public_key
4+
LANGFUSE_BASE_URL=your_langfuse_base_url

examples/with-langfuse/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
node_modules
2+
dist
3+
.DS_Store

examples/with-langfuse/README.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<div align="center">
2+
<a href="https://voltagent.dev/">
3+
<img width="1800" alt="435380213-b6253409-8741-462b-a346-834cd18565a9" src="https://github.com/user-attachments/assets/452a03e7-eeda-4394-9ee7-0ffbcf37245c" />
4+
</a>
5+
6+
<br/>
7+
<br/>
8+
9+
<div align="center">
10+
<a href="https://voltagent.dev">Home Page</a> |
11+
<a href="https://voltagent.dev/docs/">Documentation</a> |
12+
<a href="https://github.com/voltagent/voltagent/tree/main/examples">Examples</a> |
13+
<a href="https://s.voltagent.dev/discord">Discord</a> |
14+
<a href="https://voltagent.dev/blog/">Blog</a>
15+
</div>
16+
</div>
17+
18+
<br/>
19+
20+
<div align="center">
21+
<strong>VoltAgent is an open source TypeScript framework for building and orchestrating AI agents.</strong><br>
22+
Escape the limitations of no-code builders and the complexity of starting from scratch.
23+
<br />
24+
<br />
25+
</div>
26+
27+
<div align="center">
28+
29+
[![npm version](https://img.shields.io/npm/v/@voltagent/core.svg)](https://www.npmjs.com/package/@voltagent/core)
30+
[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.0-4baaaa.svg)](CODE_OF_CONDUCT.md)
31+
[![Discord](https://img.shields.io/discord/1361559153780195478.svg?label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2)](https://s.voltagent.dev/discord)
32+
[![Twitter Follow](https://img.shields.io/twitter/follow/voltagent_dev?style=social)](https://twitter.com/voltagent_dev)
33+
34+
</div>
35+
36+
<br/>
37+
38+
<div align="center">
39+
<a href="https://voltagent.dev/">
40+
<img width="896" alt="VoltAgent Schema" src="https://github.com/user-attachments/assets/f0627868-6153-4f63-ba7f-bdfcc5dd603d" />
41+
</a>
42+
43+
</div>
44+
45+
## VoltAgent: Build AI Agents Fast and Flexibly
46+
47+
VoltAgent is an open-source TypeScript framework for creating and managing AI agents. It provides modular components to build, customize, and scale agents with ease. From connecting to APIs and memory management to supporting multiple LLMs, VoltAgent simplifies the process of creating sophisticated AI systems. It enables fast development, maintains clean code, and offers flexibility to switch between models and tools without vendor lock-in.
48+
49+
## Try Example
50+
51+
```bash
52+
npm create voltagent-app@latest -- --example with-langfuse
53+
```
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"name": "voltagent-example-with-langfuse",
3+
"private": true,
4+
"keywords": [
5+
"voltagent",
6+
"ai",
7+
"agent"
8+
],
9+
"license": "MIT",
10+
"author": "",
11+
"type": "module",
12+
"scripts": {
13+
"build": "tsc",
14+
"dev": "tsx watch --env-file=.env ./src",
15+
"start": "node dist/index.js",
16+
"volt": "volt"
17+
},
18+
"dependencies": {
19+
"@ai-sdk/openai": "^1.3.10",
20+
"@voltagent/cli": "^0.1.4",
21+
"@voltagent/core": "^0.1.11",
22+
"@voltagent/langfuse-exporter": "^0.1.0",
23+
"@voltagent/vercel-ai": "^0.1.5",
24+
"zod": "^3.24.2"
25+
},
26+
"devDependencies": {
27+
"@types/node": "^22.13.5",
28+
"tsx": "^4.19.3",
29+
"typescript": "^5.8.2"
30+
}
31+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { openai } from "@ai-sdk/openai";
2+
import { Agent, VoltAgent } from "@voltagent/core";
3+
import { LangfuseExporter } from "@voltagent/langfuse-exporter";
4+
import { VercelAIProvider } from "@voltagent/vercel-ai";
5+
import { weatherTool, searchTool, checkCalendarTool, addCalendarEventTool } from "./tools";
6+
7+
const agent = new Agent({
8+
name: "Base Agent",
9+
description: "You are a helpful assistant",
10+
llm: new VercelAIProvider(),
11+
model: openai("gpt-4o-mini"),
12+
tools: [weatherTool, searchTool, checkCalendarTool, addCalendarEventTool],
13+
});
14+
15+
new VoltAgent({
16+
agents: {
17+
agent,
18+
},
19+
telemetryExporter: new LangfuseExporter({
20+
publicKey: process.env.LANGFUSE_PUBLIC_KEY,
21+
secretKey: process.env.LANGFUSE_SECRET_KEY,
22+
baseUrl: process.env.LANGFUSE_BASE_URL,
23+
}),
24+
});
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import { createTool } from "@voltagent/core";
2+
import { z } from "zod";
3+
4+
// Mock calendar database for demonstration
5+
const mockCalendar = [
6+
{
7+
id: "1",
8+
title: "Team meeting",
9+
date: "2023-11-15",
10+
time: "10:00",
11+
duration: 60,
12+
},
13+
{
14+
id: "2",
15+
title: "Lunch with client",
16+
date: "2023-11-15",
17+
time: "12:30",
18+
duration: 90,
19+
},
20+
{
21+
id: "3",
22+
title: "Project deadline",
23+
date: "2023-11-20",
24+
time: "17:00",
25+
duration: 0,
26+
},
27+
];
28+
29+
/**
30+
* A tool for checking calendar events
31+
*/
32+
export const checkCalendarTool = createTool({
33+
name: "checkCalendar",
34+
description: "Check calendar events for a specific date",
35+
parameters: z.object({
36+
date: z.string().describe("The date to check calendar events for (YYYY-MM-DD)"),
37+
}),
38+
execute: async ({ date }) => {
39+
const events = mockCalendar.filter((event) => event.date === date);
40+
41+
if (events.length === 0) {
42+
return {
43+
events: [],
44+
message: `No events found for ${date}.`,
45+
};
46+
}
47+
48+
return {
49+
events,
50+
message: `Found ${events.length} events for ${date}: ${events
51+
.map((event) => `${event.title} at ${event.time}`)
52+
.join(", ")}`,
53+
};
54+
},
55+
});
56+
57+
/**
58+
* A tool for adding a calendar event
59+
*/
60+
export const addCalendarEventTool = createTool({
61+
name: "addCalendarEvent",
62+
description: "Add a new event to the calendar",
63+
parameters: z.object({
64+
title: z.string().describe("The title of the event"),
65+
date: z.string().describe("The date of the event (YYYY-MM-DD)"),
66+
time: z.string().describe("The time of the event (HH:MM)"),
67+
duration: z.number().describe("The duration of the event in minutes"),
68+
}),
69+
execute: async ({ title, date, time, duration }) => {
70+
const id = (mockCalendar.length + 1).toString();
71+
const newEvent = { id, title, date, time, duration };
72+
73+
// In a real implementation, this would add to a database
74+
mockCalendar.push(newEvent);
75+
76+
return {
77+
event: newEvent,
78+
message: `Added new event: "${title}" on ${date} at ${time} for ${duration} minutes.`,
79+
};
80+
},
81+
});
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export { weatherTool } from "./weather.js";
2+
export { checkCalendarTool, addCalendarEventTool } from "./calendar.js";
3+
export { searchTool } from "./search.js";
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { createTool } from "@voltagent/core";
2+
import { z } from "zod";
3+
4+
/**
5+
* A tool for performing web searches
6+
*/
7+
export const searchTool = createTool({
8+
name: "search",
9+
description: "Search the web for information",
10+
parameters: z.object({
11+
query: z.string().describe("The search query"),
12+
}),
13+
execute: async ({ query }) => {
14+
// In a real implementation, this would call a search API like Google
15+
// This is a mock implementation for demonstration purposes
16+
17+
// Mock search results
18+
const mockResults = [
19+
{
20+
title: `Information about "${query}"`,
21+
snippet: `This is the first search result about "${query}". It contains some relevant information that might be useful.`,
22+
url: `https://example.com/result1`,
23+
},
24+
{
25+
title: `More details on "${query}"`,
26+
snippet: `Another search result with additional details about "${query}". This source discusses related topics and provides deeper insights.`,
27+
url: `https://example.org/result2`,
28+
},
29+
{
30+
title: `"${query}" explained`,
31+
snippet: `An explanation of "${query}" with examples and illustrations to help understand the concept better.`,
32+
url: `https://knowledge.com/result3`,
33+
},
34+
];
35+
36+
return {
37+
results: mockResults,
38+
message: `Found ${mockResults.length} results for "${query}". Here are the top findings:\n\n${mockResults
39+
.map(
40+
(result, index) =>
41+
`${index + 1}. ${result.title}\n ${result.snippet}\n Source: ${result.url}`,
42+
)
43+
.join("\n\n")}`,
44+
};
45+
},
46+
});
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { createTool } from "@voltagent/core";
2+
import { z } from "zod";
3+
4+
/**
5+
* A tool for fetching weather information for a given location
6+
*/
7+
export const weatherTool = createTool({
8+
name: "getWeather",
9+
description: "Get the current weather for a specific location",
10+
parameters: z.object({
11+
location: z.string().describe("The city or location to get weather for"),
12+
}),
13+
execute: async ({ location }) => {
14+
// In a real implementation, this would call a weather API
15+
// This is a mock implementation for demonstration purposes
16+
17+
const mockWeatherData = {
18+
location,
19+
temperature: Math.floor(Math.random() * 30) + 5, // Random temp between 5-35°C
20+
condition: ["Sunny", "Cloudy", "Rainy", "Snowy", "Partly Cloudy"][
21+
Math.floor(Math.random() * 5)
22+
],
23+
humidity: Math.floor(Math.random() * 60) + 30, // Random humidity between 30-90%
24+
windSpeed: Math.floor(Math.random() * 30), // Random wind speed between 0-30 km/h
25+
};
26+
27+
return {
28+
weather: mockWeatherData,
29+
message: `Current weather in ${location}: ${mockWeatherData.temperature}°C and ${mockWeatherData.condition.toLowerCase()} with ${mockWeatherData.humidity}% humidity and wind speed of ${mockWeatherData.windSpeed} km/h.`,
30+
};
31+
},
32+
});

0 commit comments

Comments
 (0)