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
@@ -7,7 +7,10 @@ from agno.db.base import BaseDb, SessionType
7
7
  from agno.os.auth import get_authentication_dependency
8
8
  from agno.os.schema import (
9
9
  AgentSessionDetailSchema,
10
+ BadRequestResponse,
10
11
  DeleteSessionRequest,
12
+ InternalServerErrorResponse,
13
+ NotFoundResponse,
11
14
  PaginatedResponse,
12
15
  PaginationInfo,
13
16
  RunSchema,
@@ -15,6 +18,8 @@ from agno.os.schema import (
15
18
  SortOrder,
16
19
  TeamRunSchema,
17
20
  TeamSessionDetailSchema,
21
+ UnauthenticatedResponse,
22
+ ValidationErrorResponse,
18
23
  WorkflowRunSchema,
19
24
  WorkflowSessionDetailSchema,
20
25
  )
@@ -25,24 +30,77 @@ logger = logging.getLogger(__name__)
25
30
 
26
31
 
27
32
  def get_session_router(dbs: dict[str, BaseDb], settings: AgnoAPISettings = AgnoAPISettings()) -> APIRouter:
28
- session_router = APIRouter(dependencies=[Depends(get_authentication_dependency(settings))], tags=["Sessions"])
33
+ """Create session router with comprehensive OpenAPI documentation for session management endpoints."""
34
+ session_router = APIRouter(
35
+ dependencies=[Depends(get_authentication_dependency(settings))],
36
+ tags=["Sessions"],
37
+ responses={
38
+ 400: {"description": "Bad Request", "model": BadRequestResponse},
39
+ 401: {"description": "Unauthorized", "model": UnauthenticatedResponse},
40
+ 404: {"description": "Not Found", "model": NotFoundResponse},
41
+ 422: {"description": "Validation Error", "model": ValidationErrorResponse},
42
+ 500: {"description": "Internal Server Error", "model": InternalServerErrorResponse},
43
+ },
44
+ )
29
45
  return attach_routes(router=session_router, dbs=dbs)
30
46
 
31
47
 
32
48
  def attach_routes(router: APIRouter, dbs: dict[str, BaseDb]) -> APIRouter:
33
49
  @router.get(
34
- "/sessions", response_model=PaginatedResponse[SessionSchema], status_code=200, operation_id="get_sessions"
50
+ "/sessions",
51
+ response_model=PaginatedResponse[SessionSchema],
52
+ status_code=200,
53
+ operation_id="get_sessions",
54
+ summary="List Sessions",
55
+ description=(
56
+ "Retrieve paginated list of sessions with filtering and sorting options. "
57
+ "Supports filtering by session type (agent, team, workflow), component, user, and name. "
58
+ "Sessions represent conversation histories and execution contexts."
59
+ ),
60
+ responses={
61
+ 200: {
62
+ "description": "Sessions retrieved successfully",
63
+ "content": {
64
+ "application/json": {
65
+ "example": {
66
+ "session_example": {
67
+ "summary": "Example session response",
68
+ "value": {
69
+ "data": [
70
+ {
71
+ "session_id": "6f6cfbfd-9643-479a-ae47-b8f32eb4d710",
72
+ "session_name": "What tools do you have?",
73
+ "session_state": {},
74
+ "created_at": "2025-09-05T16:02:09Z",
75
+ "updated_at": "2025-09-05T16:02:09Z",
76
+ }
77
+ ]
78
+ },
79
+ }
80
+ }
81
+ }
82
+ },
83
+ },
84
+ 400: {"description": "Invalid session type or filter parameters", "model": BadRequestResponse},
85
+ 422: {"description": "Validation error in query parameters", "model": ValidationErrorResponse},
86
+ },
35
87
  )
36
88
  async def get_sessions(
37
- session_type: SessionType = Query(default=SessionType.AGENT, alias="type"),
38
- component_id: Optional[str] = Query(default=None, description="Filter sessions by component ID"),
89
+ session_type: SessionType = Query(
90
+ default=SessionType.AGENT,
91
+ alias="type",
92
+ description="Type of sessions to retrieve (agent, team, or workflow)",
93
+ ),
94
+ component_id: Optional[str] = Query(
95
+ default=None, description="Filter sessions by component ID (agent/team/workflow ID)"
96
+ ),
39
97
  user_id: Optional[str] = Query(default=None, description="Filter sessions by user ID"),
40
- session_name: Optional[str] = Query(default=None, description="Filter sessions by name"),
41
- limit: Optional[int] = Query(default=20, description="Number of sessions to return"),
42
- page: Optional[int] = Query(default=1, description="Page number"),
43
- sort_by: Optional[str] = Query(default="created_at", description="Field to sort by"),
98
+ session_name: Optional[str] = Query(default=None, description="Filter sessions by name (partial match)"),
99
+ limit: Optional[int] = Query(default=20, description="Number of sessions to return per page"),
100
+ page: Optional[int] = Query(default=1, description="Page number for pagination"),
101
+ sort_by: Optional[str] = Query(default="created_at", description="Field to sort sessions by"),
44
102
  sort_order: Optional[SortOrder] = Query(default="desc", description="Sort order (asc or desc)"),
45
- db_id: Optional[str] = Query(default=None, description="The ID of the database to use"),
103
+ db_id: Optional[str] = Query(default=None, description="Database ID to query sessions from"),
46
104
  ) -> PaginatedResponse[SessionSchema]:
47
105
  db = get_db(dbs, db_id)
48
106
  sessions, total_count = db.get_sessions(
@@ -72,11 +130,94 @@ def attach_routes(router: APIRouter, dbs: dict[str, BaseDb]) -> APIRouter:
72
130
  response_model=Union[AgentSessionDetailSchema, TeamSessionDetailSchema, WorkflowSessionDetailSchema],
73
131
  status_code=200,
74
132
  operation_id="get_session_by_id",
133
+ summary="Get Session by ID",
134
+ description=(
135
+ "Retrieve detailed information about a specific session including metadata, configuration, "
136
+ "and run history. Response schema varies based on session type (agent, team, or workflow)."
137
+ ),
138
+ responses={
139
+ 200: {
140
+ "description": "Session details retrieved successfully",
141
+ "content": {
142
+ "application/json": {
143
+ "examples": {
144
+ "agent_session_example": {
145
+ "summary": "Example agent session response",
146
+ "value": {
147
+ "user_id": "123",
148
+ "agent_session_id": "6f6cfbfd-9643-479a-ae47-b8f32eb4d710",
149
+ "session_id": "6f6cfbfd-9643-479a-ae47-b8f32eb4d710",
150
+ "session_name": "What tools do you have?",
151
+ "session_summary": {
152
+ "summary": "The user and assistant engaged in a conversation about the tools the agent has available.",
153
+ "updated_at": "2025-09-05T18:02:12.269392",
154
+ },
155
+ "session_state": {},
156
+ "agent_id": "basic-agent",
157
+ "total_tokens": 160,
158
+ "agent_data": {
159
+ "name": "Basic Agent",
160
+ "agent_id": "basic-agent",
161
+ "model": {"provider": "OpenAI", "name": "OpenAIChat", "id": "gpt-4o"},
162
+ },
163
+ "metrics": {
164
+ "input_tokens": 134,
165
+ "output_tokens": 26,
166
+ "total_tokens": 160,
167
+ "audio_input_tokens": 0,
168
+ "audio_output_tokens": 0,
169
+ "audio_total_tokens": 0,
170
+ "cache_read_tokens": 0,
171
+ "cache_write_tokens": 0,
172
+ "reasoning_tokens": 0,
173
+ "timer": None,
174
+ "time_to_first_token": None,
175
+ "duration": None,
176
+ "provider_metrics": None,
177
+ "additional_metrics": None,
178
+ },
179
+ "chat_history": [
180
+ {
181
+ "content": "<additional_information>\n- Use markdown to format your answers.\n- The current time is 2025-09-05 18:02:09.171627.\n</additional_information>\n\nYou have access to memories from previous interactions with the user that you can use:\n\n<memories_from_previous_interactions>\n- User really likes Digimon and Japan.\n- User really likes Japan.\n- User likes coffee.\n</memories_from_previous_interactions>\n\nNote: this information is from previous interactions and may be updated in this conversation. You should always prefer information from this conversation over the past memories.",
182
+ "from_history": False,
183
+ "stop_after_tool_call": False,
184
+ "role": "system",
185
+ "created_at": 1757088129,
186
+ },
187
+ {
188
+ "content": "What tools do you have?",
189
+ "from_history": False,
190
+ "stop_after_tool_call": False,
191
+ "role": "user",
192
+ "created_at": 1757088129,
193
+ },
194
+ {
195
+ "content": "I don't have access to external tools or the internet. However, I can assist you with a wide range of topics by providing information, answering questions, and offering suggestions based on the knowledge I've been trained on. If there's anything specific you need help with, feel free to ask!",
196
+ "from_history": False,
197
+ "stop_after_tool_call": False,
198
+ "role": "assistant",
199
+ "metrics": {"input_tokens": 134, "output_tokens": 26, "total_tokens": 160},
200
+ "created_at": 1757088129,
201
+ },
202
+ ],
203
+ "created_at": "2025-09-05T16:02:09Z",
204
+ "updated_at": "2025-09-05T16:02:09Z",
205
+ },
206
+ }
207
+ }
208
+ }
209
+ },
210
+ },
211
+ 404: {"description": "Session not found", "model": NotFoundResponse},
212
+ 422: {"description": "Invalid session type", "model": ValidationErrorResponse},
213
+ },
75
214
  )
76
215
  async def get_session_by_id(
77
- session_id: str = Path(...),
78
- session_type: SessionType = Query(default=SessionType.AGENT, description="Session type filter", alias="type"),
79
- db_id: Optional[str] = Query(default=None, description="The ID of the database to use"),
216
+ session_id: str = Path(description="Session ID to retrieve"),
217
+ session_type: SessionType = Query(
218
+ default=SessionType.AGENT, description="Session type (agent, team, or workflow)", alias="type"
219
+ ),
220
+ db_id: Optional[str] = Query(default=None, description="Database ID to query session from"),
80
221
  ) -> Union[AgentSessionDetailSchema, TeamSessionDetailSchema, WorkflowSessionDetailSchema]:
81
222
  db = get_db(dbs, db_id)
82
223
  session = db.get_session(session_id=session_id, session_type=session_type)
@@ -95,11 +236,121 @@ def attach_routes(router: APIRouter, dbs: dict[str, BaseDb]) -> APIRouter:
95
236
  response_model=Union[List[RunSchema], List[TeamRunSchema], List[WorkflowRunSchema]],
96
237
  status_code=200,
97
238
  operation_id="get_session_runs",
239
+ summary="Get Session Runs",
240
+ description=(
241
+ "Retrieve all runs (executions) for a specific session. Runs represent individual "
242
+ "interactions or executions within a session. Response schema varies based on session type."
243
+ ),
244
+ responses={
245
+ 200: {
246
+ "description": "Session runs retrieved successfully",
247
+ "content": {
248
+ "application/json": {
249
+ "examples": {
250
+ "completed_run": {
251
+ "summary": "Example completed run",
252
+ "value": {
253
+ "run_id": "fcdf50f0-7c32-4593-b2ef-68a558774340",
254
+ "agent_session_id": "80056af0-c7a5-4d69-b6a2-c3eba9f040e0",
255
+ "user_id": "",
256
+ "run_input": "Which tools do you have access to?",
257
+ "content": "I don't have access to external tools or the internet. However, I can assist you with a wide range of topics by providing information, answering questions, and offering suggestions based on the knowledge I've been trained on. If there's anything specific you need help with, feel free to ask!",
258
+ "run_response_format": "text",
259
+ "reasoning_content": "",
260
+ "metrics": {
261
+ "input_tokens": 82,
262
+ "output_tokens": 56,
263
+ "total_tokens": 138,
264
+ "time_to_first_token": 0.047505500027909875,
265
+ "duration": 4.840060166025069,
266
+ },
267
+ "messages": [
268
+ {
269
+ "content": "<additional_information>\n- Use markdown to format your answers.\n- The current time is 2025-09-08 17:52:10.101003.\n</additional_information>\n\nYou have the capability to retain memories from previous interactions with the user, but have not had any interactions with the user yet.",
270
+ "from_history": False,
271
+ "stop_after_tool_call": False,
272
+ "role": "system",
273
+ "created_at": 1757346730,
274
+ },
275
+ {
276
+ "content": "Which tools do you have access to?",
277
+ "from_history": False,
278
+ "stop_after_tool_call": False,
279
+ "role": "user",
280
+ "created_at": 1757346730,
281
+ },
282
+ {
283
+ "content": "I don't have access to external tools or the internet. However, I can assist you with a wide range of topics by providing information, answering questions, and offering suggestions based on the knowledge I've been trained on. If there's anything specific you need help with, feel free to ask!",
284
+ "from_history": False,
285
+ "stop_after_tool_call": False,
286
+ "role": "assistant",
287
+ "metrics": {"input_tokens": 82, "output_tokens": 56, "total_tokens": 138},
288
+ "created_at": 1757346730,
289
+ },
290
+ ],
291
+ "tools": None,
292
+ "events": [
293
+ {
294
+ "created_at": 1757346730,
295
+ "event": "RunStarted",
296
+ "agent_id": "basic-agent",
297
+ "agent_name": "Basic Agent",
298
+ "run_id": "fcdf50f0-7c32-4593-b2ef-68a558774340",
299
+ "session_id": "80056af0-c7a5-4d69-b6a2-c3eba9f040e0",
300
+ "model": "gpt-4o",
301
+ "model_provider": "OpenAI",
302
+ },
303
+ {
304
+ "created_at": 1757346733,
305
+ "event": "MemoryUpdateStarted",
306
+ "agent_id": "basic-agent",
307
+ "agent_name": "Basic Agent",
308
+ "run_id": "fcdf50f0-7c32-4593-b2ef-68a558774340",
309
+ "session_id": "80056af0-c7a5-4d69-b6a2-c3eba9f040e0",
310
+ },
311
+ {
312
+ "created_at": 1757346734,
313
+ "event": "MemoryUpdateCompleted",
314
+ "agent_id": "basic-agent",
315
+ "agent_name": "Basic Agent",
316
+ "run_id": "fcdf50f0-7c32-4593-b2ef-68a558774340",
317
+ "session_id": "80056af0-c7a5-4d69-b6a2-c3eba9f040e0",
318
+ },
319
+ {
320
+ "created_at": 1757346734,
321
+ "event": "RunCompleted",
322
+ "agent_id": "basic-agent",
323
+ "agent_name": "Basic Agent",
324
+ "run_id": "fcdf50f0-7c32-4593-b2ef-68a558774340",
325
+ "session_id": "80056af0-c7a5-4d69-b6a2-c3eba9f040e0",
326
+ "content": "I don't have access to external tools or the internet. However, I can assist you with a wide range of topics by providing information, answering questions, and offering suggestions based on the knowledge I've been trained on. If there's anything specific you need help with, feel free to ask!",
327
+ "content_type": "str",
328
+ "metrics": {
329
+ "input_tokens": 82,
330
+ "output_tokens": 56,
331
+ "total_tokens": 138,
332
+ "time_to_first_token": 0.047505500027909875,
333
+ "duration": 4.840060166025069,
334
+ },
335
+ },
336
+ ],
337
+ "created_at": "2025-09-08T15:52:10Z",
338
+ },
339
+ }
340
+ }
341
+ }
342
+ },
343
+ },
344
+ 404: {"description": "Session not found or has no runs", "model": NotFoundResponse},
345
+ 422: {"description": "Invalid session type", "model": ValidationErrorResponse},
346
+ },
98
347
  )
99
348
  async def get_session_runs(
100
- session_id: str = Path(..., description="Session ID", alias="session_id"),
101
- session_type: SessionType = Query(default=SessionType.AGENT, description="Session type filter", alias="type"),
102
- db_id: Optional[str] = Query(default=None, description="The ID of the database to use"),
349
+ session_id: str = Path(description="Session ID to get runs from"),
350
+ session_type: SessionType = Query(
351
+ default=SessionType.AGENT, description="Session type (agent, team, or workflow)", alias="type"
352
+ ),
353
+ db_id: Optional[str] = Query(default=None, description="Database ID to query runs from"),
103
354
  ) -> Union[List[RunSchema], List[TeamRunSchema], List[WorkflowRunSchema]]:
104
355
  db = get_db(dbs, db_id)
105
356
  session = db.get_session(session_id=session_id, session_type=session_type, deserialize=False)
@@ -122,19 +373,51 @@ def attach_routes(router: APIRouter, dbs: dict[str, BaseDb]) -> APIRouter:
122
373
  else:
123
374
  return [RunSchema.from_dict(run) for run in runs]
124
375
 
125
- @router.delete("/sessions/{session_id}", status_code=204, operation_id="delete_session")
376
+ @router.delete(
377
+ "/sessions/{session_id}",
378
+ status_code=204,
379
+ operation_id="delete_session",
380
+ summary="Delete Session",
381
+ description=(
382
+ "Permanently delete a specific session and all its associated runs. "
383
+ "This action cannot be undone and will remove all conversation history."
384
+ ),
385
+ responses={
386
+ 204: {},
387
+ 500: {"description": "Failed to delete session", "model": InternalServerErrorResponse},
388
+ },
389
+ )
126
390
  async def delete_session(
127
- session_id: str = Path(...),
128
- db_id: Optional[str] = Query(default=None, description="The ID of the database to use"),
391
+ session_id: str = Path(description="Session ID to delete"),
392
+ db_id: Optional[str] = Query(default=None, description="Database ID to use for deletion"),
129
393
  ) -> None:
130
394
  db = get_db(dbs, db_id)
131
395
  db.delete_session(session_id=session_id)
132
396
 
133
- @router.delete("/sessions", status_code=204, operation_id="delete_sessions")
397
+ @router.delete(
398
+ "/sessions",
399
+ status_code=204,
400
+ operation_id="delete_sessions",
401
+ summary="Delete Multiple Sessions",
402
+ description=(
403
+ "Delete multiple sessions by their IDs in a single operation. "
404
+ "This action cannot be undone and will permanently remove all specified sessions and their runs."
405
+ ),
406
+ responses={
407
+ 204: {"description": "Sessions deleted successfully"},
408
+ 400: {
409
+ "description": "Invalid request - session IDs and types length mismatch",
410
+ "model": BadRequestResponse,
411
+ },
412
+ 500: {"description": "Failed to delete sessions", "model": InternalServerErrorResponse},
413
+ },
414
+ )
134
415
  async def delete_sessions(
135
416
  request: DeleteSessionRequest,
136
- session_type: SessionType = Query(default=SessionType.AGENT, description="Session type filter", alias="type"),
137
- db_id: Optional[str] = Query(default=None, description="The ID of the database to use"),
417
+ session_type: SessionType = Query(
418
+ default=SessionType.AGENT, description="Default session type filter", alias="type"
419
+ ),
420
+ db_id: Optional[str] = Query(default=None, description="Database ID to use for deletion"),
138
421
  ) -> None:
139
422
  if len(request.session_ids) != len(request.session_types):
140
423
  raise HTTPException(status_code=400, detail="Session IDs and session types must have the same length")
@@ -145,13 +428,98 @@ def attach_routes(router: APIRouter, dbs: dict[str, BaseDb]) -> APIRouter:
145
428
  @router.post(
146
429
  "/sessions/{session_id}/rename",
147
430
  response_model=Union[AgentSessionDetailSchema, TeamSessionDetailSchema, WorkflowSessionDetailSchema],
431
+ status_code=200,
148
432
  operation_id="rename_session",
433
+ summary="Rename Session",
434
+ description=(
435
+ "Update the name of an existing session. Useful for organizing and categorizing "
436
+ "sessions with meaningful names for better identification and management."
437
+ ),
438
+ responses={
439
+ 200: {
440
+ "description": "Session renamed successfully",
441
+ "content": {
442
+ "application/json": {
443
+ "examples": {
444
+ "agent_session_example": {
445
+ "summary": "Example agent session response",
446
+ "value": {
447
+ "user_id": "123",
448
+ "agent_session_id": "6f6cfbfd-9643-479a-ae47-b8f32eb4d710",
449
+ "session_id": "6f6cfbfd-9643-479a-ae47-b8f32eb4d710",
450
+ "session_name": "What tools do you have?",
451
+ "session_summary": {
452
+ "summary": "The user and assistant engaged in a conversation about the tools the agent has available.",
453
+ "updated_at": "2025-09-05T18:02:12.269392",
454
+ },
455
+ "session_state": {},
456
+ "agent_id": "basic-agent",
457
+ "total_tokens": 160,
458
+ "agent_data": {
459
+ "name": "Basic Agent",
460
+ "agent_id": "basic-agent",
461
+ "model": {"provider": "OpenAI", "name": "OpenAIChat", "id": "gpt-4o"},
462
+ },
463
+ "metrics": {
464
+ "input_tokens": 134,
465
+ "output_tokens": 26,
466
+ "total_tokens": 160,
467
+ "audio_input_tokens": 0,
468
+ "audio_output_tokens": 0,
469
+ "audio_total_tokens": 0,
470
+ "cache_read_tokens": 0,
471
+ "cache_write_tokens": 0,
472
+ "reasoning_tokens": 0,
473
+ "timer": None,
474
+ "time_to_first_token": None,
475
+ "duration": None,
476
+ "provider_metrics": None,
477
+ "additional_metrics": None,
478
+ },
479
+ "chat_history": [
480
+ {
481
+ "content": "<additional_information>\n- Use markdown to format your answers.\n- The current time is 2025-09-05 18:02:09.171627.\n</additional_information>\n\nYou have access to memories from previous interactions with the user that you can use:\n\n<memories_from_previous_interactions>\n- User really likes Digimon and Japan.\n- User really likes Japan.\n- User likes coffee.\n</memories_from_previous_interactions>\n\nNote: this information is from previous interactions and may be updated in this conversation. You should always prefer information from this conversation over the past memories.",
482
+ "from_history": False,
483
+ "stop_after_tool_call": False,
484
+ "role": "system",
485
+ "created_at": 1757088129,
486
+ },
487
+ {
488
+ "content": "What tools do you have?",
489
+ "from_history": False,
490
+ "stop_after_tool_call": False,
491
+ "role": "user",
492
+ "created_at": 1757088129,
493
+ },
494
+ {
495
+ "content": "I don't have access to external tools or the internet. However, I can assist you with a wide range of topics by providing information, answering questions, and offering suggestions based on the knowledge I've been trained on. If there's anything specific you need help with, feel free to ask!",
496
+ "from_history": False,
497
+ "stop_after_tool_call": False,
498
+ "role": "assistant",
499
+ "metrics": {"input_tokens": 134, "output_tokens": 26, "total_tokens": 160},
500
+ "created_at": 1757088129,
501
+ },
502
+ ],
503
+ "created_at": "2025-09-05T16:02:09Z",
504
+ "updated_at": "2025-09-05T16:02:09Z",
505
+ },
506
+ }
507
+ }
508
+ }
509
+ },
510
+ },
511
+ 400: {"description": "Invalid session name", "model": BadRequestResponse},
512
+ 404: {"description": "Session not found", "model": NotFoundResponse},
513
+ 422: {"description": "Invalid session type or validation error", "model": ValidationErrorResponse},
514
+ },
149
515
  )
150
516
  async def rename_session(
151
- session_id: str = Path(...),
152
- session_type: SessionType = Query(default=SessionType.AGENT, description="Session type filter", alias="type"),
153
- session_name: str = Body(embed=True),
154
- db_id: Optional[str] = Query(default=None, description="The ID of the database to use"),
517
+ session_id: str = Path(description="Session ID to rename"),
518
+ session_type: SessionType = Query(
519
+ default=SessionType.AGENT, description="Session type (agent, team, or workflow)", alias="type"
520
+ ),
521
+ session_name: str = Body(embed=True, description="New name for the session"),
522
+ db_id: Optional[str] = Query(default=None, description="Database ID to use for rename operation"),
155
523
  ) -> Union[AgentSessionDetailSchema, TeamSessionDetailSchema, WorkflowSessionDetailSchema]:
156
524
  db = get_db(dbs, db_id)
157
525
  session = db.rename_session(session_id=session_id, session_type=session_type, session_name=session_name)
agno/os/schema.py CHANGED
@@ -23,6 +23,61 @@ from agno.team.team import Team
23
23
  from agno.workflow.workflow import Workflow
24
24
 
25
25
 
26
+ class BadRequestResponse(BaseModel):
27
+ detail: str
28
+ error_code: Optional[str] = None
29
+
30
+ class Config:
31
+ json_schema_extra = {"example": {"detail": "Bad request", "error_code": "BAD_REQUEST"}}
32
+
33
+
34
+ class NotFoundResponse(BaseModel):
35
+ detail: str
36
+ error_code: Optional[str] = None
37
+
38
+ class Config:
39
+ json_schema_extra = {"example": {"detail": "Not found", "error_code": "NOT_FOUND"}}
40
+
41
+
42
+ class UnauthorizedResponse(BaseModel):
43
+ detail: str
44
+ error_code: Optional[str] = None
45
+
46
+ class Config:
47
+ json_schema_extra = {"example": {"detail": "Unauthorized access", "error_code": "UNAUTHORIZED"}}
48
+
49
+
50
+ class UnauthenticatedResponse(BaseModel):
51
+ detail: str
52
+ error_code: Optional[str] = None
53
+
54
+ class Config:
55
+ json_schema_extra = {"example": {"detail": "Unauthenticated access", "error_code": "UNAUTHENTICATED"}}
56
+
57
+
58
+ class ValidationErrorResponse(BaseModel):
59
+ detail: str
60
+ error_code: Optional[str] = None
61
+
62
+ class Config:
63
+ json_schema_extra = {"example": {"detail": "Validation error", "error_code": "VALIDATION_ERROR"}}
64
+
65
+
66
+ class InternalServerErrorResponse(BaseModel):
67
+ detail: str
68
+ error_code: Optional[str] = None
69
+
70
+ class Config:
71
+ json_schema_extra = {"example": {"detail": "Internal server error", "error_code": "INTERNAL_SERVER_ERROR"}}
72
+
73
+
74
+ class HealthResponse(BaseModel):
75
+ status: str
76
+
77
+ class Config:
78
+ json_schema_extra = {"example": {"status": "ok"}}
79
+
80
+
26
81
  class InterfaceResponse(BaseModel):
27
82
  type: str
28
83
  version: str
@@ -342,7 +397,6 @@ class TeamResponse(BaseModel):
342
397
  name: Optional[str] = None
343
398
  db_id: Optional[str] = None
344
399
  description: Optional[str] = None
345
- mode: Optional[str] = None
346
400
  model: Optional[ModelResponse] = None
347
401
  tools: Optional[Dict[str, Any]] = None
348
402
  sessions: Optional[Dict[str, Any]] = None
@@ -541,7 +595,6 @@ class TeamResponse(BaseModel):
541
595
  return TeamResponse(
542
596
  id=team.id,
543
597
  name=team.name,
544
- mode=team.mode,
545
598
  db_id=team.db.id if team.db else None,
546
599
  model=ModelResponse(**_team_model_data) if _team_model_data else None,
547
600
  tools=filter_meaningful_config(tools_info, {}),
agno/run/agent.py CHANGED
@@ -43,6 +43,8 @@ class RunEvent(str, Enum):
43
43
  output_model_response_started = "OutputModelResponseStarted"
44
44
  output_model_response_completed = "OutputModelResponseCompleted"
45
45
 
46
+ custom_event = "CustomEvent"
47
+
46
48
 
47
49
  @dataclass
48
50
  class BaseAgentRunEvent(BaseRunOutputEvent):
@@ -226,6 +228,11 @@ class OutputModelResponseCompletedEvent(BaseAgentRunEvent):
226
228
  event: str = RunEvent.output_model_response_completed.value
227
229
 
228
230
 
231
+ @dataclass
232
+ class CustomEvent(BaseAgentRunEvent):
233
+ event: str = RunEvent.custom_event.value
234
+
235
+
229
236
  RunOutputEvent = Union[
230
237
  RunStartedEvent,
231
238
  RunContentEvent,
@@ -246,6 +253,7 @@ RunOutputEvent = Union[
246
253
  ParserModelResponseCompletedEvent,
247
254
  OutputModelResponseStartedEvent,
248
255
  OutputModelResponseCompletedEvent,
256
+ CustomEvent,
249
257
  ]
250
258
 
251
259
 
@@ -270,6 +278,7 @@ RUN_EVENT_TYPE_REGISTRY = {
270
278
  RunEvent.parser_model_response_completed.value: ParserModelResponseCompletedEvent,
271
279
  RunEvent.output_model_response_started.value: OutputModelResponseStartedEvent,
272
280
  RunEvent.output_model_response_completed.value: OutputModelResponseCompletedEvent,
281
+ RunEvent.custom_event.value: CustomEvent,
273
282
  }
274
283
 
275
284