agno 2.0.0a1__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.
- agno/agent/agent.py +416 -41
- agno/api/agent.py +2 -2
- agno/api/evals.py +2 -2
- agno/api/os.py +1 -1
- agno/api/settings.py +2 -2
- agno/api/team.py +2 -2
- agno/db/dynamo/dynamo.py +0 -6
- agno/db/firestore/firestore.py +0 -6
- agno/db/in_memory/in_memory_db.py +0 -6
- agno/db/json/json_db.py +0 -6
- agno/db/mongo/mongo.py +8 -9
- agno/db/mysql/utils.py +0 -1
- agno/db/postgres/postgres.py +0 -10
- agno/db/postgres/utils.py +0 -1
- agno/db/redis/redis.py +0 -4
- agno/db/singlestore/singlestore.py +0 -10
- agno/db/singlestore/utils.py +0 -1
- agno/db/sqlite/sqlite.py +0 -4
- agno/db/sqlite/utils.py +0 -1
- agno/eval/accuracy.py +12 -5
- agno/integrations/discord/client.py +5 -1
- agno/knowledge/chunking/strategy.py +14 -14
- agno/knowledge/embedder/aws_bedrock.py +2 -2
- agno/knowledge/knowledge.py +156 -120
- agno/knowledge/reader/arxiv_reader.py +5 -5
- agno/knowledge/reader/csv_reader.py +6 -77
- agno/knowledge/reader/docx_reader.py +5 -5
- agno/knowledge/reader/firecrawl_reader.py +5 -5
- agno/knowledge/reader/json_reader.py +5 -5
- agno/knowledge/reader/markdown_reader.py +31 -9
- agno/knowledge/reader/pdf_reader.py +10 -123
- agno/knowledge/reader/reader_factory.py +65 -72
- agno/knowledge/reader/s3_reader.py +44 -114
- agno/knowledge/reader/text_reader.py +5 -5
- agno/knowledge/reader/url_reader.py +75 -31
- agno/knowledge/reader/web_search_reader.py +6 -29
- agno/knowledge/reader/website_reader.py +5 -5
- agno/knowledge/reader/wikipedia_reader.py +5 -5
- agno/knowledge/reader/youtube_reader.py +6 -6
- agno/knowledge/utils.py +10 -10
- agno/models/anthropic/claude.py +2 -49
- agno/models/aws/bedrock.py +3 -7
- agno/models/base.py +37 -6
- agno/models/message.py +7 -6
- agno/os/app.py +168 -64
- agno/os/interfaces/agui/agui.py +1 -1
- agno/os/interfaces/agui/utils.py +16 -9
- agno/os/interfaces/slack/slack.py +2 -3
- agno/os/interfaces/whatsapp/whatsapp.py +2 -3
- agno/os/mcp.py +235 -0
- agno/os/router.py +576 -19
- agno/os/routers/evals/evals.py +201 -12
- agno/os/routers/knowledge/knowledge.py +455 -18
- agno/os/routers/memory/memory.py +260 -29
- agno/os/routers/metrics/metrics.py +127 -7
- agno/os/routers/session/session.py +398 -25
- agno/os/schema.py +55 -2
- agno/os/settings.py +0 -1
- agno/run/agent.py +96 -2
- agno/run/cancel.py +0 -2
- agno/run/team.py +93 -2
- agno/run/workflow.py +25 -12
- agno/team/team.py +863 -1053
- agno/tools/function.py +65 -7
- agno/tools/linear.py +1 -1
- agno/tools/mcp.py +1 -2
- agno/utils/gemini.py +31 -1
- agno/utils/log.py +52 -2
- agno/utils/mcp.py +55 -3
- agno/utils/models/claude.py +41 -0
- agno/utils/print_response/team.py +177 -73
- agno/utils/streamlit.py +481 -0
- agno/workflow/workflow.py +17 -1
- {agno-2.0.0a1.dist-info → agno-2.0.0rc2.dist-info}/METADATA +1 -1
- {agno-2.0.0a1.dist-info → agno-2.0.0rc2.dist-info}/RECORD +78 -77
- agno/knowledge/reader/gcs_reader.py +0 -67
- {agno-2.0.0a1.dist-info → agno-2.0.0rc2.dist-info}/WHEEL +0 -0
- {agno-2.0.0a1.dist-info → agno-2.0.0rc2.dist-info}/licenses/LICENSE +0 -0
- {agno-2.0.0a1.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,22 +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
|
-
|
|
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
|
-
@router.get(
|
|
49
|
+
@router.get(
|
|
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
|
+
},
|
|
87
|
+
)
|
|
34
88
|
async def get_sessions(
|
|
35
|
-
session_type: SessionType = Query(
|
|
36
|
-
|
|
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
|
+
),
|
|
37
97
|
user_id: Optional[str] = Query(default=None, description="Filter sessions by user ID"),
|
|
38
|
-
session_name: Optional[str] = Query(default=None, description="Filter sessions by name"),
|
|
39
|
-
limit: Optional[int] = Query(default=20, description="Number of sessions to return"),
|
|
40
|
-
page: Optional[int] = Query(default=1, description="Page number"),
|
|
41
|
-
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"),
|
|
42
102
|
sort_order: Optional[SortOrder] = Query(default="desc", description="Sort order (asc or desc)"),
|
|
43
|
-
db_id: Optional[str] = Query(default=None, description="
|
|
103
|
+
db_id: Optional[str] = Query(default=None, description="Database ID to query sessions from"),
|
|
44
104
|
) -> PaginatedResponse[SessionSchema]:
|
|
45
105
|
db = get_db(dbs, db_id)
|
|
46
106
|
sessions, total_count = db.get_sessions(
|
|
@@ -69,11 +129,95 @@ def attach_routes(router: APIRouter, dbs: dict[str, BaseDb]) -> APIRouter:
|
|
|
69
129
|
"/sessions/{session_id}",
|
|
70
130
|
response_model=Union[AgentSessionDetailSchema, TeamSessionDetailSchema, WorkflowSessionDetailSchema],
|
|
71
131
|
status_code=200,
|
|
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
|
+
},
|
|
72
214
|
)
|
|
73
215
|
async def get_session_by_id(
|
|
74
|
-
session_id: str = Path(
|
|
75
|
-
session_type: SessionType = Query(
|
|
76
|
-
|
|
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"),
|
|
77
221
|
) -> Union[AgentSessionDetailSchema, TeamSessionDetailSchema, WorkflowSessionDetailSchema]:
|
|
78
222
|
db = get_db(dbs, db_id)
|
|
79
223
|
session = db.get_session(session_id=session_id, session_type=session_type)
|
|
@@ -91,11 +235,122 @@ def attach_routes(router: APIRouter, dbs: dict[str, BaseDb]) -> APIRouter:
|
|
|
91
235
|
"/sessions/{session_id}/runs",
|
|
92
236
|
response_model=Union[List[RunSchema], List[TeamRunSchema], List[WorkflowRunSchema]],
|
|
93
237
|
status_code=200,
|
|
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
|
+
},
|
|
94
347
|
)
|
|
95
348
|
async def get_session_runs(
|
|
96
|
-
session_id: str = Path(
|
|
97
|
-
session_type: SessionType = Query(
|
|
98
|
-
|
|
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"),
|
|
99
354
|
) -> Union[List[RunSchema], List[TeamRunSchema], List[WorkflowRunSchema]]:
|
|
100
355
|
db = get_db(dbs, db_id)
|
|
101
356
|
session = db.get_session(session_id=session_id, session_type=session_type, deserialize=False)
|
|
@@ -118,19 +373,51 @@ def attach_routes(router: APIRouter, dbs: dict[str, BaseDb]) -> APIRouter:
|
|
|
118
373
|
else:
|
|
119
374
|
return [RunSchema.from_dict(run) for run in runs]
|
|
120
375
|
|
|
121
|
-
@router.delete(
|
|
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
|
+
)
|
|
122
390
|
async def delete_session(
|
|
123
|
-
session_id: str = Path(
|
|
124
|
-
db_id: Optional[str] = Query(default=None, description="
|
|
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"),
|
|
125
393
|
) -> None:
|
|
126
394
|
db = get_db(dbs, db_id)
|
|
127
395
|
db.delete_session(session_id=session_id)
|
|
128
396
|
|
|
129
|
-
@router.delete(
|
|
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
|
+
)
|
|
130
415
|
async def delete_sessions(
|
|
131
416
|
request: DeleteSessionRequest,
|
|
132
|
-
session_type: SessionType = Query(
|
|
133
|
-
|
|
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"),
|
|
134
421
|
) -> None:
|
|
135
422
|
if len(request.session_ids) != len(request.session_types):
|
|
136
423
|
raise HTTPException(status_code=400, detail="Session IDs and session types must have the same length")
|
|
@@ -141,12 +428,98 @@ def attach_routes(router: APIRouter, dbs: dict[str, BaseDb]) -> APIRouter:
|
|
|
141
428
|
@router.post(
|
|
142
429
|
"/sessions/{session_id}/rename",
|
|
143
430
|
response_model=Union[AgentSessionDetailSchema, TeamSessionDetailSchema, WorkflowSessionDetailSchema],
|
|
431
|
+
status_code=200,
|
|
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
|
+
},
|
|
144
515
|
)
|
|
145
516
|
async def rename_session(
|
|
146
|
-
session_id: str = Path(
|
|
147
|
-
session_type: SessionType = Query(
|
|
148
|
-
|
|
149
|
-
|
|
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"),
|
|
150
523
|
) -> Union[AgentSessionDetailSchema, TeamSessionDetailSchema, WorkflowSessionDetailSchema]:
|
|
151
524
|
db = get_db(dbs, db_id)
|
|
152
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, {}),
|