fiddler-langgraph 0.1.0rc1__tar.gz → 1.0.0__tar.gz

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 (24) hide show
  1. {fiddler_langgraph-0.1.0rc1 → fiddler_langgraph-1.0.0}/MANIFEST.in +1 -1
  2. {fiddler_langgraph-0.1.0rc1 → fiddler_langgraph-1.0.0}/PKG-INFO +9 -4
  3. fiddler_langgraph-1.0.0/PUBLIC.md +169 -0
  4. {fiddler_langgraph-0.1.0rc1 → fiddler_langgraph-1.0.0}/README.md +8 -3
  5. fiddler_langgraph-1.0.0/fiddler_langgraph/VERSION +1 -0
  6. {fiddler_langgraph-0.1.0rc1 → fiddler_langgraph-1.0.0}/fiddler_langgraph/core/attributes.py +0 -21
  7. {fiddler_langgraph-0.1.0rc1 → fiddler_langgraph-1.0.0}/fiddler_langgraph/core/client.py +59 -27
  8. {fiddler_langgraph-0.1.0rc1 → fiddler_langgraph-1.0.0}/fiddler_langgraph/tracing/callback.py +6 -2
  9. fiddler_langgraph-1.0.0/fiddler_langgraph/tracing/instrumentation.py +536 -0
  10. {fiddler_langgraph-0.1.0rc1 → fiddler_langgraph-1.0.0}/fiddler_langgraph.egg-info/PKG-INFO +9 -4
  11. {fiddler_langgraph-0.1.0rc1 → fiddler_langgraph-1.0.0}/fiddler_langgraph.egg-info/SOURCES.txt +1 -0
  12. fiddler_langgraph-0.1.0rc1/fiddler_langgraph/VERSION +0 -1
  13. fiddler_langgraph-0.1.0rc1/fiddler_langgraph/tracing/instrumentation.py +0 -264
  14. {fiddler_langgraph-0.1.0rc1 → fiddler_langgraph-1.0.0}/fiddler_langgraph/__init__.py +0 -0
  15. {fiddler_langgraph-0.1.0rc1 → fiddler_langgraph-1.0.0}/fiddler_langgraph/core/__init__.py +0 -0
  16. {fiddler_langgraph-0.1.0rc1 → fiddler_langgraph-1.0.0}/fiddler_langgraph/core/span_processor.py +0 -0
  17. {fiddler_langgraph-0.1.0rc1 → fiddler_langgraph-1.0.0}/fiddler_langgraph/tracing/__init__.py +0 -0
  18. {fiddler_langgraph-0.1.0rc1 → fiddler_langgraph-1.0.0}/fiddler_langgraph/tracing/jsonl_capture.py +0 -0
  19. {fiddler_langgraph-0.1.0rc1 → fiddler_langgraph-1.0.0}/fiddler_langgraph/tracing/util.py +0 -0
  20. {fiddler_langgraph-0.1.0rc1 → fiddler_langgraph-1.0.0}/fiddler_langgraph.egg-info/dependency_links.txt +0 -0
  21. {fiddler_langgraph-0.1.0rc1 → fiddler_langgraph-1.0.0}/fiddler_langgraph.egg-info/requires.txt +0 -0
  22. {fiddler_langgraph-0.1.0rc1 → fiddler_langgraph-1.0.0}/fiddler_langgraph.egg-info/top_level.txt +0 -0
  23. {fiddler_langgraph-0.1.0rc1 → fiddler_langgraph-1.0.0}/pyproject.toml +0 -0
  24. {fiddler_langgraph-0.1.0rc1 → fiddler_langgraph-1.0.0}/setup.cfg +0 -0
@@ -1,5 +1,5 @@
1
1
  include LICENSE
2
- include README.md
2
+ include PUBLIC.md
3
3
  include fiddler_langgraph/VERSION
4
4
  recursive-include fiddler_langgraph *.py
5
5
  recursive-exclude tests *
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fiddler-langgraph
3
- Version: 0.1.0rc1
3
+ Version: 1.0.0
4
4
  Summary: Python SDK for instrumenting GenAI Applications with Fiddler
5
5
  Home-page: https://fiddler.ai
6
6
  Author: Fiddler AI
@@ -87,7 +87,7 @@ from fiddler_langgraph import FiddlerClient
87
87
 
88
88
  # Initialize the FiddlerClient with basic configuration
89
89
  client = FiddlerClient(
90
- url="https://api.fiddler.ai",
90
+ url="https://your-instance.fiddler.ai",
91
91
  api_key="fdl_api_key",
92
92
  application_id="fdl_application_id" # Must be a valid UUID4
93
93
  )
@@ -152,7 +152,7 @@ The Fiddler SDK provides flexible configuration options for OpenTelemetry integr
152
152
  client = FiddlerClient(
153
153
  api_key="your-api-key",
154
154
  application_id="your-app-id", # Must be a valid UUID4
155
- url="https://api.fiddler.ai"
155
+ url="https://your-instance.fiddler.ai"
156
156
  )
157
157
  ```
158
158
 
@@ -178,6 +178,7 @@ sampler = sampling.TraceIdRatioBased(0.1) # Sample 10% of traces
178
178
  client = FiddlerClient(
179
179
  api_key="your-api-key",
180
180
  application_id="your-app-id",
181
+ url="https://your-instance.fiddler.ai",
181
182
  span_limits=custom_limits,
182
183
  sampler=sampler,
183
184
  console_tracer=False, # Set to True for debugging
@@ -196,6 +197,7 @@ from opentelemetry.exporter.otlp.proto.http.trace_exporter import Compression
196
197
  client = FiddlerClient(
197
198
  api_key="your-api-key",
198
199
  application_id="your-app-id",
200
+ url="https://your-instance.fiddler.ai",
199
201
  compression=Compression.Gzip,
200
202
  )
201
203
 
@@ -203,6 +205,7 @@ client = FiddlerClient(
203
205
  client = FiddlerClient(
204
206
  api_key="your-api-key",
205
207
  application_id="your-app-id",
208
+ url="https://your-instance.fiddler.ai",
206
209
  compression=Compression.NoCompression,
207
210
  )
208
211
 
@@ -210,6 +213,7 @@ client = FiddlerClient(
210
213
  client = FiddlerClient(
211
214
  api_key="your-api-key",
212
215
  application_id="your-app-id",
216
+ url="https://your-instance.fiddler.ai",
213
217
  compression=Compression.Deflate,
214
218
  )
215
219
  ```
@@ -229,7 +233,8 @@ os.environ['OTEL_BSP_EXPORT_TIMEOUT'] = '10000'
229
233
 
230
234
  client = FiddlerClient(
231
235
  api_key="your-api-key",
232
- application_id="your-app-id"
236
+ application_id="your-app-id",
237
+ url="https://your-instance.fiddler.ai"
233
238
  )
234
239
  ```
235
240
 
@@ -0,0 +1,169 @@
1
+ # fiddler-langgraph
2
+
3
+ [![Python Version](https://img.shields.io/pypi/pyversions/fiddler-langgraph.svg)](https://pypi.org/project/fiddler-langgraph/)
4
+
5
+ [![PyPI Version](https://img.shields.io/pypi/v/fiddler-langgraph.svg)](https://pypi.org/project/fiddler-langgraph/)
6
+
7
+ [![License](https://img.shields.io/pypi/l/fiddler-langgraph.svg)](https://pypi.org/project/fiddler-langgraph/)
8
+
9
+ The official Python SDK for instrumenting GenAI Applications with [Fiddler](https://www.fiddler.ai) using OpenTelemetry and LangGraph. Monitor, analyze, and protect your LangGraph workflows, LLMs, and AI Agents in production.
10
+
11
+ ## Platform Features
12
+
13
+ - 🚀 **Easy Integration** - Simple Python API for LangGraph application instrumentation
14
+ - 📊 **OpenTelemetry Tracing** - Full distributed tracing support with configurable span limits
15
+ - 🔍 **Automatic Instrumentation** - Zero-config tracing for LangGraph workflows, chains, and tools
16
+ - 🎯 **LLM Context Management** - Set additional context for LLM processing with `set_llm_context()`
17
+ - 💬 **Conversation Tracking** - Track multi-turn conversations with `set_conversation_id()`
18
+ - 📈 **Performance Metrics** - Automatic tracking of timing, token usage, and model information
19
+ - 🛡️ **Error Handling** - Comprehensive error tracking with detailed stack traces
20
+ - 🔄 **Flexible Configuration** - Custom span limits, sampling strategies, and batch processing
21
+ - 📊 **Resource Management** - Conservative defaults to prevent resource exhaustion
22
+ - 🎨 **Message Serialization** - Smart handling of complex message content (lists, dicts)
23
+ - 🔔 **Attribute Truncation** - Automatic truncation of long attribute values to prevent oversized spans
24
+
25
+ ## Installation
26
+
27
+ ```bash
28
+ pip install fiddler-langgraph
29
+ ```
30
+
31
+ ## Requirements
32
+
33
+ - Python 3.10, 3.11, 3.12, or 3.13
34
+ - LangGraph >= 0.3.28 and <= 1.0.2 or Langchain >= 0.3.28 and <= 1.0.2
35
+
36
+ ### With Example Dependencies
37
+
38
+ To run the example scripts:
39
+
40
+ ```bash
41
+ pip install fiddler-langgraph[examples]
42
+ ```
43
+
44
+ ## Quick Start
45
+
46
+ ```python
47
+ from fiddler_langgraph import FiddlerClient
48
+ from fiddler_langgraph.tracing.instrumentation import LangGraphInstrumentor, set_llm_context, set_conversation_id
49
+
50
+ # Initialize the FiddlerClient
51
+ client = FiddlerClient(
52
+ url="https://your-instance.fiddler.ai",
53
+ api_key="your-api-key",
54
+ application_id="your-application-id" # Must be a valid UUID4
55
+ )
56
+
57
+ # Instrument LangGraph applications
58
+ LangGraphInstrumentor(client).instrument()
59
+
60
+ # Set additional context for LLM processing
61
+ from langchain_openai import ChatOpenAI
62
+ model = ChatOpenAI(model='gpt-4o-mini')
63
+ set_llm_context(model, "Previous conversation context")
64
+
65
+ # Set conversation ID for multi-turn conversations
66
+ from langgraph.graph import StateGraph
67
+ workflow = StateGraph(state_schema=State)
68
+ app = workflow.compile()
69
+ set_conversation_id("conversation_123")
70
+ app.invoke({"messages": [{"role": "user", "content": "Write a novel"}]})
71
+ ```
72
+
73
+ ## Documentation
74
+
75
+ * 📚 [Complete Documentation](https://docs.fiddler.ai/)
76
+ * 🚀 [LangGraph Quick Start Guide](https://docs.fiddler.ai/developers/tutorials/llm-monitoring/langgraph-sdk-quick-start)
77
+ * 📖 [API Reference](https://docs.fiddler.ai/api/fiddler-langgraph-sdk/langgraph)
78
+
79
+ ## Example Usage
80
+
81
+ ### Basic Instrumentation
82
+
83
+ ```python
84
+ from fiddler_langgraph.tracing.instrumentation import LangGraphInstrumentor
85
+
86
+ # Initialize and instrument
87
+ instrumentor = LangGraphInstrumentor(client)
88
+ instrumentor.instrument()
89
+ ```
90
+
91
+ ### Setting LLM Context
92
+
93
+ ```python
94
+ from fiddler_langgraph.tracing.instrumentation import set_llm_context
95
+ from langchain_openai import ChatOpenAI
96
+
97
+ model = ChatOpenAI(model='gpt-4o-mini')
98
+ set_llm_context(model, "User prefers concise responses")
99
+ ```
100
+
101
+ ### Conversation Tracking
102
+
103
+ ```python
104
+ from fiddler_langgraph.tracing.instrumentation import set_conversation_id
105
+ import uuid
106
+
107
+ # Set conversation ID for tracking multi-turn conversations
108
+ conversation_id = str(uuid.uuid4())
109
+ set_conversation_id(conversation_id)
110
+ ```
111
+
112
+ ### Advanced Configuration
113
+
114
+ ```python
115
+ from opentelemetry.sdk.trace import SpanLimits, sampling
116
+ from opentelemetry.exporter.otlp.proto.http.trace_exporter import Compression
117
+
118
+ # Custom span limits for high-volume applications
119
+ custom_limits = SpanLimits(
120
+ max_events=64,
121
+ max_links=64,
122
+ max_span_attributes=64,
123
+ max_event_attributes=64,
124
+ max_link_attributes=64,
125
+ max_span_attribute_length=4096,
126
+ )
127
+
128
+ # Sampling strategy for production
129
+ sampler = sampling.TraceIdRatioBased(0.1) # Sample 10% of traces
130
+
131
+ client = FiddlerClient(
132
+ api_key="your-api-key",
133
+ application_id="your-app-id",
134
+ url="https://your-instance.fiddler.ai",
135
+ span_limits=custom_limits,
136
+ sampler=sampler,
137
+ console_tracer=False, # Set to True for debugging
138
+ compression=Compression.Gzip, # Enable gzip compression (default)
139
+ )
140
+ ```
141
+
142
+ ## Example Notebooks
143
+
144
+ Check out our [GitHub repository](https://github.com/fiddler-labs/fiddler-sdk/tree/main/examples) for example scripts demonstrating:
145
+
146
+ - Basic LangGraph instrumentation
147
+ - LLM context management
148
+ - Conversation tracking
149
+ - Multi-agent workflows
150
+ - Travel agent applications
151
+ - Chatbot implementations
152
+
153
+ ## Version History
154
+
155
+ See our [release notes](https://docs.fiddler.ai/history/python-client-history) for detailed version history.
156
+
157
+ ## Support
158
+
159
+ - 📧 Email: [support@fiddler.ai](mailto:support@fiddler.ai)
160
+ - 💬 Community: [Join our Slack](https://www.fiddler.ai/slack)
161
+ - 🐛 Issues: [GitHub Issues](https://github.com/fiddler-labs/fiddler-sdk/issues)
162
+
163
+ ## License
164
+
165
+ Apache License 2.0 - see LICENSE file for details
166
+
167
+ ---
168
+
169
+ **Want to see Fiddler in action?** [Request a demo](https://www.fiddler.ai/demo)
@@ -33,7 +33,7 @@ from fiddler_langgraph import FiddlerClient
33
33
 
34
34
  # Initialize the FiddlerClient with basic configuration
35
35
  client = FiddlerClient(
36
- url="https://api.fiddler.ai",
36
+ url="https://your-instance.fiddler.ai",
37
37
  api_key="fdl_api_key",
38
38
  application_id="fdl_application_id" # Must be a valid UUID4
39
39
  )
@@ -98,7 +98,7 @@ The Fiddler SDK provides flexible configuration options for OpenTelemetry integr
98
98
  client = FiddlerClient(
99
99
  api_key="your-api-key",
100
100
  application_id="your-app-id", # Must be a valid UUID4
101
- url="https://api.fiddler.ai"
101
+ url="https://your-instance.fiddler.ai"
102
102
  )
103
103
  ```
104
104
 
@@ -124,6 +124,7 @@ sampler = sampling.TraceIdRatioBased(0.1) # Sample 10% of traces
124
124
  client = FiddlerClient(
125
125
  api_key="your-api-key",
126
126
  application_id="your-app-id",
127
+ url="https://your-instance.fiddler.ai",
127
128
  span_limits=custom_limits,
128
129
  sampler=sampler,
129
130
  console_tracer=False, # Set to True for debugging
@@ -142,6 +143,7 @@ from opentelemetry.exporter.otlp.proto.http.trace_exporter import Compression
142
143
  client = FiddlerClient(
143
144
  api_key="your-api-key",
144
145
  application_id="your-app-id",
146
+ url="https://your-instance.fiddler.ai",
145
147
  compression=Compression.Gzip,
146
148
  )
147
149
 
@@ -149,6 +151,7 @@ client = FiddlerClient(
149
151
  client = FiddlerClient(
150
152
  api_key="your-api-key",
151
153
  application_id="your-app-id",
154
+ url="https://your-instance.fiddler.ai",
152
155
  compression=Compression.NoCompression,
153
156
  )
154
157
 
@@ -156,6 +159,7 @@ client = FiddlerClient(
156
159
  client = FiddlerClient(
157
160
  api_key="your-api-key",
158
161
  application_id="your-app-id",
162
+ url="https://your-instance.fiddler.ai",
159
163
  compression=Compression.Deflate,
160
164
  )
161
165
  ```
@@ -175,7 +179,8 @@ os.environ['OTEL_BSP_EXPORT_TIMEOUT'] = '10000'
175
179
 
176
180
  client = FiddlerClient(
177
181
  api_key="your-api-key",
178
- application_id="your-app-id"
182
+ application_id="your-app-id",
183
+ url="https://your-instance.fiddler.ai"
179
184
  )
180
185
  ```
181
186
 
@@ -0,0 +1 @@
1
+ 1.0.0
@@ -3,8 +3,6 @@
3
3
  import contextvars
4
4
  from typing import Any
5
5
 
6
- from pydantic import ConfigDict, validate_call
7
-
8
6
  # Key used for storing Fiddler-specific attributes in metadata dictionary
9
7
  FIDDLER_METADATA_KEY = '_fiddler_attributes'
10
8
 
@@ -66,22 +64,3 @@ _CONVERSATION_ID: contextvars.ContextVar[str] = contextvars.ContextVar(
66
64
  _CUSTOM_ATTRIBUTES: contextvars.ContextVar[dict[str, Any]] = contextvars.ContextVar(
67
65
  '_CUSTOM_ATTRIBUTES'
68
66
  )
69
-
70
-
71
- @validate_call(config=ConfigDict(strict=True, arbitrary_types_allowed=True))
72
- def add_session_attributes(key: str, value: str) -> None:
73
- """Adds Fiddler-specific attributes to a runnable's metadata.
74
-
75
- This is used for various runnable types like Pregel nodes, LLM calls, tool
76
- calls, and retriever calls.
77
-
78
- Args:
79
- key (str): The attribute key to add or update.
80
- value (str): The attribute value to set.
81
- """
82
- try:
83
- current_attributes = _CUSTOM_ATTRIBUTES.get().copy()
84
- except LookupError:
85
- current_attributes = {}
86
- current_attributes[key] = value
87
- _CUSTOM_ATTRIBUTES.set(current_attributes)
@@ -60,7 +60,7 @@ class FiddlerClient:
60
60
  self,
61
61
  api_key: str,
62
62
  application_id: str,
63
- url: str = 'http://localhost:4318',
63
+ url: str,
64
64
  console_tracer: bool = False,
65
65
  span_limits: SpanLimits | None = _default_span_limits,
66
66
  sampler: sampling.Sampler | None = None,
@@ -76,41 +76,69 @@ class FiddlerClient:
76
76
  Args:
77
77
  api_key (str): The API key for authenticating with the Fiddler backend. **Required**.
78
78
  application_id (str): The unique identifier (UUID4) for the application. **Required**.
79
- url (str): The base URL for the Fiddler backend. While it defaults to
80
- `http://localhost:4318` for local development, this **must** be set to your
81
- Fiddler instance URL for any other use.
79
+ url (str): The base URL for your Fiddler instance. This is specific to your
80
+ deployment, whether hosted, VPC-deployed, on-premise, or local development
81
+ (e.g., `https://your-instance.fiddler.ai`, `http://localhost:4318`). **Required**.
82
82
  console_tracer (bool): If True, traces will be printed to the console
83
83
  instead of being sent to the Fiddler backend. Useful for debugging.
84
84
  Defaults to `False`.
85
85
  span_limits (SpanLimits | None): Configuration for span limits, such as the
86
86
  maximum number of attributes or events. Defaults to a restrictive
87
- set of internal limits.
87
+ set of internal limits (32 events/links/attributes, 2048 char limit).
88
88
  sampler (sampling.Sampler | None): The sampler for deciding which spans to record.
89
- Defaults to `None`, which uses the parent-based OpenTelemetry sampler.
89
+ Defaults to `None`, which uses the parent-based always-on OpenTelemetry sampler
90
+ (100% sampling).
90
91
  compression (Compression): The compression for exporting traces.
91
- Can be `Compression.Gzip` or `Compression.NoCompression`.
92
- Defaults to `Compression.Gzip`.
92
+ Can be `Compression.Gzip`, `Compression.Deflate`, or `Compression.NoCompression`.
93
+ Defaults to `Compression.Gzip` (recommended for production).
93
94
  jsonl_capture_enabled (bool): Whether to enable JSONL capture of trace data.
94
95
  When enabled, all span data will be captured and saved to a JSONL file
95
- in OpenTelemetry format for analysis. Defaults to `False`.
96
+ in OpenTelemetry format for offline analysis. Defaults to `False`.
96
97
  jsonl_file_path (str): Path to the JSONL file where trace data will be saved.
97
98
  Only used when `jsonl_capture_enabled` is `True`. Defaults to
98
99
  "fiddler_trace_data.jsonl".
99
100
 
100
101
  Raises:
101
102
  ValueError: If `application_id` is not a valid UUID4 or if the
102
- `url` is not a valid HTTPS URL.
103
+ `url` is not a valid HTTP/HTTPS URL.
103
104
 
104
105
  Examples:
105
- >>> from opentelemetry.sdk.trace import SpanLimits
106
- >>> from fiddler_langgraph import FiddlerClient
107
- >>>
108
- >>> client = FiddlerClient(
109
- ... api_key='YOUR_API_KEY',
110
- ... application_id='YOUR_APPLICATION_ID',
111
- ... url='https://your-fiddler-instance.fiddler.ai',
112
- ... span_limits=SpanLimits(max_span_attributes=64),
113
- ... )
106
+ Basic connection to your Fiddler instance:
107
+
108
+ .. code-block:: python
109
+
110
+ client = FiddlerClient(
111
+ api_key='YOUR_API_KEY',
112
+ application_id='YOUR_APPLICATION_ID',
113
+ url='https://your-instance.fiddler.ai',
114
+ )
115
+
116
+ High-volume applications with custom configuration:
117
+
118
+ .. code-block:: python
119
+
120
+ from opentelemetry.sdk.trace import SpanLimits, sampling
121
+ from opentelemetry.exporter.otlp.proto.http.trace_exporter import Compression
122
+
123
+ client = FiddlerClient(
124
+ api_key='YOUR_API_KEY',
125
+ application_id='YOUR_APPLICATION_ID',
126
+ url='https://your-instance.fiddler.ai',
127
+ span_limits=SpanLimits(max_span_attributes=64),
128
+ sampler=sampling.TraceIdRatioBased(0.1), # Sample 10% of traces
129
+ compression=Compression.Gzip,
130
+ )
131
+
132
+ Local development with console output:
133
+
134
+ .. code-block:: python
135
+
136
+ client = FiddlerClient(
137
+ api_key='dev-key',
138
+ application_id='00000000-0000-0000-0000-000000000000',
139
+ url='http://localhost:4318',
140
+ console_tracer=True, # Print traces to console for debugging
141
+ )
114
142
  """
115
143
  # Validate application_id is a valid UUID4
116
144
 
@@ -216,9 +244,11 @@ class FiddlerClient:
216
244
  ValueError: If the tracer has already been initialized.
217
245
 
218
246
  Examples:
219
- >>> from fiddler_langgraph import FiddlerClient
220
- >>> client = FiddlerClient(api_key='...', application_id='...')
221
- >>> client.update_resource({'service.version': '1.2.3'})
247
+ .. code-block:: python
248
+
249
+ from fiddler_langgraph import FiddlerClient
250
+ client = FiddlerClient(api_key='...', application_id='...', url='https://your-instance.fiddler.ai')
251
+ client.update_resource({'service.version': '1.2.3'})
222
252
  """
223
253
  if self._tracer is not None:
224
254
  raise ValueError('Cannot update resource after tracer is initialized')
@@ -305,11 +335,13 @@ class FiddlerClient:
305
335
  RuntimeError: If tracer initialization fails.
306
336
 
307
337
  Examples:
308
- >>> from fiddler_langgraph import FiddlerClient
309
- >>> client = FiddlerClient(api_key='...', application_id='...')
310
- >>> tracer = client.get_tracer()
311
- >>> with tracer.start_as_current_span('my-operation'):
312
- ... print('Doing some work...')
338
+ .. code-block:: python
339
+
340
+ from fiddler_langgraph import FiddlerClient
341
+ client = FiddlerClient(api_key='...', application_id='...', url='https://your-instance.fiddler.ai')
342
+ tracer = client.get_tracer()
343
+ with tracer.start_as_current_span('my-operation'):
344
+ print('Doing some work...')
313
345
  """
314
346
  if self._tracer is None:
315
347
  self._initialize_tracer()
@@ -208,7 +208,12 @@ class _CallbackHandler(BaseCallbackHandler):
208
208
  if metadata is not None:
209
209
  fiddler_attributes = metadata.get(FIDDLER_METADATA_KEY, {})
210
210
  for key, value in fiddler_attributes.items():
211
- fdl_key = FIDDLER_USER_SPAN_ATTRIBUTE_TEMPLATE.format(key=key)
211
+ # FiddlerSpanAttributes keys should not be prefixed with fiddler.span.user.
212
+ fdl_key = (
213
+ key
214
+ if key in vars(FiddlerSpanAttributes).values()
215
+ else FIDDLER_USER_SPAN_ATTRIBUTE_TEMPLATE.format(key=key)
216
+ )
212
217
  span.set_attribute(fdl_key, value)
213
218
 
214
219
  def _update_root_span_agent_name(self, agent_name: str) -> None:
@@ -626,7 +631,6 @@ class _CallbackHandler(BaseCallbackHandler):
626
631
  system_message = [m for m in messages[0] if isinstance(m, SystemMessage)]
627
632
  user_message = [m for m in messages[0] if isinstance(m, HumanMessage)]
628
633
 
629
- # breakpoint()
630
634
  if metadata is not None:
631
635
  _set_agent_name(child_span, metadata)
632
636