agno 2.3.20__py3-none-any.whl → 2.3.22__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 (58) hide show
  1. agno/agent/agent.py +26 -1
  2. agno/agent/remote.py +233 -72
  3. agno/client/a2a/__init__.py +10 -0
  4. agno/client/a2a/client.py +554 -0
  5. agno/client/a2a/schemas.py +112 -0
  6. agno/client/a2a/utils.py +369 -0
  7. agno/db/migrations/utils.py +19 -0
  8. agno/db/migrations/v1_to_v2.py +54 -16
  9. agno/db/migrations/versions/v2_3_0.py +92 -53
  10. agno/db/postgres/async_postgres.py +162 -40
  11. agno/db/postgres/postgres.py +181 -31
  12. agno/db/postgres/utils.py +6 -2
  13. agno/eval/agent_as_judge.py +24 -14
  14. agno/knowledge/chunking/document.py +3 -2
  15. agno/knowledge/chunking/markdown.py +8 -3
  16. agno/knowledge/chunking/recursive.py +2 -2
  17. agno/knowledge/embedder/mistral.py +1 -1
  18. agno/models/openai/chat.py +1 -1
  19. agno/models/openai/responses.py +14 -7
  20. agno/os/middleware/jwt.py +66 -27
  21. agno/os/routers/agents/router.py +2 -2
  22. agno/os/routers/evals/evals.py +0 -9
  23. agno/os/routers/evals/utils.py +6 -6
  24. agno/os/routers/knowledge/knowledge.py +3 -3
  25. agno/os/routers/teams/router.py +2 -2
  26. agno/os/routers/workflows/router.py +2 -2
  27. agno/reasoning/deepseek.py +11 -1
  28. agno/reasoning/gemini.py +6 -2
  29. agno/reasoning/groq.py +8 -3
  30. agno/reasoning/openai.py +2 -0
  31. agno/remote/base.py +105 -8
  32. agno/run/agent.py +19 -19
  33. agno/run/team.py +19 -19
  34. agno/skills/__init__.py +17 -0
  35. agno/skills/agent_skills.py +370 -0
  36. agno/skills/errors.py +32 -0
  37. agno/skills/loaders/__init__.py +4 -0
  38. agno/skills/loaders/base.py +27 -0
  39. agno/skills/loaders/local.py +216 -0
  40. agno/skills/skill.py +65 -0
  41. agno/skills/utils.py +107 -0
  42. agno/skills/validator.py +277 -0
  43. agno/team/remote.py +219 -59
  44. agno/team/team.py +22 -2
  45. agno/tools/mcp/mcp.py +299 -17
  46. agno/tools/mcp/multi_mcp.py +269 -14
  47. agno/utils/mcp.py +49 -8
  48. agno/utils/string.py +43 -1
  49. agno/workflow/condition.py +4 -2
  50. agno/workflow/loop.py +20 -1
  51. agno/workflow/remote.py +172 -32
  52. agno/workflow/router.py +4 -1
  53. agno/workflow/steps.py +4 -0
  54. {agno-2.3.20.dist-info → agno-2.3.22.dist-info}/METADATA +59 -130
  55. {agno-2.3.20.dist-info → agno-2.3.22.dist-info}/RECORD +58 -44
  56. {agno-2.3.20.dist-info → agno-2.3.22.dist-info}/WHEEL +0 -0
  57. {agno-2.3.20.dist-info → agno-2.3.22.dist-info}/licenses/LICENSE +0 -0
  58. {agno-2.3.20.dist-info → agno-2.3.22.dist-info}/top_level.txt +0 -0
agno/workflow/remote.py CHANGED
@@ -24,21 +24,28 @@ class RemoteWorkflow(BaseRemote):
24
24
  base_url: str,
25
25
  workflow_id: str,
26
26
  timeout: float = 300.0,
27
+ protocol: Literal["agentos", "a2a"] = "agentos",
28
+ a2a_protocol: Literal["json-rpc", "rest"] = "rest",
27
29
  config_ttl: float = 300.0,
28
30
  ):
29
- """Initialize AgentOSRunner for local or remote execution.
31
+ """Initialize RemoteWorkflow for remote execution.
30
32
 
31
- For remote execution, provide base_url and workflow_id.
33
+ Supports two protocols:
34
+ - "agentos": Agno's proprietary AgentOS REST API (default)
35
+ - "a2a": A2A (Agent-to-Agent) protocol for cross-framework communication
32
36
 
33
37
  Args:
34
- base_url: Base URL for remote AgentOS instance (e.g., "http://localhost:7777")
35
- workflow_id: ID of remote workflow
38
+ base_url: Base URL for remote instance (e.g., "http://localhost:7777")
39
+ workflow_id: ID of remote workflow on the remote server
36
40
  timeout: Request timeout in seconds (default: 300)
41
+ protocol: Communication protocol - "agentos" (default) or "a2a"
42
+ a2a_protocol: For A2A protocol only - Whether to use JSON-RPC or REST protocol.
37
43
  config_ttl: Time-to-live for cached config in seconds (default: 300)
38
44
  """
39
- super().__init__(base_url, timeout, config_ttl)
45
+ super().__init__(base_url, timeout, protocol, a2a_protocol, config_ttl)
40
46
  self.workflow_id = workflow_id
41
47
  self._cached_workflow_config = None
48
+ self._config_ttl = config_ttl
42
49
 
43
50
  @property
44
51
  def id(self) -> str:
@@ -46,13 +53,38 @@ class RemoteWorkflow(BaseRemote):
46
53
 
47
54
  async def get_workflow_config(self) -> "WorkflowResponse":
48
55
  """Get the workflow config from remote (always fetches fresh)."""
49
- return await self.client.aget_workflow(self.workflow_id)
56
+ from agno.os.routers.workflows.schema import WorkflowResponse
57
+
58
+ if self.protocol == "a2a":
59
+ from agno.client.a2a.schemas import AgentCard
60
+
61
+ agent_card: Optional[AgentCard] = await self.a2a_client.aget_agent_card() # type: ignore
62
+
63
+ return WorkflowResponse(
64
+ id=self.workflow_id,
65
+ name=agent_card.name if agent_card else self.workflow_id,
66
+ description=agent_card.description if agent_card else f"A2A workflow: {self.workflow_id}",
67
+ )
68
+
69
+ # AgentOS protocol: fetch fresh config from remote
70
+ return await self.agentos_client.aget_workflow(self.workflow_id) # type: ignore
50
71
 
51
72
  @property
52
73
  def _workflow_config(self) -> "WorkflowResponse":
53
74
  """Get the workflow config from remote, cached with TTL."""
54
75
  from agno.os.routers.workflows.schema import WorkflowResponse
55
76
 
77
+ if self.protocol == "a2a":
78
+ from agno.client.a2a.schemas import AgentCard
79
+
80
+ agent_card: Optional[AgentCard] = self.a2a_client.get_agent_card() # type: ignore
81
+
82
+ return WorkflowResponse(
83
+ id=self.workflow_id,
84
+ name=agent_card.name if agent_card else self.workflow_id,
85
+ description=agent_card.description if agent_card else f"A2A workflow: {self.workflow_id}",
86
+ )
87
+
56
88
  current_time = time.time()
57
89
 
58
90
  # Check if cache is valid
@@ -62,15 +94,15 @@ class RemoteWorkflow(BaseRemote):
62
94
  return config
63
95
 
64
96
  # Fetch fresh config
65
- config: WorkflowResponse = self.client.get_workflow(self.workflow_id) # type: ignore
97
+ config: WorkflowResponse = self.agentos_client.get_workflow(self.workflow_id) # type: ignore
66
98
  self._cached_workflow_config = (config, current_time)
67
99
  return config
68
100
 
69
- def refresh_config(self) -> "WorkflowResponse":
101
+ async def refresh_config(self) -> "WorkflowResponse":
70
102
  """Force refresh the cached workflow config."""
71
103
  from agno.os.routers.workflows.schema import WorkflowResponse
72
104
 
73
- config: WorkflowResponse = self.client.get_workflow(self.workflow_id)
105
+ config: WorkflowResponse = await self.agentos_client.aget_workflow(self.workflow_id) # type: ignore
74
106
  self._cached_workflow_config = (config, time.time())
75
107
  return config
76
108
 
@@ -88,10 +120,15 @@ class RemoteWorkflow(BaseRemote):
88
120
 
89
121
  @property
90
122
  def db(self) -> Optional[RemoteDb]:
91
- if self._workflow_config is not None and self._workflow_config.db_id is not None:
123
+ if (
124
+ self.agentos_client
125
+ and self._config
126
+ and self._workflow_config is not None
127
+ and self._workflow_config.db_id is not None
128
+ ):
92
129
  return RemoteDb.from_config(
93
130
  db_id=self._workflow_config.db_id,
94
- client=self.client,
131
+ client=self.agentos_client,
95
132
  config=self._config,
96
133
  )
97
134
  return None
@@ -165,41 +202,144 @@ class RemoteWorkflow(BaseRemote):
165
202
  serialized_input = serialize_input(validated_input)
166
203
  headers = self._get_auth_headers(auth_token)
167
204
 
168
- if stream:
169
- # Handle streaming response
170
- return self.get_client().run_workflow_stream(
171
- workflow_id=self.workflow_id,
205
+ # A2A protocol path
206
+ if self.a2a_client:
207
+ return self._arun_a2a( # type: ignore[return-value]
172
208
  message=serialized_input,
173
- additional_data=additional_data,
174
- run_id=run_id,
175
- session_id=session_id,
209
+ stream=stream or False,
176
210
  user_id=user_id,
177
- audio=audio,
211
+ context_id=session_id, # Map session_id → context_id for A2A
178
212
  images=images,
179
213
  videos=videos,
214
+ audio=audio,
180
215
  files=files,
181
- session_state=session_state,
182
- stream_events=stream_events,
183
216
  headers=headers,
184
- **kwargs,
185
217
  )
218
+
219
+ # AgentOS protocol path (default)
220
+ if self.agentos_client:
221
+ if stream:
222
+ # Handle streaming response
223
+ return self.agentos_client.run_workflow_stream(
224
+ workflow_id=self.workflow_id,
225
+ message=serialized_input,
226
+ additional_data=additional_data,
227
+ run_id=run_id,
228
+ session_id=session_id,
229
+ user_id=user_id,
230
+ audio=audio,
231
+ images=images,
232
+ videos=videos,
233
+ files=files,
234
+ session_state=session_state,
235
+ stream_events=stream_events,
236
+ headers=headers,
237
+ **kwargs,
238
+ )
239
+ else:
240
+ return self.agentos_client.run_workflow( # type: ignore
241
+ workflow_id=self.workflow_id,
242
+ message=serialized_input,
243
+ additional_data=additional_data,
244
+ run_id=run_id,
245
+ session_id=session_id,
246
+ user_id=user_id,
247
+ audio=audio,
248
+ images=images,
249
+ videos=videos,
250
+ files=files,
251
+ session_state=session_state,
252
+ headers=headers,
253
+ **kwargs,
254
+ )
186
255
  else:
187
- return self.get_client().run_workflow( # type: ignore
188
- workflow_id=self.workflow_id,
189
- message=serialized_input,
190
- additional_data=additional_data,
191
- run_id=run_id,
192
- session_id=session_id,
256
+ raise ValueError("No client available")
257
+
258
+ def _arun_a2a(
259
+ self,
260
+ message: str,
261
+ stream: bool,
262
+ user_id: Optional[str],
263
+ context_id: Optional[str],
264
+ images: Optional[List[Image]],
265
+ videos: Optional[List[Video]],
266
+ audio: Optional[List[Audio]],
267
+ files: Optional[List[File]],
268
+ headers: Optional[Dict[str, str]],
269
+ ) -> Union[WorkflowRunOutput, AsyncIterator[WorkflowRunOutputEvent]]:
270
+ """Execute via A2A protocol.
271
+
272
+ Args:
273
+ message: Serialized message string
274
+ stream: Whether to stream the response
275
+ user_id: User identifier
276
+ context_id: Session/context ID (maps to session_id)
277
+ images: Images to include
278
+ videos: Videos to include
279
+ audio: Audio files to include
280
+ files: Files to include
281
+ headers: HTTP headers to include in the request (optional)
282
+ Returns:
283
+ WorkflowRunOutput for non-streaming, AsyncIterator[WorkflowRunOutputEvent] for streaming
284
+ """
285
+ if not self.a2a_client:
286
+ raise ValueError("A2A client not available")
287
+ from agno.client.a2a.utils import map_stream_events_to_workflow_run_events
288
+
289
+ if stream:
290
+ # Return async generator for streaming
291
+ event_stream = self.a2a_client.stream_message(
292
+ message=message,
293
+ context_id=context_id,
193
294
  user_id=user_id,
194
- audio=audio,
295
+ images=list(images) if images else None,
296
+ audio=list(audio) if audio else None,
297
+ videos=list(videos) if videos else None,
298
+ files=list(files) if files else None,
299
+ headers=headers,
300
+ )
301
+ return map_stream_events_to_workflow_run_events(event_stream, workflow_id=self.workflow_id) # type: ignore
302
+ else:
303
+ # Return coroutine for non-streaming
304
+ return self._arun_a2a_send( # type: ignore[return-value]
305
+ message=message,
306
+ user_id=user_id,
307
+ context_id=context_id,
195
308
  images=images,
309
+ audio=audio,
196
310
  videos=videos,
197
311
  files=files,
198
- session_state=session_state,
199
312
  headers=headers,
200
- **kwargs,
201
313
  )
202
314
 
315
+ async def _arun_a2a_send(
316
+ self,
317
+ message: str,
318
+ user_id: Optional[str],
319
+ context_id: Optional[str],
320
+ images: Optional[List[Image]],
321
+ videos: Optional[List[Video]],
322
+ audio: Optional[List[Audio]],
323
+ files: Optional[List[File]],
324
+ headers: Optional[Dict[str, str]],
325
+ ) -> WorkflowRunOutput:
326
+ """Send a non-streaming A2A message and convert response to WorkflowRunOutput."""
327
+ if not self.a2a_client:
328
+ raise ValueError("A2A client not available")
329
+ from agno.client.a2a.utils import map_task_result_to_workflow_run_output
330
+
331
+ task_result = await self.a2a_client.send_message(
332
+ message=message,
333
+ context_id=context_id,
334
+ user_id=user_id,
335
+ images=list(images) if images else None,
336
+ audio=list(audio) if audio else None,
337
+ videos=list(videos) if videos else None,
338
+ files=list(files) if files else None,
339
+ headers=headers,
340
+ )
341
+ return map_task_result_to_workflow_run_output(task_result, workflow_id=self.workflow_id, user_id=user_id)
342
+
203
343
  async def cancel_run(self, run_id: str, auth_token: Optional[str] = None) -> bool:
204
344
  """Cancel a running workflow execution.
205
345
 
@@ -212,7 +352,7 @@ class RemoteWorkflow(BaseRemote):
212
352
  """
213
353
  headers = self._get_auth_headers(auth_token)
214
354
  try:
215
- await self.get_client().cancel_workflow_run(
355
+ await self.get_os_client().cancel_workflow_run(
216
356
  workflow_id=self.workflow_id,
217
357
  run_id=run_id,
218
358
  headers=headers,
agno/workflow/router.py CHANGED
@@ -267,6 +267,7 @@ class Router:
267
267
  step_type=StepType.ROUTER,
268
268
  content=f"Router {self.name} completed with {len(all_results)} results",
269
269
  success=all(result.success for result in all_results) if all_results else True,
270
+ stop=any(result.stop for result in all_results) if all_results else False,
270
271
  steps=all_results,
271
272
  )
272
273
 
@@ -438,6 +439,7 @@ class Router:
438
439
  step_type=StepType.ROUTER,
439
440
  content=f"Router {self.name} completed with {len(all_results)} results",
440
441
  success=all(result.success for result in all_results) if all_results else True,
442
+ stop=any(result.stop for result in all_results) if all_results else False,
441
443
  steps=all_results,
442
444
  )
443
445
 
@@ -544,6 +546,7 @@ class Router:
544
546
  step_type=StepType.ROUTER,
545
547
  content=f"Router {self.name} completed with {len(all_results)} results",
546
548
  success=all(result.success for result in all_results) if all_results else True,
549
+ stop=any(result.stop for result in all_results) if all_results else False,
547
550
  steps=all_results,
548
551
  )
549
552
 
@@ -718,6 +721,6 @@ class Router:
718
721
  content=f"Router {self.name} completed with {len(all_results)} results",
719
722
  success=all(result.success for result in all_results) if all_results else True,
720
723
  error=None,
721
- stop=False,
724
+ stop=any(result.stop for result in all_results) if all_results else False,
722
725
  steps=all_results,
723
726
  )
agno/workflow/steps.py CHANGED
@@ -194,6 +194,7 @@ class Steps:
194
194
  step_type=StepType.STEPS,
195
195
  content=f"Steps {self.name} completed with {len(all_results)} results",
196
196
  success=all(result.success for result in all_results) if all_results else True,
197
+ stop=any(result.stop for result in all_results) if all_results else False,
197
198
  steps=all_results,
198
199
  )
199
200
 
@@ -351,6 +352,7 @@ class Steps:
351
352
  step_type=StepType.STEPS,
352
353
  content=f"Steps {self.name} completed with {len(all_results)} results",
353
354
  success=all(result.success for result in all_results) if all_results else True,
355
+ stop=any(result.stop for result in all_results) if all_results else False,
354
356
  steps=all_results,
355
357
  )
356
358
 
@@ -443,6 +445,7 @@ class Steps:
443
445
  step_type=StepType.STEPS,
444
446
  content=f"Steps {self.name} completed with {len(all_results)} results",
445
447
  success=all(result.success for result in all_results) if all_results else True,
448
+ stop=any(result.stop for result in all_results) if all_results else False,
446
449
  steps=all_results,
447
450
  )
448
451
 
@@ -599,6 +602,7 @@ class Steps:
599
602
  step_type=StepType.STEPS,
600
603
  content=f"Steps {self.name} completed with {len(all_results)} results",
601
604
  success=all(result.success for result in all_results) if all_results else True,
605
+ stop=any(result.stop for result in all_results) if all_results else False,
602
606
  steps=all_results,
603
607
  )
604
608
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agno
3
- Version: 2.3.20
3
+ Version: 2.3.22
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
@@ -157,7 +157,7 @@ Requires-Dist: mcp>=1.9.2; extra == "mcp"
157
157
  Provides-Extra: mem0
158
158
  Requires-Dist: mem0ai; extra == "mem0"
159
159
  Provides-Extra: memori
160
- Requires-Dist: memorisdk==3.0.5; extra == "memori"
160
+ Requires-Dist: memori>=3.0.5; extra == "memori"
161
161
  Provides-Extra: newspaper
162
162
  Requires-Dist: newspaper4k; extra == "newspaper"
163
163
  Requires-Dist: lxml_html_clean; extra == "newspaper"
@@ -415,7 +415,7 @@ Dynamic: license-file
415
415
  <div align="center">
416
416
  <a href="https://docs.agno.com">Documentation</a>
417
417
  <span>&nbsp;&nbsp;•&nbsp;&nbsp;</span>
418
- <a href="https://docs.agno.com/examples/use-cases/agents/overview">Examples</a>
418
+ <a href="https://github.com/agno-agi/agno/tree/main/cookbook">Cookbook</a>
419
419
  <span>&nbsp;&nbsp;•&nbsp;&nbsp;</span>
420
420
  <a href="https://www.agno.com/?utm_source=github&utm_medium=readme&utm_campaign=agno-github">Website</a>
421
421
  <br />
@@ -423,25 +423,26 @@ Dynamic: license-file
423
423
 
424
424
  ## What is Agno?
425
425
 
426
- Agno is an incredibly fast multi-agent framework, runtime and control plane.
426
+ Agno is a multi-agent framework, runtime, and control plane. Use it to build private and secure AI products that run in your cloud.
427
427
 
428
- Companies want to build AI products, run them securely in their cloud, and manage their agents with a beautiful UI. This takes more than calling an LLM API, it requires a thoughtfully designed agentic platform.
428
+ - **Build** agents, teams, and workflows with memory, knowledge, guardrails and 100+ integrations.
429
+ - **Run** in production with a stateless FastAPI runtime. Horizontally scalable.
430
+ - **Manage** with a control plane that connects directly to your runtime — no data leaves your environment.
429
431
 
430
- Agno provides the unified stack for building, running and managing multi-agent systems:
432
+ ## Why Agno?
431
433
 
432
- - **Framework**: Build agents, multi-agent teams and workflows with memory, knowledge, state, guardrails, HITL, context compression, MCP, A2A and 100+ toolkits.
433
- - **AgentOS Runtime**: Run your multi-agent system in production with a secure, stateless runtime and ready to use integration endpoints.
434
- - **AgentOS Control Plane**: Test, monitor and manage AgentOS deployments across environments with full operational visibility.
434
+ - **Your cloud, your data:** Runs entirely in your infrastructure. Nothing leaves your environment.
435
+ - **Ready for production on day one:** Pre-built FastAPI runtime with SSE endpoints, ready to deploy.
436
+ - **Incredibly fast:** 529× faster than LangGraph, 24× lower memory.
435
437
 
436
- Checkout the full list of features [here](#features).
438
+ ## Getting Started
437
439
 
438
- ## Getting started
440
+ Start with the [getting started guide](https://github.com/agno-agi/agno/tree/main/cookbook/00_getting_started), then:
439
441
 
440
- If you're new to Agno, follow our [quickstart](https://docs.agno.com/get-started/quickstart) to build your first Agent and chat with it using the AgentOS UI.
442
+ - Browse the [cookbooks](https://github.com/agno-agi/agno/tree/main/cookbook) for real-world examples
443
+ - Read the [docs](https://docs.agno.com) to learn more
441
444
 
442
- After that, checkout the [examples gallery](https://docs.agno.com/examples/use-cases/agents/overview) and build real-world applications with Agno.
443
-
444
- ## Documentation, Community & More Examples
445
+ ## Resources
445
446
 
446
447
  - Docs: <a href="https://docs.agno.com" target="_blank" rel="noopener noreferrer">docs.agno.com</a>
447
448
  - Cookbook: <a href="https://github.com/agno-agi/agno/tree/main/cookbook" target="_blank" rel="noopener noreferrer">Cookbook</a>
@@ -497,144 +498,72 @@ When you run the example script shared above, you get a FastAPI app that you can
497
498
 
498
499
  https://github.com/user-attachments/assets/feb23db8-15cc-4e88-be7c-01a21a03ebf6
499
500
 
500
- ## The Complete Agentic Solution
501
+ ## Private by Design
501
502
 
502
- Agno provides the complete solution for companies building agentic systems:
503
+ This is the part we care most about.
503
504
 
504
- - The fastest framework for building agents, multi-agent teams and agentic workflows.
505
- - A ready-to-use FastAPI app that gets you building AI products on day one.
506
- - A control plane for testing, monitoring and managing your system.
505
+ AgentOS runs in **your** cloud. The control plane UI connects directly to your runtime from your browser. Your data never touches our servers. No retention costs, no vendor lock-in, no compliance headaches.
507
506
 
508
- 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.
507
+ This isn't a privacy mode or enterprise add-on. It's how Agno works.
509
508
 
510
509
  ## Features
511
510
 
512
- Agno is an incredibly feature-rich framework purpose-built for Agent Engineering. Here are some key features:
513
-
514
- | **Category** | **Feature** | **Description** |
515
- | -------------------------------------- | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
516
- | **Foundational Principles** | **Model Agnostic** | Supports all model providers so you can choose the best model for your use case |
517
- | | **Type Safe** | Enforces structured I/O through input_schema and output_schema for predictable and composable agent behavior. |
518
- | | **Dynamic Context** | Inject variables, state, and retrieved data at runtime into context. Compress, summarize and filter context to keep your Agents focused and efficient. |
519
- | | **Designed for Scale** | Designed around async execution and long-running tasks for high throughput agent workloads. |
520
- | **Memory, Knowledge, and Persistence** | **Persistent Storage** | Give your Agents, Teams, and Workflows a database to persist session history, state, and messages. |
521
- | | **User Memory** | Built in memory layer that helps agents recall user specific context across sessions. |
522
- | | **Agentic RAG** | Connect to 20+ vector stores (called **Knowledge**) with hybrid search, reranking, and chunking out of the box. |
523
- | | **Culture** | Shared long term collective memory that compounds across agents and time. |
524
- | | **Ephemeral Context** | In memory scratchpad for short lived reasoning without polluting long term state. |
525
- | **Execution & Control** | **Human-in-the-Loop** | Native support for confirmations, approvals, manual overrides, and external actions. |
526
- | | **Guardrails** | Built-in safeguards for validation, security, and prompt protection. |
527
- | | **Agent Lifecycle Hooks** | Pre and post hooks to validate, enrich, or transform inputs and outputs. |
528
- | | **MCP Integration** | First-class support for the Model Context Protocol (MCP) to connect Agents with external systems. |
529
- | | **A2A Integration** | First-class support for the Agent to Agent communication protocol (A2A). |
530
- | | **Toolkits** | 100+ built in toolkits with thousands of tools covering data, code, web, and enterprise APIs. |
531
- | **Runtime & Evaluation** | **Runtime** | Prebuilt FastAPI runtime with SSE compatible endpoints. Production ready from day one. |
532
- | | **Control Plane (UI)** | Integrated interface to test, observe, and debug your agents, teams, and workflows in real time. |
533
- | | **Natively Multimodal** | Agents can process and generate text, images, audio, video, and files. |
534
- | | **Evals** | Measure Accuracy, Performance, Latency, and Reliability across agents and workflows. |
535
- | | **Durable Execution** | Built in support for long running, resumable workflows. |
536
- | **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. |
537
- | | **Data Governance** | Your data lives securely in your Agent database, no external data sharing or vendor lock-in. |
538
- | | **Access Control** | Role-based access (RBAC) and per-agent permissions to protect sensitive contexts and tools. |
539
-
540
- Every part of Agno is built for real-world deployment — where developer experience meets production performance.
541
-
542
- ## Setup Your Coding Agent to Use Agno
543
-
544
- For LLMs and AI assistants to understand and navigate Agno's documentation, we provide an [llms.txt](https://docs.agno.com/llms.txt) or [llms-full.txt](https://docs.agno.com/llms-full.txt) file. This file is built for AI systems to efficiently parse and reference our documentation.
545
-
546
- ### IDE Integration
547
-
548
- When building Agno agents, using Agno documentation as a source in your IDE is a great way to speed up your development. Here's how to integrate with Cursor:
549
-
550
- 1. In Cursor, go to the "Cursor Settings" menu.
551
- 2. Find the "Indexing & Docs" section.
552
- 3. Add `https://docs.agno.com/llms-full.txt` to the list of documentation URLs.
553
- 4. Save the changes.
554
-
555
- Now, Cursor will have access to the Agno documentation. You can do the same with other IDEs like VSCode, Windsurf etc.
511
+ ### Core:
512
+ - Model agnostic — works with OpenAI, Anthropic, Google, local models, whatever
513
+ - Type-safe I/O with `input_schema` and `output_schema`
514
+ - Async-first, built for long-running tasks
515
+ - Natively multimodal (text, images, audio, video, files)
516
+
517
+ ### Memory & Knowledge:
518
+ - Persistent storage for session history and state
519
+ - User memory that persists across sessions
520
+ - Agentic RAG with 20+ vector stores, hybrid search, reranking
521
+ - Culture shared long-term memory across agents
522
+
523
+ ### Execution:
524
+ - Human-in-the-loop (confirmations, approvals, overrides)
525
+ - Guardrails for validation and security
526
+ - Pre/post hooks for the agent lifecycle
527
+ - First-class MCP and A2A support
528
+ - 100+ built-in toolkits
529
+
530
+ ### Production:
531
+ - Ready-to-use FastAPI runtime
532
+ - Integrated control plane UI
533
+ - Evals for accuracy, performance, latency
534
+ - Durable execution for resumable workflows
535
+ - RBAC and per-agent permissions
556
536
 
557
537
  ## Performance
558
538
 
559
- If you're building with Agno, you're guaranteed best-in-class performance by default. Our obsession with performance is necessary because even simple AI workflows can spawn hundreds of Agents and because many tasks are long-running -- stateless, horizontal scalability is key for success.
560
-
561
- At Agno, we optimize performance across 3 dimensions:
562
-
563
- 1. **Agent performance:** We optimize static operations (instantiation, memory footprint) and runtime operations (tool calls, memory updates, history management).
564
- 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.
565
- 3. **Agent reliability and accuracy:** Monitored through evals, which we'll explore later.
566
-
567
- ### Agent Performance
568
-
569
- Let's measure the time it takes to instantiate an Agent and the memory footprint of an Agent. Here are the numbers (last measured in Oct 2025, on an Apple M4 MacBook Pro):
570
-
571
- - **Agent instantiation:** ~3μs on average
572
- - **Memory footprint:** ~6.6Kib on average
573
-
574
- We'll show below that Agno Agents instantiate **529× faster than Langgraph**, **57× faster than PydanticAI**, and **70× faster than CrewAI**. Agno Agents also use **24× lower memory than Langgraph**, **4× lower than PydanticAI**, and **10× lower than CrewAI**.
575
-
576
- > [!NOTE]
577
- > Run time performance is bottlenecked by inference and hard to benchmark accurately, so we focus on minimizing overhead, reducing memory usage, and parallelizing tool calls.
578
-
579
- ### Instantiation Time
539
+ We're obsessive about performance because agent workloads spawn hundreds of instances and run long tasks. Stateless, horizontal scalability isn't optional.
580
540
 
581
- Let's measure instantiation time for an Agent with 1 tool. We'll run the evaluation 1000 times to get a baseline measurement. We'll compare Agno to LangGraph, CrewAI and Pydantic AI.
541
+ **Benchmarks** (Apple M4 MacBook Pro, Oct 2025):
582
542
 
583
- > [!NOTE]
584
- > The code for this benchmark is available [here](https://github.com/agno-agi/agno/tree/main/cookbook/evals/performance). You should run the evaluation yourself on your own machine, please, do not take these results at face value.
543
+ | Metric | Agno | LangGraph | PydanticAI | CrewAI |
544
+ |--------|------|-----------|------------|--------|
545
+ | Instantiation | **3μs** | 1,587μs (529× slower) | 170μs (57× slower) | 210μs (70× slower) |
546
+ | Memory | **6.6 KiB** | 161 KiB (24× higher) | 29 KiB (4× higher) | 66 KiB (10× higher) |
585
547
 
586
- ```shell
587
- # Setup virtual environment
588
- ./scripts/perf_setup.sh
589
- source .venvs/perfenv/bin/activate
590
-
591
- # Agno
592
- python cookbook/evals/performance/instantiate_agent_with_tool.py
593
-
594
- # LangGraph
595
- python cookbook/evals/performance/comparison/langgraph_instantiation.py
596
- # CrewAI
597
- python cookbook/evals/performance/comparison/crewai_instantiation.py
598
- # Pydantic AI
599
- python cookbook/evals/performance/comparison/pydantic_ai_instantiation.py
600
- ```
601
-
602
- LangGraph is on the right, **let's start it first and give it a head start**. Then CrewAI and Pydantic AI follow, and finally Agno. Agno obviously finishes first, but let's see by how much.
548
+ Run the benchmarks yourself: [`cookbook/12_evals/performance`](https://github.com/agno-agi/agno/tree/main/cookbook/12_evals/performance)
603
549
 
604
550
  https://github.com/user-attachments/assets/54b98576-1859-4880-9f2d-15e1a426719d
605
551
 
606
- ### Memory Usage
607
-
608
- To measure memory usage, we use the `tracemalloc` library. We first calculate a baseline memory usage by running an empty function, then run the Agent 1000x times and calculate the difference. This gives a (reasonably) isolated measurement of the memory usage of the Agent.
609
-
610
- We recommend running the evaluation yourself on your own machine, and digging into the code to see how it works. If we've made a mistake, please let us know.
611
-
612
- ### Results
613
-
614
- Taking Agno as the baseline, we can see that:
615
-
616
- | Metric | Agno | Langgraph | PydanticAI | CrewAI |
617
- | ------------------ | ---- | ----------- | ---------- | ---------- |
618
- | **Time (seconds)** | 1× | 529× slower | 57× slower | 70× slower |
619
- | **Memory (MiB)** | 1× | 24× higher | 4× higher | 10× higher |
552
+ ## IDE Integration
620
553
 
621
- Exact numbers from the benchmark:
554
+ For AI-assisted development, add our docs to your IDE:
622
555
 
623
- | Metric | Agno | Langgraph | PydanticAI | CrewAI |
624
- | ------------------ | -------- | --------- | ---------- | -------- |
625
- | **Time (seconds)** | 0.000003 | 0.001587 | 0.000170 | 0.000210 |
626
- | **Memory (MiB)** | 0.006642 | 0.161435 | 0.028712 | 0.065652 |
556
+ **Cursor:** Settings Indexing & Docs Add `https://docs.agno.com/llms-full.txt`
627
557
 
628
- > [!NOTE]
629
- > Agno agents are designed for performance and while we share benchmarks against other frameworks, we should be mindful that accuracy and reliability are more important than speed.
558
+ Works with VSCode, Windsurf, and other AI-enabled editors too.
630
559
 
631
- ## Contributions
560
+ ## Contributing
632
561
 
633
- We welcome contributions, read our [contributing guide](https://github.com/agno-agi/agno/blob/v2.0/CONTRIBUTING.md) to get started.
562
+ We welcome contributions. See the [contributing guide](https://github.com/agno-agi/agno/blob/v2.0/CONTRIBUTING.md).
634
563
 
635
564
  ## Telemetry
636
565
 
637
- Agno logs which model an agent used so we can prioritize updates to the most popular providers. You can disable this by setting `AGNO_TELEMETRY=false` in your environment.
566
+ Agno logs which model providers are used so we can prioritize updates. Disable with `AGNO_TELEMETRY=false`.
638
567
 
639
568
  <p align="left">
640
569
  <a href="#top">⬆️ Back to Top</a>