agno 2.1.2__py3-none-any.whl → 2.3.13__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 (314) hide show
  1. agno/agent/agent.py +5540 -2273
  2. agno/api/api.py +2 -0
  3. agno/api/os.py +1 -1
  4. agno/compression/__init__.py +3 -0
  5. agno/compression/manager.py +247 -0
  6. agno/culture/__init__.py +3 -0
  7. agno/culture/manager.py +956 -0
  8. agno/db/async_postgres/__init__.py +3 -0
  9. agno/db/base.py +689 -6
  10. agno/db/dynamo/dynamo.py +933 -37
  11. agno/db/dynamo/schemas.py +174 -10
  12. agno/db/dynamo/utils.py +63 -4
  13. agno/db/firestore/firestore.py +831 -9
  14. agno/db/firestore/schemas.py +51 -0
  15. agno/db/firestore/utils.py +102 -4
  16. agno/db/gcs_json/gcs_json_db.py +660 -12
  17. agno/db/gcs_json/utils.py +60 -26
  18. agno/db/in_memory/in_memory_db.py +287 -14
  19. agno/db/in_memory/utils.py +60 -2
  20. agno/db/json/json_db.py +590 -14
  21. agno/db/json/utils.py +60 -26
  22. agno/db/migrations/manager.py +199 -0
  23. agno/db/migrations/v1_to_v2.py +43 -13
  24. agno/db/migrations/versions/__init__.py +0 -0
  25. agno/db/migrations/versions/v2_3_0.py +938 -0
  26. agno/db/mongo/__init__.py +15 -1
  27. agno/db/mongo/async_mongo.py +2760 -0
  28. agno/db/mongo/mongo.py +879 -11
  29. agno/db/mongo/schemas.py +42 -0
  30. agno/db/mongo/utils.py +80 -8
  31. agno/db/mysql/__init__.py +2 -1
  32. agno/db/mysql/async_mysql.py +2912 -0
  33. agno/db/mysql/mysql.py +946 -68
  34. agno/db/mysql/schemas.py +72 -10
  35. agno/db/mysql/utils.py +198 -7
  36. agno/db/postgres/__init__.py +2 -1
  37. agno/db/postgres/async_postgres.py +2579 -0
  38. agno/db/postgres/postgres.py +942 -57
  39. agno/db/postgres/schemas.py +81 -18
  40. agno/db/postgres/utils.py +164 -2
  41. agno/db/redis/redis.py +671 -7
  42. agno/db/redis/schemas.py +50 -0
  43. agno/db/redis/utils.py +65 -7
  44. agno/db/schemas/__init__.py +2 -1
  45. agno/db/schemas/culture.py +120 -0
  46. agno/db/schemas/evals.py +1 -0
  47. agno/db/schemas/memory.py +17 -2
  48. agno/db/singlestore/schemas.py +63 -0
  49. agno/db/singlestore/singlestore.py +949 -83
  50. agno/db/singlestore/utils.py +60 -2
  51. agno/db/sqlite/__init__.py +2 -1
  52. agno/db/sqlite/async_sqlite.py +2911 -0
  53. agno/db/sqlite/schemas.py +62 -0
  54. agno/db/sqlite/sqlite.py +965 -46
  55. agno/db/sqlite/utils.py +169 -8
  56. agno/db/surrealdb/__init__.py +3 -0
  57. agno/db/surrealdb/metrics.py +292 -0
  58. agno/db/surrealdb/models.py +334 -0
  59. agno/db/surrealdb/queries.py +71 -0
  60. agno/db/surrealdb/surrealdb.py +1908 -0
  61. agno/db/surrealdb/utils.py +147 -0
  62. agno/db/utils.py +2 -0
  63. agno/eval/__init__.py +10 -0
  64. agno/eval/accuracy.py +75 -55
  65. agno/eval/agent_as_judge.py +861 -0
  66. agno/eval/base.py +29 -0
  67. agno/eval/performance.py +16 -7
  68. agno/eval/reliability.py +28 -16
  69. agno/eval/utils.py +35 -17
  70. agno/exceptions.py +27 -2
  71. agno/filters.py +354 -0
  72. agno/guardrails/prompt_injection.py +1 -0
  73. agno/hooks/__init__.py +3 -0
  74. agno/hooks/decorator.py +164 -0
  75. agno/integrations/discord/client.py +1 -1
  76. agno/knowledge/chunking/agentic.py +13 -10
  77. agno/knowledge/chunking/fixed.py +4 -1
  78. agno/knowledge/chunking/semantic.py +9 -4
  79. agno/knowledge/chunking/strategy.py +59 -15
  80. agno/knowledge/embedder/fastembed.py +1 -1
  81. agno/knowledge/embedder/nebius.py +1 -1
  82. agno/knowledge/embedder/ollama.py +8 -0
  83. agno/knowledge/embedder/openai.py +8 -8
  84. agno/knowledge/embedder/sentence_transformer.py +6 -2
  85. agno/knowledge/embedder/vllm.py +262 -0
  86. agno/knowledge/knowledge.py +1618 -318
  87. agno/knowledge/reader/base.py +6 -2
  88. agno/knowledge/reader/csv_reader.py +8 -10
  89. agno/knowledge/reader/docx_reader.py +5 -6
  90. agno/knowledge/reader/field_labeled_csv_reader.py +16 -20
  91. agno/knowledge/reader/json_reader.py +5 -4
  92. agno/knowledge/reader/markdown_reader.py +8 -8
  93. agno/knowledge/reader/pdf_reader.py +17 -19
  94. agno/knowledge/reader/pptx_reader.py +101 -0
  95. agno/knowledge/reader/reader_factory.py +32 -3
  96. agno/knowledge/reader/s3_reader.py +3 -3
  97. agno/knowledge/reader/tavily_reader.py +193 -0
  98. agno/knowledge/reader/text_reader.py +22 -10
  99. agno/knowledge/reader/web_search_reader.py +1 -48
  100. agno/knowledge/reader/website_reader.py +10 -10
  101. agno/knowledge/reader/wikipedia_reader.py +33 -1
  102. agno/knowledge/types.py +1 -0
  103. agno/knowledge/utils.py +72 -7
  104. agno/media.py +22 -6
  105. agno/memory/__init__.py +14 -1
  106. agno/memory/manager.py +544 -83
  107. agno/memory/strategies/__init__.py +15 -0
  108. agno/memory/strategies/base.py +66 -0
  109. agno/memory/strategies/summarize.py +196 -0
  110. agno/memory/strategies/types.py +37 -0
  111. agno/models/aimlapi/aimlapi.py +17 -0
  112. agno/models/anthropic/claude.py +515 -40
  113. agno/models/aws/bedrock.py +102 -21
  114. agno/models/aws/claude.py +131 -274
  115. agno/models/azure/ai_foundry.py +41 -19
  116. agno/models/azure/openai_chat.py +39 -8
  117. agno/models/base.py +1249 -525
  118. agno/models/cerebras/cerebras.py +91 -21
  119. agno/models/cerebras/cerebras_openai.py +21 -2
  120. agno/models/cohere/chat.py +40 -6
  121. agno/models/cometapi/cometapi.py +18 -1
  122. agno/models/dashscope/dashscope.py +2 -3
  123. agno/models/deepinfra/deepinfra.py +18 -1
  124. agno/models/deepseek/deepseek.py +69 -3
  125. agno/models/fireworks/fireworks.py +18 -1
  126. agno/models/google/gemini.py +877 -80
  127. agno/models/google/utils.py +22 -0
  128. agno/models/groq/groq.py +51 -18
  129. agno/models/huggingface/huggingface.py +17 -6
  130. agno/models/ibm/watsonx.py +16 -6
  131. agno/models/internlm/internlm.py +18 -1
  132. agno/models/langdb/langdb.py +13 -1
  133. agno/models/litellm/chat.py +44 -9
  134. agno/models/litellm/litellm_openai.py +18 -1
  135. agno/models/message.py +28 -5
  136. agno/models/meta/llama.py +47 -14
  137. agno/models/meta/llama_openai.py +22 -17
  138. agno/models/mistral/mistral.py +8 -4
  139. agno/models/nebius/nebius.py +6 -7
  140. agno/models/nvidia/nvidia.py +20 -3
  141. agno/models/ollama/chat.py +24 -8
  142. agno/models/openai/chat.py +104 -29
  143. agno/models/openai/responses.py +101 -81
  144. agno/models/openrouter/openrouter.py +60 -3
  145. agno/models/perplexity/perplexity.py +17 -1
  146. agno/models/portkey/portkey.py +7 -6
  147. agno/models/requesty/requesty.py +24 -4
  148. agno/models/response.py +73 -2
  149. agno/models/sambanova/sambanova.py +20 -3
  150. agno/models/siliconflow/siliconflow.py +19 -2
  151. agno/models/together/together.py +20 -3
  152. agno/models/utils.py +254 -8
  153. agno/models/vercel/v0.py +20 -3
  154. agno/models/vertexai/__init__.py +0 -0
  155. agno/models/vertexai/claude.py +190 -0
  156. agno/models/vllm/vllm.py +19 -14
  157. agno/models/xai/xai.py +19 -2
  158. agno/os/app.py +549 -152
  159. agno/os/auth.py +190 -3
  160. agno/os/config.py +23 -0
  161. agno/os/interfaces/a2a/router.py +8 -11
  162. agno/os/interfaces/a2a/utils.py +1 -1
  163. agno/os/interfaces/agui/router.py +18 -3
  164. agno/os/interfaces/agui/utils.py +152 -39
  165. agno/os/interfaces/slack/router.py +55 -37
  166. agno/os/interfaces/slack/slack.py +9 -1
  167. agno/os/interfaces/whatsapp/router.py +0 -1
  168. agno/os/interfaces/whatsapp/security.py +3 -1
  169. agno/os/mcp.py +110 -52
  170. agno/os/middleware/__init__.py +2 -0
  171. agno/os/middleware/jwt.py +676 -112
  172. agno/os/router.py +40 -1478
  173. agno/os/routers/agents/__init__.py +3 -0
  174. agno/os/routers/agents/router.py +599 -0
  175. agno/os/routers/agents/schema.py +261 -0
  176. agno/os/routers/evals/evals.py +96 -39
  177. agno/os/routers/evals/schemas.py +65 -33
  178. agno/os/routers/evals/utils.py +80 -10
  179. agno/os/routers/health.py +10 -4
  180. agno/os/routers/knowledge/knowledge.py +196 -38
  181. agno/os/routers/knowledge/schemas.py +82 -22
  182. agno/os/routers/memory/memory.py +279 -52
  183. agno/os/routers/memory/schemas.py +46 -17
  184. agno/os/routers/metrics/metrics.py +20 -8
  185. agno/os/routers/metrics/schemas.py +16 -16
  186. agno/os/routers/session/session.py +462 -34
  187. agno/os/routers/teams/__init__.py +3 -0
  188. agno/os/routers/teams/router.py +512 -0
  189. agno/os/routers/teams/schema.py +257 -0
  190. agno/os/routers/traces/__init__.py +3 -0
  191. agno/os/routers/traces/schemas.py +414 -0
  192. agno/os/routers/traces/traces.py +499 -0
  193. agno/os/routers/workflows/__init__.py +3 -0
  194. agno/os/routers/workflows/router.py +624 -0
  195. agno/os/routers/workflows/schema.py +75 -0
  196. agno/os/schema.py +256 -693
  197. agno/os/scopes.py +469 -0
  198. agno/os/utils.py +514 -36
  199. agno/reasoning/anthropic.py +80 -0
  200. agno/reasoning/gemini.py +73 -0
  201. agno/reasoning/openai.py +5 -0
  202. agno/reasoning/vertexai.py +76 -0
  203. agno/run/__init__.py +6 -0
  204. agno/run/agent.py +155 -32
  205. agno/run/base.py +55 -3
  206. agno/run/requirement.py +181 -0
  207. agno/run/team.py +125 -38
  208. agno/run/workflow.py +72 -18
  209. agno/session/agent.py +102 -89
  210. agno/session/summary.py +56 -15
  211. agno/session/team.py +164 -90
  212. agno/session/workflow.py +405 -40
  213. agno/table.py +10 -0
  214. agno/team/team.py +3974 -1903
  215. agno/tools/dalle.py +2 -4
  216. agno/tools/eleven_labs.py +23 -25
  217. agno/tools/exa.py +21 -16
  218. agno/tools/file.py +153 -23
  219. agno/tools/file_generation.py +16 -10
  220. agno/tools/firecrawl.py +15 -7
  221. agno/tools/function.py +193 -38
  222. agno/tools/gmail.py +238 -14
  223. agno/tools/google_drive.py +271 -0
  224. agno/tools/googlecalendar.py +36 -8
  225. agno/tools/googlesheets.py +20 -5
  226. agno/tools/jira.py +20 -0
  227. agno/tools/mcp/__init__.py +10 -0
  228. agno/tools/mcp/mcp.py +331 -0
  229. agno/tools/mcp/multi_mcp.py +347 -0
  230. agno/tools/mcp/params.py +24 -0
  231. agno/tools/mcp_toolbox.py +3 -3
  232. agno/tools/models/nebius.py +5 -5
  233. agno/tools/models_labs.py +20 -10
  234. agno/tools/nano_banana.py +151 -0
  235. agno/tools/notion.py +204 -0
  236. agno/tools/parallel.py +314 -0
  237. agno/tools/postgres.py +76 -36
  238. agno/tools/redshift.py +406 -0
  239. agno/tools/scrapegraph.py +1 -1
  240. agno/tools/shopify.py +1519 -0
  241. agno/tools/slack.py +18 -3
  242. agno/tools/spotify.py +919 -0
  243. agno/tools/tavily.py +146 -0
  244. agno/tools/toolkit.py +25 -0
  245. agno/tools/workflow.py +8 -1
  246. agno/tools/yfinance.py +12 -11
  247. agno/tracing/__init__.py +12 -0
  248. agno/tracing/exporter.py +157 -0
  249. agno/tracing/schemas.py +276 -0
  250. agno/tracing/setup.py +111 -0
  251. agno/utils/agent.py +938 -0
  252. agno/utils/cryptography.py +22 -0
  253. agno/utils/dttm.py +33 -0
  254. agno/utils/events.py +151 -3
  255. agno/utils/gemini.py +15 -5
  256. agno/utils/hooks.py +118 -4
  257. agno/utils/http.py +113 -2
  258. agno/utils/knowledge.py +12 -5
  259. agno/utils/log.py +1 -0
  260. agno/utils/mcp.py +92 -2
  261. agno/utils/media.py +187 -1
  262. agno/utils/merge_dict.py +3 -3
  263. agno/utils/message.py +60 -0
  264. agno/utils/models/ai_foundry.py +9 -2
  265. agno/utils/models/claude.py +49 -14
  266. agno/utils/models/cohere.py +9 -2
  267. agno/utils/models/llama.py +9 -2
  268. agno/utils/models/mistral.py +4 -2
  269. agno/utils/print_response/agent.py +109 -16
  270. agno/utils/print_response/team.py +223 -30
  271. agno/utils/print_response/workflow.py +251 -34
  272. agno/utils/streamlit.py +1 -1
  273. agno/utils/team.py +98 -9
  274. agno/utils/tokens.py +657 -0
  275. agno/vectordb/base.py +39 -7
  276. agno/vectordb/cassandra/cassandra.py +21 -5
  277. agno/vectordb/chroma/chromadb.py +43 -12
  278. agno/vectordb/clickhouse/clickhousedb.py +21 -5
  279. agno/vectordb/couchbase/couchbase.py +29 -5
  280. agno/vectordb/lancedb/lance_db.py +92 -181
  281. agno/vectordb/langchaindb/langchaindb.py +24 -4
  282. agno/vectordb/lightrag/lightrag.py +17 -3
  283. agno/vectordb/llamaindex/llamaindexdb.py +25 -5
  284. agno/vectordb/milvus/milvus.py +50 -37
  285. agno/vectordb/mongodb/__init__.py +7 -1
  286. agno/vectordb/mongodb/mongodb.py +36 -30
  287. agno/vectordb/pgvector/pgvector.py +201 -77
  288. agno/vectordb/pineconedb/pineconedb.py +41 -23
  289. agno/vectordb/qdrant/qdrant.py +67 -54
  290. agno/vectordb/redis/__init__.py +9 -0
  291. agno/vectordb/redis/redisdb.py +682 -0
  292. agno/vectordb/singlestore/singlestore.py +50 -29
  293. agno/vectordb/surrealdb/surrealdb.py +31 -41
  294. agno/vectordb/upstashdb/upstashdb.py +34 -6
  295. agno/vectordb/weaviate/weaviate.py +53 -14
  296. agno/workflow/__init__.py +2 -0
  297. agno/workflow/agent.py +299 -0
  298. agno/workflow/condition.py +120 -18
  299. agno/workflow/loop.py +77 -10
  300. agno/workflow/parallel.py +231 -143
  301. agno/workflow/router.py +118 -17
  302. agno/workflow/step.py +609 -170
  303. agno/workflow/steps.py +73 -6
  304. agno/workflow/types.py +96 -21
  305. agno/workflow/workflow.py +2039 -262
  306. {agno-2.1.2.dist-info → agno-2.3.13.dist-info}/METADATA +201 -66
  307. agno-2.3.13.dist-info/RECORD +613 -0
  308. agno/tools/googlesearch.py +0 -98
  309. agno/tools/mcp.py +0 -679
  310. agno/tools/memori.py +0 -339
  311. agno-2.1.2.dist-info/RECORD +0 -543
  312. {agno-2.1.2.dist-info → agno-2.3.13.dist-info}/WHEEL +0 -0
  313. {agno-2.1.2.dist-info → agno-2.3.13.dist-info}/licenses/LICENSE +0 -0
  314. {agno-2.1.2.dist-info → agno-2.3.13.dist-info}/top_level.txt +0 -0
agno/os/schema.py CHANGED
@@ -1,101 +1,105 @@
1
1
  from datetime import datetime, timezone
2
2
  from enum import Enum
3
3
  from typing import Any, Dict, Generic, List, Optional, TypeVar, Union
4
- from uuid import uuid4
5
4
 
6
- from pydantic import BaseModel
5
+ from pydantic import BaseModel, ConfigDict, Field
7
6
 
8
7
  from agno.agent import Agent
9
8
  from agno.db.base import SessionType
10
- from agno.models.message import Message
11
- from agno.os.config import ChatConfig, EvalsConfig, KnowledgeConfig, MemoryConfig, MetricsConfig, SessionConfig
9
+ from agno.os.config import (
10
+ ChatConfig,
11
+ EvalsConfig,
12
+ KnowledgeConfig,
13
+ MemoryConfig,
14
+ MetricsConfig,
15
+ SessionConfig,
16
+ TracesConfig,
17
+ )
12
18
  from agno.os.utils import (
13
- format_team_tools,
14
- format_tools,
19
+ extract_input_media,
15
20
  get_run_input,
16
21
  get_session_name,
17
- get_workflow_input_schema_dict,
18
22
  )
19
- from agno.run.agent import RunOutput
20
- from agno.run.team import TeamRunOutput
21
23
  from agno.session import AgentSession, TeamSession, WorkflowSession
22
24
  from agno.team.team import Team
23
25
  from agno.workflow.workflow import Workflow
24
26
 
25
27
 
26
28
  class BadRequestResponse(BaseModel):
27
- detail: str
28
- error_code: Optional[str] = None
29
+ model_config = ConfigDict(json_schema_extra={"example": {"detail": "Bad request", "error_code": "BAD_REQUEST"}})
29
30
 
30
- class Config:
31
- json_schema_extra = {"example": {"detail": "Bad request", "error_code": "BAD_REQUEST"}}
31
+ detail: str = Field(..., description="Error detail message")
32
+ error_code: Optional[str] = Field(None, description="Error code for categorization")
32
33
 
33
34
 
34
35
  class NotFoundResponse(BaseModel):
35
- detail: str
36
- error_code: Optional[str] = None
36
+ model_config = ConfigDict(json_schema_extra={"example": {"detail": "Not found", "error_code": "NOT_FOUND"}})
37
37
 
38
- class Config:
39
- json_schema_extra = {"example": {"detail": "Not found", "error_code": "NOT_FOUND"}}
38
+ detail: str = Field(..., description="Error detail message")
39
+ error_code: Optional[str] = Field(None, description="Error code for categorization")
40
40
 
41
41
 
42
42
  class UnauthorizedResponse(BaseModel):
43
- detail: str
44
- error_code: Optional[str] = None
43
+ model_config = ConfigDict(
44
+ json_schema_extra={"example": {"detail": "Unauthorized access", "error_code": "UNAUTHORIZED"}}
45
+ )
45
46
 
46
- class Config:
47
- json_schema_extra = {"example": {"detail": "Unauthorized access", "error_code": "UNAUTHORIZED"}}
47
+ detail: str = Field(..., description="Error detail message")
48
+ error_code: Optional[str] = Field(None, description="Error code for categorization")
48
49
 
49
50
 
50
51
  class UnauthenticatedResponse(BaseModel):
51
- detail: str
52
- error_code: Optional[str] = None
52
+ model_config = ConfigDict(
53
+ json_schema_extra={"example": {"detail": "Unauthenticated access", "error_code": "UNAUTHENTICATED"}}
54
+ )
53
55
 
54
- class Config:
55
- json_schema_extra = {"example": {"detail": "Unauthenticated access", "error_code": "UNAUTHENTICATED"}}
56
+ detail: str = Field(..., description="Error detail message")
57
+ error_code: Optional[str] = Field(None, description="Error code for categorization")
56
58
 
57
59
 
58
60
  class ValidationErrorResponse(BaseModel):
59
- detail: str
60
- error_code: Optional[str] = None
61
+ model_config = ConfigDict(
62
+ json_schema_extra={"example": {"detail": "Validation error", "error_code": "VALIDATION_ERROR"}}
63
+ )
61
64
 
62
- class Config:
63
- json_schema_extra = {"example": {"detail": "Validation error", "error_code": "VALIDATION_ERROR"}}
65
+ detail: str = Field(..., description="Error detail message")
66
+ error_code: Optional[str] = Field(None, description="Error code for categorization")
64
67
 
65
68
 
66
69
  class InternalServerErrorResponse(BaseModel):
67
- detail: str
68
- error_code: Optional[str] = None
70
+ model_config = ConfigDict(
71
+ json_schema_extra={"example": {"detail": "Internal server error", "error_code": "INTERNAL_SERVER_ERROR"}}
72
+ )
69
73
 
70
- class Config:
71
- json_schema_extra = {"example": {"detail": "Internal server error", "error_code": "INTERNAL_SERVER_ERROR"}}
74
+ detail: str = Field(..., description="Error detail message")
75
+ error_code: Optional[str] = Field(None, description="Error code for categorization")
72
76
 
73
77
 
74
78
  class HealthResponse(BaseModel):
75
- status: str
79
+ model_config = ConfigDict(json_schema_extra={"example": {"status": "ok", "instantiated_at": "1760169236.778903"}})
76
80
 
77
- class Config:
78
- json_schema_extra = {"example": {"status": "ok"}}
81
+ status: str = Field(..., description="Health status of the service")
82
+ instantiated_at: str = Field(..., description="Unix timestamp when service was instantiated")
79
83
 
80
84
 
81
85
  class InterfaceResponse(BaseModel):
82
- type: str
83
- version: str
84
- route: str
86
+ type: str = Field(..., description="Type of the interface")
87
+ version: str = Field(..., description="Version of the interface")
88
+ route: str = Field(..., description="API route path")
85
89
 
86
90
 
87
91
  class ManagerResponse(BaseModel):
88
- type: str
89
- name: str
90
- version: str
91
- route: str
92
+ type: str = Field(..., description="Type of the manager")
93
+ name: str = Field(..., description="Name of the manager")
94
+ version: str = Field(..., description="Version of the manager")
95
+ route: str = Field(..., description="API route path")
92
96
 
93
97
 
94
98
  class AgentSummaryResponse(BaseModel):
95
- id: Optional[str] = None
96
- name: Optional[str] = None
97
- description: Optional[str] = None
98
- db_id: Optional[str] = None
99
+ id: Optional[str] = Field(None, description="Unique identifier for the agent")
100
+ name: Optional[str] = Field(None, description="Name of the agent")
101
+ description: Optional[str] = Field(None, description="Description of the agent")
102
+ db_id: Optional[str] = Field(None, description="Database identifier")
99
103
 
100
104
  @classmethod
101
105
  def from_agent(cls, agent: Agent) -> "AgentSummaryResponse":
@@ -103,10 +107,10 @@ class AgentSummaryResponse(BaseModel):
103
107
 
104
108
 
105
109
  class TeamSummaryResponse(BaseModel):
106
- id: Optional[str] = None
107
- name: Optional[str] = None
108
- description: Optional[str] = None
109
- db_id: Optional[str] = None
110
+ id: Optional[str] = Field(None, description="Unique identifier for the team")
111
+ name: Optional[str] = Field(None, description="Name of the team")
112
+ description: Optional[str] = Field(None, description="Description of the team")
113
+ db_id: Optional[str] = Field(None, description="Database identifier")
110
114
 
111
115
  @classmethod
112
116
  def from_team(cls, team: Team) -> "TeamSummaryResponse":
@@ -114,10 +118,10 @@ class TeamSummaryResponse(BaseModel):
114
118
 
115
119
 
116
120
  class WorkflowSummaryResponse(BaseModel):
117
- id: Optional[str] = None
118
- name: Optional[str] = None
119
- description: Optional[str] = None
120
- db_id: Optional[str] = None
121
+ id: Optional[str] = Field(None, description="Unique identifier for the workflow")
122
+ name: Optional[str] = Field(None, description="Name of the workflow")
123
+ description: Optional[str] = Field(None, description="Description of the workflow")
124
+ db_id: Optional[str] = Field(None, description="Database identifier")
121
125
 
122
126
  @classmethod
123
127
  def from_workflow(cls, workflow: Workflow) -> "WorkflowSummaryResponse":
@@ -132,574 +136,58 @@ class WorkflowSummaryResponse(BaseModel):
132
136
  class ConfigResponse(BaseModel):
133
137
  """Response schema for the general config endpoint"""
134
138
 
135
- os_id: str
136
- name: Optional[str] = None
137
- description: Optional[str] = None
138
- available_models: Optional[List[str]] = None
139
- databases: List[str]
140
- chat: Optional[ChatConfig] = None
139
+ os_id: str = Field(..., description="Unique identifier for the OS instance")
140
+ name: Optional[str] = Field(None, description="Name of the OS instance")
141
+ description: Optional[str] = Field(None, description="Description of the OS instance")
142
+ available_models: Optional[List[str]] = Field(None, description="List of available models")
143
+ databases: List[str] = Field(..., description="List of database IDs")
144
+ chat: Optional[ChatConfig] = Field(None, description="Chat configuration")
141
145
 
142
- session: Optional[SessionConfig] = None
143
- metrics: Optional[MetricsConfig] = None
144
- memory: Optional[MemoryConfig] = None
145
- knowledge: Optional[KnowledgeConfig] = None
146
- evals: Optional[EvalsConfig] = None
146
+ session: Optional[SessionConfig] = Field(None, description="Session configuration")
147
+ metrics: Optional[MetricsConfig] = Field(None, description="Metrics configuration")
148
+ memory: Optional[MemoryConfig] = Field(None, description="Memory configuration")
149
+ knowledge: Optional[KnowledgeConfig] = Field(None, description="Knowledge configuration")
150
+ evals: Optional[EvalsConfig] = Field(None, description="Evaluations configuration")
151
+ traces: Optional[TracesConfig] = Field(None, description="Traces configuration")
147
152
 
148
- agents: List[AgentSummaryResponse]
149
- teams: List[TeamSummaryResponse]
150
- workflows: List[WorkflowSummaryResponse]
151
- interfaces: List[InterfaceResponse]
153
+ agents: List[AgentSummaryResponse] = Field(..., description="List of registered agents")
154
+ teams: List[TeamSummaryResponse] = Field(..., description="List of registered teams")
155
+ workflows: List[WorkflowSummaryResponse] = Field(..., description="List of registered workflows")
156
+ interfaces: List[InterfaceResponse] = Field(..., description="List of available interfaces")
152
157
 
153
158
 
154
159
  class Model(BaseModel):
155
- id: Optional[str] = None
156
- provider: Optional[str] = None
160
+ id: Optional[str] = Field(None, description="Model identifier")
161
+ provider: Optional[str] = Field(None, description="Model provider name")
157
162
 
158
163
 
159
164
  class ModelResponse(BaseModel):
160
- name: Optional[str] = None
161
- model: Optional[str] = None
162
- provider: Optional[str] = None
163
-
164
-
165
- class AgentResponse(BaseModel):
166
- id: Optional[str] = None
167
- name: Optional[str] = None
168
- db_id: Optional[str] = None
169
- model: Optional[ModelResponse] = None
170
- tools: Optional[Dict[str, Any]] = None
171
- sessions: Optional[Dict[str, Any]] = None
172
- knowledge: Optional[Dict[str, Any]] = None
173
- memory: Optional[Dict[str, Any]] = None
174
- reasoning: Optional[Dict[str, Any]] = None
175
- default_tools: Optional[Dict[str, Any]] = None
176
- system_message: Optional[Dict[str, Any]] = None
177
- extra_messages: Optional[Dict[str, Any]] = None
178
- response_settings: Optional[Dict[str, Any]] = None
179
- streaming: Optional[Dict[str, Any]] = None
180
- metadata: Optional[Dict[str, Any]] = None
181
-
182
- class Config:
183
- exclude_none = True
184
-
185
- @classmethod
186
- def from_agent(cls, agent: Agent) -> "AgentResponse":
187
- def filter_meaningful_config(d: Dict[str, Any], defaults: Dict[str, Any]) -> Optional[Dict[str, Any]]:
188
- """Filter out fields that match their default values, keeping only meaningful user configurations"""
189
- filtered = {}
190
- for key, value in d.items():
191
- if value is None:
192
- continue
193
- # Skip if value matches the default exactly
194
- if key in defaults and value == defaults[key]:
195
- continue
196
- # Keep non-default values
197
- filtered[key] = value
198
- return filtered if filtered else None
199
-
200
- # Define default values for filtering
201
- agent_defaults = {
202
- # Sessions defaults
203
- "add_history_to_context": False,
204
- "num_history_runs": 3,
205
- "enable_session_summaries": False,
206
- "search_session_history": False,
207
- "cache_session": False,
208
- # Knowledge defaults
209
- "add_references": False,
210
- "references_format": "json",
211
- "enable_agentic_knowledge_filters": False,
212
- # Memory defaults
213
- "enable_agentic_memory": False,
214
- "enable_user_memories": False,
215
- # Reasoning defaults
216
- "reasoning": False,
217
- "reasoning_min_steps": 1,
218
- "reasoning_max_steps": 10,
219
- # Default tools defaults
220
- "read_chat_history": False,
221
- "search_knowledge": True,
222
- "update_knowledge": False,
223
- "read_tool_call_history": False,
224
- # System message defaults
225
- "system_message_role": "system",
226
- "build_context": True,
227
- "markdown": False,
228
- "add_name_to_context": False,
229
- "add_datetime_to_context": False,
230
- "add_location_to_context": False,
231
- "resolve_in_context": True,
232
- # Extra messages defaults
233
- "user_message_role": "user",
234
- "build_user_context": True,
235
- # Response settings defaults
236
- "retries": 0,
237
- "delay_between_retries": 1,
238
- "exponential_backoff": False,
239
- "parse_response": True,
240
- "use_json_mode": False,
241
- # Streaming defaults
242
- "stream_intermediate_steps": False,
243
- }
244
-
245
- agent_tools = agent.get_tools(
246
- session=AgentSession(session_id=str(uuid4()), session_data={}),
247
- run_response=RunOutput(run_id=str(uuid4())),
248
- async_mode=True,
249
- )
250
- formatted_tools = format_tools(agent_tools) if agent_tools else None
251
-
252
- additional_input = agent.additional_input
253
- if additional_input and isinstance(additional_input[0], Message):
254
- additional_input = [message.to_dict() for message in additional_input] # type: ignore
255
-
256
- # Build model only if it has at least one non-null field
257
- model_name = agent.model.name if (agent.model and agent.model.name) else None
258
- model_provider = agent.model.provider if (agent.model and agent.model.provider) else None
259
- model_id = agent.model.id if (agent.model and agent.model.id) else None
260
- _agent_model_data: Dict[str, Any] = {}
261
- if model_name is not None:
262
- _agent_model_data["name"] = model_name
263
- if model_id is not None:
264
- _agent_model_data["model"] = model_id
265
- if model_provider is not None:
266
- _agent_model_data["provider"] = model_provider
267
-
268
- session_table = agent.db.session_table_name if agent.db else None
269
- knowledge_table = agent.db.knowledge_table_name if agent.db and agent.knowledge else None
270
-
271
- tools_info = {
272
- "tools": formatted_tools,
273
- "tool_call_limit": agent.tool_call_limit,
274
- "tool_choice": agent.tool_choice,
275
- }
276
-
277
- sessions_info = {
278
- "session_table": session_table,
279
- "add_history_to_context": agent.add_history_to_context,
280
- "enable_session_summaries": agent.enable_session_summaries,
281
- "num_history_runs": agent.num_history_runs,
282
- "search_session_history": agent.search_session_history,
283
- "num_history_sessions": agent.num_history_sessions,
284
- "cache_session": agent.cache_session,
285
- }
286
-
287
- knowledge_info = {
288
- "knowledge_table": knowledge_table,
289
- "enable_agentic_knowledge_filters": agent.enable_agentic_knowledge_filters,
290
- "knowledge_filters": agent.knowledge_filters,
291
- "references_format": agent.references_format,
292
- }
293
-
294
- memory_info: Optional[Dict[str, Any]] = None
295
- if agent.memory_manager is not None:
296
- memory_info = {
297
- "enable_agentic_memory": agent.enable_agentic_memory,
298
- "enable_user_memories": agent.enable_user_memories,
299
- "metadata": agent.metadata,
300
- "memory_table": agent.db.memory_table_name if agent.db and agent.enable_user_memories else None,
301
- }
302
-
303
- if agent.memory_manager.model is not None:
304
- memory_info["model"] = ModelResponse(
305
- name=agent.memory_manager.model.name,
306
- model=agent.memory_manager.model.id,
307
- provider=agent.memory_manager.model.provider,
308
- ).model_dump()
309
-
310
- reasoning_info: Dict[str, Any] = {
311
- "reasoning": agent.reasoning,
312
- "reasoning_agent_id": agent.reasoning_agent.id if agent.reasoning_agent else None,
313
- "reasoning_min_steps": agent.reasoning_min_steps,
314
- "reasoning_max_steps": agent.reasoning_max_steps,
315
- }
316
-
317
- if agent.reasoning_model:
318
- reasoning_info["reasoning_model"] = ModelResponse(
319
- name=agent.reasoning_model.name,
320
- model=agent.reasoning_model.id,
321
- provider=agent.reasoning_model.provider,
322
- ).model_dump()
323
-
324
- default_tools_info = {
325
- "read_chat_history": agent.read_chat_history,
326
- "search_knowledge": agent.search_knowledge,
327
- "update_knowledge": agent.update_knowledge,
328
- "read_tool_call_history": agent.read_tool_call_history,
329
- }
330
-
331
- system_message_info = {
332
- "system_message": str(agent.system_message) if agent.system_message else None,
333
- "system_message_role": agent.system_message_role,
334
- "build_context": agent.build_context,
335
- "description": agent.description,
336
- "instructions": agent.instructions if agent.instructions else None,
337
- "expected_output": agent.expected_output,
338
- "additional_context": agent.additional_context,
339
- "markdown": agent.markdown,
340
- "add_name_to_context": agent.add_name_to_context,
341
- "add_datetime_to_context": agent.add_datetime_to_context,
342
- "add_location_to_context": agent.add_location_to_context,
343
- "timezone_identifier": agent.timezone_identifier,
344
- "resolve_in_context": agent.resolve_in_context,
345
- }
346
-
347
- extra_messages_info = {
348
- "additional_input": additional_input, # type: ignore
349
- "user_message_role": agent.user_message_role,
350
- "build_user_context": agent.build_user_context,
351
- }
352
-
353
- response_settings_info: Dict[str, Any] = {
354
- "retries": agent.retries,
355
- "delay_between_retries": agent.delay_between_retries,
356
- "exponential_backoff": agent.exponential_backoff,
357
- "output_schema_name": agent.output_schema.__name__ if agent.output_schema else None,
358
- "parser_model_prompt": agent.parser_model_prompt,
359
- "parse_response": agent.parse_response,
360
- "structured_outputs": agent.structured_outputs,
361
- "use_json_mode": agent.use_json_mode,
362
- "save_response_to_file": agent.save_response_to_file,
363
- }
364
-
365
- if agent.parser_model:
366
- response_settings_info["parser_model"] = ModelResponse(
367
- name=agent.parser_model.name,
368
- model=agent.parser_model.id,
369
- provider=agent.parser_model.provider,
370
- ).model_dump()
371
-
372
- streaming_info = {
373
- "stream": agent.stream,
374
- "stream_intermediate_steps": agent.stream_intermediate_steps,
375
- }
376
- return AgentResponse(
377
- id=agent.id,
378
- name=agent.name,
379
- db_id=agent.db.id if agent.db else None,
380
- model=ModelResponse(**_agent_model_data) if _agent_model_data else None,
381
- tools=filter_meaningful_config(tools_info, {}),
382
- sessions=filter_meaningful_config(sessions_info, agent_defaults),
383
- knowledge=filter_meaningful_config(knowledge_info, agent_defaults),
384
- memory=filter_meaningful_config(memory_info, agent_defaults) if memory_info else None,
385
- reasoning=filter_meaningful_config(reasoning_info, agent_defaults),
386
- default_tools=filter_meaningful_config(default_tools_info, agent_defaults),
387
- system_message=filter_meaningful_config(system_message_info, agent_defaults),
388
- extra_messages=filter_meaningful_config(extra_messages_info, agent_defaults),
389
- response_settings=filter_meaningful_config(response_settings_info, agent_defaults),
390
- streaming=filter_meaningful_config(streaming_info, agent_defaults),
391
- metadata=agent.metadata,
392
- )
393
-
394
-
395
- class TeamResponse(BaseModel):
396
- id: Optional[str] = None
397
- name: Optional[str] = None
398
- db_id: Optional[str] = None
399
- description: Optional[str] = None
400
- model: Optional[ModelResponse] = None
401
- tools: Optional[Dict[str, Any]] = None
402
- sessions: Optional[Dict[str, Any]] = None
403
- knowledge: Optional[Dict[str, Any]] = None
404
- memory: Optional[Dict[str, Any]] = None
405
- reasoning: Optional[Dict[str, Any]] = None
406
- default_tools: Optional[Dict[str, Any]] = None
407
- system_message: Optional[Dict[str, Any]] = None
408
- response_settings: Optional[Dict[str, Any]] = None
409
- streaming: Optional[Dict[str, Any]] = None
410
- members: Optional[List[Union[AgentResponse, "TeamResponse"]]] = None
411
- metadata: Optional[Dict[str, Any]] = None
412
-
413
- @classmethod
414
- def from_team(cls, team: Team) -> "TeamResponse":
415
- def filter_meaningful_config(d: Dict[str, Any], defaults: Dict[str, Any]) -> Optional[Dict[str, Any]]:
416
- """Filter out fields that match their default values, keeping only meaningful user configurations"""
417
- filtered = {}
418
- for key, value in d.items():
419
- if value is None:
420
- continue
421
- # Skip if value matches the default exactly
422
- if key in defaults and value == defaults[key]:
423
- continue
424
- # Keep non-default values
425
- filtered[key] = value
426
- return filtered if filtered else None
427
-
428
- # Define default values for filtering (similar to agent defaults)
429
- team_defaults = {
430
- # Sessions defaults
431
- "add_history_to_context": False,
432
- "num_history_runs": 3,
433
- "enable_session_summaries": False,
434
- "cache_session": False,
435
- # Knowledge defaults
436
- "add_references": False,
437
- "references_format": "json",
438
- "enable_agentic_knowledge_filters": False,
439
- # Memory defaults
440
- "enable_agentic_memory": False,
441
- "enable_user_memories": False,
442
- # Reasoning defaults
443
- "reasoning": False,
444
- "reasoning_min_steps": 1,
445
- "reasoning_max_steps": 10,
446
- # Default tools defaults
447
- "search_knowledge": True,
448
- "read_team_history": False,
449
- "get_member_information_tool": False,
450
- # System message defaults
451
- "system_message_role": "system",
452
- "markdown": False,
453
- "add_datetime_to_context": False,
454
- "add_location_to_context": False,
455
- "resolve_in_context": True,
456
- # Response settings defaults
457
- "parse_response": True,
458
- "use_json_mode": False,
459
- # Streaming defaults
460
- "stream_intermediate_steps": False,
461
- "stream_member_events": False,
462
- }
463
-
464
- team.determine_tools_for_model(
465
- model=team.model, # type: ignore
466
- session=TeamSession(session_id=str(uuid4()), session_data={}),
467
- run_response=TeamRunOutput(run_id=str(uuid4())),
468
- async_mode=True,
469
- session_state={},
470
- team_run_context={},
471
- )
472
- team_tools = list(team._functions_for_model.values()) if team._functions_for_model else []
473
- formatted_tools = format_team_tools(team_tools) if team_tools else None
474
-
475
- model_name = team.model.name or team.model.__class__.__name__ if team.model else None
476
- model_provider = team.model.provider or team.model.__class__.__name__ if team.model else ""
477
- model_id = team.model.id if team.model else None
478
-
479
- if model_provider and model_id:
480
- model_provider = f"{model_provider} {model_id}"
481
- elif model_name and model_id:
482
- model_provider = f"{model_name} {model_id}"
483
- elif model_id:
484
- model_provider = model_id
485
-
486
- session_table = team.db.session_table_name if team.db else None
487
- knowledge_table = team.db.knowledge_table_name if team.db and team.knowledge else None
488
-
489
- tools_info = {
490
- "tools": formatted_tools,
491
- "tool_call_limit": team.tool_call_limit,
492
- "tool_choice": team.tool_choice,
493
- }
494
-
495
- sessions_info = {
496
- "session_table": session_table,
497
- "add_history_to_context": team.add_history_to_context,
498
- "enable_session_summaries": team.enable_session_summaries,
499
- "num_history_runs": team.num_history_runs,
500
- "cache_session": team.cache_session,
501
- }
502
-
503
- knowledge_info = {
504
- "knowledge_table": knowledge_table,
505
- "enable_agentic_knowledge_filters": team.enable_agentic_knowledge_filters,
506
- "knowledge_filters": team.knowledge_filters,
507
- "references_format": team.references_format,
508
- }
509
-
510
- memory_info: Optional[Dict[str, Any]] = None
511
- if team.memory_manager is not None:
512
- memory_info = {
513
- "enable_agentic_memory": team.enable_agentic_memory,
514
- "enable_user_memories": team.enable_user_memories,
515
- "metadata": team.metadata,
516
- "memory_table": team.db.memory_table_name if team.db and team.enable_user_memories else None,
517
- }
518
-
519
- if team.memory_manager.model is not None:
520
- memory_info["model"] = ModelResponse(
521
- name=team.memory_manager.model.name,
522
- model=team.memory_manager.model.id,
523
- provider=team.memory_manager.model.provider,
524
- ).model_dump()
525
-
526
- reasoning_info: Dict[str, Any] = {
527
- "reasoning": team.reasoning,
528
- "reasoning_agent_id": team.reasoning_agent.id if team.reasoning_agent else None,
529
- "reasoning_min_steps": team.reasoning_min_steps,
530
- "reasoning_max_steps": team.reasoning_max_steps,
531
- }
532
-
533
- if team.reasoning_model:
534
- reasoning_info["reasoning_model"] = ModelResponse(
535
- name=team.reasoning_model.name,
536
- model=team.reasoning_model.id,
537
- provider=team.reasoning_model.provider,
538
- ).model_dump()
539
-
540
- default_tools_info = {
541
- "search_knowledge": team.search_knowledge,
542
- "read_team_history": team.read_team_history,
543
- "get_member_information_tool": team.get_member_information_tool,
544
- }
545
-
546
- team_instructions = (
547
- team.instructions() if team.instructions and callable(team.instructions) else team.instructions
548
- )
549
-
550
- system_message_info = {
551
- "system_message": str(team.system_message) if team.system_message else None,
552
- "system_message_role": team.system_message_role,
553
- "description": team.description,
554
- "instructions": team_instructions,
555
- "expected_output": team.expected_output,
556
- "additional_context": team.additional_context,
557
- "markdown": team.markdown,
558
- "add_datetime_to_context": team.add_datetime_to_context,
559
- "add_location_to_context": team.add_location_to_context,
560
- "resolve_in_context": team.resolve_in_context,
561
- }
562
-
563
- response_settings_info: Dict[str, Any] = {
564
- "output_schema_name": team.output_schema.__name__ if team.output_schema else None,
565
- "parser_model_prompt": team.parser_model_prompt,
566
- "parse_response": team.parse_response,
567
- "use_json_mode": team.use_json_mode,
568
- }
569
-
570
- if team.parser_model:
571
- response_settings_info["parser_model"] = ModelResponse(
572
- name=team.parser_model.name,
573
- model=team.parser_model.id,
574
- provider=team.parser_model.provider,
575
- ).model_dump()
576
-
577
- streaming_info = {
578
- "stream": team.stream,
579
- "stream_intermediate_steps": team.stream_intermediate_steps,
580
- "stream_member_events": team.stream_member_events,
581
- }
582
-
583
- # Build team model only if it has at least one non-null field
584
- _team_model_data: Dict[str, Any] = {}
585
- if team.model and team.model.name is not None:
586
- _team_model_data["name"] = team.model.name
587
- if team.model and team.model.id is not None:
588
- _team_model_data["model"] = team.model.id
589
- if team.model and team.model.provider is not None:
590
- _team_model_data["provider"] = team.model.provider
591
-
592
- return TeamResponse(
593
- id=team.id,
594
- name=team.name,
595
- db_id=team.db.id if team.db else None,
596
- model=ModelResponse(**_team_model_data) if _team_model_data else None,
597
- tools=filter_meaningful_config(tools_info, {}),
598
- sessions=filter_meaningful_config(sessions_info, team_defaults),
599
- knowledge=filter_meaningful_config(knowledge_info, team_defaults),
600
- memory=filter_meaningful_config(memory_info, team_defaults) if memory_info else None,
601
- reasoning=filter_meaningful_config(reasoning_info, team_defaults),
602
- default_tools=filter_meaningful_config(default_tools_info, team_defaults),
603
- system_message=filter_meaningful_config(system_message_info, team_defaults),
604
- response_settings=filter_meaningful_config(response_settings_info, team_defaults),
605
- streaming=filter_meaningful_config(streaming_info, team_defaults),
606
- members=[ # type: ignore
607
- AgentResponse.from_agent(member)
608
- if isinstance(member, Agent)
609
- else TeamResponse.from_team(member)
610
- if isinstance(member, Team)
611
- else None
612
- for member in team.members
613
- ],
614
- metadata=team.metadata,
615
- )
616
-
617
-
618
- class WorkflowResponse(BaseModel):
619
- id: Optional[str] = None
620
- name: Optional[str] = None
621
- db_id: Optional[str] = None
622
- description: Optional[str] = None
623
- input_schema: Optional[Dict[str, Any]] = None
624
- steps: Optional[List[Dict[str, Any]]] = None
625
- agent: Optional[AgentResponse] = None
626
- team: Optional[TeamResponse] = None
627
- metadata: Optional[Dict[str, Any]] = None
628
-
629
- class Config:
630
- exclude_none = True
631
-
632
- @classmethod
633
- def _resolve_agents_and_teams_recursively(cls, steps: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
634
- """Parse Agents and Teams into AgentResponse and TeamResponse objects.
635
-
636
- If the given steps have nested steps, recursively work on those."""
637
- if not steps:
638
- return steps
639
-
640
- def _prune_none(value: Any) -> Any:
641
- # Recursively remove None values from dicts and lists
642
- if isinstance(value, dict):
643
- return {k: _prune_none(v) for k, v in value.items() if v is not None}
644
- if isinstance(value, list):
645
- return [_prune_none(v) for v in value]
646
- return value
647
-
648
- for idx, step in enumerate(steps):
649
- if step.get("agent"):
650
- # Convert to dict and exclude fields that are None
651
- step["agent"] = AgentResponse.from_agent(step["agent"]).model_dump(exclude_none=True)
652
-
653
- if step.get("team"):
654
- step["team"] = TeamResponse.from_team(step["team"]).model_dump(exclude_none=True)
655
-
656
- if step.get("steps"):
657
- step["steps"] = cls._resolve_agents_and_teams_recursively(step["steps"])
658
-
659
- # Prune None values in the entire step
660
- steps[idx] = _prune_none(step)
661
-
662
- return steps
663
-
664
- @classmethod
665
- def from_workflow(cls, workflow: Workflow) -> "WorkflowResponse":
666
- workflow_dict = workflow.to_dict()
667
- steps = workflow_dict.get("steps")
668
-
669
- if steps:
670
- steps = cls._resolve_agents_and_teams_recursively(steps)
671
-
672
- return cls(
673
- id=workflow.id,
674
- name=workflow.name,
675
- db_id=workflow.db.id if workflow.db else None,
676
- description=workflow.description,
677
- steps=steps,
678
- input_schema=get_workflow_input_schema_dict(workflow),
679
- metadata=workflow.metadata,
680
- )
165
+ name: Optional[str] = Field(None, description="Name of the model")
166
+ model: Optional[str] = Field(None, description="Model identifier")
167
+ provider: Optional[str] = Field(None, description="Model provider name")
681
168
 
682
169
 
683
170
  class WorkflowRunRequest(BaseModel):
684
- input: Dict[str, Any]
685
- user_id: Optional[str] = None
686
- session_id: Optional[str] = None
171
+ input: Dict[str, Any] = Field(..., description="Input parameters for the workflow run")
172
+ user_id: Optional[str] = Field(None, description="User identifier for the workflow run")
173
+ session_id: Optional[str] = Field(None, description="Session identifier for context persistence")
687
174
 
688
175
 
689
176
  class SessionSchema(BaseModel):
690
- session_id: str
691
- session_name: str
692
- session_state: Optional[dict]
693
- created_at: Optional[datetime]
694
- updated_at: Optional[datetime]
177
+ session_id: str = Field(..., description="Unique identifier for the session")
178
+ session_name: str = Field(..., description="Human-readable name for the session")
179
+ session_state: Optional[dict] = Field(None, description="Current state data of the session")
180
+ created_at: Optional[datetime] = Field(None, description="Timestamp when session was created")
181
+ updated_at: Optional[datetime] = Field(None, description="Timestamp when session was last updated")
695
182
 
696
183
  @classmethod
697
184
  def from_dict(cls, session: Dict[str, Any]) -> "SessionSchema":
698
185
  session_name = get_session_name(session)
186
+ session_data = session.get("session_data", {}) or {}
699
187
  return cls(
700
188
  session_id=session.get("session_id", ""),
701
189
  session_name=session_name,
702
- session_state=session.get("session_data", {}).get("session_state", None),
190
+ session_state=session_data.get("session_state", None),
703
191
  created_at=datetime.fromtimestamp(session.get("created_at", 0), tz=timezone.utc)
704
192
  if session.get("created_at")
705
193
  else None,
@@ -710,24 +198,43 @@ class SessionSchema(BaseModel):
710
198
 
711
199
 
712
200
  class DeleteSessionRequest(BaseModel):
713
- session_ids: List[str]
714
- session_types: List[SessionType]
201
+ session_ids: List[str] = Field(..., description="List of session IDs to delete", min_length=1)
202
+ session_types: List[SessionType] = Field(..., description="Types of sessions to delete", min_length=1)
203
+
204
+
205
+ class CreateSessionRequest(BaseModel):
206
+ session_id: Optional[str] = Field(None, description="Optional session ID (generated if not provided)")
207
+ session_name: Optional[str] = Field(None, description="Name for the session")
208
+ session_state: Optional[Dict[str, Any]] = Field(None, description="Initial session state")
209
+ metadata: Optional[Dict[str, Any]] = Field(None, description="Additional metadata")
210
+ user_id: Optional[str] = Field(None, description="User ID associated with the session")
211
+ agent_id: Optional[str] = Field(None, description="Agent ID if this is an agent session")
212
+ team_id: Optional[str] = Field(None, description="Team ID if this is a team session")
213
+ workflow_id: Optional[str] = Field(None, description="Workflow ID if this is a workflow session")
214
+
215
+
216
+ class UpdateSessionRequest(BaseModel):
217
+ session_name: Optional[str] = Field(None, description="Updated session name")
218
+ session_state: Optional[Dict[str, Any]] = Field(None, description="Updated session state")
219
+ metadata: Optional[Dict[str, Any]] = Field(None, description="Updated metadata")
220
+ summary: Optional[Dict[str, Any]] = Field(None, description="Session summary")
715
221
 
716
222
 
717
223
  class AgentSessionDetailSchema(BaseModel):
718
- user_id: Optional[str]
719
- agent_session_id: str
720
- session_id: str
721
- session_name: str
722
- session_summary: Optional[dict]
723
- session_state: Optional[dict]
724
- agent_id: Optional[str]
725
- total_tokens: Optional[int]
726
- agent_data: Optional[dict]
727
- metrics: Optional[dict]
728
- chat_history: Optional[List[dict]]
729
- created_at: Optional[datetime]
730
- updated_at: Optional[datetime]
224
+ user_id: Optional[str] = Field(None, description="User ID associated with the session")
225
+ agent_session_id: str = Field(..., description="Unique agent session identifier")
226
+ session_id: str = Field(..., description="Session identifier")
227
+ session_name: str = Field(..., description="Human-readable session name")
228
+ session_summary: Optional[dict] = Field(None, description="Summary of session interactions")
229
+ session_state: Optional[dict] = Field(None, description="Current state of the session")
230
+ agent_id: Optional[str] = Field(None, description="Agent ID used in this session")
231
+ total_tokens: Optional[int] = Field(None, description="Total tokens used in this session")
232
+ agent_data: Optional[dict] = Field(None, description="Agent-specific data")
233
+ metrics: Optional[dict] = Field(None, description="Session metrics")
234
+ metadata: Optional[dict] = Field(None, description="Additional metadata")
235
+ chat_history: Optional[List[dict]] = Field(None, description="Complete chat history")
236
+ created_at: Optional[datetime] = Field(None, description="Session creation timestamp")
237
+ updated_at: Optional[datetime] = Field(None, description="Last update timestamp")
731
238
 
732
239
  @classmethod
733
240
  def from_session(cls, session: AgentSession) -> "AgentSessionDetailSchema":
@@ -745,6 +252,7 @@ class AgentSessionDetailSchema(BaseModel):
745
252
  if session.session_data
746
253
  else None,
747
254
  metrics=session.session_data.get("session_metrics", {}) if session.session_data else None, # type: ignore
255
+ metadata=session.metadata,
748
256
  chat_history=[message.to_dict() for message in session.get_chat_history()],
749
257
  created_at=datetime.fromtimestamp(session.created_at, tz=timezone.utc) if session.created_at else None,
750
258
  updated_at=datetime.fromtimestamp(session.updated_at, tz=timezone.utc) if session.updated_at else None,
@@ -752,18 +260,19 @@ class AgentSessionDetailSchema(BaseModel):
752
260
 
753
261
 
754
262
  class TeamSessionDetailSchema(BaseModel):
755
- session_id: str
756
- session_name: str
757
- user_id: Optional[str]
758
- team_id: Optional[str]
759
- session_summary: Optional[dict]
760
- session_state: Optional[dict]
761
- metrics: Optional[dict]
762
- team_data: Optional[dict]
763
- chat_history: Optional[List[dict]]
764
- created_at: Optional[datetime]
765
- updated_at: Optional[datetime]
766
- total_tokens: Optional[int]
263
+ session_id: str = Field(..., description="Unique session identifier")
264
+ session_name: str = Field(..., description="Human-readable session name")
265
+ user_id: Optional[str] = Field(None, description="User ID associated with the session")
266
+ team_id: Optional[str] = Field(None, description="Team ID used in this session")
267
+ session_summary: Optional[dict] = Field(None, description="Summary of team interactions")
268
+ session_state: Optional[dict] = Field(None, description="Current state of the session")
269
+ metrics: Optional[dict] = Field(None, description="Session metrics")
270
+ team_data: Optional[dict] = Field(None, description="Team-specific data")
271
+ metadata: Optional[dict] = Field(None, description="Additional metadata")
272
+ chat_history: Optional[List[dict]] = Field(None, description="Complete chat history")
273
+ created_at: Optional[datetime] = Field(None, description="Session creation timestamp")
274
+ updated_at: Optional[datetime] = Field(None, description="Last update timestamp")
275
+ total_tokens: Optional[int] = Field(None, description="Total tokens used in this session")
767
276
 
768
277
  @classmethod
769
278
  def from_session(cls, session: TeamSession) -> "TeamSessionDetailSchema":
@@ -782,6 +291,7 @@ class TeamSessionDetailSchema(BaseModel):
782
291
  if session.session_data
783
292
  else None,
784
293
  metrics=session.session_data.get("session_metrics", {}) if session.session_data else None,
294
+ metadata=session.metadata,
785
295
  chat_history=[message.to_dict() for message in session.get_chat_history()],
786
296
  created_at=datetime.fromtimestamp(session.created_at, tz=timezone.utc) if session.created_at else None,
787
297
  updated_at=datetime.fromtimestamp(session.updated_at, tz=timezone.utc) if session.updated_at else None,
@@ -789,20 +299,19 @@ class TeamSessionDetailSchema(BaseModel):
789
299
 
790
300
 
791
301
  class WorkflowSessionDetailSchema(BaseModel):
792
- user_id: Optional[str]
793
- workflow_id: Optional[str]
794
- workflow_name: Optional[str]
302
+ user_id: Optional[str] = Field(None, description="User ID associated with the session")
303
+ workflow_id: Optional[str] = Field(None, description="Workflow ID used in this session")
304
+ workflow_name: Optional[str] = Field(None, description="Name of the workflow")
305
+ session_id: str = Field(..., description="Unique session identifier")
306
+ session_name: str = Field(..., description="Human-readable session name")
795
307
 
796
- session_id: str
797
- session_name: str
308
+ session_data: Optional[dict] = Field(None, description="Complete session data")
309
+ session_state: Optional[dict] = Field(None, description="Current workflow state")
310
+ workflow_data: Optional[dict] = Field(None, description="Workflow-specific data")
311
+ metadata: Optional[dict] = Field(None, description="Additional metadata")
798
312
 
799
- session_data: Optional[dict]
800
- session_state: Optional[dict]
801
- workflow_data: Optional[dict]
802
- metadata: Optional[dict]
803
-
804
- created_at: Optional[int]
805
- updated_at: Optional[int]
313
+ created_at: Optional[int] = Field(None, description="Unix timestamp of session creation")
314
+ updated_at: Optional[int] = Field(None, description="Unix timestamp of last update")
806
315
 
807
316
  @classmethod
808
317
  def from_session(cls, session: WorkflowSession) -> "WorkflowSessionDetailSchema":
@@ -825,27 +334,38 @@ class WorkflowSessionDetailSchema(BaseModel):
825
334
 
826
335
 
827
336
  class RunSchema(BaseModel):
828
- run_id: str
829
- parent_run_id: Optional[str]
830
- agent_id: Optional[str]
831
- user_id: Optional[str]
832
- run_input: Optional[str]
833
- content: Optional[Union[str, dict]]
834
- run_response_format: Optional[str]
835
- reasoning_content: Optional[str]
836
- reasoning_steps: Optional[List[dict]]
837
- metrics: Optional[dict]
838
- messages: Optional[List[dict]]
839
- tools: Optional[List[dict]]
840
- events: Optional[List[dict]]
841
- created_at: Optional[datetime]
842
- references: Optional[List[dict]]
843
- reasoning_messages: Optional[List[dict]]
337
+ run_id: str = Field(..., description="Unique identifier for the run")
338
+ parent_run_id: Optional[str] = Field(None, description="Parent run ID if this is a nested run")
339
+ agent_id: Optional[str] = Field(None, description="Agent ID that executed this run")
340
+ user_id: Optional[str] = Field(None, description="User ID associated with the run")
341
+ run_input: Optional[str] = Field(None, description="Input provided to the run")
342
+ content: Optional[Union[str, dict]] = Field(None, description="Output content from the run")
343
+ run_response_format: Optional[str] = Field(None, description="Format of the response (text/json)")
344
+ reasoning_content: Optional[str] = Field(None, description="Reasoning content if reasoning was enabled")
345
+ reasoning_steps: Optional[List[dict]] = Field(None, description="List of reasoning steps")
346
+ metrics: Optional[dict] = Field(None, description="Performance and usage metrics")
347
+ messages: Optional[List[dict]] = Field(None, description="Message history for the run")
348
+ tools: Optional[List[dict]] = Field(None, description="Tools used in the run")
349
+ events: Optional[List[dict]] = Field(None, description="Events generated during the run")
350
+ created_at: Optional[datetime] = Field(None, description="Run creation timestamp")
351
+ references: Optional[List[dict]] = Field(None, description="References cited in the run")
352
+ citations: Optional[Dict[str, Any]] = Field(
353
+ None, description="Citations from the model (e.g., from Gemini grounding/search)"
354
+ )
355
+ reasoning_messages: Optional[List[dict]] = Field(None, description="Reasoning process messages")
356
+ session_state: Optional[dict] = Field(None, description="Session state at the end of the run")
357
+ images: Optional[List[dict]] = Field(None, description="Images included in the run")
358
+ videos: Optional[List[dict]] = Field(None, description="Videos included in the run")
359
+ audio: Optional[List[dict]] = Field(None, description="Audio files included in the run")
360
+ files: Optional[List[dict]] = Field(None, description="Files included in the run")
361
+ response_audio: Optional[dict] = Field(None, description="Audio response if generated")
362
+ input_media: Optional[Dict[str, Any]] = Field(None, description="Input media attachments")
844
363
 
845
364
  @classmethod
846
365
  def from_dict(cls, run_dict: Dict[str, Any]) -> "RunSchema":
847
366
  run_input = get_run_input(run_dict)
848
367
  run_response_format = "text" if run_dict.get("content_type", "str") == "str" else "json"
368
+
849
369
  return cls(
850
370
  run_id=run_dict.get("run_id", ""),
851
371
  parent_run_id=run_dict.get("parent_run_id", ""),
@@ -861,7 +381,15 @@ class RunSchema(BaseModel):
861
381
  tools=[tool for tool in run_dict.get("tools", [])] if run_dict.get("tools") else None,
862
382
  events=[event for event in run_dict["events"]] if run_dict.get("events") else None,
863
383
  references=run_dict.get("references", []),
384
+ citations=run_dict.get("citations", None),
864
385
  reasoning_messages=run_dict.get("reasoning_messages", []),
386
+ session_state=run_dict.get("session_state"),
387
+ images=run_dict.get("images", []),
388
+ videos=run_dict.get("videos", []),
389
+ audio=run_dict.get("audio", []),
390
+ files=run_dict.get("files", []),
391
+ response_audio=run_dict.get("response_audio", None),
392
+ input_media=extract_input_media(run_dict),
865
393
  created_at=datetime.fromtimestamp(run_dict.get("created_at", 0), tz=timezone.utc)
866
394
  if run_dict.get("created_at") is not None
867
395
  else None,
@@ -869,21 +397,31 @@ class RunSchema(BaseModel):
869
397
 
870
398
 
871
399
  class TeamRunSchema(BaseModel):
872
- run_id: str
873
- parent_run_id: Optional[str]
874
- team_id: Optional[str]
875
- content: Optional[Union[str, dict]]
876
- reasoning_content: Optional[str]
877
- reasoning_steps: Optional[List[dict]]
878
- run_input: Optional[str]
879
- run_response_format: Optional[str]
880
- metrics: Optional[dict]
881
- tools: Optional[List[dict]]
882
- messages: Optional[List[dict]]
883
- events: Optional[List[dict]]
884
- created_at: Optional[datetime]
885
- references: Optional[List[dict]]
886
- reasoning_messages: Optional[List[dict]]
400
+ run_id: str = Field(..., description="Unique identifier for the team run")
401
+ parent_run_id: Optional[str] = Field(None, description="Parent run ID if this is a nested run")
402
+ team_id: Optional[str] = Field(None, description="Team ID that executed this run")
403
+ content: Optional[Union[str, dict]] = Field(None, description="Output content from the team run")
404
+ reasoning_content: Optional[str] = Field(None, description="Reasoning content if reasoning was enabled")
405
+ reasoning_steps: Optional[List[dict]] = Field(None, description="List of reasoning steps")
406
+ run_input: Optional[str] = Field(None, description="Input provided to the run")
407
+ run_response_format: Optional[str] = Field(None, description="Format of the response (text/json)")
408
+ metrics: Optional[dict] = Field(None, description="Performance and usage metrics")
409
+ tools: Optional[List[dict]] = Field(None, description="Tools used in the run")
410
+ messages: Optional[List[dict]] = Field(None, description="Message history for the run")
411
+ events: Optional[List[dict]] = Field(None, description="Events generated during the run")
412
+ created_at: Optional[datetime] = Field(None, description="Run creation timestamp")
413
+ references: Optional[List[dict]] = Field(None, description="References cited in the run")
414
+ citations: Optional[Dict[str, Any]] = Field(
415
+ None, description="Citations from the model (e.g., from Gemini grounding/search)"
416
+ )
417
+ reasoning_messages: Optional[List[dict]] = Field(None, description="Reasoning process messages")
418
+ session_state: Optional[dict] = Field(None, description="Session state at the end of the run")
419
+ input_media: Optional[Dict[str, Any]] = Field(None, description="Input media attachments")
420
+ images: Optional[List[dict]] = Field(None, description="Images included in the run")
421
+ videos: Optional[List[dict]] = Field(None, description="Videos included in the run")
422
+ audio: Optional[List[dict]] = Field(None, description="Audio files included in the run")
423
+ files: Optional[List[dict]] = Field(None, description="Files included in the run")
424
+ response_audio: Optional[dict] = Field(None, description="Audio response if generated")
887
425
 
888
426
  @classmethod
889
427
  def from_dict(cls, run_dict: Dict[str, Any]) -> "TeamRunSchema":
@@ -906,26 +444,43 @@ class TeamRunSchema(BaseModel):
906
444
  if run_dict.get("created_at") is not None
907
445
  else None,
908
446
  references=run_dict.get("references", []),
447
+ citations=run_dict.get("citations", None),
909
448
  reasoning_messages=run_dict.get("reasoning_messages", []),
449
+ session_state=run_dict.get("session_state"),
450
+ images=run_dict.get("images", []),
451
+ videos=run_dict.get("videos", []),
452
+ audio=run_dict.get("audio", []),
453
+ files=run_dict.get("files", []),
454
+ response_audio=run_dict.get("response_audio", None),
455
+ input_media=extract_input_media(run_dict),
910
456
  )
911
457
 
912
458
 
913
459
  class WorkflowRunSchema(BaseModel):
914
- run_id: str
915
- run_input: Optional[str]
916
- workflow_id: Optional[str]
917
- user_id: Optional[str]
918
- content: Optional[Union[str, dict]]
919
- content_type: Optional[str]
920
- status: Optional[str]
921
- step_results: Optional[list[dict]]
922
- step_executor_runs: Optional[list[dict]]
923
- metrics: Optional[dict]
924
- created_at: Optional[int]
925
- reasoning_content: Optional[str]
926
- reasoning_steps: Optional[List[dict]]
927
- references: Optional[List[dict]]
928
- reasoning_messages: Optional[List[dict]]
460
+ run_id: str = Field(..., description="Unique identifier for the workflow run")
461
+ run_input: Optional[str] = Field(None, description="Input provided to the workflow")
462
+ events: Optional[List[dict]] = Field(None, description="Events generated during the workflow")
463
+ workflow_id: Optional[str] = Field(None, description="Workflow ID that was executed")
464
+ user_id: Optional[str] = Field(None, description="User ID associated with the run")
465
+ content: Optional[Union[str, dict]] = Field(None, description="Output content from the workflow")
466
+ content_type: Optional[str] = Field(None, description="Type of content returned")
467
+ status: Optional[str] = Field(None, description="Status of the workflow run")
468
+ step_results: Optional[list[dict]] = Field(None, description="Results from each workflow step")
469
+ step_executor_runs: Optional[list[dict]] = Field(None, description="Executor runs for each step")
470
+ metrics: Optional[dict] = Field(None, description="Performance and usage metrics")
471
+ created_at: Optional[int] = Field(None, description="Unix timestamp of run creation")
472
+ reasoning_content: Optional[str] = Field(None, description="Reasoning content if reasoning was enabled")
473
+ reasoning_steps: Optional[List[dict]] = Field(None, description="List of reasoning steps")
474
+ references: Optional[List[dict]] = Field(None, description="References cited in the workflow")
475
+ citations: Optional[Dict[str, Any]] = Field(
476
+ None, description="Citations from the model (e.g., from Gemini grounding/search)"
477
+ )
478
+ reasoning_messages: Optional[List[dict]] = Field(None, description="Reasoning process messages")
479
+ images: Optional[List[dict]] = Field(None, description="Images included in the workflow")
480
+ videos: Optional[List[dict]] = Field(None, description="Videos included in the workflow")
481
+ audio: Optional[List[dict]] = Field(None, description="Audio files included in the workflow")
482
+ files: Optional[List[dict]] = Field(None, description="Files included in the workflow")
483
+ response_audio: Optional[dict] = Field(None, description="Audio response if generated")
929
484
 
930
485
  @classmethod
931
486
  def from_dict(cls, run_response: Dict[str, Any]) -> "WorkflowRunSchema":
@@ -933,6 +488,7 @@ class WorkflowRunSchema(BaseModel):
933
488
  return cls(
934
489
  run_id=run_response.get("run_id", ""),
935
490
  run_input=run_input,
491
+ events=run_response.get("events", []),
936
492
  workflow_id=run_response.get("workflow_id", ""),
937
493
  user_id=run_response.get("user_id", ""),
938
494
  content=run_response.get("content", ""),
@@ -945,7 +501,13 @@ class WorkflowRunSchema(BaseModel):
945
501
  reasoning_content=run_response.get("reasoning_content", ""),
946
502
  reasoning_steps=run_response.get("reasoning_steps", []),
947
503
  references=run_response.get("references", []),
504
+ citations=run_response.get("citations", None),
948
505
  reasoning_messages=run_response.get("reasoning_messages", []),
506
+ images=run_response.get("images", []),
507
+ videos=run_response.get("videos", []),
508
+ audio=run_response.get("audio", []),
509
+ files=run_response.get("files", []),
510
+ response_audio=run_response.get("response_audio", None),
949
511
  )
950
512
 
951
513
 
@@ -958,14 +520,15 @@ class SortOrder(str, Enum):
958
520
 
959
521
 
960
522
  class PaginationInfo(BaseModel):
961
- page: Optional[int] = 0
962
- limit: Optional[int] = 20
963
- total_pages: Optional[int] = 0
964
- total_count: Optional[int] = 0
523
+ page: int = Field(0, description="Current page number (0-indexed)", ge=0)
524
+ limit: int = Field(20, description="Number of items per page", ge=1, le=100)
525
+ total_pages: int = Field(0, description="Total number of pages", ge=0)
526
+ total_count: int = Field(0, description="Total count of items", ge=0)
527
+ search_time_ms: float = Field(0, description="Search execution time in milliseconds", ge=0)
965
528
 
966
529
 
967
530
  class PaginatedResponse(BaseModel, Generic[T]):
968
531
  """Wrapper to add pagination info to classes used as response models"""
969
532
 
970
- data: List[T]
971
- meta: PaginationInfo
533
+ data: List[T] = Field(..., description="List of items for the current page")
534
+ meta: PaginationInfo = Field(..., description="Pagination metadata")