agno 2.3.25__py3-none-any.whl → 2.4.0__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 (128) hide show
  1. agno/agent/__init__.py +4 -0
  2. agno/agent/agent.py +1428 -558
  3. agno/agent/remote.py +13 -0
  4. agno/db/base.py +339 -0
  5. agno/db/postgres/async_postgres.py +116 -12
  6. agno/db/postgres/postgres.py +1229 -25
  7. agno/db/postgres/schemas.py +48 -1
  8. agno/db/sqlite/async_sqlite.py +119 -4
  9. agno/db/sqlite/schemas.py +51 -0
  10. agno/db/sqlite/sqlite.py +1173 -13
  11. agno/db/utils.py +37 -1
  12. agno/knowledge/__init__.py +4 -0
  13. agno/knowledge/chunking/code.py +1 -1
  14. agno/knowledge/chunking/semantic.py +1 -1
  15. agno/knowledge/chunking/strategy.py +4 -0
  16. agno/knowledge/filesystem.py +412 -0
  17. agno/knowledge/knowledge.py +2767 -2254
  18. agno/knowledge/protocol.py +134 -0
  19. agno/knowledge/reader/arxiv_reader.py +2 -2
  20. agno/knowledge/reader/base.py +9 -7
  21. agno/knowledge/reader/csv_reader.py +5 -5
  22. agno/knowledge/reader/docx_reader.py +2 -2
  23. agno/knowledge/reader/field_labeled_csv_reader.py +2 -2
  24. agno/knowledge/reader/firecrawl_reader.py +2 -2
  25. agno/knowledge/reader/json_reader.py +2 -2
  26. agno/knowledge/reader/markdown_reader.py +2 -2
  27. agno/knowledge/reader/pdf_reader.py +5 -4
  28. agno/knowledge/reader/pptx_reader.py +2 -2
  29. agno/knowledge/reader/reader_factory.py +110 -0
  30. agno/knowledge/reader/s3_reader.py +2 -2
  31. agno/knowledge/reader/tavily_reader.py +2 -2
  32. agno/knowledge/reader/text_reader.py +2 -2
  33. agno/knowledge/reader/web_search_reader.py +2 -2
  34. agno/knowledge/reader/website_reader.py +5 -3
  35. agno/knowledge/reader/wikipedia_reader.py +2 -2
  36. agno/knowledge/reader/youtube_reader.py +2 -2
  37. agno/knowledge/utils.py +37 -29
  38. agno/learn/__init__.py +6 -0
  39. agno/learn/machine.py +35 -0
  40. agno/learn/schemas.py +82 -11
  41. agno/learn/stores/__init__.py +3 -0
  42. agno/learn/stores/decision_log.py +1156 -0
  43. agno/learn/stores/learned_knowledge.py +6 -6
  44. agno/models/anthropic/claude.py +24 -0
  45. agno/models/aws/bedrock.py +20 -0
  46. agno/models/base.py +48 -4
  47. agno/models/cohere/chat.py +25 -0
  48. agno/models/google/gemini.py +50 -5
  49. agno/models/litellm/chat.py +38 -0
  50. agno/models/openai/chat.py +7 -0
  51. agno/models/openrouter/openrouter.py +46 -0
  52. agno/models/response.py +16 -0
  53. agno/os/app.py +83 -44
  54. agno/os/middleware/__init__.py +2 -0
  55. agno/os/middleware/trailing_slash.py +27 -0
  56. agno/os/router.py +1 -0
  57. agno/os/routers/agents/router.py +29 -16
  58. agno/os/routers/agents/schema.py +6 -4
  59. agno/os/routers/components/__init__.py +3 -0
  60. agno/os/routers/components/components.py +466 -0
  61. agno/os/routers/evals/schemas.py +4 -3
  62. agno/os/routers/health.py +3 -3
  63. agno/os/routers/knowledge/knowledge.py +3 -3
  64. agno/os/routers/memory/schemas.py +4 -2
  65. agno/os/routers/metrics/metrics.py +9 -11
  66. agno/os/routers/metrics/schemas.py +10 -6
  67. agno/os/routers/registry/__init__.py +3 -0
  68. agno/os/routers/registry/registry.py +337 -0
  69. agno/os/routers/teams/router.py +20 -8
  70. agno/os/routers/teams/schema.py +6 -4
  71. agno/os/routers/traces/traces.py +5 -5
  72. agno/os/routers/workflows/router.py +38 -11
  73. agno/os/routers/workflows/schema.py +1 -1
  74. agno/os/schema.py +92 -26
  75. agno/os/utils.py +133 -16
  76. agno/reasoning/anthropic.py +2 -2
  77. agno/reasoning/azure_ai_foundry.py +2 -2
  78. agno/reasoning/deepseek.py +2 -2
  79. agno/reasoning/default.py +6 -7
  80. agno/reasoning/gemini.py +2 -2
  81. agno/reasoning/helpers.py +6 -7
  82. agno/reasoning/manager.py +4 -10
  83. agno/reasoning/ollama.py +2 -2
  84. agno/reasoning/openai.py +2 -2
  85. agno/reasoning/vertexai.py +2 -2
  86. agno/registry/__init__.py +3 -0
  87. agno/registry/registry.py +68 -0
  88. agno/run/agent.py +57 -0
  89. agno/run/base.py +7 -0
  90. agno/run/team.py +57 -0
  91. agno/skills/agent_skills.py +10 -3
  92. agno/team/__init__.py +3 -1
  93. agno/team/team.py +1276 -326
  94. agno/tools/duckduckgo.py +25 -71
  95. agno/tools/exa.py +0 -21
  96. agno/tools/function.py +35 -83
  97. agno/tools/knowledge.py +9 -4
  98. agno/tools/mem0.py +11 -10
  99. agno/tools/memory.py +47 -46
  100. agno/tools/parallel.py +0 -7
  101. agno/tools/reasoning.py +30 -23
  102. agno/tools/tavily.py +4 -1
  103. agno/tools/websearch.py +93 -0
  104. agno/tools/website.py +1 -1
  105. agno/tools/wikipedia.py +1 -1
  106. agno/tools/workflow.py +48 -47
  107. agno/utils/agent.py +42 -5
  108. agno/utils/events.py +160 -2
  109. agno/utils/print_response/agent.py +0 -31
  110. agno/utils/print_response/team.py +0 -2
  111. agno/utils/print_response/workflow.py +0 -2
  112. agno/utils/team.py +61 -11
  113. agno/vectordb/lancedb/lance_db.py +4 -1
  114. agno/vectordb/mongodb/mongodb.py +1 -1
  115. agno/vectordb/qdrant/qdrant.py +4 -4
  116. agno/workflow/__init__.py +3 -1
  117. agno/workflow/condition.py +0 -21
  118. agno/workflow/loop.py +0 -21
  119. agno/workflow/parallel.py +0 -21
  120. agno/workflow/router.py +0 -21
  121. agno/workflow/step.py +117 -24
  122. agno/workflow/steps.py +0 -21
  123. agno/workflow/workflow.py +625 -63
  124. {agno-2.3.25.dist-info → agno-2.4.0.dist-info}/METADATA +46 -76
  125. {agno-2.3.25.dist-info → agno-2.4.0.dist-info}/RECORD +128 -117
  126. {agno-2.3.25.dist-info → agno-2.4.0.dist-info}/WHEEL +0 -0
  127. {agno-2.3.25.dist-info → agno-2.4.0.dist-info}/licenses/LICENSE +0 -0
  128. {agno-2.3.25.dist-info → agno-2.4.0.dist-info}/top_level.txt +0 -0
@@ -4,7 +4,7 @@ from typing import Any
4
4
 
5
5
  try:
6
6
  from sqlalchemy.dialects.postgresql import JSONB
7
- from sqlalchemy.types import BigInteger, Boolean, Date, String, Text
7
+ from sqlalchemy.types import BigInteger, Boolean, Date, Integer, String, Text
8
8
  except ImportError:
9
9
  raise ImportError("`sqlalchemy` not installed. Please install it using `pip install sqlalchemy`")
10
10
 
@@ -169,6 +169,50 @@ def _get_span_table_schema(traces_table_name: str = "agno_traces", db_schema: st
169
169
  }
170
170
 
171
171
 
172
+ COMPONENT_TABLE_SCHEMA = {
173
+ "component_id": {"type": String, "primary_key": True},
174
+ "component_type": {"type": String, "nullable": False, "index": True}, # agent|team|workflow
175
+ "name": {"type": String, "nullable": True, "index": True},
176
+ "description": {"type": Text, "nullable": True},
177
+ "current_version": {"type": Integer, "nullable": True, "index": True},
178
+ "metadata": {"type": JSONB, "nullable": True},
179
+ "created_at": {"type": BigInteger, "nullable": False, "index": True},
180
+ "updated_at": {"type": BigInteger, "nullable": True},
181
+ "deleted_at": {"type": BigInteger, "nullable": True},
182
+ }
183
+
184
+ COMPONENT_CONFIGS_TABLE_SCHEMA = {
185
+ "component_id": {"type": String, "primary_key": True, "foreign_key": "components.component_id"},
186
+ "version": {"type": Integer, "primary_key": True},
187
+ "label": {"type": String, "nullable": True}, # stable|v1.2.0|pre-refactor
188
+ "stage": {"type": String, "nullable": False, "default": "draft", "index": True}, # draft|published
189
+ "config": {"type": JSONB, "nullable": False},
190
+ "notes": {"type": Text, "nullable": True},
191
+ "created_at": {"type": BigInteger, "nullable": False, "index": True},
192
+ "updated_at": {"type": BigInteger, "nullable": True},
193
+ "deleted_at": {"type": BigInteger, "nullable": True},
194
+ }
195
+
196
+ COMPONENT_LINKS_TABLE_SCHEMA = {
197
+ "parent_component_id": {"type": String, "nullable": False},
198
+ "parent_version": {"type": Integer, "nullable": False},
199
+ "link_kind": {"type": String, "nullable": False, "index": True},
200
+ "link_key": {"type": String, "nullable": False},
201
+ "child_component_id": {"type": String, "nullable": False, "foreign_key": "components.component_id"},
202
+ "child_version": {"type": Integer, "nullable": True},
203
+ "position": {"type": Integer, "nullable": False},
204
+ "meta": {"type": JSONB, "nullable": True},
205
+ "created_at": {"type": BigInteger, "nullable": True, "index": True},
206
+ "updated_at": {"type": BigInteger, "nullable": True},
207
+ "__primary_key__": ["parent_component_id", "parent_version", "link_kind", "link_key"],
208
+ "__foreign_keys__": [
209
+ {
210
+ "columns": ["parent_component_id", "parent_version"],
211
+ "ref_table": "component_configs",
212
+ "ref_columns": ["component_id", "version"],
213
+ }
214
+ ],
215
+ }
172
216
  LEARNINGS_TABLE_SCHEMA = {
173
217
  "learning_id": {"type": String, "primary_key": True, "nullable": False},
174
218
  "learning_type": {"type": String, "nullable": False, "index": True},
@@ -214,6 +258,9 @@ def get_table_schema_definition(
214
258
  "culture": CULTURAL_KNOWLEDGE_TABLE_SCHEMA,
215
259
  "versions": VERSIONS_TABLE_SCHEMA,
216
260
  "traces": TRACE_TABLE_SCHEMA,
261
+ "components": COMPONENT_TABLE_SCHEMA,
262
+ "component_configs": COMPONENT_CONFIGS_TABLE_SCHEMA,
263
+ "component_links": COMPONENT_LINKS_TABLE_SCHEMA,
217
264
  "learnings": LEARNINGS_TABLE_SCHEMA,
218
265
  }
219
266
 
@@ -7,7 +7,7 @@ from uuid import uuid4
7
7
  if TYPE_CHECKING:
8
8
  from agno.tracing.schemas import Span, Trace
9
9
 
10
- from agno.db.base import AsyncBaseDb, SessionType
10
+ from agno.db.base import AsyncBaseDb, ComponentType, SessionType
11
11
  from agno.db.migrations.manager import MigrationManager
12
12
  from agno.db.schemas.culture import CulturalKnowledge
13
13
  from agno.db.schemas.evals import EvalFilterType, EvalRunRecord, EvalType
@@ -362,7 +362,7 @@ class AsyncSqliteDb(AsyncBaseDb):
362
362
  table_name: str,
363
363
  table_type: str,
364
364
  create_table_if_not_found: Optional[bool] = False,
365
- ) -> Table:
365
+ ) -> Optional[Table]:
366
366
  """
367
367
  Check if the table exists and is valid, else create it.
368
368
 
@@ -376,7 +376,9 @@ class AsyncSqliteDb(AsyncBaseDb):
376
376
  async with self.async_session_factory() as sess, sess.begin():
377
377
  table_is_available = await ais_table_available(session=sess, table_name=table_name)
378
378
 
379
- if (not table_is_available) and create_table_if_not_found:
379
+ if not table_is_available:
380
+ if not create_table_if_not_found:
381
+ return None
380
382
  return await self._create_table(table_name=table_name, table_type=table_type)
381
383
 
382
384
  # SQLite version of table validation (no schema)
@@ -3090,7 +3092,7 @@ class AsyncSqliteDb(AsyncBaseDb):
3090
3092
  async with self.async_session_factory() as sess, sess.begin():
3091
3093
  stmt = table.delete().where(table.c.learning_id == id)
3092
3094
  result = await sess.execute(stmt)
3093
- return result.rowcount > 0
3095
+ return getattr(result, "rowcount", 0) > 0
3094
3096
 
3095
3097
  except Exception as e:
3096
3098
  log_debug(f"Error deleting learning: {e}")
@@ -3165,3 +3167,116 @@ class AsyncSqliteDb(AsyncBaseDb):
3165
3167
  except Exception as e:
3166
3168
  log_debug(f"Error getting learnings: {e}")
3167
3169
  return []
3170
+
3171
+ # --- Components (Not yet supported for async) ---
3172
+ def get_component(
3173
+ self,
3174
+ component_id: str,
3175
+ component_type: Optional[ComponentType] = None,
3176
+ ) -> Optional[Dict[str, Any]]:
3177
+ raise NotImplementedError("Component methods not yet supported for async databases")
3178
+
3179
+ def upsert_component(
3180
+ self,
3181
+ component_id: str,
3182
+ component_type: Optional[ComponentType] = None,
3183
+ name: Optional[str] = None,
3184
+ description: Optional[str] = None,
3185
+ metadata: Optional[Dict[str, Any]] = None,
3186
+ ) -> Dict[str, Any]:
3187
+ raise NotImplementedError("Component methods not yet supported for async databases")
3188
+
3189
+ def delete_component(
3190
+ self,
3191
+ component_id: str,
3192
+ hard_delete: bool = False,
3193
+ ) -> bool:
3194
+ raise NotImplementedError("Component methods not yet supported for async databases")
3195
+
3196
+ def list_components(
3197
+ self,
3198
+ component_type: Optional[ComponentType] = None,
3199
+ include_deleted: bool = False,
3200
+ limit: int = 20,
3201
+ offset: int = 0,
3202
+ ) -> Tuple[List[Dict[str, Any]], int]:
3203
+ raise NotImplementedError("Component methods not yet supported for async databases")
3204
+
3205
+ def create_component_with_config(
3206
+ self,
3207
+ component_id: str,
3208
+ component_type: ComponentType,
3209
+ name: Optional[str],
3210
+ config: Dict[str, Any],
3211
+ description: Optional[str] = None,
3212
+ metadata: Optional[Dict[str, Any]] = None,
3213
+ label: Optional[str] = None,
3214
+ stage: str = "draft",
3215
+ notes: Optional[str] = None,
3216
+ links: Optional[List[Dict[str, Any]]] = None,
3217
+ ) -> Tuple[Dict[str, Any], Dict[str, Any]]:
3218
+ raise NotImplementedError("Component methods not yet supported for async databases")
3219
+
3220
+ def get_config(
3221
+ self,
3222
+ component_id: str,
3223
+ version: Optional[int] = None,
3224
+ label: Optional[str] = None,
3225
+ ) -> Optional[Dict[str, Any]]:
3226
+ raise NotImplementedError("Component methods not yet supported for async databases")
3227
+
3228
+ def upsert_config(
3229
+ self,
3230
+ component_id: str,
3231
+ config: Optional[Dict[str, Any]] = None,
3232
+ version: Optional[int] = None,
3233
+ label: Optional[str] = None,
3234
+ stage: Optional[str] = None,
3235
+ notes: Optional[str] = None,
3236
+ links: Optional[List[Dict[str, Any]]] = None,
3237
+ ) -> Dict[str, Any]:
3238
+ raise NotImplementedError("Component methods not yet supported for async databases")
3239
+
3240
+ def delete_config(
3241
+ self,
3242
+ component_id: str,
3243
+ version: int,
3244
+ ) -> bool:
3245
+ raise NotImplementedError("Component methods not yet supported for async databases")
3246
+
3247
+ def list_configs(
3248
+ self,
3249
+ component_id: str,
3250
+ include_config: bool = False,
3251
+ ) -> List[Dict[str, Any]]:
3252
+ raise NotImplementedError("Component methods not yet supported for async databases")
3253
+
3254
+ def set_current_version(
3255
+ self,
3256
+ component_id: str,
3257
+ version: int,
3258
+ ) -> bool:
3259
+ raise NotImplementedError("Component methods not yet supported for async databases")
3260
+
3261
+ def get_links(
3262
+ self,
3263
+ component_id: str,
3264
+ version: int,
3265
+ link_kind: Optional[str] = None,
3266
+ ) -> List[Dict[str, Any]]:
3267
+ raise NotImplementedError("Component methods not yet supported for async databases")
3268
+
3269
+ def get_dependents(
3270
+ self,
3271
+ component_id: str,
3272
+ version: Optional[int] = None,
3273
+ ) -> List[Dict[str, Any]]:
3274
+ raise NotImplementedError("Component methods not yet supported for async databases")
3275
+
3276
+ def load_component_graph(
3277
+ self,
3278
+ component_id: str,
3279
+ version: Optional[int] = None,
3280
+ label: Optional[str] = None,
3281
+ ) -> Optional[Dict[str, Any]]:
3282
+ raise NotImplementedError("Component methods not yet supported for async databases")
agno/db/sqlite/schemas.py CHANGED
@@ -162,6 +162,54 @@ VERSIONS_TABLE_SCHEMA = {
162
162
  "updated_at": {"type": String, "nullable": True},
163
163
  }
164
164
 
165
+ COMPONENTS_TABLE_SCHEMA = {
166
+ "component_id": {"type": String, "primary_key": True},
167
+ "component_type": {"type": String, "nullable": False, "index": True}, # agent|team|workflow
168
+ "name": {"type": String, "nullable": False, "index": True},
169
+ "description": {"type": String, "nullable": True},
170
+ "current_version": {"type": BigInteger, "nullable": True, "index": True},
171
+ "metadata": {"type": JSON, "nullable": True},
172
+ "created_at": {"type": BigInteger, "nullable": False, "index": True},
173
+ "updated_at": {"type": BigInteger, "nullable": True},
174
+ "deleted_at": {"type": BigInteger, "nullable": True},
175
+ }
176
+
177
+ COMPONENT_CONFIGS_TABLE_SCHEMA = {
178
+ "component_id": {"type": String, "nullable": False},
179
+ "version": {"type": BigInteger, "nullable": False},
180
+ "label": {"type": String, "nullable": True}, # stable|v1.2.0|pre-refactor
181
+ "stage": {"type": String, "nullable": False, "default": "draft", "index": True}, # draft|published
182
+ "config": {"type": JSON, "nullable": False},
183
+ "notes": {"type": String, "nullable": True},
184
+ "created_at": {"type": BigInteger, "nullable": False, "index": True},
185
+ "updated_at": {"type": BigInteger, "nullable": True},
186
+ "_unique_constraints": [
187
+ {
188
+ "name": "uq_config_component_version",
189
+ "columns": ["component_id", "version"],
190
+ },
191
+ ],
192
+ }
193
+
194
+ COMPONENT_LINKS_TABLE_SCHEMA = {
195
+ "parent_component_id": {"type": String, "nullable": False},
196
+ "parent_version": {"type": BigInteger, "nullable": False},
197
+ "link_kind": {"type": String, "nullable": False, "index": True},
198
+ "link_key": {"type": String, "nullable": False},
199
+ "child_component_id": {"type": String, "nullable": False},
200
+ "child_version": {"type": BigInteger, "nullable": True},
201
+ "position": {"type": BigInteger, "nullable": False},
202
+ "meta": {"type": JSON, "nullable": True},
203
+ "created_at": {"type": BigInteger, "nullable": True, "index": True},
204
+ "updated_at": {"type": BigInteger, "nullable": True},
205
+ "_unique_constraints": [
206
+ {
207
+ "name": "uq_link_parent_kind_key",
208
+ "columns": ["parent_component_id", "parent_version", "link_kind", "link_key"],
209
+ },
210
+ ],
211
+ }
212
+
165
213
  LEARNINGS_TABLE_SCHEMA = {
166
214
  "learning_id": {"type": String, "primary_key": True, "nullable": False},
167
215
  "learning_type": {"type": String, "nullable": False, "index": True},
@@ -204,6 +252,9 @@ def get_table_schema_definition(table_type: str, traces_table_name: str = "agno_
204
252
  "traces": TRACE_TABLE_SCHEMA,
205
253
  "culture": CULTURAL_KNOWLEDGE_TABLE_SCHEMA,
206
254
  "versions": VERSIONS_TABLE_SCHEMA,
255
+ "components": COMPONENTS_TABLE_SCHEMA,
256
+ "component_configs": COMPONENT_CONFIGS_TABLE_SCHEMA,
257
+ "component_links": COMPONENT_LINKS_TABLE_SCHEMA,
207
258
  "learnings": LEARNINGS_TABLE_SCHEMA,
208
259
  }
209
260
  schema = schemas.get(table_type, {})