agno 2.3.4__py3-none-any.whl → 2.3.6__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 (116) hide show
  1. agno/agent/agent.py +184 -45
  2. agno/culture/manager.py +2 -2
  3. agno/db/base.py +330 -8
  4. agno/db/dynamo/dynamo.py +722 -2
  5. agno/db/dynamo/schemas.py +127 -0
  6. agno/db/firestore/firestore.py +573 -1
  7. agno/db/firestore/schemas.py +40 -0
  8. agno/db/gcs_json/gcs_json_db.py +446 -1
  9. agno/db/in_memory/in_memory_db.py +143 -1
  10. agno/db/json/json_db.py +438 -1
  11. agno/db/mongo/async_mongo.py +522 -0
  12. agno/db/mongo/mongo.py +523 -1
  13. agno/db/mongo/schemas.py +29 -0
  14. agno/db/mysql/mysql.py +536 -3
  15. agno/db/mysql/schemas.py +38 -0
  16. agno/db/postgres/async_postgres.py +553 -15
  17. agno/db/postgres/postgres.py +544 -5
  18. agno/db/postgres/schemas.py +38 -0
  19. agno/db/redis/redis.py +468 -1
  20. agno/db/redis/schemas.py +32 -0
  21. agno/db/singlestore/schemas.py +38 -0
  22. agno/db/singlestore/singlestore.py +523 -1
  23. agno/db/sqlite/async_sqlite.py +549 -10
  24. agno/db/sqlite/schemas.py +38 -0
  25. agno/db/sqlite/sqlite.py +540 -9
  26. agno/db/sqlite/utils.py +6 -8
  27. agno/db/surrealdb/models.py +25 -0
  28. agno/db/surrealdb/surrealdb.py +548 -1
  29. agno/eval/accuracy.py +18 -8
  30. agno/eval/performance.py +10 -4
  31. agno/eval/reliability.py +22 -13
  32. agno/exceptions.py +11 -0
  33. agno/hooks/__init__.py +3 -0
  34. agno/hooks/decorator.py +164 -0
  35. agno/integrations/discord/client.py +1 -1
  36. agno/knowledge/chunking/semantic.py +2 -2
  37. agno/models/aimlapi/aimlapi.py +2 -3
  38. agno/models/anthropic/claude.py +18 -13
  39. agno/models/aws/bedrock.py +3 -4
  40. agno/models/aws/claude.py +5 -1
  41. agno/models/azure/ai_foundry.py +2 -2
  42. agno/models/azure/openai_chat.py +8 -0
  43. agno/models/cerebras/cerebras.py +62 -11
  44. agno/models/cerebras/cerebras_openai.py +2 -3
  45. agno/models/cohere/chat.py +1 -5
  46. agno/models/cometapi/cometapi.py +2 -3
  47. agno/models/dashscope/dashscope.py +2 -3
  48. agno/models/deepinfra/deepinfra.py +2 -3
  49. agno/models/deepseek/deepseek.py +2 -3
  50. agno/models/fireworks/fireworks.py +2 -3
  51. agno/models/google/gemini.py +9 -7
  52. agno/models/groq/groq.py +2 -3
  53. agno/models/huggingface/huggingface.py +1 -5
  54. agno/models/ibm/watsonx.py +1 -5
  55. agno/models/internlm/internlm.py +2 -3
  56. agno/models/langdb/langdb.py +6 -4
  57. agno/models/litellm/chat.py +2 -2
  58. agno/models/litellm/litellm_openai.py +2 -3
  59. agno/models/meta/llama.py +1 -5
  60. agno/models/meta/llama_openai.py +4 -5
  61. agno/models/mistral/mistral.py +1 -5
  62. agno/models/nebius/nebius.py +2 -3
  63. agno/models/nvidia/nvidia.py +4 -5
  64. agno/models/openai/chat.py +14 -3
  65. agno/models/openai/responses.py +14 -3
  66. agno/models/openrouter/openrouter.py +4 -5
  67. agno/models/perplexity/perplexity.py +2 -3
  68. agno/models/portkey/portkey.py +7 -6
  69. agno/models/requesty/requesty.py +4 -5
  70. agno/models/response.py +2 -1
  71. agno/models/sambanova/sambanova.py +4 -5
  72. agno/models/siliconflow/siliconflow.py +3 -4
  73. agno/models/together/together.py +4 -5
  74. agno/models/vercel/v0.py +4 -5
  75. agno/models/vllm/vllm.py +19 -14
  76. agno/models/xai/xai.py +4 -5
  77. agno/os/app.py +104 -0
  78. agno/os/config.py +13 -0
  79. agno/os/interfaces/whatsapp/router.py +0 -1
  80. agno/os/interfaces/whatsapp/security.py +3 -1
  81. agno/os/mcp.py +1 -0
  82. agno/os/router.py +31 -0
  83. agno/os/routers/traces/__init__.py +3 -0
  84. agno/os/routers/traces/schemas.py +414 -0
  85. agno/os/routers/traces/traces.py +499 -0
  86. agno/os/schema.py +12 -2
  87. agno/os/utils.py +57 -0
  88. agno/run/agent.py +1 -0
  89. agno/run/base.py +17 -0
  90. agno/run/team.py +4 -0
  91. agno/table.py +10 -0
  92. agno/team/team.py +221 -69
  93. agno/tools/function.py +10 -8
  94. agno/tools/google_drive.py +4 -3
  95. agno/tools/nano_banana.py +1 -1
  96. agno/tools/spotify.py +922 -0
  97. agno/tracing/__init__.py +12 -0
  98. agno/tracing/exporter.py +157 -0
  99. agno/tracing/schemas.py +276 -0
  100. agno/tracing/setup.py +111 -0
  101. agno/utils/agent.py +6 -6
  102. agno/utils/hooks.py +56 -1
  103. agno/utils/mcp.py +1 -1
  104. agno/vectordb/qdrant/qdrant.py +22 -22
  105. agno/workflow/condition.py +8 -0
  106. agno/workflow/loop.py +8 -0
  107. agno/workflow/parallel.py +8 -0
  108. agno/workflow/router.py +8 -0
  109. agno/workflow/step.py +20 -0
  110. agno/workflow/steps.py +8 -0
  111. agno/workflow/workflow.py +88 -19
  112. {agno-2.3.4.dist-info → agno-2.3.6.dist-info}/METADATA +38 -33
  113. {agno-2.3.4.dist-info → agno-2.3.6.dist-info}/RECORD +116 -105
  114. {agno-2.3.4.dist-info → agno-2.3.6.dist-info}/WHEEL +0 -0
  115. {agno-2.3.4.dist-info → agno-2.3.6.dist-info}/licenses/LICENSE +0 -0
  116. {agno-2.3.4.dist-info → agno-2.3.6.dist-info}/top_level.txt +0 -0
agno/workflow/workflow.py CHANGED
@@ -186,6 +186,9 @@ class Workflow:
186
186
  # Deprecated. Use stream_events instead.
187
187
  stream_intermediate_steps: bool = False
188
188
 
189
+ # If True, run hooks as FastAPI background tasks (non-blocking). Set by AgentOS.
190
+ _run_hooks_in_background: bool = False
191
+
189
192
  def __init__(
190
193
  self,
191
194
  id: Optional[str] = None,
@@ -198,6 +201,7 @@ class Workflow:
198
201
  session_state: Optional[Dict[str, Any]] = None,
199
202
  overwrite_db_session_state: bool = False,
200
203
  user_id: Optional[str] = None,
204
+ debug_level: Literal[1, 2] = 1,
201
205
  debug_mode: Optional[bool] = False,
202
206
  stream: Optional[bool] = None,
203
207
  stream_events: bool = False,
@@ -223,6 +227,7 @@ class Workflow:
223
227
  self.overwrite_db_session_state = overwrite_db_session_state
224
228
  self.user_id = user_id
225
229
  self.debug_mode = debug_mode
230
+ self.debug_level = debug_level
226
231
  self.store_events = store_events
227
232
  self.events_to_skip = events_to_skip or []
228
233
  self.stream = stream
@@ -1105,9 +1110,12 @@ class Workflow:
1105
1110
  """Set debug mode and configure logging"""
1106
1111
  if self.debug_mode or getenv("AGNO_DEBUG", "false").lower() == "true":
1107
1112
  use_workflow_logger()
1113
+ debug_level: Literal[1, 2] = (
1114
+ cast(Literal[1, 2], int(env)) if (env := getenv("AGNO_DEBUG_LEVEL")) in ("1", "2") else self.debug_level
1115
+ )
1108
1116
 
1109
1117
  self.debug_mode = True
1110
- set_log_level_to_debug(source_type="workflow")
1118
+ set_log_level_to_debug(source_type="workflow", level=debug_level)
1111
1119
 
1112
1120
  # Propagate to steps - only if steps is iterable (not callable)
1113
1121
  if self.steps and not callable(self.steps):
@@ -1282,14 +1290,13 @@ class Workflow:
1282
1290
  execution_input: WorkflowExecutionInput,
1283
1291
  workflow_run_response: WorkflowRunOutput,
1284
1292
  run_context: RunContext,
1293
+ background_tasks: Optional[Any] = None,
1285
1294
  **kwargs: Any,
1286
1295
  ) -> WorkflowRunOutput:
1287
1296
  """Execute a specific pipeline by name synchronously"""
1288
1297
  from inspect import isasyncgenfunction, iscoroutinefunction, isgeneratorfunction
1289
1298
 
1290
1299
  workflow_run_response.status = RunStatus.running
1291
- if workflow_run_response.run_id:
1292
- register_run(workflow_run_response.run_id) # type: ignore
1293
1300
 
1294
1301
  if callable(self.steps):
1295
1302
  if iscoroutinefunction(self.steps) or isasyncgenfunction(self.steps):
@@ -1355,6 +1362,7 @@ class Workflow:
1355
1362
  if self.add_workflow_history_to_steps
1356
1363
  else None,
1357
1364
  num_history_runs=self.num_history_runs,
1365
+ background_tasks=background_tasks,
1358
1366
  )
1359
1367
 
1360
1368
  # Check for cancellation after step execution
@@ -1455,6 +1463,7 @@ class Workflow:
1455
1463
  workflow_run_response: WorkflowRunOutput,
1456
1464
  run_context: RunContext,
1457
1465
  stream_events: bool = False,
1466
+ background_tasks: Optional[Any] = None,
1458
1467
  **kwargs: Any,
1459
1468
  ) -> Iterator[WorkflowRunOutputEvent]:
1460
1469
  """Execute a specific pipeline by name with event streaming"""
@@ -1462,10 +1471,6 @@ class Workflow:
1462
1471
 
1463
1472
  workflow_run_response.status = RunStatus.running
1464
1473
 
1465
- # Register run for cancellation tracking
1466
- if workflow_run_response.run_id:
1467
- register_run(workflow_run_response.run_id)
1468
-
1469
1474
  workflow_started_event = WorkflowStartedEvent(
1470
1475
  run_id=workflow_run_response.run_id or "",
1471
1476
  workflow_name=workflow_run_response.workflow_name,
@@ -1552,6 +1557,7 @@ class Workflow:
1552
1557
  if self.add_workflow_history_to_steps
1553
1558
  else None,
1554
1559
  num_history_runs=self.num_history_runs,
1560
+ background_tasks=background_tasks,
1555
1561
  ):
1556
1562
  raise_if_cancelled(workflow_run_response.run_id) # type: ignore
1557
1563
 
@@ -1831,7 +1837,7 @@ class Workflow:
1831
1837
  self._update_metadata(session=workflow_session)
1832
1838
 
1833
1839
  # Update session state from DB
1834
- _session_state = session_state or {}
1840
+ _session_state = session_state if session_state is not None else {}
1835
1841
  _session_state = self._load_session_state(session=workflow_session, session_state=_session_state)
1836
1842
 
1837
1843
  return workflow_session, _session_state
@@ -1843,6 +1849,7 @@ class Workflow:
1843
1849
  execution_input: WorkflowExecutionInput,
1844
1850
  workflow_run_response: WorkflowRunOutput,
1845
1851
  run_context: RunContext,
1852
+ background_tasks: Optional[Any] = None,
1846
1853
  **kwargs: Any,
1847
1854
  ) -> WorkflowRunOutput:
1848
1855
  """Execute a specific pipeline by name asynchronously"""
@@ -1855,10 +1862,6 @@ class Workflow:
1855
1862
 
1856
1863
  workflow_run_response.status = RunStatus.running
1857
1864
 
1858
- # Register run for cancellation tracking
1859
- if workflow_run_response.run_id:
1860
- register_run(workflow_run_response.run_id) # type: ignore
1861
-
1862
1865
  if callable(self.steps):
1863
1866
  # Execute the workflow with the custom executor
1864
1867
  content = ""
@@ -1931,6 +1934,7 @@ class Workflow:
1931
1934
  if self.add_workflow_history_to_steps
1932
1935
  else None,
1933
1936
  num_history_runs=self.num_history_runs,
1937
+ background_tasks=background_tasks,
1934
1938
  )
1935
1939
 
1936
1940
  # Check for cancellation after step execution
@@ -2031,6 +2035,7 @@ class Workflow:
2031
2035
  run_context: RunContext,
2032
2036
  stream_events: bool = False,
2033
2037
  websocket_handler: Optional[WebSocketHandler] = None,
2038
+ background_tasks: Optional[Any] = None,
2034
2039
  **kwargs: Any,
2035
2040
  ) -> AsyncIterator[WorkflowRunOutputEvent]:
2036
2041
  """Execute a specific pipeline by name with event streaming"""
@@ -2043,10 +2048,6 @@ class Workflow:
2043
2048
 
2044
2049
  workflow_run_response.status = RunStatus.running
2045
2050
 
2046
- # Register run for cancellation tracking
2047
- if workflow_run_response.run_id:
2048
- register_run(workflow_run_response.run_id)
2049
-
2050
2051
  workflow_started_event = WorkflowStartedEvent(
2051
2052
  run_id=workflow_run_response.run_id or "",
2052
2053
  workflow_name=workflow_run_response.workflow_name,
@@ -2141,6 +2142,7 @@ class Workflow:
2141
2142
  if self.add_workflow_history_to_steps
2142
2143
  else None,
2143
2144
  num_history_runs=self.num_history_runs,
2145
+ background_tasks=background_tasks,
2144
2146
  ):
2145
2147
  if workflow_run_response.run_id:
2146
2148
  raise_if_cancelled(workflow_run_response.run_id)
@@ -3457,6 +3459,7 @@ class Workflow:
3457
3459
  stream_events: Optional[bool] = None,
3458
3460
  stream_intermediate_steps: Optional[bool] = None,
3459
3461
  background: Optional[bool] = False,
3462
+ background_tasks: Optional[Any] = None,
3460
3463
  ) -> WorkflowRunOutput: ...
3461
3464
 
3462
3465
  @overload
@@ -3475,6 +3478,7 @@ class Workflow:
3475
3478
  stream_events: Optional[bool] = None,
3476
3479
  stream_intermediate_steps: Optional[bool] = None,
3477
3480
  background: Optional[bool] = False,
3481
+ background_tasks: Optional[Any] = None,
3478
3482
  ) -> Iterator[WorkflowRunOutputEvent]: ...
3479
3483
 
3480
3484
  def run(
@@ -3492,20 +3496,23 @@ class Workflow:
3492
3496
  stream_events: Optional[bool] = None,
3493
3497
  stream_intermediate_steps: Optional[bool] = None,
3494
3498
  background: Optional[bool] = False,
3499
+ background_tasks: Optional[Any] = None,
3495
3500
  **kwargs: Any,
3496
3501
  ) -> Union[WorkflowRunOutput, Iterator[WorkflowRunOutputEvent]]:
3497
3502
  """Execute the workflow synchronously with optional streaming"""
3498
3503
  if self._has_async_db():
3499
3504
  raise Exception("`run()` is not supported with an async DB. Please use `arun()`.")
3500
3505
 
3506
+ # Create a run_id for this specific run and register immediately for cancellation tracking
3507
+ run_id = str(uuid4())
3508
+ register_run(run_id)
3509
+
3501
3510
  input = self._validate_input(input)
3502
3511
  if background:
3503
3512
  raise RuntimeError("Background execution is not supported for sync run()")
3504
3513
 
3505
3514
  self._set_debug()
3506
3515
 
3507
- run_id = str(uuid4())
3508
-
3509
3516
  self.initialize_workflow()
3510
3517
  session_id, user_id = self._initialize_session(session_id=session_id, user_id=user_id)
3511
3518
 
@@ -3515,7 +3522,10 @@ class Workflow:
3515
3522
 
3516
3523
  # Initialize session state
3517
3524
  session_state = self._initialize_session_state(
3518
- session_state=session_state or {}, user_id=user_id, session_id=session_id, run_id=run_id
3525
+ session_state=session_state if session_state is not None else {},
3526
+ user_id=user_id,
3527
+ session_id=session_id,
3528
+ run_id=run_id,
3519
3529
  )
3520
3530
  # Update session state from DB
3521
3531
  session_state = self._load_session_state(session=workflow_session, session_state=session_state)
@@ -3592,6 +3602,7 @@ class Workflow:
3592
3602
  workflow_run_response=workflow_run_response,
3593
3603
  stream_events=stream_events,
3594
3604
  run_context=run_context,
3605
+ background_tasks=background_tasks,
3595
3606
  **kwargs,
3596
3607
  )
3597
3608
  else:
@@ -3600,6 +3611,7 @@ class Workflow:
3600
3611
  execution_input=inputs, # type: ignore[arg-type]
3601
3612
  workflow_run_response=workflow_run_response,
3602
3613
  run_context=run_context,
3614
+ background_tasks=background_tasks,
3603
3615
  **kwargs,
3604
3616
  )
3605
3617
 
@@ -3620,6 +3632,7 @@ class Workflow:
3620
3632
  stream_intermediate_steps: Optional[bool] = None,
3621
3633
  background: Optional[bool] = False,
3622
3634
  websocket: Optional[WebSocket] = None,
3635
+ background_tasks: Optional[Any] = None,
3623
3636
  ) -> WorkflowRunOutput: ...
3624
3637
 
3625
3638
  @overload
@@ -3639,6 +3652,7 @@ class Workflow:
3639
3652
  stream_intermediate_steps: Optional[bool] = None,
3640
3653
  background: Optional[bool] = False,
3641
3654
  websocket: Optional[WebSocket] = None,
3655
+ background_tasks: Optional[Any] = None,
3642
3656
  ) -> AsyncIterator[WorkflowRunOutputEvent]: ...
3643
3657
 
3644
3658
  def arun( # type: ignore
@@ -3657,6 +3671,7 @@ class Workflow:
3657
3671
  stream_intermediate_steps: Optional[bool] = False,
3658
3672
  background: Optional[bool] = False,
3659
3673
  websocket: Optional[WebSocket] = None,
3674
+ background_tasks: Optional[Any] = None,
3660
3675
  **kwargs: Any,
3661
3676
  ) -> Union[WorkflowRunOutput, AsyncIterator[WorkflowRunOutputEvent]]:
3662
3677
  """Execute the workflow synchronously with optional streaming"""
@@ -3715,7 +3730,9 @@ class Workflow:
3715
3730
 
3716
3731
  self._set_debug()
3717
3732
 
3733
+ # Create a run_id for this specific run and register immediately for cancellation tracking
3718
3734
  run_id = str(uuid4())
3735
+ register_run(run_id)
3719
3736
 
3720
3737
  self.initialize_workflow()
3721
3738
  session_id, user_id = self._initialize_session(session_id=session_id, user_id=user_id)
@@ -3793,6 +3810,7 @@ class Workflow:
3793
3810
  files=files,
3794
3811
  session_state=session_state,
3795
3812
  run_context=run_context,
3813
+ background_tasks=background_tasks,
3796
3814
  **kwargs,
3797
3815
  )
3798
3816
  else:
@@ -3805,6 +3823,7 @@ class Workflow:
3805
3823
  files=files,
3806
3824
  session_state=session_state,
3807
3825
  run_context=run_context,
3826
+ background_tasks=background_tasks,
3808
3827
  **kwargs,
3809
3828
  )
3810
3829
 
@@ -4153,6 +4172,56 @@ class Workflow:
4153
4172
  if hasattr(member, "workflow_id"):
4154
4173
  member.workflow_id = self.id
4155
4174
 
4175
+ def propagate_run_hooks_in_background(self, run_in_background: bool = True) -> None:
4176
+ """
4177
+ Propagate _run_hooks_in_background setting to this workflow and all agents/teams in steps.
4178
+
4179
+ This method sets _run_hooks_in_background on the workflow and all agents/teams
4180
+ within its steps, including nested teams and their members.
4181
+
4182
+ Args:
4183
+ run_in_background: Whether hooks should run in background. Defaults to True.
4184
+ """
4185
+ self._run_hooks_in_background = run_in_background
4186
+
4187
+ if not self.steps or callable(self.steps):
4188
+ return
4189
+
4190
+ steps_list = self.steps.steps if isinstance(self.steps, Steps) else self.steps
4191
+
4192
+ for step in steps_list:
4193
+ self._propagate_hooks_to_step(step, run_in_background)
4194
+
4195
+ def _propagate_hooks_to_step(self, step: Any, run_in_background: bool) -> None:
4196
+ """Recursively propagate _run_hooks_in_background to a step and its nested content."""
4197
+ # Handle Step objects with active executor
4198
+ if hasattr(step, "active_executor") and step.active_executor:
4199
+ executor = step.active_executor
4200
+ # If it's a team, use its propagation method
4201
+ if hasattr(executor, "propagate_run_hooks_in_background"):
4202
+ executor.propagate_run_hooks_in_background(run_in_background)
4203
+ elif hasattr(executor, "_run_hooks_in_background"):
4204
+ executor._run_hooks_in_background = run_in_background
4205
+
4206
+ # Handle agent/team directly on step
4207
+ if hasattr(step, "agent") and step.agent:
4208
+ if hasattr(step.agent, "_run_hooks_in_background"):
4209
+ step.agent._run_hooks_in_background = run_in_background
4210
+ if hasattr(step, "team") and step.team:
4211
+ # Use team's method to propagate to all nested members
4212
+ if hasattr(step.team, "propagate_run_hooks_in_background"):
4213
+ step.team.propagate_run_hooks_in_background(run_in_background)
4214
+ elif hasattr(step.team, "_run_hooks_in_background"):
4215
+ step.team._run_hooks_in_background = run_in_background
4216
+
4217
+ # Handle nested primitives - check 'steps' and 'choices' attributes
4218
+ for attr_name in ["steps", "choices"]:
4219
+ if hasattr(step, attr_name):
4220
+ attr_value = getattr(step, attr_name)
4221
+ if attr_value and isinstance(attr_value, list):
4222
+ for nested_step in attr_value:
4223
+ self._propagate_hooks_to_step(nested_step, run_in_background)
4224
+
4156
4225
  ###########################################################################
4157
4226
  # Telemetry functions
4158
4227
  ###########################################################################
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agno
3
- Version: 2.3.4
3
+ Version: 2.3.6
4
4
  Summary: Agno: a lightweight library for building Multi-Agent Systems
5
5
  Author-email: Ashpreet Bedi <ashpreet@agno.com>
6
6
  Project-URL: homepage, https://agno.com
@@ -153,7 +153,7 @@ Requires-Dist: mcp>=1.9.2; extra == "mcp"
153
153
  Provides-Extra: mem0
154
154
  Requires-Dist: mem0ai; extra == "mem0"
155
155
  Provides-Extra: memori
156
- Requires-Dist: memorisdk; extra == "memori"
156
+ Requires-Dist: memorisdk==2.3.3; extra == "memori"
157
157
  Provides-Extra: newspaper
158
158
  Requires-Dist: newspaper4k; extra == "newspaper"
159
159
  Requires-Dist: lxml_html_clean; extra == "newspaper"
@@ -381,6 +381,7 @@ Requires-Dist: agno[agui]; extra == "tests"
381
381
  Requires-Dist: agno[integration-tests]; extra == "tests"
382
382
  Requires-Dist: twine; extra == "tests"
383
383
  Requires-Dist: build; extra == "tests"
384
+ Requires-Dist: grpcio==1.74.0; extra == "tests"
384
385
  Provides-Extra: integration-tests
385
386
  Requires-Dist: exa_py; extra == "integration-tests"
386
387
  Requires-Dist: ddgs; extra == "integration-tests"
@@ -411,15 +412,15 @@ Dynamic: license-file
411
412
 
412
413
  ## What is Agno?
413
414
 
414
- Agno is a multi-agent framework, runtime and control plane. Built for speed, privacy, and scale.
415
+ Agno is an incredibly fast multi-agent framework, runtime and control plane.
415
416
 
416
- It provides a rich set of tools for building:
417
+ It provides the complete stack for building, running and managing multi-agent systems:
417
418
 
418
- - **Agents** with memory, knowledge, session management, and advanced features like human-in-the-loop, guardrails, dynamic context management and best-in-class MCP support.
419
- - **Multi-Agent Teams** that operate autonomously under a team leader that maintains shared state and context. Perfect for use cases where the scope exceeds beyond a single agent.
420
- - **Step-based Workflows** for controlled, deterministic execution. Steps can be Agents, Teams, or regular python functions that run sequentially, in parallel, in loops, branches, or conditionally.
419
+ - **Framework**: Build agents, multi-agent teams and workflows with memory, knowledge, state, guardrails, HITL, context compression, MCP, A2A and 100+ toolkits.
420
+ - **AgentOS Runtime**: Run your multi-agent system in production with a secure, stateless runtime and ready to use integration endpoints.
421
+ - **AgentOS Control Plane**: Test, monitor and manage AgentOS deployments across environments with full operational visibility.
421
422
 
422
- Agno also provides a ready-to-use FastAPI app (called the AgentOS) for serving your agents, teams and workflows in production. Stateless, horizontally scalable and designed for scale, the AgentOS gives you major head start in building your AI product.
423
+ Checkout the full list of features [here](#features).
423
424
 
424
425
  ## Getting started
425
426
 
@@ -436,7 +437,7 @@ After that, checkout the [examples gallery](https://docs.agno.com/examples/use-c
436
437
 
437
438
  ## Example
438
439
 
439
- Heres an example of an Agent that connects to an MCP server, manages conversation state in a database, is served using a FastAPI application that you can chat with using the [AgentOS UI](https://os.agno.com).
440
+ Here's an example of an Agent that connects to an MCP server, manages conversation state in a database, is served using a FastAPI application that you can chat with using the [AgentOS UI](https://os.agno.com).
440
441
 
441
442
  ```python agno_agent.py
442
443
  from agno.agent import Agent
@@ -471,21 +472,21 @@ if __name__ == "__main__":
471
472
 
472
473
  ## AgentOS - Production Runtime for Multi-Agent Systems
473
474
 
474
- Building Agents is easy, running them is hard, and that's where the AgentOS comes in. AgentOS is a high-performance runtime for serving multi-agent systems in production. Key features include:
475
+ Building Agents is easy, running them as a secure, scalable service is hard. AgentOS solves this by providing a high performance runtime for serving multi-agent systems in production. Key features include:
475
476
 
476
- 1. **Pre-built FastAPI app**: AgentOS ships with a ready-to-use FastAPI app for orchestrating your agents, teams, and workflows. This gives you a major head start in building your AI product.
477
+ 1. **Pre-built FastAPI app**: AgentOS includes a ready-to-use FastAPI app for running your agents, teams and workflows. This gives you a significant head start when building an AI product.
477
478
 
478
- 2. **Integrated Control Plane**: The [AgentOS UI](https://os.agno.com) connects directly to your runtime, letting you test, monitor, and manage your system in real time, giving you unmatched control over your system.
479
+ 2. **Integrated Control Plane**: The [AgentOS UI](https://os.agno.com) connects directly to your runtime, so you can test, monitor and manage your system in real time with full operational visibility.
479
480
 
480
- 3. **Private by Design**: AgentOS runs entirely in your cloud, ensuring complete data privacy. No data ever leaves your system. This is ideal for security-conscious enterprises.
481
+ 3. **Private by Design**: AgentOS runs entirely in your cloud, ensuring complete data privacy. No data leaves your environment, making it ideal for security conscious enterprises..
481
482
 
482
- Here's what the [AgentOS UI](https://os.agno.com) looks like in action:
483
+ When you run the example script shared above, you get a FastAPI app that you can connect to the [AgentOS UI](https://os.agno.com). Here's what it looks like in action:
483
484
 
484
485
  https://github.com/user-attachments/assets/feb23db8-15cc-4e88-be7c-01a21a03ebf6
485
486
 
486
487
  ## The Complete Agentic Solution
487
488
 
488
- For companies building agents, Agno provides the complete agentic solution:
489
+ Agno provides the complete solution for companies building agentic systems:
489
490
 
490
491
  - The fastest framework for building agents, multi-agent teams and agentic workflows.
491
492
  - A ready-to-use FastAPI app that gets you building AI products on day one.
@@ -493,28 +494,32 @@ For companies building agents, Agno provides the complete agentic solution:
493
494
 
494
495
  Agno brings a novel architecture that no other framework provides, your AgentOS runs securely in your cloud, and the control plane connects directly to it from your browser. You don't need to send data to any external services or pay retention costs, you get complete privacy and control.
495
496
 
496
- ## Designed for Agent Engineering
497
+ ## Features
497
498
 
498
- Agno is an incredibly feature-rich framework, designed for Agent Engineering. Here are some key features:
499
+ Agno is an incredibly feature-rich framework purpose-built for Agent Engineering. Here are some key features:
499
500
 
500
501
  | **Category** | **Feature** | **Description** |
501
502
  | -------------------------------------- | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
502
- | **Core Intelligence** | **Model Agnostic** | Works with any model provider so you can use your favorite LLMs. |
503
- | | **Type Safe** | Enforce structured I/O through `input_schema` and `output_schema` for predictable, composable behavior. |
504
- | | **Dynamic Context Engineering** | Inject variables, state, and retrieved data on the fly into context. Perfect for dependency-driven agents. |
505
- | **Memory, Knowledge, and Persistence** | **Persistent Storage** | Give your Agents, Teams, and Workflows a database to persist session history, state, and messages. |
506
- | | **User Memory** | Built-in memory system that allows Agents to recall user-specific context across sessions. |
507
- | | **Agentic RAG** | Connect to 20+ vector stores (called **Knowledge** in Agno) with hybrid search + reranking out of the box. |
508
- | | **Culture (Collective Memory)** | Shared knowledge that compounds across agents and time. |
509
- | **Execution & Control** | **Human-in-the-Loop** | Native support for confirmations, manual overrides, and external tool execution. |
503
+ | **Foundational Principles** | **Model Agnostic** | Supports all model providers so you can choose the best model for your use case |
504
+ | | **Type Safe** | Enforces structured I/O through input_schema and output_schema for predictable and composable agent behavior. |
505
+ | | **Dynamic Context** | Inject variables, state, and retrieved data at runtime into context. Compress, summarize and filter context to keep your Agents focused and efficient. |
506
+ | | **Designed for Scale** | Designed around async execution and long-running tasks for high throughput agent workloads. |
507
+ | **Memory, Knowledge, and Persistence** | **Persistent Storage** | Give your Agents, Teams, and Workflows a database to persist session history, state, and messages. |
508
+ | | **User Memory** | Built in memory layer that helps agents recall user specific context across sessions. |
509
+ | | **Agentic RAG** | Connect to 20+ vector stores (called **Knowledge**) with hybrid search, reranking, and chunking out of the box. |
510
+ | | **Culture** | Shared long term collective memory that compounds across agents and time. |
511
+ | | **Ephemeral Context** | In memory scratchpad for short lived reasoning without polluting long term state. |
512
+ | **Execution & Control** | **Human-in-the-Loop** | Native support for confirmations, approvals, manual overrides, and external actions. |
510
513
  | | **Guardrails** | Built-in safeguards for validation, security, and prompt protection. |
511
- | | **Agent Lifecycle Hooks** | Pre- and post-hooks to validate or transform inputs and outputs. |
512
- | | **MCP Integration** | First-class support for the Model Context Protocol (MCP) to connect Agents with external systems. |
513
- | | **Toolkits** | 100+ built-in toolkits with thousands of tools, ready for use across data, code, web, and enterprise APIs. |
514
- | **Runtime & Evaluation** | **Runtime** | Pre-built FastAPI based runtime with SSE compatible endpoints, ready for production on day 1. |
515
- | | **Control Plane (UI)** | Integrated interface to visualize, monitor, and debug agent activity in real time. |
516
- | | **Natively Multimodal** | Agents can process and generate text, images, audio, video, and files. |
517
- | | **Evals** | Measure your Agents' Accuracy, Performance, and Reliability. |
514
+ | | **Agent Lifecycle Hooks** | Pre and post hooks to validate, enrich, or transform inputs and outputs. |
515
+ | | **MCP Integration** | First-class support for the Model Context Protocol (MCP) to connect Agents with external systems. |
516
+ | | **A2A Integration** | First-class support for the Agent to Agent communication protocol (A2A). |
517
+ | | **Toolkits** | 100+ built in toolkits with thousands of tools covering data, code, web, and enterprise APIs. |
518
+ | **Runtime & Evaluation** | **Runtime** | Prebuilt FastAPI runtime with SSE compatible endpoints. Production ready from day one. |
519
+ | | **Control Plane (UI)** | Integrated interface to test, observe, and debug your agents, teams, and workflows in real time. |
520
+ | | **Natively Multimodal** | Agents can process and generate text, images, audio, video, and files. |
521
+ | | **Evals** | Measure Accuracy, Performance, Latency, and Reliability across agents and workflows. |
522
+ | | **Durable Execution** | Built in support for long running, resumable workflows. |
518
523
  | **Security & Privacy** | **Private by Design** | Runs entirely in your cloud. The UI connects directly to your AgentOS from your browser, no data is ever sent externally. |
519
524
  | | **Data Governance** | Your data lives securely in your Agent database, no external data sharing or vendor lock-in. |
520
525
  | | **Access Control** | Role-based access (RBAC) and per-agent permissions to protect sensitive contexts and tools. |
@@ -544,7 +549,7 @@ At Agno, we optimize performance across 3 dimensions:
544
549
 
545
550
  1. **Agent performance:** We optimize static operations (instantiation, memory footprint) and runtime operations (tool calls, memory updates, history management).
546
551
  2. **System performance:** The AgentOS API is async by default and has a minimal memory footprint. The system is stateless and horizontally scalable, with a focus on preventing memory leaks. It handles parallel and batch embedding generation during knowledge ingestion, metrics collection in background tasks, and other system-level optimizations.
547
- 3. **Agent reliability and accuracy:** Monitored through evals, which well explore later.
552
+ 3. **Agent reliability and accuracy:** Monitored through evals, which we'll explore later.
548
553
 
549
554
  ### Agent Performance
550
555