agno 2.4.0__py3-none-any.whl → 2.4.2__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 (41) hide show
  1. agno/db/firestore/firestore.py +58 -65
  2. agno/db/mysql/async_mysql.py +47 -55
  3. agno/db/postgres/async_postgres.py +52 -61
  4. agno/db/postgres/postgres.py +25 -12
  5. agno/db/sqlite/async_sqlite.py +52 -61
  6. agno/db/sqlite/sqlite.py +24 -11
  7. agno/integrations/discord/client.py +12 -1
  8. agno/knowledge/knowledge.py +1511 -47
  9. agno/knowledge/reader/csv_reader.py +231 -8
  10. agno/knowledge/reader/field_labeled_csv_reader.py +167 -3
  11. agno/knowledge/reader/reader_factory.py +8 -1
  12. agno/knowledge/remote_content/__init__.py +33 -0
  13. agno/knowledge/remote_content/config.py +266 -0
  14. agno/knowledge/remote_content/remote_content.py +105 -17
  15. agno/models/base.py +12 -2
  16. agno/models/cerebras/cerebras.py +34 -2
  17. agno/models/n1n/__init__.py +3 -0
  18. agno/models/n1n/n1n.py +57 -0
  19. agno/models/ollama/__init__.py +2 -0
  20. agno/models/ollama/responses.py +100 -0
  21. agno/models/openai/__init__.py +2 -0
  22. agno/models/openai/chat.py +18 -1
  23. agno/models/openai/open_responses.py +46 -0
  24. agno/models/openrouter/__init__.py +2 -0
  25. agno/models/openrouter/responses.py +146 -0
  26. agno/models/perplexity/perplexity.py +2 -0
  27. agno/os/interfaces/slack/router.py +10 -1
  28. agno/os/interfaces/whatsapp/router.py +6 -0
  29. agno/os/routers/components/components.py +10 -1
  30. agno/os/routers/knowledge/knowledge.py +125 -0
  31. agno/os/routers/knowledge/schemas.py +12 -0
  32. agno/run/agent.py +2 -0
  33. agno/team/team.py +20 -4
  34. agno/vectordb/lightrag/lightrag.py +7 -6
  35. agno/vectordb/milvus/milvus.py +79 -48
  36. agno/vectordb/pgvector/pgvector.py +3 -3
  37. {agno-2.4.0.dist-info → agno-2.4.2.dist-info}/METADATA +4 -1
  38. {agno-2.4.0.dist-info → agno-2.4.2.dist-info}/RECORD +41 -35
  39. {agno-2.4.0.dist-info → agno-2.4.2.dist-info}/WHEEL +1 -1
  40. {agno-2.4.0.dist-info → agno-2.4.2.dist-info}/licenses/LICENSE +0 -0
  41. {agno-2.4.0.dist-info → agno-2.4.2.dist-info}/top_level.txt +0 -0
@@ -121,93 +121,86 @@ class FirestoreDb(BaseDb):
121
121
  CollectionReference: The collection reference.
122
122
  """
123
123
  if table_type == "sessions":
124
- if not hasattr(self, "session_collection"):
125
- if self.session_table_name is None:
126
- raise ValueError("Session collection was not provided on initialization")
127
- self.session_collection = self._get_or_create_collection(
128
- collection_name=self.session_table_name,
129
- collection_type="sessions",
130
- create_collection_if_not_found=create_collection_if_not_found,
131
- )
124
+ if self.session_table_name is None:
125
+ raise ValueError("Session collection was not provided on initialization")
126
+ self.session_collection = self._get_or_create_collection(
127
+ collection_name=self.session_table_name,
128
+ collection_type="sessions",
129
+ create_collection_if_not_found=create_collection_if_not_found,
130
+ )
132
131
  return self.session_collection
133
132
 
134
133
  if table_type == "memories":
135
- if not hasattr(self, "memory_collection"):
136
- if self.memory_table_name is None:
137
- raise ValueError("Memory collection was not provided on initialization")
138
- self.memory_collection = self._get_or_create_collection(
139
- collection_name=self.memory_table_name,
140
- collection_type="memories",
141
- create_collection_if_not_found=create_collection_if_not_found,
142
- )
134
+ if self.memory_table_name is None:
135
+ raise ValueError("Memory collection was not provided on initialization")
136
+ self.memory_collection = self._get_or_create_collection(
137
+ collection_name=self.memory_table_name,
138
+ collection_type="memories",
139
+ create_collection_if_not_found=create_collection_if_not_found,
140
+ )
143
141
  return self.memory_collection
144
142
 
145
143
  if table_type == "metrics":
146
- if not hasattr(self, "metrics_collection"):
147
- if self.metrics_table_name is None:
148
- raise ValueError("Metrics collection was not provided on initialization")
149
- self.metrics_collection = self._get_or_create_collection(
150
- collection_name=self.metrics_table_name,
151
- collection_type="metrics",
152
- create_collection_if_not_found=create_collection_if_not_found,
153
- )
144
+ if self.metrics_table_name is None:
145
+ raise ValueError("Metrics collection was not provided on initialization")
146
+ self.metrics_collection = self._get_or_create_collection(
147
+ collection_name=self.metrics_table_name,
148
+ collection_type="metrics",
149
+ create_collection_if_not_found=create_collection_if_not_found,
150
+ )
154
151
  return self.metrics_collection
155
152
 
156
153
  if table_type == "evals":
157
- if not hasattr(self, "eval_collection"):
158
- if self.eval_table_name is None:
159
- raise ValueError("Eval collection was not provided on initialization")
160
- self.eval_collection = self._get_or_create_collection(
161
- collection_name=self.eval_table_name,
162
- collection_type="evals",
163
- create_collection_if_not_found=create_collection_if_not_found,
164
- )
154
+ if self.eval_table_name is None:
155
+ raise ValueError("Eval collection was not provided on initialization")
156
+ self.eval_collection = self._get_or_create_collection(
157
+ collection_name=self.eval_table_name,
158
+ collection_type="evals",
159
+ create_collection_if_not_found=create_collection_if_not_found,
160
+ )
165
161
  return self.eval_collection
166
162
 
167
163
  if table_type == "knowledge":
168
- if not hasattr(self, "knowledge_collection"):
169
- if self.knowledge_table_name is None:
170
- raise ValueError("Knowledge collection was not provided on initialization")
171
- self.knowledge_collection = self._get_or_create_collection(
172
- collection_name=self.knowledge_table_name,
173
- collection_type="knowledge",
174
- create_collection_if_not_found=create_collection_if_not_found,
175
- )
164
+ if self.knowledge_table_name is None:
165
+ raise ValueError("Knowledge collection was not provided on initialization")
166
+ self.knowledge_collection = self._get_or_create_collection(
167
+ collection_name=self.knowledge_table_name,
168
+ collection_type="knowledge",
169
+ create_collection_if_not_found=create_collection_if_not_found,
170
+ )
176
171
  return self.knowledge_collection
177
172
 
178
173
  if table_type == "culture":
179
- if not hasattr(self, "culture_collection"):
180
- if self.culture_table_name is None:
181
- raise ValueError("Culture collection was not provided on initialization")
182
- self.culture_collection = self._get_or_create_collection(
183
- collection_name=self.culture_table_name,
184
- collection_type="culture",
185
- create_collection_if_not_found=create_collection_if_not_found,
186
- )
174
+ if self.culture_table_name is None:
175
+ raise ValueError("Culture collection was not provided on initialization")
176
+ self.culture_collection = self._get_or_create_collection(
177
+ collection_name=self.culture_table_name,
178
+ collection_type="culture",
179
+ create_collection_if_not_found=create_collection_if_not_found,
180
+ )
187
181
  return self.culture_collection
188
182
 
189
183
  if table_type == "traces":
190
- if not hasattr(self, "traces_collection"):
191
- if self.trace_table_name is None:
192
- raise ValueError("Traces collection was not provided on initialization")
193
- self.traces_collection = self._get_or_create_collection(
194
- collection_name=self.trace_table_name,
195
- collection_type="traces",
196
- create_collection_if_not_found=create_collection_if_not_found,
197
- )
184
+ if self.trace_table_name is None:
185
+ raise ValueError("Traces collection was not provided on initialization")
186
+ self.traces_collection = self._get_or_create_collection(
187
+ collection_name=self.trace_table_name,
188
+ collection_type="traces",
189
+ create_collection_if_not_found=create_collection_if_not_found,
190
+ )
198
191
  return self.traces_collection
199
192
 
200
193
  if table_type == "spans":
201
194
  # Ensure traces collection exists first (spans reference traces)
202
- self._get_collection("traces", create_collection_if_not_found=create_collection_if_not_found)
203
- if not hasattr(self, "spans_collection"):
204
- if self.span_table_name is None:
205
- raise ValueError("Spans collection was not provided on initialization")
206
- self.spans_collection = self._get_or_create_collection(
207
- collection_name=self.span_table_name,
208
- collection_type="spans",
209
- create_collection_if_not_found=create_collection_if_not_found,
210
- )
195
+ if create_collection_if_not_found:
196
+ self._get_collection("traces", create_collection_if_not_found=True)
197
+ if self.span_table_name is None:
198
+ raise ValueError("Spans collection was not provided on initialization")
199
+ self.spans_collection = self._get_or_create_collection(
200
+ collection_name=self.span_table_name,
201
+ collection_type="spans",
202
+ create_collection_if_not_found=create_collection_if_not_found,
203
+ )
211
204
  return self.spans_collection
212
205
 
213
206
  raise ValueError(f"Unknown table type: {table_type}")
@@ -282,86 +282,78 @@ class AsyncMySQLDb(AsyncBaseDb):
282
282
 
283
283
  async def _get_table(self, table_type: str, create_table_if_not_found: Optional[bool] = False) -> Table:
284
284
  if table_type == "sessions":
285
- if not hasattr(self, "session_table"):
286
- self.session_table = await self._get_or_create_table(
287
- table_name=self.session_table_name,
288
- table_type="sessions",
289
- create_table_if_not_found=create_table_if_not_found,
290
- )
285
+ self.session_table = await self._get_or_create_table(
286
+ table_name=self.session_table_name,
287
+ table_type="sessions",
288
+ create_table_if_not_found=create_table_if_not_found,
289
+ )
291
290
  return self.session_table
292
291
 
293
292
  if table_type == "memories":
294
- if not hasattr(self, "memory_table"):
295
- self.memory_table = await self._get_or_create_table(
296
- table_name=self.memory_table_name,
297
- table_type="memories",
298
- create_table_if_not_found=create_table_if_not_found,
299
- )
293
+ self.memory_table = await self._get_or_create_table(
294
+ table_name=self.memory_table_name,
295
+ table_type="memories",
296
+ create_table_if_not_found=create_table_if_not_found,
297
+ )
300
298
  return self.memory_table
301
299
 
302
300
  if table_type == "metrics":
303
- if not hasattr(self, "metrics_table"):
304
- self.metrics_table = await self._get_or_create_table(
305
- table_name=self.metrics_table_name,
306
- table_type="metrics",
307
- create_table_if_not_found=create_table_if_not_found,
308
- )
301
+ self.metrics_table = await self._get_or_create_table(
302
+ table_name=self.metrics_table_name,
303
+ table_type="metrics",
304
+ create_table_if_not_found=create_table_if_not_found,
305
+ )
309
306
  return self.metrics_table
310
307
 
311
308
  if table_type == "evals":
312
- if not hasattr(self, "eval_table"):
313
- self.eval_table = await self._get_or_create_table(
314
- table_name=self.eval_table_name,
315
- table_type="evals",
316
- create_table_if_not_found=create_table_if_not_found,
317
- )
309
+ self.eval_table = await self._get_or_create_table(
310
+ table_name=self.eval_table_name,
311
+ table_type="evals",
312
+ create_table_if_not_found=create_table_if_not_found,
313
+ )
318
314
  return self.eval_table
319
315
 
320
316
  if table_type == "knowledge":
321
- if not hasattr(self, "knowledge_table"):
322
- self.knowledge_table = await self._get_or_create_table(
323
- table_name=self.knowledge_table_name,
324
- table_type="knowledge",
325
- create_table_if_not_found=create_table_if_not_found,
326
- )
317
+ self.knowledge_table = await self._get_or_create_table(
318
+ table_name=self.knowledge_table_name,
319
+ table_type="knowledge",
320
+ create_table_if_not_found=create_table_if_not_found,
321
+ )
327
322
  return self.knowledge_table
328
323
 
329
324
  if table_type == "culture":
330
- if not hasattr(self, "culture_table"):
331
- self.culture_table = await self._get_or_create_table(
332
- table_name=self.culture_table_name,
333
- table_type="culture",
334
- create_table_if_not_found=create_table_if_not_found,
335
- )
325
+ self.culture_table = await self._get_or_create_table(
326
+ table_name=self.culture_table_name,
327
+ table_type="culture",
328
+ create_table_if_not_found=create_table_if_not_found,
329
+ )
336
330
  return self.culture_table
337
331
 
338
332
  if table_type == "versions":
339
- if not hasattr(self, "versions_table"):
340
- self.versions_table = await self._get_or_create_table(
341
- table_name=self.versions_table_name,
342
- table_type="versions",
343
- create_table_if_not_found=create_table_if_not_found,
344
- )
333
+ self.versions_table = await self._get_or_create_table(
334
+ table_name=self.versions_table_name,
335
+ table_type="versions",
336
+ create_table_if_not_found=create_table_if_not_found,
337
+ )
345
338
  return self.versions_table
346
339
 
347
340
  if table_type == "traces":
348
- if not hasattr(self, "traces_table"):
349
- self.traces_table = await self._get_or_create_table(
350
- table_name=self.trace_table_name,
351
- table_type="traces",
352
- create_table_if_not_found=create_table_if_not_found,
353
- )
341
+ self.traces_table = await self._get_or_create_table(
342
+ table_name=self.trace_table_name,
343
+ table_type="traces",
344
+ create_table_if_not_found=create_table_if_not_found,
345
+ )
354
346
  return self.traces_table
355
347
 
356
348
  if table_type == "spans":
357
- if not hasattr(self, "spans_table"):
358
- # Ensure traces table exists first (spans has FK to traces)
349
+ # Ensure traces table exists first (spans has FK to traces)
350
+ if create_table_if_not_found:
359
351
  await self._get_table(table_type="traces", create_table_if_not_found=True)
360
- self.spans_table = await self._get_or_create_table(
361
- table_name=self.span_table_name,
362
- table_type="spans",
363
- create_table_if_not_found=create_table_if_not_found,
364
- )
352
+ self.spans_table = await self._get_or_create_table(
353
+ table_name=self.span_table_name,
354
+ table_type="spans",
355
+ create_table_if_not_found=create_table_if_not_found,
356
+ )
365
357
  return self.spans_table
366
358
 
367
359
  raise ValueError(f"Unknown table type: {table_type}")
@@ -285,95 +285,86 @@ class AsyncPostgresDb(AsyncBaseDb):
285
285
 
286
286
  async def _get_table(self, table_type: str, create_table_if_not_found: Optional[bool] = False) -> Table:
287
287
  if table_type == "sessions":
288
- if not hasattr(self, "session_table"):
289
- self.session_table = await self._get_or_create_table(
290
- table_name=self.session_table_name,
291
- table_type="sessions",
292
- create_table_if_not_found=create_table_if_not_found,
293
- )
288
+ self.session_table = await self._get_or_create_table(
289
+ table_name=self.session_table_name,
290
+ table_type="sessions",
291
+ create_table_if_not_found=create_table_if_not_found,
292
+ )
294
293
  return self.session_table
295
294
 
296
295
  if table_type == "memories":
297
- if not hasattr(self, "memory_table"):
298
- self.memory_table = await self._get_or_create_table(
299
- table_name=self.memory_table_name,
300
- table_type="memories",
301
- create_table_if_not_found=create_table_if_not_found,
302
- )
296
+ self.memory_table = await self._get_or_create_table(
297
+ table_name=self.memory_table_name,
298
+ table_type="memories",
299
+ create_table_if_not_found=create_table_if_not_found,
300
+ )
303
301
  return self.memory_table
304
302
 
305
303
  if table_type == "metrics":
306
- if not hasattr(self, "metrics_table"):
307
- self.metrics_table = await self._get_or_create_table(
308
- table_name=self.metrics_table_name,
309
- table_type="metrics",
310
- create_table_if_not_found=create_table_if_not_found,
311
- )
304
+ self.metrics_table = await self._get_or_create_table(
305
+ table_name=self.metrics_table_name,
306
+ table_type="metrics",
307
+ create_table_if_not_found=create_table_if_not_found,
308
+ )
312
309
  return self.metrics_table
313
310
 
314
311
  if table_type == "evals":
315
- if not hasattr(self, "eval_table"):
316
- self.eval_table = await self._get_or_create_table(
317
- table_name=self.eval_table_name,
318
- table_type="evals",
319
- create_table_if_not_found=create_table_if_not_found,
320
- )
312
+ self.eval_table = await self._get_or_create_table(
313
+ table_name=self.eval_table_name,
314
+ table_type="evals",
315
+ create_table_if_not_found=create_table_if_not_found,
316
+ )
321
317
  return self.eval_table
322
318
 
323
319
  if table_type == "knowledge":
324
- if not hasattr(self, "knowledge_table"):
325
- self.knowledge_table = await self._get_or_create_table(
326
- table_name=self.knowledge_table_name,
327
- table_type="knowledge",
328
- create_table_if_not_found=create_table_if_not_found,
329
- )
320
+ self.knowledge_table = await self._get_or_create_table(
321
+ table_name=self.knowledge_table_name,
322
+ table_type="knowledge",
323
+ create_table_if_not_found=create_table_if_not_found,
324
+ )
330
325
  return self.knowledge_table
331
326
 
332
327
  if table_type == "culture":
333
- if not hasattr(self, "culture_table"):
334
- self.culture_table = await self._get_or_create_table(
335
- table_name=self.culture_table_name,
336
- table_type="culture",
337
- create_table_if_not_found=create_table_if_not_found,
338
- )
328
+ self.culture_table = await self._get_or_create_table(
329
+ table_name=self.culture_table_name,
330
+ table_type="culture",
331
+ create_table_if_not_found=create_table_if_not_found,
332
+ )
339
333
  return self.culture_table
340
334
 
341
335
  if table_type == "versions":
342
- if not hasattr(self, "versions_table"):
343
- self.versions_table = await self._get_or_create_table(
344
- table_name=self.versions_table_name,
345
- table_type="versions",
346
- create_table_if_not_found=create_table_if_not_found,
347
- )
336
+ self.versions_table = await self._get_or_create_table(
337
+ table_name=self.versions_table_name,
338
+ table_type="versions",
339
+ create_table_if_not_found=create_table_if_not_found,
340
+ )
348
341
  return self.versions_table
349
342
 
350
343
  if table_type == "traces":
351
- if not hasattr(self, "traces_table"):
352
- self.traces_table = await self._get_or_create_table(
353
- table_name=self.trace_table_name,
354
- table_type="traces",
355
- create_table_if_not_found=create_table_if_not_found,
356
- )
344
+ self.traces_table = await self._get_or_create_table(
345
+ table_name=self.trace_table_name,
346
+ table_type="traces",
347
+ create_table_if_not_found=create_table_if_not_found,
348
+ )
357
349
  return self.traces_table
358
350
 
359
351
  if table_type == "spans":
360
- if not hasattr(self, "spans_table"):
361
- # Ensure traces table exists first (spans has FK to traces)
352
+ # Ensure traces table exists first (spans has FK to traces)
353
+ if create_table_if_not_found:
362
354
  await self._get_table(table_type="traces", create_table_if_not_found=True)
363
- self.spans_table = await self._get_or_create_table(
364
- table_name=self.span_table_name,
365
- table_type="spans",
366
- create_table_if_not_found=create_table_if_not_found,
367
- )
355
+ self.spans_table = await self._get_or_create_table(
356
+ table_name=self.span_table_name,
357
+ table_type="spans",
358
+ create_table_if_not_found=create_table_if_not_found,
359
+ )
368
360
  return self.spans_table
369
361
 
370
362
  if table_type == "learnings":
371
- if not hasattr(self, "learnings_table"):
372
- self.learnings_table = await self._get_or_create_table(
373
- table_name=self.learnings_table_name,
374
- table_type="learnings",
375
- create_table_if_not_found=create_table_if_not_found,
376
- )
363
+ self.learnings_table = await self._get_or_create_table(
364
+ table_name=self.learnings_table_name,
365
+ table_type="learnings",
366
+ create_table_if_not_found=create_table_if_not_found,
367
+ )
377
368
  return self.learnings_table
378
369
 
379
370
  raise ValueError(f"Unknown table type: {table_type}")
@@ -3593,7 +3593,7 @@ class PostgresDb(BaseDb):
3593
3593
 
3594
3594
  Args:
3595
3595
  component_id: The component ID.
3596
- version: Specific version number. If None, uses current.
3596
+ version: Specific version number. If None, uses current or latest draft.
3597
3597
  label: Config label to lookup. Ignored if version is provided.
3598
3598
 
3599
3599
  Returns:
@@ -3607,17 +3607,23 @@ class PostgresDb(BaseDb):
3607
3607
  return None
3608
3608
 
3609
3609
  with self.Session() as sess:
3610
- # Always verify component exists and is not deleted
3611
- component = sess.execute(
3612
- select(components_table.c.current_version).where(
3613
- components_table.c.component_id == component_id,
3614
- components_table.c.deleted_at.is_(None),
3610
+ # Verify component exists and get current_version
3611
+ component_row = (
3612
+ sess.execute(
3613
+ select(components_table.c.component_id, components_table.c.current_version).where(
3614
+ components_table.c.component_id == component_id,
3615
+ components_table.c.deleted_at.is_(None),
3616
+ )
3615
3617
  )
3616
- ).scalar_one_or_none()
3618
+ .mappings()
3619
+ .one_or_none()
3620
+ )
3617
3621
 
3618
- if component is None:
3622
+ if component_row is None:
3619
3623
  return None
3620
3624
 
3625
+ current_version = component_row["current_version"]
3626
+
3621
3627
  if version is not None:
3622
3628
  stmt = select(configs_table).where(
3623
3629
  configs_table.c.component_id == component_id,
@@ -3628,12 +3634,19 @@ class PostgresDb(BaseDb):
3628
3634
  configs_table.c.component_id == component_id,
3629
3635
  configs_table.c.label == label,
3630
3636
  )
3631
- else:
3632
- if component is None: # current_version is NULL
3633
- return None
3637
+ elif current_version is not None:
3638
+ # Use the current published version
3634
3639
  stmt = select(configs_table).where(
3635
3640
  configs_table.c.component_id == component_id,
3636
- configs_table.c.version == component,
3641
+ configs_table.c.version == current_version,
3642
+ )
3643
+ else:
3644
+ # No current_version set (draft only) - get the latest version
3645
+ stmt = (
3646
+ select(configs_table)
3647
+ .where(configs_table.c.component_id == component_id)
3648
+ .order_by(configs_table.c.version.desc())
3649
+ .limit(1)
3637
3650
  )
3638
3651
 
3639
3652
  row = sess.execute(stmt).mappings().one_or_none()