agno 2.0.0rc1__py3-none-any.whl → 2.0.0rc2__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 (49) hide show
  1. agno/agent/agent.py +32 -14
  2. agno/db/mongo/mongo.py +8 -3
  3. agno/eval/accuracy.py +12 -5
  4. agno/knowledge/chunking/strategy.py +14 -14
  5. agno/knowledge/knowledge.py +156 -120
  6. agno/knowledge/reader/arxiv_reader.py +5 -5
  7. agno/knowledge/reader/csv_reader.py +6 -77
  8. agno/knowledge/reader/docx_reader.py +5 -5
  9. agno/knowledge/reader/firecrawl_reader.py +5 -5
  10. agno/knowledge/reader/json_reader.py +5 -5
  11. agno/knowledge/reader/markdown_reader.py +31 -9
  12. agno/knowledge/reader/pdf_reader.py +10 -123
  13. agno/knowledge/reader/reader_factory.py +65 -72
  14. agno/knowledge/reader/s3_reader.py +44 -114
  15. agno/knowledge/reader/text_reader.py +5 -5
  16. agno/knowledge/reader/url_reader.py +75 -31
  17. agno/knowledge/reader/web_search_reader.py +6 -29
  18. agno/knowledge/reader/website_reader.py +5 -5
  19. agno/knowledge/reader/wikipedia_reader.py +5 -5
  20. agno/knowledge/reader/youtube_reader.py +6 -6
  21. agno/knowledge/utils.py +10 -10
  22. agno/models/aws/bedrock.py +3 -7
  23. agno/models/base.py +37 -6
  24. agno/os/app.py +32 -24
  25. agno/os/mcp.py +39 -59
  26. agno/os/router.py +547 -16
  27. agno/os/routers/evals/evals.py +197 -12
  28. agno/os/routers/knowledge/knowledge.py +428 -14
  29. agno/os/routers/memory/memory.py +250 -28
  30. agno/os/routers/metrics/metrics.py +125 -7
  31. agno/os/routers/session/session.py +393 -25
  32. agno/os/schema.py +55 -2
  33. agno/run/agent.py +9 -0
  34. agno/run/team.py +93 -2
  35. agno/run/workflow.py +25 -12
  36. agno/team/team.py +861 -1051
  37. agno/tools/mcp.py +1 -2
  38. agno/utils/log.py +52 -2
  39. agno/utils/mcp.py +55 -3
  40. agno/utils/models/claude.py +0 -8
  41. agno/utils/print_response/team.py +177 -73
  42. agno/utils/streamlit.py +27 -0
  43. agno/workflow/workflow.py +9 -0
  44. {agno-2.0.0rc1.dist-info → agno-2.0.0rc2.dist-info}/METADATA +1 -1
  45. {agno-2.0.0rc1.dist-info → agno-2.0.0rc2.dist-info}/RECORD +48 -49
  46. agno/knowledge/reader/gcs_reader.py +0 -67
  47. {agno-2.0.0rc1.dist-info → agno-2.0.0rc2.dist-info}/WHEEL +0 -0
  48. {agno-2.0.0rc1.dist-info → agno-2.0.0rc2.dist-info}/licenses/LICENSE +0 -0
  49. {agno-2.0.0rc1.dist-info → agno-2.0.0rc2.dist-info}/top_level.txt +0 -0
agno/os/app.py CHANGED
@@ -83,7 +83,12 @@ class AgentOS:
83
83
  self.interfaces = interfaces or []
84
84
 
85
85
  self.settings: AgnoAPISettings = settings or AgnoAPISettings()
86
- self.fastapi_app: Optional[FastAPI] = fastapi_app
86
+
87
+ self._app_set = False
88
+ self.fastapi_app: Optional[FastAPI] = None
89
+ if fastapi_app:
90
+ self.fastapi_app = fastapi_app
91
+ self._app_set = True
87
92
 
88
93
  self.interfaces = interfaces or []
89
94
 
@@ -213,33 +218,35 @@ class AgentOS:
213
218
  if self.enable_mcp and self.mcp_app:
214
219
  self.fastapi_app.mount("/", self.mcp_app)
215
220
 
216
- # Add middleware
217
- @self.fastapi_app.exception_handler(HTTPException)
218
- async def http_exception_handler(request: Request, exc: HTTPException) -> JSONResponse:
219
- return JSONResponse(
220
- status_code=exc.status_code,
221
- content={"detail": str(exc.detail)},
222
- )
221
+ # Add middleware (only if app is not set)
222
+ if not self._app_set:
223
223
 
224
- async def general_exception_handler(request: Request, call_next):
225
- try:
226
- return await call_next(request)
227
- except Exception as e:
224
+ @self.fastapi_app.exception_handler(HTTPException)
225
+ async def http_exception_handler(request: Request, exc: HTTPException) -> JSONResponse:
228
226
  return JSONResponse(
229
- status_code=e.status_code if hasattr(e, "status_code") else 500, # type: ignore
230
- content={"detail": str(e)},
227
+ status_code=exc.status_code,
228
+ content={"detail": str(exc.detail)},
231
229
  )
232
230
 
233
- self.fastapi_app.middleware("http")(general_exception_handler)
231
+ async def general_exception_handler(request: Request, call_next):
232
+ try:
233
+ return await call_next(request)
234
+ except Exception as e:
235
+ return JSONResponse(
236
+ status_code=e.status_code if hasattr(e, "status_code") else 500, # type: ignore
237
+ content={"detail": str(e)},
238
+ )
239
+
240
+ self.fastapi_app.middleware("http")(general_exception_handler)
234
241
 
235
- self.fastapi_app.add_middleware(
236
- CORSMiddleware,
237
- allow_origins=self.settings.cors_origin_list, # type: ignore
238
- allow_credentials=True,
239
- allow_methods=["*"],
240
- allow_headers=["*"],
241
- expose_headers=["*"],
242
- )
242
+ self.fastapi_app.add_middleware(
243
+ CORSMiddleware,
244
+ allow_origins=self.settings.cors_origin_list, # type: ignore
245
+ allow_credentials=True,
246
+ allow_methods=["*"],
247
+ allow_headers=["*"],
248
+ expose_headers=["*"],
249
+ )
243
250
 
244
251
  return self.fastapi_app
245
252
 
@@ -458,6 +465,7 @@ class AgentOS:
458
465
  host: str = "localhost",
459
466
  port: int = 7777,
460
467
  reload: bool = False,
468
+ workers: Optional[int] = None,
461
469
  **kwargs,
462
470
  ):
463
471
  import uvicorn
@@ -486,4 +494,4 @@ class AgentOS:
486
494
  )
487
495
  )
488
496
 
489
- uvicorn.run(app=app, host=host, port=port, reload=reload, **kwargs)
497
+ uvicorn.run(app=app, host=host, port=port, reload=reload, workers=workers, **kwargs)
agno/os/mcp.py CHANGED
@@ -25,7 +25,6 @@ from agno.os.schema import (
25
25
  from agno.os.utils import (
26
26
  get_agent_by_id,
27
27
  get_db,
28
- get_knowledge_instance_by_db_id,
29
28
  get_team_by_id,
30
29
  get_workflow_by_id,
31
30
  )
@@ -50,7 +49,7 @@ def get_mcp_server(
50
49
  @mcp.tool(
51
50
  name="get_agentos_config",
52
51
  description="Get the configuration of the AgentOS",
53
- tags=["core"],
52
+ tags={"core"},
54
53
  output_schema=ConfigResponse.model_json_schema(),
55
54
  ) # type: ignore
56
55
  async def config() -> ConfigResponse:
@@ -74,21 +73,21 @@ def get_mcp_server(
74
73
  ],
75
74
  )
76
75
 
77
- @mcp.tool(name="run_agent", description="Run an agent", tags=["core"]) # type: ignore
76
+ @mcp.tool(name="run_agent", description="Run an agent", tags={"core"}) # type: ignore
78
77
  async def run_agent(agent_id: str, message: str) -> RunOutput:
79
78
  agent = get_agent_by_id(agent_id, os.agents)
80
79
  if agent is None:
81
80
  raise Exception(f"Agent {agent_id} not found")
82
81
  return agent.run(message)
83
82
 
84
- @mcp.tool(name="run_team", description="Run a team", tags=["core"]) # type: ignore
83
+ @mcp.tool(name="run_team", description="Run a team", tags={"core"}) # type: ignore
85
84
  async def run_team(team_id: str, message: str) -> TeamRunOutput:
86
85
  team = get_team_by_id(team_id, os.teams)
87
86
  if team is None:
88
87
  raise Exception(f"Team {team_id} not found")
89
88
  return team.run(message)
90
89
 
91
- @mcp.tool(name="run_workflow", description="Run a workflow", tags=["core"]) # type: ignore
90
+ @mcp.tool(name="run_workflow", description="Run a workflow", tags={"core"}) # type: ignore
92
91
  async def run_workflow(workflow_id: str, message: str) -> WorkflowRunOutput:
93
92
  workflow = get_workflow_by_id(workflow_id, os.workflows)
94
93
  if workflow is None:
@@ -96,7 +95,7 @@ def get_mcp_server(
96
95
  return workflow.run(message)
97
96
 
98
97
  # Session Management Tools
99
- @mcp.tool(name="get_sessions_for_agent", description="Get list of sessions for an agent", tags=["session"]) # type: ignore
98
+ @mcp.tool(name="get_sessions_for_agent", description="Get list of sessions for an agent", tags={"session"}) # type: ignore
100
99
  async def get_sessions_for_agent(
101
100
  agent_id: str,
102
101
  db_id: str,
@@ -105,7 +104,7 @@ def get_mcp_server(
105
104
  sort_order: str = "desc",
106
105
  ):
107
106
  db = get_db(os.dbs, db_id)
108
- sessions = db.get_sessions(
107
+ sessions, _ = db.get_sessions(
109
108
  session_type=SessionType.AGENT,
110
109
  component_id=agent_id,
111
110
  user_id=user_id,
@@ -118,7 +117,7 @@ def get_mcp_server(
118
117
  "data": [SessionSchema.from_dict(session) for session in sessions], # type: ignore
119
118
  }
120
119
 
121
- @mcp.tool(name="get_sessions_for_team", description="Get list of sessions for a team", tags=["session"]) # type: ignore
120
+ @mcp.tool(name="get_sessions_for_team", description="Get list of sessions for a team", tags={"session"}) # type: ignore
122
121
  async def get_sessions_for_team(
123
122
  team_id: str,
124
123
  db_id: str,
@@ -127,7 +126,7 @@ def get_mcp_server(
127
126
  sort_order: str = "desc",
128
127
  ):
129
128
  db = get_db(os.dbs, db_id)
130
- sessions = db.get_sessions(
129
+ sessions, _ = db.get_sessions(
131
130
  session_type=SessionType.TEAM,
132
131
  component_id=team_id,
133
132
  user_id=user_id,
@@ -137,11 +136,33 @@ def get_mcp_server(
137
136
  )
138
137
 
139
138
  return {
140
- "data": sessions, # type: ignore
139
+ "data": [SessionSchema.from_dict(session) for session in sessions], # type: ignore
140
+ }
141
+
142
+ @mcp.tool(name="get_sessions_for_workflow", description="Get list of sessions for a workflow", tags={"session"}) # type: ignore
143
+ async def get_sessions_for_workflow(
144
+ workflow_id: str,
145
+ db_id: str,
146
+ user_id: Optional[str] = None,
147
+ sort_by: str = "created_at",
148
+ sort_order: str = "desc",
149
+ ):
150
+ db = get_db(os.dbs, db_id)
151
+ sessions, _ = db.get_sessions(
152
+ session_type=SessionType.WORKFLOW,
153
+ component_id=workflow_id,
154
+ user_id=user_id,
155
+ sort_by=sort_by,
156
+ sort_order=sort_order,
157
+ deserialize=False,
158
+ )
159
+
160
+ return {
161
+ "data": [SessionSchema.from_dict(session) for session in sessions], # type: ignore
141
162
  }
142
163
 
143
164
  # Memory Management Tools
144
- @mcp.tool(name="create_memory", description="Create a new user memory", tags=["memory"]) # type: ignore
165
+ @mcp.tool(name="create_memory", description="Create a new user memory", tags={"memory"}) # type: ignore
145
166
  async def create_memory(
146
167
  db_id: str,
147
168
  memory: str,
@@ -161,27 +182,27 @@ def get_mcp_server(
161
182
  if not user_memory:
162
183
  raise Exception("Failed to create memory")
163
184
 
164
- return UserMemorySchema.from_dict(user_memory.to_dict()) # type: ignore
185
+ return UserMemorySchema.from_dict(user_memory) # type: ignore
165
186
 
166
- @mcp.tool(name="get_memories_for_user", description="Get a list of memories for a user", tags=["memory"]) # type: ignore
167
- async def get_memories(
187
+ @mcp.tool(name="get_memories_for_user", description="Get a list of memories for a user", tags={"memory"}) # type: ignore
188
+ async def get_memories_for_user(
168
189
  user_id: str,
169
190
  sort_by: str = "updated_at",
170
191
  sort_order: str = "desc",
171
192
  db_id: Optional[str] = None,
172
193
  ):
173
194
  db = get_db(os.dbs, db_id)
174
- user_memories = db.get_user_memories(
195
+ user_memories, _ = db.get_user_memories(
175
196
  user_id=user_id,
176
197
  sort_by=sort_by,
177
198
  sort_order=sort_order,
178
199
  deserialize=False,
179
200
  )
180
201
  return {
181
- "data": user_memories, # type: ignore
202
+ "data": [UserMemorySchema.from_dict(user_memory) for user_memory in user_memories], # type: ignore
182
203
  }
183
204
 
184
- @mcp.tool(name="update_memory", description="Update a memory", tags=["memory"]) # type: ignore
205
+ @mcp.tool(name="update_memory", description="Update a memory", tags={"memory"}) # type: ignore
185
206
  async def update_memory(
186
207
  db_id: str,
187
208
  memory_id: str,
@@ -202,7 +223,7 @@ def get_mcp_server(
202
223
 
203
224
  return UserMemorySchema.from_dict(user_memory) # type: ignore
204
225
 
205
- @mcp.tool(name="delete_memory", description="Delete a memory by ID", tags=["memory"]) # type: ignore
226
+ @mcp.tool(name="delete_memory", description="Delete a memory by ID", tags={"memory"}) # type: ignore
206
227
  async def delete_memory(
207
228
  db_id: str,
208
229
  memory_id: str,
@@ -210,46 +231,5 @@ def get_mcp_server(
210
231
  db = get_db(os.dbs, db_id)
211
232
  db.delete_user_memory(memory_id=memory_id)
212
233
 
213
- # Knowledge Management Tools
214
- @mcp.tool(name="get_content", description="Get paginated list of knowledge content", tags=["knowledge"]) # type: ignore
215
- async def get_content(
216
- sort_by: str = "created_at",
217
- sort_order: str = "desc",
218
- db_id: Optional[str] = None,
219
- ):
220
- knowledge = get_knowledge_instance_by_db_id(
221
- os.knowledge_instances if hasattr(os, "knowledge_instances") else [], db_id
222
- )
223
- contents, count = knowledge.get_content(sort_by=sort_by, sort_order=sort_order)
224
-
225
- return {
226
- "data": [
227
- {
228
- "id": content.id,
229
- "name": content.name,
230
- "description": content.description,
231
- "file_type": content.file_type,
232
- "size": content.size,
233
- "metadata": content.metadata,
234
- "status": content.status,
235
- "status_message": content.status_message,
236
- "created_at": content.created_at,
237
- "updated_at": content.updated_at,
238
- }
239
- for content in contents
240
- ]
241
- }
242
-
243
- @mcp.tool(name="delete_content_by_id", description="Delete knowledge content by ID", tags=["knowledge"]) # type: ignore
244
- async def delete_content_by_id(
245
- content_id: str,
246
- db_id: str,
247
- ) -> str:
248
- knowledge = get_knowledge_instance_by_db_id(
249
- os.knowledge_instances if hasattr(os, "knowledge_instances") else [], db_id
250
- )
251
- knowledge.remove_content_by_id(content_id=content_id)
252
- return "Successfully deleted content"
253
-
254
234
  mcp_app = mcp.http_app(path="/mcp")
255
235
  return mcp_app