mseep-agentops 0.4.18__py3-none-any.whl → 0.4.23__py3-none-any.whl

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 (153) hide show
  1. agentops/__init__.py +0 -0
  2. agentops/client/api/base.py +28 -30
  3. agentops/client/api/versions/v3.py +29 -25
  4. agentops/client/api/versions/v4.py +87 -46
  5. agentops/client/client.py +98 -29
  6. agentops/client/http/README.md +87 -0
  7. agentops/client/http/http_client.py +126 -172
  8. agentops/config.py +8 -2
  9. agentops/instrumentation/OpenTelemetry.md +133 -0
  10. agentops/instrumentation/README.md +167 -0
  11. agentops/instrumentation/__init__.py +13 -1
  12. agentops/instrumentation/agentic/ag2/__init__.py +18 -0
  13. agentops/instrumentation/agentic/ag2/instrumentor.py +922 -0
  14. agentops/instrumentation/agentic/agno/__init__.py +19 -0
  15. agentops/instrumentation/agentic/agno/attributes/__init__.py +20 -0
  16. agentops/instrumentation/agentic/agno/attributes/agent.py +250 -0
  17. agentops/instrumentation/agentic/agno/attributes/metrics.py +214 -0
  18. agentops/instrumentation/agentic/agno/attributes/storage.py +158 -0
  19. agentops/instrumentation/agentic/agno/attributes/team.py +195 -0
  20. agentops/instrumentation/agentic/agno/attributes/tool.py +210 -0
  21. agentops/instrumentation/agentic/agno/attributes/workflow.py +254 -0
  22. agentops/instrumentation/agentic/agno/instrumentor.py +1313 -0
  23. agentops/instrumentation/agentic/crewai/LICENSE +201 -0
  24. agentops/instrumentation/agentic/crewai/NOTICE.md +10 -0
  25. agentops/instrumentation/agentic/crewai/__init__.py +6 -0
  26. agentops/instrumentation/agentic/crewai/crewai_span_attributes.py +335 -0
  27. agentops/instrumentation/agentic/crewai/instrumentation.py +535 -0
  28. agentops/instrumentation/agentic/crewai/version.py +1 -0
  29. agentops/instrumentation/agentic/google_adk/__init__.py +19 -0
  30. agentops/instrumentation/agentic/google_adk/instrumentor.py +68 -0
  31. agentops/instrumentation/agentic/google_adk/patch.py +767 -0
  32. agentops/instrumentation/agentic/haystack/__init__.py +1 -0
  33. agentops/instrumentation/agentic/haystack/instrumentor.py +186 -0
  34. agentops/instrumentation/agentic/langgraph/__init__.py +3 -0
  35. agentops/instrumentation/agentic/langgraph/attributes.py +54 -0
  36. agentops/instrumentation/agentic/langgraph/instrumentation.py +598 -0
  37. agentops/instrumentation/agentic/langgraph/version.py +1 -0
  38. agentops/instrumentation/agentic/openai_agents/README.md +156 -0
  39. agentops/instrumentation/agentic/openai_agents/SPANS.md +145 -0
  40. agentops/instrumentation/agentic/openai_agents/TRACING_API.md +144 -0
  41. agentops/instrumentation/agentic/openai_agents/__init__.py +30 -0
  42. agentops/instrumentation/agentic/openai_agents/attributes/common.py +549 -0
  43. agentops/instrumentation/agentic/openai_agents/attributes/completion.py +172 -0
  44. agentops/instrumentation/agentic/openai_agents/attributes/model.py +58 -0
  45. agentops/instrumentation/agentic/openai_agents/attributes/tokens.py +275 -0
  46. agentops/instrumentation/agentic/openai_agents/exporter.py +469 -0
  47. agentops/instrumentation/agentic/openai_agents/instrumentor.py +107 -0
  48. agentops/instrumentation/agentic/openai_agents/processor.py +58 -0
  49. agentops/instrumentation/agentic/smolagents/README.md +88 -0
  50. agentops/instrumentation/agentic/smolagents/__init__.py +12 -0
  51. agentops/instrumentation/agentic/smolagents/attributes/agent.py +354 -0
  52. agentops/instrumentation/agentic/smolagents/attributes/model.py +205 -0
  53. agentops/instrumentation/agentic/smolagents/instrumentor.py +286 -0
  54. agentops/instrumentation/agentic/smolagents/stream_wrapper.py +258 -0
  55. agentops/instrumentation/agentic/xpander/__init__.py +15 -0
  56. agentops/instrumentation/agentic/xpander/context.py +112 -0
  57. agentops/instrumentation/agentic/xpander/instrumentor.py +877 -0
  58. agentops/instrumentation/agentic/xpander/trace_probe.py +86 -0
  59. agentops/instrumentation/agentic/xpander/version.py +3 -0
  60. agentops/instrumentation/common/README.md +65 -0
  61. agentops/instrumentation/common/attributes.py +1 -2
  62. agentops/instrumentation/providers/anthropic/__init__.py +24 -0
  63. agentops/instrumentation/providers/anthropic/attributes/__init__.py +23 -0
  64. agentops/instrumentation/providers/anthropic/attributes/common.py +64 -0
  65. agentops/instrumentation/providers/anthropic/attributes/message.py +541 -0
  66. agentops/instrumentation/providers/anthropic/attributes/tools.py +231 -0
  67. agentops/instrumentation/providers/anthropic/event_handler_wrapper.py +90 -0
  68. agentops/instrumentation/providers/anthropic/instrumentor.py +146 -0
  69. agentops/instrumentation/providers/anthropic/stream_wrapper.py +436 -0
  70. agentops/instrumentation/providers/google_genai/README.md +33 -0
  71. agentops/instrumentation/providers/google_genai/__init__.py +24 -0
  72. agentops/instrumentation/providers/google_genai/attributes/__init__.py +25 -0
  73. agentops/instrumentation/providers/google_genai/attributes/chat.py +125 -0
  74. agentops/instrumentation/providers/google_genai/attributes/common.py +88 -0
  75. agentops/instrumentation/providers/google_genai/attributes/model.py +284 -0
  76. agentops/instrumentation/providers/google_genai/instrumentor.py +170 -0
  77. agentops/instrumentation/providers/google_genai/stream_wrapper.py +238 -0
  78. agentops/instrumentation/providers/ibm_watsonx_ai/__init__.py +28 -0
  79. agentops/instrumentation/providers/ibm_watsonx_ai/attributes/__init__.py +27 -0
  80. agentops/instrumentation/providers/ibm_watsonx_ai/attributes/attributes.py +277 -0
  81. agentops/instrumentation/providers/ibm_watsonx_ai/attributes/common.py +104 -0
  82. agentops/instrumentation/providers/ibm_watsonx_ai/instrumentor.py +162 -0
  83. agentops/instrumentation/providers/ibm_watsonx_ai/stream_wrapper.py +302 -0
  84. agentops/instrumentation/providers/mem0/__init__.py +45 -0
  85. agentops/instrumentation/providers/mem0/common.py +377 -0
  86. agentops/instrumentation/providers/mem0/instrumentor.py +270 -0
  87. agentops/instrumentation/providers/mem0/memory.py +430 -0
  88. agentops/instrumentation/providers/openai/__init__.py +21 -0
  89. agentops/instrumentation/providers/openai/attributes/__init__.py +7 -0
  90. agentops/instrumentation/providers/openai/attributes/common.py +55 -0
  91. agentops/instrumentation/providers/openai/attributes/response.py +607 -0
  92. agentops/instrumentation/providers/openai/config.py +36 -0
  93. agentops/instrumentation/providers/openai/instrumentor.py +312 -0
  94. agentops/instrumentation/providers/openai/stream_wrapper.py +941 -0
  95. agentops/instrumentation/providers/openai/utils.py +44 -0
  96. agentops/instrumentation/providers/openai/v0.py +176 -0
  97. agentops/instrumentation/providers/openai/v0_wrappers.py +483 -0
  98. agentops/instrumentation/providers/openai/wrappers/__init__.py +30 -0
  99. agentops/instrumentation/providers/openai/wrappers/assistant.py +277 -0
  100. agentops/instrumentation/providers/openai/wrappers/chat.py +259 -0
  101. agentops/instrumentation/providers/openai/wrappers/completion.py +109 -0
  102. agentops/instrumentation/providers/openai/wrappers/embeddings.py +94 -0
  103. agentops/instrumentation/providers/openai/wrappers/image_gen.py +75 -0
  104. agentops/instrumentation/providers/openai/wrappers/responses.py +191 -0
  105. agentops/instrumentation/providers/openai/wrappers/shared.py +81 -0
  106. agentops/instrumentation/utilities/concurrent_futures/__init__.py +10 -0
  107. agentops/instrumentation/utilities/concurrent_futures/instrumentation.py +206 -0
  108. agentops/integration/callbacks/dspy/__init__.py +11 -0
  109. agentops/integration/callbacks/dspy/callback.py +471 -0
  110. agentops/integration/callbacks/langchain/README.md +59 -0
  111. agentops/integration/callbacks/langchain/__init__.py +15 -0
  112. agentops/integration/callbacks/langchain/callback.py +791 -0
  113. agentops/integration/callbacks/langchain/utils.py +54 -0
  114. agentops/legacy/crewai.md +121 -0
  115. agentops/logging/instrument_logging.py +4 -0
  116. agentops/sdk/README.md +220 -0
  117. agentops/sdk/core.py +75 -32
  118. agentops/sdk/descriptors/classproperty.py +28 -0
  119. agentops/sdk/exporters.py +152 -33
  120. agentops/semconv/README.md +125 -0
  121. agentops/semconv/span_kinds.py +0 -2
  122. agentops/validation.py +102 -63
  123. {mseep_agentops-0.4.18.dist-info → mseep_agentops-0.4.23.dist-info}/METADATA +30 -40
  124. mseep_agentops-0.4.23.dist-info/RECORD +178 -0
  125. {mseep_agentops-0.4.18.dist-info → mseep_agentops-0.4.23.dist-info}/WHEEL +1 -2
  126. mseep_agentops-0.4.18.dist-info/RECORD +0 -94
  127. mseep_agentops-0.4.18.dist-info/top_level.txt +0 -2
  128. tests/conftest.py +0 -10
  129. tests/unit/client/__init__.py +0 -1
  130. tests/unit/client/test_http_adapter.py +0 -221
  131. tests/unit/client/test_http_client.py +0 -206
  132. tests/unit/conftest.py +0 -54
  133. tests/unit/sdk/__init__.py +0 -1
  134. tests/unit/sdk/instrumentation_tester.py +0 -207
  135. tests/unit/sdk/test_attributes.py +0 -392
  136. tests/unit/sdk/test_concurrent_instrumentation.py +0 -468
  137. tests/unit/sdk/test_decorators.py +0 -763
  138. tests/unit/sdk/test_exporters.py +0 -241
  139. tests/unit/sdk/test_factory.py +0 -1188
  140. tests/unit/sdk/test_internal_span_processor.py +0 -397
  141. tests/unit/sdk/test_resource_attributes.py +0 -35
  142. tests/unit/test_config.py +0 -82
  143. tests/unit/test_context_manager.py +0 -777
  144. tests/unit/test_events.py +0 -27
  145. tests/unit/test_host_env.py +0 -54
  146. tests/unit/test_init_py.py +0 -501
  147. tests/unit/test_serialization.py +0 -433
  148. tests/unit/test_session.py +0 -676
  149. tests/unit/test_user_agent.py +0 -34
  150. tests/unit/test_validation.py +0 -405
  151. {tests → agentops/instrumentation/agentic/openai_agents/attributes}/__init__.py +0 -0
  152. /tests/unit/__init__.py → /agentops/instrumentation/providers/openai/attributes/tools.py +0 -0
  153. {mseep_agentops-0.4.18.dist-info → mseep_agentops-0.4.23.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,430 @@
1
+ """Memory operation attribute extractors and wrappers for Mem0 instrumentation."""
2
+
3
+ from typing import Optional, Tuple, Dict, Any
4
+
5
+ from agentops.instrumentation.common.attributes import AttributeMap
6
+ from agentops.semconv import SpanAttributes, LLMRequestTypeValues, MessageAttributes
7
+ from .common import (
8
+ get_common_attributes,
9
+ _extract_common_kwargs_attributes,
10
+ _extract_memory_response_attributes,
11
+ create_universal_mem0_wrapper,
12
+ )
13
+
14
+
15
+ def get_add_attributes(
16
+ args: Optional[Tuple] = None, kwargs: Optional[Dict[str, Any]] = None, return_value: Optional[Any] = None
17
+ ) -> AttributeMap:
18
+ """Extract attributes for Mem0's add method.
19
+
20
+ Args:
21
+ args: Positional arguments to the method
22
+ kwargs: Keyword arguments to the method
23
+ return_value: Return value from the method
24
+
25
+ Returns:
26
+ Dictionary of extracted attributes
27
+ """
28
+ print(f"args: {args}")
29
+ print(f"kwargs: {kwargs}")
30
+ print(f"return_value: {return_value}")
31
+ attributes = get_common_attributes()
32
+ attributes[SpanAttributes.OPERATION_NAME] = "add"
33
+ attributes[SpanAttributes.LLM_REQUEST_TYPE] = LLMRequestTypeValues.CHAT.value
34
+
35
+ # Extract message content from args
36
+ if args and len(args) > 0:
37
+ messages = args[0]
38
+ # Get user_id from kwargs for speaker, default to "user" if not found
39
+ speaker = kwargs.get("user_id", "user") if kwargs else "user"
40
+
41
+ if isinstance(messages, str):
42
+ attributes["mem0.message"] = messages
43
+ # Set as prompt for consistency with LLM patterns
44
+ attributes[MessageAttributes.PROMPT_CONTENT.format(i=0)] = messages
45
+ attributes[MessageAttributes.PROMPT_SPEAKER.format(i=0)] = speaker
46
+ elif isinstance(messages, list):
47
+ attributes["mem0.message_count"] = len(messages)
48
+ # Extract message types if available
49
+ message_types = set()
50
+ for i, msg in enumerate(messages):
51
+ if isinstance(msg, dict):
52
+ if "role" in msg:
53
+ message_types.add(msg["role"])
54
+ attributes[MessageAttributes.PROMPT_ROLE.format(i=i)] = msg["role"]
55
+ if "content" in msg:
56
+ attributes[MessageAttributes.PROMPT_CONTENT.format(i=i)] = msg["content"]
57
+ # Set speaker for each message
58
+ attributes[MessageAttributes.PROMPT_SPEAKER.format(i=i)] = speaker
59
+ else:
60
+ # String message
61
+ attributes[MessageAttributes.PROMPT_CONTENT.format(i=i)] = str(msg)
62
+
63
+ attributes[MessageAttributes.PROMPT_SPEAKER.format(i=i)] = speaker
64
+ if message_types:
65
+ attributes["mem0.message_types"] = ",".join(message_types)
66
+
67
+ # Extract kwargs attributes
68
+ if kwargs:
69
+ attributes.update(_extract_common_kwargs_attributes(kwargs))
70
+
71
+ # Extract memory type
72
+ if "memory_type" in kwargs:
73
+ attributes["mem0.memory_type"] = str(kwargs["memory_type"])
74
+
75
+ # Extract inference flag
76
+ if "infer" in kwargs:
77
+ attributes[SpanAttributes.MEM0_INFER] = str(kwargs["infer"])
78
+
79
+ # Extract response attributes
80
+ if return_value:
81
+ attributes.update(_extract_memory_response_attributes(return_value))
82
+
83
+ return attributes
84
+
85
+
86
+ def get_search_attributes(
87
+ args: Optional[Tuple] = None, kwargs: Optional[Dict[str, Any]] = None, return_value: Optional[Any] = None
88
+ ) -> AttributeMap:
89
+ """Extract attributes for Mem0's search method.
90
+
91
+ Args:
92
+ args: Positional arguments to the method
93
+ kwargs: Keyword arguments to the method
94
+ return_value: Return value from the method
95
+
96
+ Returns:
97
+ Dictionary of extracted attributes
98
+ """
99
+ print(f"get_search_attributes args: {args}")
100
+ print(f"get_search_attributes kwargs: {kwargs}")
101
+ print(f"get_search_attributes return_value: {return_value}")
102
+ attributes = get_common_attributes()
103
+ attributes[SpanAttributes.OPERATION_NAME] = "search"
104
+ attributes[SpanAttributes.LLM_REQUEST_TYPE] = LLMRequestTypeValues.CHAT.value
105
+
106
+ # Extract search query from args
107
+ if args and len(args) > 0:
108
+ query = args[0]
109
+ # Get user_id from kwargs for speaker, default to "user" if not found
110
+ speaker = kwargs.get("user_id", "user") if kwargs else "user"
111
+
112
+ if isinstance(query, str):
113
+ attributes["mem0.message"] = query
114
+ # Set as prompt for consistency
115
+ attributes[MessageAttributes.PROMPT_CONTENT.format(i=0)] = query
116
+ attributes[MessageAttributes.PROMPT_SPEAKER.format(i=0)] = speaker
117
+
118
+ # Extract kwargs attributes
119
+ if kwargs:
120
+ attributes.update(_extract_common_kwargs_attributes(kwargs))
121
+
122
+ # Extract memory type
123
+ if "memory_type" in kwargs:
124
+ attributes["mem0.memory_type"] = str(kwargs["memory_type"])
125
+
126
+ # Extract limit parameter
127
+ if "limit" in kwargs:
128
+ attributes["mem0.search.limit"] = str(kwargs["limit"])
129
+
130
+ # Extract response attributes
131
+ if return_value:
132
+ attributes.update(_extract_memory_response_attributes(return_value))
133
+
134
+ return attributes
135
+
136
+
137
+ def get_get_all_attributes(
138
+ args: Optional[Tuple] = None, kwargs: Optional[Dict[str, Any]] = None, return_value: Optional[Any] = None
139
+ ) -> AttributeMap:
140
+ """Extract attributes for Mem0's get_all method.
141
+
142
+ Args:
143
+ args: Positional arguments to the method
144
+ kwargs: Keyword arguments to the method
145
+ return_value: Return value from the method
146
+
147
+ Returns:
148
+ Dictionary of extracted attributes
149
+ """
150
+ attributes = get_common_attributes()
151
+ attributes[SpanAttributes.OPERATION_NAME] = "get_all"
152
+
153
+ # Extract kwargs attributes
154
+ if kwargs:
155
+ attributes.update(_extract_common_kwargs_attributes(kwargs))
156
+
157
+ # Extract memory type
158
+ if "memory_type" in kwargs:
159
+ attributes["mem0.memory_type"] = str(kwargs["memory_type"])
160
+
161
+ # Extract response attributes
162
+ if return_value:
163
+ attributes.update(_extract_memory_response_attributes(return_value))
164
+
165
+ return attributes
166
+
167
+
168
+ def get_get_attributes(
169
+ args: Optional[Tuple] = None, kwargs: Optional[Dict[str, Any]] = None, return_value: Optional[Any] = None
170
+ ) -> AttributeMap:
171
+ """Extract attributes for Mem0's get method.
172
+
173
+ Args:
174
+ args: Positional arguments to the method
175
+ kwargs: Keyword arguments to the method
176
+ return_value: Return value from the method
177
+
178
+ Returns:
179
+ Dictionary of extracted attributes
180
+ """
181
+ attributes = get_common_attributes()
182
+ attributes[SpanAttributes.OPERATION_NAME] = "get"
183
+
184
+ # Extract memory ID from args
185
+ if args and len(args) > 0:
186
+ memory_id = args[0]
187
+ if memory_id:
188
+ attributes["mem0.memory_id"] = str(memory_id)
189
+
190
+ # Extract response attributes
191
+ if return_value:
192
+ attributes.update(_extract_memory_response_attributes(return_value))
193
+
194
+ return attributes
195
+
196
+
197
+ def get_delete_attributes(
198
+ args: Optional[Tuple] = None, kwargs: Optional[Dict[str, Any]] = None, return_value: Optional[Any] = None
199
+ ) -> AttributeMap:
200
+ """Extract attributes for Mem0's delete method.
201
+
202
+ Args:
203
+ args: Positional arguments to the method
204
+ kwargs: Keyword arguments to the method
205
+ return_value: Return value from the method
206
+
207
+ Returns:
208
+ Dictionary of extracted attributes
209
+ """
210
+ attributes = get_common_attributes()
211
+ attributes[SpanAttributes.OPERATION_NAME] = "delete"
212
+
213
+ # Extract memory ID from args if available
214
+ if args and len(args) > 0:
215
+ memory_id = args[0]
216
+ if memory_id:
217
+ attributes["mem0.memory_id"] = str(memory_id)
218
+
219
+ # Extract kwargs attributes if available
220
+ if kwargs:
221
+ attributes.update(_extract_common_kwargs_attributes(kwargs))
222
+
223
+ # Extract memory type
224
+ if "memory_type" in kwargs:
225
+ attributes["mem0.memory_type"] = str(kwargs["memory_type"])
226
+
227
+ # Extract response attributes
228
+ if return_value:
229
+ attributes.update(_extract_memory_response_attributes(return_value))
230
+
231
+ return attributes
232
+
233
+
234
+ def get_update_attributes(
235
+ args: Optional[Tuple] = None, kwargs: Optional[Dict[str, Any]] = None, return_value: Optional[Any] = None
236
+ ) -> AttributeMap:
237
+ """Extract attributes for Mem0's update method.
238
+
239
+ Args:
240
+ args: Positional arguments to the method
241
+ kwargs: Keyword arguments to the method
242
+ return_value: Return value from the method
243
+
244
+ Returns:
245
+ Dictionary of extracted attributes
246
+ """
247
+ attributes = get_common_attributes()
248
+ attributes[SpanAttributes.OPERATION_NAME] = "update"
249
+
250
+ # Extract memory ID from args (if available)
251
+ if args and len(args) > 0:
252
+ memory_id = args[0]
253
+ if memory_id:
254
+ attributes["mem0.memory_id"] = str(memory_id)
255
+
256
+ # Extract data from args (if available)
257
+ if args and len(args) > 1:
258
+ data = args[1]
259
+ if isinstance(data, str):
260
+ attributes["mem0.message"] = data
261
+ # Set as prompt for consistency
262
+ attributes[MessageAttributes.PROMPT_CONTENT.format(i=0)] = data
263
+ elif isinstance(data, dict):
264
+ # Handle case where data is a dictionary with "memory" key
265
+ if "memory" in data:
266
+ memory_text = data["memory"]
267
+ attributes["mem0.message"] = memory_text
268
+ # Set as prompt for consistency
269
+ attributes[MessageAttributes.PROMPT_CONTENT.format(i=0)] = memory_text
270
+
271
+ # Extract metadata from data dict if present
272
+ if "metadata" in data and isinstance(data["metadata"], dict):
273
+ for key, value in data["metadata"].items():
274
+ attributes[f"mem0.metadata.{key}"] = str(value)
275
+
276
+ # Extract kwargs attributes (if available)
277
+ if kwargs:
278
+ attributes.update(_extract_common_kwargs_attributes(kwargs))
279
+
280
+ # Extract memory type
281
+ if "memory_type" in kwargs:
282
+ attributes["mem0.memory_type"] = str(kwargs["memory_type"])
283
+
284
+ # Extract response attributes
285
+ if return_value:
286
+ attributes.update(_extract_memory_response_attributes(return_value))
287
+
288
+ return attributes
289
+
290
+
291
+ def get_delete_all_attributes(
292
+ args: Optional[Tuple] = None, kwargs: Optional[Dict[str, Any]] = None, return_value: Optional[Any] = None
293
+ ) -> AttributeMap:
294
+ """Extract attributes for Mem0's delete_all method.
295
+
296
+ Args:
297
+ args: Positional arguments to the method
298
+ kwargs: Keyword arguments to the method
299
+ return_value: Return value from the method
300
+
301
+ Returns:
302
+ Dictionary of extracted attributes
303
+ """
304
+ attributes = get_common_attributes()
305
+ attributes[SpanAttributes.OPERATION_NAME] = "delete_all"
306
+
307
+ # Extract kwargs attributes if available
308
+ if kwargs:
309
+ attributes.update(_extract_common_kwargs_attributes(kwargs))
310
+
311
+ # Extract memory type
312
+ if "memory_type" in kwargs:
313
+ attributes["mem0.memory_type"] = str(kwargs["memory_type"])
314
+
315
+ # Extract user_id for tracking which user's memories are being deleted
316
+ if "user_id" in kwargs:
317
+ attributes["mem0.delete_all.user_id"] = str(kwargs["user_id"])
318
+
319
+ # Extract agent_id for tracking which agent's memories are being deleted
320
+ if "agent_id" in kwargs:
321
+ attributes["mem0.delete_all.agent_id"] = str(kwargs["agent_id"])
322
+
323
+ # Extract run_id for tracking which run's memories are being deleted
324
+ if "run_id" in kwargs:
325
+ attributes["mem0.delete_all.run_id"] = str(kwargs["run_id"])
326
+
327
+ # Extract response attributes
328
+ if return_value:
329
+ attributes.update(_extract_memory_response_attributes(return_value))
330
+
331
+ return attributes
332
+
333
+
334
+ def get_history_attributes(
335
+ args: Optional[Tuple] = None, kwargs: Optional[Dict[str, Any]] = None, return_value: Optional[Any] = None
336
+ ) -> AttributeMap:
337
+ """Extract attributes for Mem0's history method.
338
+
339
+ Args:
340
+ args: Positional arguments to the method
341
+ kwargs: Keyword arguments to the method
342
+ return_value: Return value from the method
343
+
344
+ Returns:
345
+ Dictionary of extracted attributes
346
+ """
347
+ attributes = get_common_attributes()
348
+ attributes[SpanAttributes.OPERATION_NAME] = "history"
349
+
350
+ # Extract memory ID from args
351
+ if args and len(args) > 0:
352
+ memory_id = args[0]
353
+ if memory_id:
354
+ attributes["mem0.memory_id"] = str(memory_id)
355
+
356
+ # Extract kwargs attributes if available
357
+ if kwargs:
358
+ attributes.update(_extract_common_kwargs_attributes(kwargs))
359
+
360
+ # Extract history data from return value
361
+ if return_value and isinstance(return_value, list):
362
+ attributes["mem0.history.count"] = len(return_value)
363
+
364
+ # Extract event types and other details from history entries
365
+ event_types = set()
366
+ actor_ids = set()
367
+ roles = set()
368
+
369
+ for i, entry in enumerate(return_value):
370
+ if isinstance(entry, dict):
371
+ # Extract event type
372
+ if "event" in entry:
373
+ event_types.add(entry["event"])
374
+ attributes[f"mem0.history.{i}.event"] = entry["event"]
375
+
376
+ # Extract memory content changes
377
+ if "old_memory" in entry:
378
+ if entry["old_memory"]:
379
+ attributes[f"mem0.history.{i}.old_memory"] = entry["old_memory"]
380
+
381
+ if "new_memory" in entry:
382
+ if entry["new_memory"]:
383
+ attributes[f"mem0.history.{i}.new_memory"] = entry["new_memory"]
384
+
385
+ # Extract timestamps
386
+ if "created_at" in entry:
387
+ attributes[f"mem0.history.{i}.created_at"] = entry["created_at"]
388
+
389
+ if "updated_at" in entry and entry["updated_at"]:
390
+ attributes[f"mem0.history.{i}.updated_at"] = entry["updated_at"]
391
+
392
+ # Extract actor information
393
+ if "actor_id" in entry and entry["actor_id"]:
394
+ actor_ids.add(entry["actor_id"])
395
+ attributes[f"mem0.history.{i}.actor_id"] = entry["actor_id"]
396
+
397
+ if "role" in entry and entry["role"]:
398
+ roles.add(entry["role"])
399
+ attributes[f"mem0.history.{i}.role"] = entry["role"]
400
+
401
+ # Extract deletion status
402
+ if "is_deleted" in entry:
403
+ attributes[f"mem0.history.{i}.is_deleted"] = str(entry["is_deleted"])
404
+
405
+ # Extract history entry ID
406
+ if "id" in entry:
407
+ attributes[f"mem0.history.{i}.id"] = entry["id"]
408
+
409
+ # Set aggregated attributes
410
+ if event_types:
411
+ attributes["mem0.history.event_types"] = ",".join(event_types)
412
+
413
+ if actor_ids:
414
+ attributes["mem0.history.actor_ids"] = ",".join(actor_ids)
415
+
416
+ if roles:
417
+ attributes["mem0.history.roles"] = ",".join(roles)
418
+
419
+ return attributes
420
+
421
+
422
+ # Create universal Mem0 wrappers that work for both sync and async operations
423
+ mem0_add_wrapper = create_universal_mem0_wrapper("add", get_add_attributes)
424
+ mem0_search_wrapper = create_universal_mem0_wrapper("search", get_search_attributes)
425
+ mem0_get_all_wrapper = create_universal_mem0_wrapper("get_all", get_get_all_attributes)
426
+ mem0_get_wrapper = create_universal_mem0_wrapper("get", get_get_attributes)
427
+ mem0_delete_wrapper = create_universal_mem0_wrapper("delete", get_delete_attributes)
428
+ mem0_update_wrapper = create_universal_mem0_wrapper("update", get_update_attributes)
429
+ mem0_delete_all_wrapper = create_universal_mem0_wrapper("delete_all", get_delete_all_attributes)
430
+ mem0_history_wrapper = create_universal_mem0_wrapper("history", get_history_attributes)
@@ -0,0 +1,21 @@
1
+ """OpenAI API instrumentation for AgentOps.
2
+
3
+ This package provides OpenTelemetry-based instrumentation for OpenAI API calls,
4
+ extending the third-party instrumentation to add support for OpenAI responses.
5
+ """
6
+
7
+ from agentops.instrumentation.common import LibraryInfo
8
+
9
+ # Library information
10
+ _library_info = LibraryInfo(name="openai")
11
+ LIBRARY_NAME = _library_info.name
12
+ LIBRARY_VERSION = _library_info.version
13
+
14
+ # Import after defining constants to avoid circular imports
15
+ from agentops.instrumentation.providers.openai.instrumentor import OpenaiInstrumentor # noqa: E402
16
+
17
+ __all__ = [
18
+ "LIBRARY_NAME",
19
+ "LIBRARY_VERSION",
20
+ "OpenaiInstrumentor",
21
+ ]
@@ -0,0 +1,7 @@
1
+ """Attribute helpers for OpenAI API instrumentation.
2
+
3
+ This package contains helpers for extracting attributes from OpenAI API responses
4
+ for use in OpenTelemetry spans.
5
+ """
6
+
7
+ # Will contain attribute extraction helpers in the future
@@ -0,0 +1,55 @@
1
+ from typing import Optional, Tuple, Dict
2
+ from agentops.logging import logger
3
+ from agentops.semconv import InstrumentationAttributes
4
+ from agentops.instrumentation.providers.openai import LIBRARY_NAME, LIBRARY_VERSION
5
+ from agentops.instrumentation.common.attributes import AttributeMap, get_common_attributes
6
+ from agentops.instrumentation.providers.openai.attributes.response import (
7
+ get_response_kwarg_attributes,
8
+ get_response_response_attributes,
9
+ )
10
+
11
+ try:
12
+ from openai.types.responses import Response
13
+ except ImportError as e:
14
+ logger.debug(f"[agentops.instrumentation.openai] Could not import OpenAI types: {e}")
15
+
16
+
17
+ def get_common_instrumentation_attributes() -> AttributeMap:
18
+ """Get common instrumentation attributes for the OpenAI Agents instrumentation.
19
+
20
+ This combines the generic AgentOps attributes with OpenAI Agents specific library attributes.
21
+
22
+ Returns:
23
+ Dictionary of common instrumentation attributes
24
+ """
25
+ attributes = get_common_attributes()
26
+ attributes.update(
27
+ {
28
+ InstrumentationAttributes.LIBRARY_NAME: LIBRARY_NAME,
29
+ InstrumentationAttributes.LIBRARY_VERSION: LIBRARY_VERSION,
30
+ }
31
+ )
32
+ return attributes
33
+
34
+
35
+ def get_response_attributes(
36
+ args: Optional[Tuple] = None, kwargs: Optional[Dict] = None, return_value: Optional["Response"] = None
37
+ ) -> AttributeMap:
38
+ """ """
39
+ # We can get an context object before, and after the request is made, so
40
+ # conditionally handle the data we have available.
41
+ attributes = get_common_instrumentation_attributes()
42
+
43
+ # Parse the keyword arguments to extract relevant attributes
44
+ # We do not ever get `args` from this method call since it is a keyword-only method
45
+ if kwargs:
46
+ attributes.update(get_response_kwarg_attributes(kwargs))
47
+
48
+ # Parse the return value to extract relevant attributes
49
+ if return_value:
50
+ if isinstance(return_value, Response):
51
+ attributes.update(get_response_response_attributes(return_value))
52
+ else:
53
+ logger.debug(f"[agentops.instrumentation.openai] Got an unexpected return type: {type(return_value)}")
54
+
55
+ return attributes