agenticmem 0.1.2.4__py3-none-any.whl → 0.1.3.8__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.

Potentially problematic release.


This version of agenticmem might be problematic. Click here for more details.

agenticmem/__init__.py CHANGED
@@ -2,7 +2,7 @@ __app_name__ = "agenticmem"
2
2
  __version__ = "0.1.1"
3
3
 
4
4
 
5
- from agenticmem.client import AgenticMemClient
5
+ from .client import AgenticMemClient
6
6
  from agenticmem_commons.api_schema.service_schemas import (
7
7
  UserActionType,
8
8
  ProfileTimeToLive,
@@ -31,6 +31,8 @@ from agenticmem_commons.config_schema import (
31
31
  ProfileExtractorConfig,
32
32
  FeedbackAggregatorConfig,
33
33
  AgentFeedbackConfig,
34
+ AgentSuccessConfig,
35
+ ToolUseConfig,
34
36
  Config,
35
37
  )
36
38
 
@@ -63,5 +65,7 @@ __all__ = [
63
65
  "ProfileExtractorConfig",
64
66
  "FeedbackAggregatorConfig",
65
67
  "AgentFeedbackConfig",
68
+ "AgentSuccessConfig",
69
+ "ToolUseConfig",
66
70
  "Config",
67
71
  ]
agenticmem/client.py CHANGED
@@ -1,7 +1,9 @@
1
- from agenticmem_commons import IS_TEST_ENV
1
+ import os
2
2
  import aiohttp
3
+ import asyncio
3
4
  from urllib.parse import urljoin
4
5
  import requests
6
+ from concurrent.futures import ThreadPoolExecutor
5
7
  from typing import Optional, Union
6
8
  from agenticmem_commons.api_schema.retriever_schema import (
7
9
  SearchInteractionRequest,
@@ -18,6 +20,13 @@ from agenticmem_commons.api_schema.retriever_schema import (
18
20
  GetFeedbacksResponse,
19
21
  )
20
22
 
23
+ from dotenv import load_dotenv
24
+
25
+ # Load environment variables from .env file
26
+ load_dotenv()
27
+
28
+ IS_TEST_ENV = os.environ.get("IS_TEST_ENV", "false").strip() == "true"
29
+
21
30
  if IS_TEST_ENV:
22
31
  BACKEND_URL = "http://127.0.0.1:8000" # Local server for testing
23
32
  else:
@@ -40,6 +49,9 @@ from agenticmem_commons.config_schema import Config
40
49
  class AgenticMemClient:
41
50
  """Client for interacting with the AgenticMem API."""
42
51
 
52
+ # Shared thread pool for all instances to maximize efficiency
53
+ _thread_pool = ThreadPoolExecutor(max_workers=4, thread_name_prefix="agenticmem")
54
+
43
55
  def __init__(self, api_key: str = "", url_endpoint: str = ""):
44
56
  """Initialize the AgenticMem client.
45
57
 
@@ -50,24 +62,83 @@ class AgenticMemClient:
50
62
  self.base_url = url_endpoint if url_endpoint else BACKEND_URL
51
63
  self.session = requests.Session()
52
64
 
65
+ def _get_auth_headers(self) -> dict:
66
+ """Get authentication headers for API requests.
67
+
68
+ Returns:
69
+ dict: Headers with authorization and content-type
70
+ """
71
+ if self.api_key:
72
+ return {
73
+ "Authorization": f"Bearer {self.api_key}",
74
+ "Content-Type": "application/json",
75
+ }
76
+ return {}
77
+
78
+ def _convert_to_model(self, data: Union[dict, object], model_class):
79
+ """Convert dict to model instance if needed.
80
+
81
+ Args:
82
+ data: Either a dict or already an instance of model_class
83
+ model_class: The target class to convert to
84
+
85
+ Returns:
86
+ An instance of model_class
87
+ """
88
+ if isinstance(data, dict):
89
+ return model_class(**data)
90
+ return data
91
+
92
+ def _fire_and_forget(self, sync_func, async_func, *args, **kwargs):
93
+ """Execute a request in fire-and-forget mode.
94
+
95
+ This method optimizes execution based on context:
96
+ - In async contexts (e.g., FastAPI): Uses existing event loop (most efficient)
97
+ - In sync contexts: Uses shared thread pool (avoids thread creation overhead)
98
+
99
+ Args:
100
+ sync_func: Synchronous function to call
101
+ async_func: Asynchronous function to call
102
+ *args: Positional arguments to pass to the function
103
+ **kwargs: Keyword arguments to pass to the function
104
+ """
105
+ try:
106
+ loop = asyncio.get_running_loop()
107
+
108
+ # We're in an async context - use the event loop
109
+ async def fire_and_forget():
110
+ try:
111
+ await async_func(*args, **kwargs)
112
+ except Exception:
113
+ # Silently ignore errors in fire-and-forget mode
114
+ pass
115
+
116
+ loop.create_task(fire_and_forget())
117
+ except RuntimeError:
118
+ # No running loop - we're in sync context, use thread pool
119
+ def send_request():
120
+ try:
121
+ sync_func(*args, **kwargs)
122
+ except Exception:
123
+ # Silently ignore errors in fire-and-forget mode
124
+ pass
125
+
126
+ self._thread_pool.submit(send_request)
127
+
53
128
  async def _make_async_request(
54
129
  self, method: str, endpoint: str, headers: Optional[dict] = None, **kwargs
55
130
  ):
56
131
  """Make an async HTTP request to the API."""
57
132
  url = urljoin(self.base_url, endpoint)
58
133
 
59
- headers = headers or {}
60
- if self.api_key:
61
- headers.update(
62
- {
63
- "Authorization": f"Bearer {self.api_key}",
64
- "Content-Type": "application/json",
65
- }
66
- )
134
+ # Merge auth headers with any provided headers
135
+ request_headers = self._get_auth_headers()
136
+ if headers:
137
+ request_headers.update(headers)
67
138
 
68
139
  async with aiohttp.ClientSession() as async_session:
69
140
  response = await async_session.request(
70
- method, url, headers=headers, **kwargs
141
+ method, url, headers=request_headers, **kwargs
71
142
  )
72
143
  response.raise_for_status()
73
144
  return await response.json()
@@ -87,22 +158,20 @@ class AgenticMemClient:
87
158
  dict: API response
88
159
  """
89
160
  url = urljoin(self.base_url, endpoint)
90
- if self.api_key:
91
- self.session.headers.update(
92
- {
93
- "Authorization": f"Bearer {self.api_key}",
94
- "Content-Type": "application/json",
95
- }
96
- )
161
+
162
+ # Merge auth headers with any provided headers
163
+ request_headers = self._get_auth_headers()
97
164
  if headers:
98
- self.session.headers.update(headers)
165
+ request_headers.update(headers)
166
+
167
+ self.session.headers.update(request_headers)
99
168
  response = self.session.request(method, url, **kwargs)
100
169
  response.raise_for_status()
101
170
  return response.json()
102
171
 
103
- async def login(self, email: str, password: str) -> Token:
104
- """Async login to the AgenticMem API."""
105
- response = await self._make_async_request(
172
+ def login(self, email: str, password: str) -> Token:
173
+ """Login to the AgenticMem API."""
174
+ response = self._make_request(
106
175
  "POST",
107
176
  "/token",
108
177
  data={"username": email, "password": password},
@@ -113,23 +182,52 @@ class AgenticMemClient:
113
182
  )
114
183
  return Token(**response)
115
184
 
116
- async def publish_interaction(
185
+ def _publish_interaction_sync(
186
+ self, request: PublishUserInteractionRequest
187
+ ) -> PublishUserInteractionResponse:
188
+ """Internal sync method to publish interaction."""
189
+ response = self._make_request(
190
+ "POST",
191
+ "/api/publish_interaction",
192
+ json=request.model_dump(),
193
+ )
194
+ return PublishUserInteractionResponse(**response)
195
+
196
+ async def _publish_interaction_async(
197
+ self, request: PublishUserInteractionRequest
198
+ ) -> PublishUserInteractionResponse:
199
+ """Internal async method to publish interaction."""
200
+ response = await self._make_async_request(
201
+ "POST",
202
+ "/api/publish_interaction",
203
+ json=request.model_dump(),
204
+ )
205
+ return PublishUserInteractionResponse(**response)
206
+
207
+ def publish_interaction(
117
208
  self,
118
209
  request_id: str,
119
210
  user_id: str,
120
211
  interaction_requests: list[Union[InteractionRequest, dict]],
121
212
  source: str = "",
122
213
  agent_version: str = "",
123
- ) -> PublishUserInteractionResponse:
214
+ wait_for_response: bool = False,
215
+ ) -> Optional[PublishUserInteractionResponse]:
124
216
  """Publish user interactions.
125
217
 
218
+ This method is optimized for resource efficiency:
219
+ - In async contexts (e.g., FastAPI): Uses existing event loop (most efficient)
220
+ - In sync contexts: Uses shared thread pool (avoids thread creation overhead)
221
+
126
222
  Args:
127
223
  request_id (str): The request ID
128
224
  user_id (str): The user ID
129
225
  interaction_requests (List[InteractionRequest]): List of interaction requests
130
226
  source (str, optional): The source of the interaction
227
+ agent_version (str, optional): The agent version
228
+ wait_for_response (bool, optional): If True, wait for response. If False, send request without waiting. Defaults to False.
131
229
  Returns:
132
- PublishUserInteractionResponse: Response containing success status and message
230
+ Optional[PublishUserInteractionResponse]: Response containing success status and message if wait_for_response=True, None otherwise
133
231
  """
134
232
  interaction_requests = [
135
233
  (
@@ -146,14 +244,18 @@ class AgenticMemClient:
146
244
  source=source,
147
245
  agent_version=agent_version,
148
246
  )
149
- response = await self._make_async_request(
150
- "POST",
151
- "/api/publish_interaction",
152
- json=request.model_dump(),
153
- )
154
- return PublishUserInteractionResponse(**response)
155
247
 
156
- async def search_interactions(
248
+ if wait_for_response:
249
+ # Synchronous blocking call
250
+ return self._publish_interaction_sync(request)
251
+ else:
252
+ # Non-blocking fire-and-forget
253
+ self._fire_and_forget(
254
+ self._publish_interaction_sync, self._publish_interaction_async, request
255
+ )
256
+ return None
257
+
258
+ def search_interactions(
157
259
  self,
158
260
  request: Union[SearchInteractionRequest, dict],
159
261
  ) -> SearchInteractionResponse:
@@ -165,16 +267,15 @@ class AgenticMemClient:
165
267
  Returns:
166
268
  SearchInteractionResponse: Response containing matching interactions
167
269
  """
168
- if isinstance(request, dict):
169
- request = SearchInteractionRequest(**request)
170
- response = await self._make_async_request(
270
+ request = self._convert_to_model(request, SearchInteractionRequest)
271
+ response = self._make_request(
171
272
  "POST",
172
273
  "/api/search_interactions",
173
274
  json=request.model_dump(),
174
275
  )
175
276
  return SearchInteractionResponse(**response)
176
277
 
177
- async def search_profiles(
278
+ def search_profiles(
178
279
  self,
179
280
  request: Union[SearchUserProfileRequest, dict],
180
281
  ) -> SearchUserProfileResponse:
@@ -186,61 +287,135 @@ class AgenticMemClient:
186
287
  Returns:
187
288
  SearchUserProfileResponse: Response containing matching profiles
188
289
  """
189
- if isinstance(request, dict):
190
- request = SearchUserProfileRequest(**request)
191
- response = await self._make_async_request(
290
+ request = self._convert_to_model(request, SearchUserProfileRequest)
291
+ response = self._make_request(
192
292
  "POST", "/api/search_profiles", json=request.model_dump()
193
293
  )
194
294
  return SearchUserProfileResponse(**response)
195
295
 
196
- async def delete_profile(
197
- self, user_id: str, profile_id: str = "", search_query: str = ""
296
+ def _delete_profile_sync(
297
+ self, request: DeleteUserProfileRequest
298
+ ) -> DeleteUserProfileResponse:
299
+ """Internal sync method to delete profile."""
300
+ response = self._make_request(
301
+ "DELETE",
302
+ "/api/delete_profile",
303
+ json=request.model_dump(),
304
+ )
305
+ return DeleteUserProfileResponse(**response)
306
+
307
+ async def _delete_profile_async(
308
+ self, request: DeleteUserProfileRequest
198
309
  ) -> DeleteUserProfileResponse:
310
+ """Internal async method to delete profile."""
311
+ response = await self._make_async_request(
312
+ "DELETE",
313
+ "/api/delete_profile",
314
+ json=request.model_dump(),
315
+ )
316
+ return DeleteUserProfileResponse(**response)
317
+
318
+ def delete_profile(
319
+ self,
320
+ user_id: str,
321
+ profile_id: str = "",
322
+ search_query: str = "",
323
+ wait_for_response: bool = False,
324
+ ) -> Optional[DeleteUserProfileResponse]:
199
325
  """Delete user profiles.
200
326
 
327
+ This method is optimized for resource efficiency:
328
+ - In async contexts (e.g., FastAPI): Uses existing event loop (most efficient)
329
+ - In sync contexts: Uses shared thread pool (avoids thread creation overhead)
330
+
201
331
  Args:
202
332
  user_id (str): The user ID
203
333
  profile_id (str, optional): Specific profile ID to delete
204
334
  search_query (str, optional): Query to match profiles for deletion
335
+ wait_for_response (bool, optional): If True, wait for response. If False, send request without waiting. Defaults to False.
205
336
 
206
337
  Returns:
207
- DeleteUserProfileResponse: Response containing success status and message
338
+ Optional[DeleteUserProfileResponse]: Response containing success status and message if wait_for_response=True, None otherwise
208
339
  """
209
340
  request = DeleteUserProfileRequest(
210
341
  user_id=user_id,
211
342
  profile_id=profile_id,
212
343
  search_query=search_query,
213
344
  )
214
- response = await self._make_async_request(
215
- "DELETE", "/api/delete_profile", json=request.model_dump()
345
+
346
+ if wait_for_response:
347
+ # Synchronous blocking call
348
+ return self._delete_profile_sync(request)
349
+ else:
350
+ # Non-blocking fire-and-forget
351
+ self._fire_and_forget(
352
+ self._delete_profile_sync, self._delete_profile_async, request
353
+ )
354
+ return None
355
+
356
+ def _delete_interaction_sync(
357
+ self, request: DeleteUserInteractionRequest
358
+ ) -> DeleteUserInteractionResponse:
359
+ """Internal sync method to delete interaction."""
360
+ response = self._make_request(
361
+ "DELETE",
362
+ "/api/delete_interaction",
363
+ json=request.model_dump(),
216
364
  )
217
- return DeleteUserProfileResponse(**response)
365
+ return DeleteUserInteractionResponse(**response)
218
366
 
219
- async def delete_interaction(
220
- self, user_id: str, interaction_id: str
367
+ async def _delete_interaction_async(
368
+ self, request: DeleteUserInteractionRequest
221
369
  ) -> DeleteUserInteractionResponse:
370
+ """Internal async method to delete interaction."""
371
+ response = await self._make_async_request(
372
+ "DELETE",
373
+ "/api/delete_interaction",
374
+ json=request.model_dump(),
375
+ )
376
+ return DeleteUserInteractionResponse(**response)
377
+
378
+ def delete_interaction(
379
+ self, user_id: str, interaction_id: str, wait_for_response: bool = False
380
+ ) -> Optional[DeleteUserInteractionResponse]:
222
381
  """Delete a user interaction.
223
382
 
383
+ This method is optimized for resource efficiency:
384
+ - In async contexts (e.g., FastAPI): Uses existing event loop (most efficient)
385
+ - In sync contexts: Uses shared thread pool (avoids thread creation overhead)
386
+
224
387
  Args:
225
388
  user_id (str): The user ID
226
389
  interaction_id (str): The interaction ID to delete
390
+ wait_for_response (bool, optional): If True, wait for response. If False, send request without waiting. Defaults to False.
227
391
 
228
392
  Returns:
229
- DeleteUserInteractionResponse: Response containing success status and message
393
+ Optional[DeleteUserInteractionResponse]: Response containing success status and message if wait_for_response=True, None otherwise
230
394
  """
231
395
  request = DeleteUserInteractionRequest(
232
396
  user_id=user_id, interaction_id=interaction_id
233
397
  )
234
- response = await self._make_async_request(
235
- "DELETE", "/api/delete_interaction", json=request.model_dump()
236
- )
237
- return DeleteUserInteractionResponse(**response)
238
398
 
239
- async def get_profile_change_log(self) -> ProfileChangeLogResponse:
240
- response = await self._make_async_request("GET", "/api/profile_change_log")
399
+ if wait_for_response:
400
+ # Synchronous blocking call
401
+ return self._delete_interaction_sync(request)
402
+ else:
403
+ # Non-blocking fire-and-forget
404
+ self._fire_and_forget(
405
+ self._delete_interaction_sync, self._delete_interaction_async, request
406
+ )
407
+ return None
408
+
409
+ def get_profile_change_log(self) -> ProfileChangeLogResponse:
410
+ """Get profile change log.
411
+
412
+ Returns:
413
+ ProfileChangeLogResponse: Response containing profile change log
414
+ """
415
+ response = self._make_request("GET", "/api/profile_change_log")
241
416
  return ProfileChangeLogResponse(**response)
242
417
 
243
- async def get_interactions(
418
+ def get_interactions(
244
419
  self,
245
420
  request: Union[GetInteractionsRequest, dict],
246
421
  ) -> GetInteractionsResponse:
@@ -252,16 +427,15 @@ class AgenticMemClient:
252
427
  Returns:
253
428
  GetInteractionsResponse: Response containing list of interactions
254
429
  """
255
- if isinstance(request, dict):
256
- request = GetInteractionsRequest(**request)
257
- response = await self._make_async_request(
430
+ request = self._convert_to_model(request, GetInteractionsRequest)
431
+ response = self._make_request(
258
432
  "POST",
259
433
  "/api/get_interactions",
260
434
  json=request.model_dump(),
261
435
  )
262
436
  return GetInteractionsResponse(**response)
263
437
 
264
- async def get_profiles(
438
+ def get_profiles(
265
439
  self,
266
440
  request: Union[GetUserProfilesRequest, dict],
267
441
  ) -> GetUserProfilesResponse:
@@ -273,16 +447,15 @@ class AgenticMemClient:
273
447
  Returns:
274
448
  GetUserProfilesResponse: Response containing list of profiles
275
449
  """
276
- if isinstance(request, dict):
277
- request = GetUserProfilesRequest(**request)
278
- response = await self._make_async_request(
450
+ request = self._convert_to_model(request, GetUserProfilesRequest)
451
+ response = self._make_request(
279
452
  "POST",
280
453
  "/api/get_profiles",
281
454
  json=request.model_dump(),
282
455
  )
283
456
  return GetUserProfilesResponse(**response)
284
457
 
285
- async def set_config(self, config: Union[Config, dict]) -> dict:
458
+ def set_config(self, config: Union[Config, dict]) -> dict:
286
459
  """Set configuration for the organization.
287
460
 
288
461
  Args:
@@ -291,28 +464,27 @@ class AgenticMemClient:
291
464
  Returns:
292
465
  dict: Response containing success status and message
293
466
  """
294
- if isinstance(config, dict):
295
- config = Config(**config)
296
- response = await self._make_async_request(
467
+ config = self._convert_to_model(config, Config)
468
+ response = self._make_request(
297
469
  "POST",
298
470
  "/api/set_config",
299
471
  json=config.model_dump(),
300
472
  )
301
473
  return response
302
474
 
303
- async def get_config(self) -> Config:
475
+ def get_config(self) -> Config:
304
476
  """Get configuration for the organization.
305
477
 
306
478
  Returns:
307
479
  Config: The current configuration
308
480
  """
309
- response = await self._make_async_request(
481
+ response = self._make_request(
310
482
  "GET",
311
483
  "/api/get_config",
312
484
  )
313
485
  return Config(**response)
314
486
 
315
- async def get_raw_feedbacks(
487
+ def get_raw_feedbacks(
316
488
  self,
317
489
  request: Optional[Union[GetRawFeedbacksRequest, dict]] = None,
318
490
  ) -> GetRawFeedbacksResponse:
@@ -326,16 +498,16 @@ class AgenticMemClient:
326
498
  """
327
499
  if request is None:
328
500
  request = GetRawFeedbacksRequest()
329
- elif isinstance(request, dict):
330
- request = GetRawFeedbacksRequest(**request)
331
- response = await self._make_async_request(
501
+ else:
502
+ request = self._convert_to_model(request, GetRawFeedbacksRequest)
503
+ response = self._make_request(
332
504
  "POST",
333
505
  "/api/get_raw_feedbacks",
334
506
  json=request.model_dump(),
335
507
  )
336
508
  return GetRawFeedbacksResponse(**response)
337
509
 
338
- async def get_feedbacks(
510
+ def get_feedbacks(
339
511
  self,
340
512
  request: Optional[Union[GetFeedbacksRequest, dict]] = None,
341
513
  ) -> GetFeedbacksResponse:
@@ -349,9 +521,9 @@ class AgenticMemClient:
349
521
  """
350
522
  if request is None:
351
523
  request = GetFeedbacksRequest()
352
- elif isinstance(request, dict):
353
- request = GetFeedbacksRequest(**request)
354
- response = await self._make_async_request(
524
+ else:
525
+ request = self._convert_to_model(request, GetFeedbacksRequest)
526
+ response = self._make_request(
355
527
  "POST",
356
528
  "/api/get_feedbacks",
357
529
  json=request.model_dump(),
@@ -0,0 +1,72 @@
1
+ Metadata-Version: 2.3
2
+ Name: agenticmem
3
+ Version: 0.1.3.8
4
+ Summary: A Python client for the AgenticMem API
5
+ License: MIT
6
+ Author: AgenticMem Team
7
+ Requires-Python: >=3.10,<4.0
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Programming Language :: Python :: 3.10
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Requires-Dist: agenticmem-commons (==0.1.3.8)
15
+ Requires-Dist: aiohttp (>=3.12.9,<4.0.0)
16
+ Requires-Dist: griffe (==0.48.0)
17
+ Requires-Dist: mkdocs-with-pdf (>=0.9.3,<0.10.0)
18
+ Requires-Dist: mkdocstrings[python] (>=0.18.0)
19
+ Requires-Dist: pydantic (>=2.0.0,<3.0.0)
20
+ Requires-Dist: python-dateutil (>=2.8.0,<3.0.0)
21
+ Requires-Dist: requests (>=2.25.0,<3.0.0)
22
+ Description-Content-Type: text/markdown
23
+
24
+ # /user_profiler/agenticmem/agenticmem_client
25
+ Description: Python SDK for remote async access to AgenticMem API
26
+
27
+ ## Main Entry Points
28
+
29
+ - **Client**: `agenticmem/client.py` - `AgenticMemClient`
30
+ - **Utils**: `agenticmem/client_utils.py` - Helper utilities
31
+
32
+ ## Purpose
33
+
34
+ 1. **Remote API access** - Async SDK for applications to call AgenticMem backend
35
+ 2. **Authentication** - Handle login and Bearer token management
36
+ 3. **Type-safe interface** - Auto-parsing responses into Pydantic models
37
+
38
+ ## API Methods
39
+
40
+ **Authentication:**
41
+ - `login(email, password)` - Get auth token
42
+
43
+ **Publishing:**
44
+ - `publish_interaction(request_id, user_id, interactions, source, agent_version)` - Publish interactions (triggers profile/feedback/evaluation)
45
+
46
+ **Profiles:**
47
+ - `search_profiles(request)` - Semantic search
48
+ - `get_profiles(request)` - Get all for user
49
+ - `delete_profile(user_id, profile_id, search_query)` - Delete profiles
50
+ - `get_profile_change_log()` - Get history
51
+
52
+ **Interactions:**
53
+ - `search_interactions(request)` - Semantic search
54
+ - `get_interactions(request)` - Get all for user
55
+ - `delete_interaction(user_id, interaction_id)` - Delete interaction
56
+
57
+ **Feedback:**
58
+ - `get_raw_feedbacks(request)` - Raw feedback from interactions
59
+ - `get_feedbacks(request)` - Aggregated feedback with status
60
+
61
+ **Configuration:**
62
+ - `set_config(config)` - Update org config (extractors, evaluators, storage)
63
+ - `get_config()` - Get current config
64
+
65
+ ## Architecture Pattern
66
+
67
+ - **All async** - Uses `aiohttp` for HTTP requests
68
+ - **Type-safe** - Pydantic models from `agenticmem_commons`
69
+ - **Auto-parsing** - Responses → Pydantic models
70
+ - **Flexible input** - Accepts Pydantic models or dicts
71
+ - **Bearer auth** - Automatic token handling
72
+
@@ -0,0 +1,6 @@
1
+ agenticmem/__init__.py,sha256=nSrWdD87z0hbmqVzZxt4xiSccgKyAQOkXosvZlte1ps,1794
2
+ agenticmem/client.py,sha256=v7B16F8X-r7vF1tFi_BVJw1KjB7vK3118VhRREBqvY8,18542
3
+ agenticmem/client_utils.py,sha256=kWTWlyO7s768v38ef41nRDq87Qmb60NX2vmZTVlCB6g,297
4
+ agenticmem-0.1.3.8.dist-info/METADATA,sha256=j1tny6rIA2zyt5nGVmpT6Znep0k8L2JE67eXwGWUCEU,2564
5
+ agenticmem-0.1.3.8.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
6
+ agenticmem-0.1.3.8.dist-info/RECORD,,
@@ -1,145 +0,0 @@
1
- Metadata-Version: 2.3
2
- Name: agenticmem
3
- Version: 0.1.2.4
4
- Summary: A Python client for the AgenticMem API
5
- License: MIT
6
- Author: AgenticMem Team
7
- Requires-Python: >=3.10,<4.0
8
- Classifier: License :: OSI Approved :: MIT License
9
- Classifier: Programming Language :: Python :: 3
10
- Classifier: Programming Language :: Python :: 3.10
11
- Classifier: Programming Language :: Python :: 3.11
12
- Classifier: Programming Language :: Python :: 3.12
13
- Classifier: Programming Language :: Python :: 3.13
14
- Requires-Dist: agenticmem-commons (==0.1.3.6)
15
- Requires-Dist: aiohttp (>=3.12.9,<4.0.0)
16
- Requires-Dist: griffe (==0.48.0)
17
- Requires-Dist: mkdocstrings[python] (>=0.18.0)
18
- Requires-Dist: pydantic (>=2.0.0,<3.0.0)
19
- Requires-Dist: python-dateutil (>=2.8.0,<3.0.0)
20
- Requires-Dist: requests (>=2.25.0,<3.0.0)
21
- Description-Content-Type: text/markdown
22
-
23
- # AgenticMem Python Client
24
-
25
- A Python client library for interacting with the AgenticMem API. This client provides easy-to-use interfaces for managing user interactions and profiles.
26
-
27
- ## Installation
28
-
29
- ```bash
30
- pip install agenticmem
31
- ```
32
-
33
- ## Quick Start
34
-
35
- ```python
36
- from agenticmem import AgenticMemClient
37
- from agenticmem_commons.api_schema.service_schemas import InteractionRequest
38
- from agenticmem_commons.api_schema.retriever_schema import (
39
- SearchInteractionRequest,
40
- SearchUserProfileRequest,
41
- GetInteractionsRequest,
42
- GetUserProfilesRequest
43
- )
44
- from datetime import datetime
45
-
46
- # Initialize the client
47
- client = AgenticMemClient(api_key="your_api_key")
48
-
49
- # Optional: Login with email/password
50
- token = client.login(email="user@example.com", password="password123")
51
-
52
- # Publish a user interaction
53
- interaction = InteractionRequest(
54
- created_at=int(datetime.utcnow().timestamp()),
55
- content="User clicked on product X",
56
- user_action="click",
57
- user_action_description="Clicked on product details button"
58
- )
59
-
60
- response = client.publish_interaction(
61
- user_id="user123",
62
- request_id="req456",
63
- interaction_requests=[interaction]
64
- )
65
- print(f"Published interaction: {response.success} - {response.message}")
66
-
67
- # Search user profiles
68
- profiles_request = SearchUserProfileRequest(
69
- user_id="user123",
70
- search_query="recent interactions",
71
- top_k=5
72
- )
73
- profiles = client.search_profiles(profiles_request)
74
- for profile in profiles.profiles:
75
- print(f"Profile {profile.profile_id}: {profile.profile_content}")
76
-
77
- # Get user profiles directly
78
- profiles_request = GetUserProfilesRequest(
79
- user_id="user123"
80
- )
81
- profiles = client.get_profiles(profiles_request)
82
- for profile in profiles.profiles:
83
- print(f"Profile: {profile}")
84
-
85
- # Search interactions
86
- interactions_request = SearchInteractionRequest(
87
- user_id="user123",
88
- start_time=int(datetime(2024, 1, 1).timestamp()),
89
- end_time=int(datetime.utcnow().timestamp())
90
- )
91
- interactions = client.search_interactions(interactions_request)
92
- for interaction in interactions.interactions:
93
- print(f"Interaction {interaction.interaction_id}: {interaction.content}")
94
-
95
- # Get interactions directly
96
- interactions_request = GetInteractionsRequest(
97
- user_id="user123"
98
- )
99
- interactions = client.get_interactions(interactions_request)
100
- for interaction in interactions.interactions:
101
- print(f"Interaction: {interaction}")
102
-
103
- # Get profile change log
104
- change_log = client.get_profile_change_log()
105
- print(f"Profile changes: {change_log}")
106
- ```
107
-
108
- ## Features
109
-
110
- - Authentication
111
- - API key authentication
112
- - Email/password login
113
- - User interaction management
114
- - Publish user interactions
115
- - Delete specific interactions
116
- - Search interactions with time range and filters
117
- - Get direct list of interactions
118
- - User profile management
119
- - Search user profiles with customizable queries
120
- - Get direct list of user profiles
121
- - Delete specific profiles or profiles matching a search query
122
- - View profile change log history
123
-
124
- ## API Response Types
125
-
126
- All API methods return strongly-typed responses:
127
-
128
- - `login()` returns `Token`
129
- - `publish_interaction()` returns `PublishUserInteractionResponse`
130
- - `search_interactions()` returns `SearchInteractionResponse`
131
- - `get_interactions()` returns `GetInteractionsResponse`
132
- - `search_profiles()` returns `SearchUserProfileResponse`
133
- - `get_profiles()` returns `GetUserProfilesResponse`
134
- - `delete_profile()` returns `DeleteUserProfileResponse`
135
- - `delete_interaction()` returns `DeleteUserInteractionResponse`
136
- - `get_profile_change_log()` returns `ProfileChangeLogResponse`
137
-
138
- ## Documentation
139
-
140
- For detailed documentation, please visit [docs link].
141
-
142
- ## License
143
-
144
- MIT License
145
-
@@ -1,6 +0,0 @@
1
- agenticmem/__init__.py,sha256=g5Xq7CEO4d7jIxkGRQg4z71MFQmL2UMeJtnP9GoMzAY,1714
2
- agenticmem/client.py,sha256=xz7eG4o0JrMq0LjvHlAIHjZnjuaOq2k5wsqixi8cLuk,12007
3
- agenticmem/client_utils.py,sha256=kWTWlyO7s768v38ef41nRDq87Qmb60NX2vmZTVlCB6g,297
4
- agenticmem-0.1.2.4.dist-info/METADATA,sha256=swSTv3f58QaaSZm-MbKQdjgbDDrJ9lFIW2ZgaLL_eSg,4461
5
- agenticmem-0.1.2.4.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
6
- agenticmem-0.1.2.4.dist-info/RECORD,,