agno 0.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.
- agno/__init__.py +8 -0
- agno/agent/__init__.py +44 -5
- agno/agent/agent.py +10531 -2975
- agno/api/agent.py +14 -53
- agno/api/api.py +7 -46
- agno/api/evals.py +22 -0
- agno/api/os.py +17 -0
- agno/api/routes.py +6 -25
- agno/api/schemas/__init__.py +9 -0
- agno/api/schemas/agent.py +6 -9
- agno/api/schemas/evals.py +16 -0
- agno/api/schemas/os.py +14 -0
- agno/api/schemas/team.py +10 -10
- agno/api/schemas/utils.py +21 -0
- agno/api/schemas/workflows.py +16 -0
- agno/api/settings.py +53 -0
- agno/api/team.py +22 -26
- agno/api/workflow.py +28 -0
- agno/cloud/aws/base.py +214 -0
- agno/cloud/aws/s3/__init__.py +2 -0
- agno/cloud/aws/s3/api_client.py +43 -0
- agno/cloud/aws/s3/bucket.py +195 -0
- agno/cloud/aws/s3/object.py +57 -0
- agno/compression/__init__.py +3 -0
- agno/compression/manager.py +247 -0
- agno/culture/__init__.py +3 -0
- agno/culture/manager.py +956 -0
- agno/db/__init__.py +24 -0
- agno/db/async_postgres/__init__.py +3 -0
- agno/db/base.py +946 -0
- agno/db/dynamo/__init__.py +3 -0
- agno/db/dynamo/dynamo.py +2781 -0
- agno/db/dynamo/schemas.py +442 -0
- agno/db/dynamo/utils.py +743 -0
- agno/db/firestore/__init__.py +3 -0
- agno/db/firestore/firestore.py +2379 -0
- agno/db/firestore/schemas.py +181 -0
- agno/db/firestore/utils.py +376 -0
- agno/db/gcs_json/__init__.py +3 -0
- agno/db/gcs_json/gcs_json_db.py +1791 -0
- agno/db/gcs_json/utils.py +228 -0
- agno/db/in_memory/__init__.py +3 -0
- agno/db/in_memory/in_memory_db.py +1312 -0
- agno/db/in_memory/utils.py +230 -0
- agno/db/json/__init__.py +3 -0
- agno/db/json/json_db.py +1777 -0
- agno/db/json/utils.py +230 -0
- agno/db/migrations/manager.py +199 -0
- agno/db/migrations/v1_to_v2.py +635 -0
- agno/db/migrations/versions/v2_3_0.py +938 -0
- agno/db/mongo/__init__.py +17 -0
- agno/db/mongo/async_mongo.py +2760 -0
- agno/db/mongo/mongo.py +2597 -0
- agno/db/mongo/schemas.py +119 -0
- agno/db/mongo/utils.py +276 -0
- agno/db/mysql/__init__.py +4 -0
- agno/db/mysql/async_mysql.py +2912 -0
- agno/db/mysql/mysql.py +2923 -0
- agno/db/mysql/schemas.py +186 -0
- agno/db/mysql/utils.py +488 -0
- agno/db/postgres/__init__.py +4 -0
- agno/db/postgres/async_postgres.py +2579 -0
- agno/db/postgres/postgres.py +2870 -0
- agno/db/postgres/schemas.py +187 -0
- agno/db/postgres/utils.py +442 -0
- agno/db/redis/__init__.py +3 -0
- agno/db/redis/redis.py +2141 -0
- agno/db/redis/schemas.py +159 -0
- agno/db/redis/utils.py +346 -0
- agno/db/schemas/__init__.py +4 -0
- agno/db/schemas/culture.py +120 -0
- agno/db/schemas/evals.py +34 -0
- agno/db/schemas/knowledge.py +40 -0
- agno/db/schemas/memory.py +61 -0
- agno/db/singlestore/__init__.py +3 -0
- agno/db/singlestore/schemas.py +179 -0
- agno/db/singlestore/singlestore.py +2877 -0
- agno/db/singlestore/utils.py +384 -0
- agno/db/sqlite/__init__.py +4 -0
- agno/db/sqlite/async_sqlite.py +2911 -0
- agno/db/sqlite/schemas.py +181 -0
- agno/db/sqlite/sqlite.py +2908 -0
- agno/db/sqlite/utils.py +429 -0
- agno/db/surrealdb/__init__.py +3 -0
- agno/db/surrealdb/metrics.py +292 -0
- agno/db/surrealdb/models.py +334 -0
- agno/db/surrealdb/queries.py +71 -0
- agno/db/surrealdb/surrealdb.py +1908 -0
- agno/db/surrealdb/utils.py +147 -0
- agno/db/utils.py +118 -0
- agno/eval/__init__.py +24 -0
- agno/eval/accuracy.py +666 -276
- agno/eval/agent_as_judge.py +861 -0
- agno/eval/base.py +29 -0
- agno/eval/performance.py +779 -0
- agno/eval/reliability.py +241 -62
- agno/eval/utils.py +120 -0
- agno/exceptions.py +143 -1
- agno/filters.py +354 -0
- agno/guardrails/__init__.py +6 -0
- agno/guardrails/base.py +19 -0
- agno/guardrails/openai.py +144 -0
- agno/guardrails/pii.py +94 -0
- agno/guardrails/prompt_injection.py +52 -0
- agno/hooks/__init__.py +3 -0
- agno/hooks/decorator.py +164 -0
- agno/integrations/discord/__init__.py +3 -0
- agno/integrations/discord/client.py +203 -0
- agno/knowledge/__init__.py +5 -1
- agno/{document → knowledge}/chunking/agentic.py +22 -14
- agno/{document → knowledge}/chunking/document.py +2 -2
- agno/{document → knowledge}/chunking/fixed.py +7 -6
- agno/knowledge/chunking/markdown.py +151 -0
- agno/{document → knowledge}/chunking/recursive.py +15 -3
- agno/knowledge/chunking/row.py +39 -0
- agno/knowledge/chunking/semantic.py +91 -0
- agno/knowledge/chunking/strategy.py +165 -0
- agno/knowledge/content.py +74 -0
- agno/knowledge/document/__init__.py +5 -0
- agno/{document → knowledge/document}/base.py +12 -2
- agno/knowledge/embedder/__init__.py +5 -0
- agno/knowledge/embedder/aws_bedrock.py +343 -0
- agno/knowledge/embedder/azure_openai.py +210 -0
- agno/{embedder → knowledge/embedder}/base.py +8 -0
- agno/knowledge/embedder/cohere.py +323 -0
- agno/knowledge/embedder/fastembed.py +62 -0
- agno/{embedder → knowledge/embedder}/fireworks.py +1 -1
- agno/knowledge/embedder/google.py +258 -0
- agno/knowledge/embedder/huggingface.py +94 -0
- agno/knowledge/embedder/jina.py +182 -0
- agno/knowledge/embedder/langdb.py +22 -0
- agno/knowledge/embedder/mistral.py +206 -0
- agno/knowledge/embedder/nebius.py +13 -0
- agno/knowledge/embedder/ollama.py +154 -0
- agno/knowledge/embedder/openai.py +195 -0
- agno/knowledge/embedder/sentence_transformer.py +63 -0
- agno/{embedder → knowledge/embedder}/together.py +1 -1
- agno/knowledge/embedder/vllm.py +262 -0
- agno/knowledge/embedder/voyageai.py +165 -0
- agno/knowledge/knowledge.py +3006 -0
- agno/knowledge/reader/__init__.py +7 -0
- agno/knowledge/reader/arxiv_reader.py +81 -0
- agno/knowledge/reader/base.py +95 -0
- agno/knowledge/reader/csv_reader.py +164 -0
- agno/knowledge/reader/docx_reader.py +82 -0
- agno/knowledge/reader/field_labeled_csv_reader.py +290 -0
- agno/knowledge/reader/firecrawl_reader.py +201 -0
- agno/knowledge/reader/json_reader.py +88 -0
- agno/knowledge/reader/markdown_reader.py +137 -0
- agno/knowledge/reader/pdf_reader.py +431 -0
- agno/knowledge/reader/pptx_reader.py +101 -0
- agno/knowledge/reader/reader_factory.py +313 -0
- agno/knowledge/reader/s3_reader.py +89 -0
- agno/knowledge/reader/tavily_reader.py +193 -0
- agno/knowledge/reader/text_reader.py +127 -0
- agno/knowledge/reader/web_search_reader.py +325 -0
- agno/knowledge/reader/website_reader.py +455 -0
- agno/knowledge/reader/wikipedia_reader.py +91 -0
- agno/knowledge/reader/youtube_reader.py +78 -0
- agno/knowledge/remote_content/remote_content.py +88 -0
- agno/knowledge/reranker/__init__.py +3 -0
- agno/{reranker → knowledge/reranker}/base.py +1 -1
- agno/{reranker → knowledge/reranker}/cohere.py +2 -2
- agno/knowledge/reranker/infinity.py +195 -0
- agno/knowledge/reranker/sentence_transformer.py +54 -0
- agno/knowledge/types.py +39 -0
- agno/knowledge/utils.py +234 -0
- agno/media.py +439 -95
- agno/memory/__init__.py +16 -3
- agno/memory/manager.py +1474 -123
- agno/memory/strategies/__init__.py +15 -0
- agno/memory/strategies/base.py +66 -0
- agno/memory/strategies/summarize.py +196 -0
- agno/memory/strategies/types.py +37 -0
- agno/models/aimlapi/__init__.py +5 -0
- agno/models/aimlapi/aimlapi.py +62 -0
- agno/models/anthropic/__init__.py +4 -0
- agno/models/anthropic/claude.py +960 -496
- agno/models/aws/__init__.py +15 -0
- agno/models/aws/bedrock.py +686 -451
- agno/models/aws/claude.py +190 -183
- agno/models/azure/__init__.py +18 -1
- agno/models/azure/ai_foundry.py +489 -0
- agno/models/azure/openai_chat.py +89 -40
- agno/models/base.py +2477 -550
- agno/models/cerebras/__init__.py +12 -0
- agno/models/cerebras/cerebras.py +565 -0
- agno/models/cerebras/cerebras_openai.py +131 -0
- agno/models/cohere/__init__.py +4 -0
- agno/models/cohere/chat.py +306 -492
- agno/models/cometapi/__init__.py +5 -0
- agno/models/cometapi/cometapi.py +74 -0
- agno/models/dashscope/__init__.py +5 -0
- agno/models/dashscope/dashscope.py +90 -0
- agno/models/deepinfra/__init__.py +5 -0
- agno/models/deepinfra/deepinfra.py +45 -0
- agno/models/deepseek/__init__.py +4 -0
- agno/models/deepseek/deepseek.py +110 -9
- agno/models/fireworks/__init__.py +4 -0
- agno/models/fireworks/fireworks.py +19 -22
- agno/models/google/__init__.py +3 -7
- agno/models/google/gemini.py +1717 -662
- agno/models/google/utils.py +22 -0
- agno/models/groq/__init__.py +4 -0
- agno/models/groq/groq.py +391 -666
- agno/models/huggingface/__init__.py +4 -0
- agno/models/huggingface/huggingface.py +266 -538
- agno/models/ibm/__init__.py +5 -0
- agno/models/ibm/watsonx.py +432 -0
- agno/models/internlm/__init__.py +3 -0
- agno/models/internlm/internlm.py +20 -3
- agno/models/langdb/__init__.py +1 -0
- agno/models/langdb/langdb.py +60 -0
- agno/models/litellm/__init__.py +14 -0
- agno/models/litellm/chat.py +503 -0
- agno/models/litellm/litellm_openai.py +42 -0
- agno/models/llama_cpp/__init__.py +5 -0
- agno/models/llama_cpp/llama_cpp.py +22 -0
- agno/models/lmstudio/__init__.py +5 -0
- agno/models/lmstudio/lmstudio.py +25 -0
- agno/models/message.py +361 -39
- agno/models/meta/__init__.py +12 -0
- agno/models/meta/llama.py +502 -0
- agno/models/meta/llama_openai.py +79 -0
- agno/models/metrics.py +120 -0
- agno/models/mistral/__init__.py +4 -0
- agno/models/mistral/mistral.py +293 -393
- agno/models/nebius/__init__.py +3 -0
- agno/models/nebius/nebius.py +53 -0
- agno/models/nexus/__init__.py +3 -0
- agno/models/nexus/nexus.py +22 -0
- agno/models/nvidia/__init__.py +4 -0
- agno/models/nvidia/nvidia.py +22 -3
- agno/models/ollama/__init__.py +4 -2
- agno/models/ollama/chat.py +257 -492
- agno/models/openai/__init__.py +7 -0
- agno/models/openai/chat.py +725 -770
- agno/models/openai/like.py +16 -2
- agno/models/openai/responses.py +1121 -0
- agno/models/openrouter/__init__.py +4 -0
- agno/models/openrouter/openrouter.py +62 -5
- agno/models/perplexity/__init__.py +5 -0
- agno/models/perplexity/perplexity.py +203 -0
- agno/models/portkey/__init__.py +3 -0
- agno/models/portkey/portkey.py +82 -0
- agno/models/requesty/__init__.py +5 -0
- agno/models/requesty/requesty.py +69 -0
- agno/models/response.py +177 -7
- agno/models/sambanova/__init__.py +4 -0
- agno/models/sambanova/sambanova.py +23 -4
- agno/models/siliconflow/__init__.py +5 -0
- agno/models/siliconflow/siliconflow.py +42 -0
- agno/models/together/__init__.py +4 -0
- agno/models/together/together.py +21 -164
- agno/models/utils.py +266 -0
- agno/models/vercel/__init__.py +3 -0
- agno/models/vercel/v0.py +43 -0
- agno/models/vertexai/__init__.py +0 -1
- agno/models/vertexai/claude.py +190 -0
- agno/models/vllm/__init__.py +3 -0
- agno/models/vllm/vllm.py +83 -0
- agno/models/xai/__init__.py +2 -0
- agno/models/xai/xai.py +111 -7
- agno/os/__init__.py +3 -0
- agno/os/app.py +1027 -0
- agno/os/auth.py +244 -0
- agno/os/config.py +126 -0
- agno/os/interfaces/__init__.py +1 -0
- agno/os/interfaces/a2a/__init__.py +3 -0
- agno/os/interfaces/a2a/a2a.py +42 -0
- agno/os/interfaces/a2a/router.py +249 -0
- agno/os/interfaces/a2a/utils.py +924 -0
- agno/os/interfaces/agui/__init__.py +3 -0
- agno/os/interfaces/agui/agui.py +47 -0
- agno/os/interfaces/agui/router.py +147 -0
- agno/os/interfaces/agui/utils.py +574 -0
- agno/os/interfaces/base.py +25 -0
- agno/os/interfaces/slack/__init__.py +3 -0
- agno/os/interfaces/slack/router.py +148 -0
- agno/os/interfaces/slack/security.py +30 -0
- agno/os/interfaces/slack/slack.py +47 -0
- agno/os/interfaces/whatsapp/__init__.py +3 -0
- agno/os/interfaces/whatsapp/router.py +210 -0
- agno/os/interfaces/whatsapp/security.py +55 -0
- agno/os/interfaces/whatsapp/whatsapp.py +36 -0
- agno/os/mcp.py +293 -0
- agno/os/middleware/__init__.py +9 -0
- agno/os/middleware/jwt.py +797 -0
- agno/os/router.py +258 -0
- agno/os/routers/__init__.py +3 -0
- agno/os/routers/agents/__init__.py +3 -0
- agno/os/routers/agents/router.py +599 -0
- agno/os/routers/agents/schema.py +261 -0
- agno/os/routers/evals/__init__.py +3 -0
- agno/os/routers/evals/evals.py +450 -0
- agno/os/routers/evals/schemas.py +174 -0
- agno/os/routers/evals/utils.py +231 -0
- agno/os/routers/health.py +31 -0
- agno/os/routers/home.py +52 -0
- agno/os/routers/knowledge/__init__.py +3 -0
- agno/os/routers/knowledge/knowledge.py +1008 -0
- agno/os/routers/knowledge/schemas.py +178 -0
- agno/os/routers/memory/__init__.py +3 -0
- agno/os/routers/memory/memory.py +661 -0
- agno/os/routers/memory/schemas.py +88 -0
- agno/os/routers/metrics/__init__.py +3 -0
- agno/os/routers/metrics/metrics.py +190 -0
- agno/os/routers/metrics/schemas.py +47 -0
- agno/os/routers/session/__init__.py +3 -0
- agno/os/routers/session/session.py +997 -0
- agno/os/routers/teams/__init__.py +3 -0
- agno/os/routers/teams/router.py +512 -0
- agno/os/routers/teams/schema.py +257 -0
- agno/os/routers/traces/__init__.py +3 -0
- agno/os/routers/traces/schemas.py +414 -0
- agno/os/routers/traces/traces.py +499 -0
- agno/os/routers/workflows/__init__.py +3 -0
- agno/os/routers/workflows/router.py +624 -0
- agno/os/routers/workflows/schema.py +75 -0
- agno/os/schema.py +534 -0
- agno/os/scopes.py +469 -0
- agno/{playground → os}/settings.py +7 -15
- agno/os/utils.py +973 -0
- agno/reasoning/anthropic.py +80 -0
- agno/reasoning/azure_ai_foundry.py +67 -0
- agno/reasoning/deepseek.py +63 -0
- agno/reasoning/default.py +97 -0
- agno/reasoning/gemini.py +73 -0
- agno/reasoning/groq.py +71 -0
- agno/reasoning/helpers.py +24 -1
- agno/reasoning/ollama.py +67 -0
- agno/reasoning/openai.py +86 -0
- agno/reasoning/step.py +2 -1
- agno/reasoning/vertexai.py +76 -0
- agno/run/__init__.py +6 -0
- agno/run/agent.py +822 -0
- agno/run/base.py +247 -0
- agno/run/cancel.py +81 -0
- agno/run/requirement.py +181 -0
- agno/run/team.py +767 -0
- agno/run/workflow.py +708 -0
- agno/session/__init__.py +10 -0
- agno/session/agent.py +260 -0
- agno/session/summary.py +265 -0
- agno/session/team.py +342 -0
- agno/session/workflow.py +501 -0
- agno/table.py +10 -0
- agno/team/__init__.py +37 -0
- agno/team/team.py +9536 -0
- agno/tools/__init__.py +7 -0
- agno/tools/agentql.py +120 -0
- agno/tools/airflow.py +22 -12
- agno/tools/api.py +122 -0
- agno/tools/apify.py +276 -83
- agno/tools/{arxiv_toolkit.py → arxiv.py} +20 -12
- agno/tools/aws_lambda.py +28 -7
- agno/tools/aws_ses.py +66 -0
- agno/tools/baidusearch.py +11 -4
- agno/tools/bitbucket.py +292 -0
- agno/tools/brandfetch.py +213 -0
- agno/tools/bravesearch.py +106 -0
- agno/tools/brightdata.py +367 -0
- agno/tools/browserbase.py +209 -0
- agno/tools/calcom.py +32 -23
- agno/tools/calculator.py +24 -37
- agno/tools/cartesia.py +187 -0
- agno/tools/{clickup_tool.py → clickup.py} +17 -28
- agno/tools/confluence.py +91 -26
- agno/tools/crawl4ai.py +139 -43
- agno/tools/csv_toolkit.py +28 -22
- agno/tools/dalle.py +36 -22
- agno/tools/daytona.py +475 -0
- agno/tools/decorator.py +169 -14
- agno/tools/desi_vocal.py +23 -11
- agno/tools/discord.py +32 -29
- agno/tools/docker.py +716 -0
- agno/tools/duckdb.py +76 -81
- agno/tools/duckduckgo.py +43 -40
- agno/tools/e2b.py +703 -0
- agno/tools/eleven_labs.py +65 -54
- agno/tools/email.py +13 -5
- agno/tools/evm.py +129 -0
- agno/tools/exa.py +324 -42
- agno/tools/fal.py +39 -35
- agno/tools/file.py +196 -30
- agno/tools/file_generation.py +356 -0
- agno/tools/financial_datasets.py +288 -0
- agno/tools/firecrawl.py +108 -33
- agno/tools/function.py +960 -122
- agno/tools/giphy.py +34 -12
- agno/tools/github.py +1294 -97
- agno/tools/gmail.py +922 -0
- agno/tools/google_bigquery.py +117 -0
- agno/tools/google_drive.py +271 -0
- agno/tools/google_maps.py +253 -0
- agno/tools/googlecalendar.py +607 -107
- agno/tools/googlesheets.py +377 -0
- agno/tools/hackernews.py +20 -12
- agno/tools/jina.py +24 -14
- agno/tools/jira.py +48 -19
- agno/tools/knowledge.py +218 -0
- agno/tools/linear.py +82 -43
- agno/tools/linkup.py +58 -0
- agno/tools/local_file_system.py +15 -7
- agno/tools/lumalab.py +41 -26
- agno/tools/mcp/__init__.py +10 -0
- agno/tools/mcp/mcp.py +331 -0
- agno/tools/mcp/multi_mcp.py +347 -0
- agno/tools/mcp/params.py +24 -0
- agno/tools/mcp_toolbox.py +284 -0
- agno/tools/mem0.py +193 -0
- agno/tools/memory.py +419 -0
- agno/tools/mlx_transcribe.py +11 -9
- agno/tools/models/azure_openai.py +190 -0
- agno/tools/models/gemini.py +203 -0
- agno/tools/models/groq.py +158 -0
- agno/tools/models/morph.py +186 -0
- agno/tools/models/nebius.py +124 -0
- agno/tools/models_labs.py +163 -82
- agno/tools/moviepy_video.py +18 -13
- agno/tools/nano_banana.py +151 -0
- agno/tools/neo4j.py +134 -0
- agno/tools/newspaper.py +15 -4
- agno/tools/newspaper4k.py +19 -6
- agno/tools/notion.py +204 -0
- agno/tools/openai.py +181 -17
- agno/tools/openbb.py +27 -20
- agno/tools/opencv.py +321 -0
- agno/tools/openweather.py +233 -0
- agno/tools/oxylabs.py +385 -0
- agno/tools/pandas.py +25 -15
- agno/tools/parallel.py +314 -0
- agno/tools/postgres.py +238 -185
- agno/tools/pubmed.py +125 -13
- agno/tools/python.py +48 -35
- agno/tools/reasoning.py +283 -0
- agno/tools/reddit.py +207 -29
- agno/tools/redshift.py +406 -0
- agno/tools/replicate.py +69 -26
- agno/tools/resend.py +11 -6
- agno/tools/scrapegraph.py +179 -19
- agno/tools/searxng.py +23 -31
- agno/tools/serpapi.py +15 -10
- agno/tools/serper.py +255 -0
- agno/tools/shell.py +23 -12
- agno/tools/shopify.py +1519 -0
- agno/tools/slack.py +56 -14
- agno/tools/sleep.py +8 -6
- agno/tools/spider.py +35 -11
- agno/tools/spotify.py +919 -0
- agno/tools/sql.py +34 -19
- agno/tools/tavily.py +158 -8
- agno/tools/telegram.py +18 -8
- agno/tools/todoist.py +218 -0
- agno/tools/toolkit.py +134 -9
- agno/tools/trafilatura.py +388 -0
- agno/tools/trello.py +25 -28
- agno/tools/twilio.py +18 -9
- agno/tools/user_control_flow.py +78 -0
- agno/tools/valyu.py +228 -0
- agno/tools/visualization.py +467 -0
- agno/tools/webbrowser.py +28 -0
- agno/tools/webex.py +76 -0
- agno/tools/website.py +23 -19
- agno/tools/webtools.py +45 -0
- agno/tools/whatsapp.py +286 -0
- agno/tools/wikipedia.py +28 -19
- agno/tools/workflow.py +285 -0
- agno/tools/{twitter.py → x.py} +142 -46
- agno/tools/yfinance.py +41 -39
- agno/tools/youtube.py +34 -17
- agno/tools/zendesk.py +15 -5
- agno/tools/zep.py +454 -0
- agno/tools/zoom.py +86 -37
- agno/tracing/__init__.py +12 -0
- agno/tracing/exporter.py +157 -0
- agno/tracing/schemas.py +276 -0
- agno/tracing/setup.py +111 -0
- agno/utils/agent.py +938 -0
- agno/utils/audio.py +37 -1
- agno/utils/certs.py +27 -0
- agno/utils/code_execution.py +11 -0
- agno/utils/common.py +103 -20
- agno/utils/cryptography.py +22 -0
- agno/utils/dttm.py +33 -0
- agno/utils/events.py +700 -0
- agno/utils/functions.py +107 -37
- agno/utils/gemini.py +426 -0
- agno/utils/hooks.py +171 -0
- agno/utils/http.py +185 -0
- agno/utils/json_schema.py +159 -37
- agno/utils/knowledge.py +36 -0
- agno/utils/location.py +19 -0
- agno/utils/log.py +221 -8
- agno/utils/mcp.py +214 -0
- agno/utils/media.py +335 -14
- agno/utils/merge_dict.py +22 -1
- agno/utils/message.py +77 -2
- agno/utils/models/ai_foundry.py +50 -0
- agno/utils/models/claude.py +373 -0
- agno/utils/models/cohere.py +94 -0
- agno/utils/models/llama.py +85 -0
- agno/utils/models/mistral.py +100 -0
- agno/utils/models/openai_responses.py +140 -0
- agno/utils/models/schema_utils.py +153 -0
- agno/utils/models/watsonx.py +41 -0
- agno/utils/openai.py +257 -0
- agno/utils/pickle.py +1 -1
- agno/utils/pprint.py +124 -8
- agno/utils/print_response/agent.py +930 -0
- agno/utils/print_response/team.py +1914 -0
- agno/utils/print_response/workflow.py +1668 -0
- agno/utils/prompts.py +111 -0
- agno/utils/reasoning.py +108 -0
- agno/utils/response.py +163 -0
- agno/utils/serialize.py +32 -0
- agno/utils/shell.py +4 -4
- agno/utils/streamlit.py +487 -0
- agno/utils/string.py +204 -51
- agno/utils/team.py +139 -0
- agno/utils/timer.py +9 -2
- agno/utils/tokens.py +657 -0
- agno/utils/tools.py +19 -1
- agno/utils/whatsapp.py +305 -0
- agno/utils/yaml_io.py +3 -3
- agno/vectordb/__init__.py +2 -0
- agno/vectordb/base.py +87 -9
- agno/vectordb/cassandra/__init__.py +5 -1
- agno/vectordb/cassandra/cassandra.py +383 -27
- agno/vectordb/chroma/__init__.py +4 -0
- agno/vectordb/chroma/chromadb.py +748 -83
- agno/vectordb/clickhouse/__init__.py +7 -1
- agno/vectordb/clickhouse/clickhousedb.py +554 -53
- agno/vectordb/couchbase/__init__.py +3 -0
- agno/vectordb/couchbase/couchbase.py +1446 -0
- agno/vectordb/lancedb/__init__.py +5 -0
- agno/vectordb/lancedb/lance_db.py +730 -98
- agno/vectordb/langchaindb/__init__.py +5 -0
- agno/vectordb/langchaindb/langchaindb.py +163 -0
- agno/vectordb/lightrag/__init__.py +5 -0
- agno/vectordb/lightrag/lightrag.py +388 -0
- agno/vectordb/llamaindex/__init__.py +3 -0
- agno/vectordb/llamaindex/llamaindexdb.py +166 -0
- agno/vectordb/milvus/__init__.py +3 -0
- agno/vectordb/milvus/milvus.py +966 -78
- agno/vectordb/mongodb/__init__.py +9 -1
- agno/vectordb/mongodb/mongodb.py +1175 -172
- agno/vectordb/pgvector/__init__.py +8 -0
- agno/vectordb/pgvector/pgvector.py +599 -115
- agno/vectordb/pineconedb/__init__.py +5 -1
- agno/vectordb/pineconedb/pineconedb.py +406 -43
- agno/vectordb/qdrant/__init__.py +4 -0
- agno/vectordb/qdrant/qdrant.py +914 -61
- agno/vectordb/redis/__init__.py +9 -0
- agno/vectordb/redis/redisdb.py +682 -0
- agno/vectordb/singlestore/__init__.py +8 -1
- agno/vectordb/singlestore/singlestore.py +771 -0
- agno/vectordb/surrealdb/__init__.py +3 -0
- agno/vectordb/surrealdb/surrealdb.py +663 -0
- agno/vectordb/upstashdb/__init__.py +5 -0
- agno/vectordb/upstashdb/upstashdb.py +718 -0
- agno/vectordb/weaviate/__init__.py +8 -0
- agno/vectordb/weaviate/index.py +15 -0
- agno/vectordb/weaviate/weaviate.py +1009 -0
- agno/workflow/__init__.py +23 -1
- agno/workflow/agent.py +299 -0
- agno/workflow/condition.py +759 -0
- agno/workflow/loop.py +756 -0
- agno/workflow/parallel.py +853 -0
- agno/workflow/router.py +723 -0
- agno/workflow/step.py +1564 -0
- agno/workflow/steps.py +613 -0
- agno/workflow/types.py +556 -0
- agno/workflow/workflow.py +4327 -514
- agno-2.3.13.dist-info/METADATA +639 -0
- agno-2.3.13.dist-info/RECORD +613 -0
- {agno-0.1.2.dist-info → agno-2.3.13.dist-info}/WHEEL +1 -1
- agno-2.3.13.dist-info/licenses/LICENSE +201 -0
- agno/api/playground.py +0 -91
- agno/api/schemas/playground.py +0 -22
- agno/api/schemas/user.py +0 -22
- agno/api/schemas/workspace.py +0 -46
- agno/api/user.py +0 -160
- agno/api/workspace.py +0 -151
- agno/cli/auth_server.py +0 -118
- agno/cli/config.py +0 -275
- agno/cli/console.py +0 -88
- agno/cli/credentials.py +0 -23
- agno/cli/entrypoint.py +0 -571
- agno/cli/operator.py +0 -355
- agno/cli/settings.py +0 -85
- agno/cli/ws/ws_cli.py +0 -817
- agno/constants.py +0 -13
- agno/document/__init__.py +0 -1
- agno/document/chunking/semantic.py +0 -47
- agno/document/chunking/strategy.py +0 -31
- agno/document/reader/__init__.py +0 -1
- agno/document/reader/arxiv_reader.py +0 -41
- agno/document/reader/base.py +0 -22
- agno/document/reader/csv_reader.py +0 -84
- agno/document/reader/docx_reader.py +0 -46
- agno/document/reader/firecrawl_reader.py +0 -99
- agno/document/reader/json_reader.py +0 -43
- agno/document/reader/pdf_reader.py +0 -219
- agno/document/reader/s3/pdf_reader.py +0 -46
- agno/document/reader/s3/text_reader.py +0 -51
- agno/document/reader/text_reader.py +0 -41
- agno/document/reader/website_reader.py +0 -175
- agno/document/reader/youtube_reader.py +0 -50
- agno/embedder/__init__.py +0 -1
- agno/embedder/azure_openai.py +0 -86
- agno/embedder/cohere.py +0 -72
- agno/embedder/fastembed.py +0 -37
- agno/embedder/google.py +0 -73
- agno/embedder/huggingface.py +0 -54
- agno/embedder/mistral.py +0 -80
- agno/embedder/ollama.py +0 -57
- agno/embedder/openai.py +0 -74
- agno/embedder/sentence_transformer.py +0 -38
- agno/embedder/voyageai.py +0 -64
- agno/eval/perf.py +0 -201
- agno/file/__init__.py +0 -1
- agno/file/file.py +0 -16
- agno/file/local/csv.py +0 -32
- agno/file/local/txt.py +0 -19
- agno/infra/app.py +0 -240
- agno/infra/base.py +0 -144
- agno/infra/context.py +0 -20
- agno/infra/db_app.py +0 -52
- agno/infra/resource.py +0 -205
- agno/infra/resources.py +0 -55
- agno/knowledge/agent.py +0 -230
- agno/knowledge/arxiv.py +0 -22
- agno/knowledge/combined.py +0 -22
- agno/knowledge/csv.py +0 -28
- agno/knowledge/csv_url.py +0 -19
- agno/knowledge/document.py +0 -20
- agno/knowledge/docx.py +0 -30
- agno/knowledge/json.py +0 -28
- agno/knowledge/langchain.py +0 -71
- agno/knowledge/llamaindex.py +0 -66
- agno/knowledge/pdf.py +0 -28
- agno/knowledge/pdf_url.py +0 -26
- agno/knowledge/s3/base.py +0 -60
- agno/knowledge/s3/pdf.py +0 -21
- agno/knowledge/s3/text.py +0 -23
- agno/knowledge/text.py +0 -30
- agno/knowledge/website.py +0 -88
- agno/knowledge/wikipedia.py +0 -31
- agno/knowledge/youtube.py +0 -22
- agno/memory/agent.py +0 -392
- agno/memory/classifier.py +0 -104
- agno/memory/db/__init__.py +0 -1
- agno/memory/db/base.py +0 -42
- agno/memory/db/mongodb.py +0 -189
- agno/memory/db/postgres.py +0 -203
- agno/memory/db/sqlite.py +0 -193
- agno/memory/memory.py +0 -15
- agno/memory/row.py +0 -36
- agno/memory/summarizer.py +0 -192
- agno/memory/summary.py +0 -19
- agno/memory/workflow.py +0 -38
- agno/models/google/gemini_openai.py +0 -26
- agno/models/ollama/hermes.py +0 -221
- agno/models/ollama/tools.py +0 -362
- agno/models/vertexai/gemini.py +0 -595
- agno/playground/__init__.py +0 -3
- agno/playground/async_router.py +0 -421
- agno/playground/deploy.py +0 -249
- agno/playground/operator.py +0 -92
- agno/playground/playground.py +0 -91
- agno/playground/schemas.py +0 -76
- agno/playground/serve.py +0 -55
- agno/playground/sync_router.py +0 -405
- agno/reasoning/agent.py +0 -68
- agno/run/response.py +0 -112
- agno/storage/agent/__init__.py +0 -0
- agno/storage/agent/base.py +0 -38
- agno/storage/agent/dynamodb.py +0 -350
- agno/storage/agent/json.py +0 -92
- agno/storage/agent/mongodb.py +0 -228
- agno/storage/agent/postgres.py +0 -367
- agno/storage/agent/session.py +0 -79
- agno/storage/agent/singlestore.py +0 -303
- agno/storage/agent/sqlite.py +0 -357
- agno/storage/agent/yaml.py +0 -93
- agno/storage/workflow/__init__.py +0 -0
- agno/storage/workflow/base.py +0 -40
- agno/storage/workflow/mongodb.py +0 -233
- agno/storage/workflow/postgres.py +0 -366
- agno/storage/workflow/session.py +0 -60
- agno/storage/workflow/sqlite.py +0 -359
- agno/tools/googlesearch.py +0 -88
- agno/utils/defaults.py +0 -57
- agno/utils/filesystem.py +0 -39
- agno/utils/git.py +0 -52
- agno/utils/json_io.py +0 -30
- agno/utils/load_env.py +0 -19
- agno/utils/py_io.py +0 -19
- agno/utils/pyproject.py +0 -18
- agno/utils/resource_filter.py +0 -31
- agno/vectordb/singlestore/s2vectordb.py +0 -390
- agno/vectordb/singlestore/s2vectordb2.py +0 -355
- agno/workspace/__init__.py +0 -0
- agno/workspace/config.py +0 -325
- agno/workspace/enums.py +0 -6
- agno/workspace/helpers.py +0 -48
- agno/workspace/operator.py +0 -758
- agno/workspace/settings.py +0 -63
- agno-0.1.2.dist-info/LICENSE +0 -375
- agno-0.1.2.dist-info/METADATA +0 -502
- agno-0.1.2.dist-info/RECORD +0 -352
- agno-0.1.2.dist-info/entry_points.txt +0 -3
- /agno/{cli → db/migrations}/__init__.py +0 -0
- /agno/{cli/ws → db/migrations/versions}/__init__.py +0 -0
- /agno/{document/chunking/__init__.py → db/schemas/metrics.py} +0 -0
- /agno/{document/reader/s3 → integrations}/__init__.py +0 -0
- /agno/{file/local → knowledge/chunking}/__init__.py +0 -0
- /agno/{infra → knowledge/remote_content}/__init__.py +0 -0
- /agno/{knowledge/s3 → tools/models}/__init__.py +0 -0
- /agno/{reranker → utils/models}/__init__.py +0 -0
- /agno/{storage → utils/print_response}/__init__.py +0 -0
- {agno-0.1.2.dist-info → agno-2.3.13.dist-info}/top_level.txt +0 -0
agno/run/agent.py
ADDED
|
@@ -0,0 +1,822 @@
|
|
|
1
|
+
from dataclasses import asdict, dataclass, field
|
|
2
|
+
from enum import Enum
|
|
3
|
+
from time import time
|
|
4
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Sequence, Union
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel
|
|
7
|
+
|
|
8
|
+
from agno.media import Audio, File, Image, Video
|
|
9
|
+
from agno.models.message import Citations, Message
|
|
10
|
+
from agno.models.metrics import Metrics
|
|
11
|
+
from agno.models.response import ToolExecution
|
|
12
|
+
from agno.reasoning.step import ReasoningStep
|
|
13
|
+
from agno.run.base import BaseRunOutputEvent, MessageReferences, RunStatus
|
|
14
|
+
from agno.run.requirement import RunRequirement
|
|
15
|
+
from agno.utils.log import logger
|
|
16
|
+
from agno.utils.media import (
|
|
17
|
+
reconstruct_audio_list,
|
|
18
|
+
reconstruct_files,
|
|
19
|
+
reconstruct_images,
|
|
20
|
+
reconstruct_response_audio,
|
|
21
|
+
reconstruct_videos,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
if TYPE_CHECKING:
|
|
25
|
+
from agno.session.summary import SessionSummary
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@dataclass
|
|
29
|
+
class RunInput:
|
|
30
|
+
"""Container for the raw input data passed to Agent.run().
|
|
31
|
+
|
|
32
|
+
This captures the original input exactly as provided by the user,
|
|
33
|
+
separate from the processed messages that go to the model.
|
|
34
|
+
|
|
35
|
+
Attributes:
|
|
36
|
+
input_content: The literal input message/content passed to run()
|
|
37
|
+
images: Images directly passed to run()
|
|
38
|
+
videos: Videos directly passed to run()
|
|
39
|
+
audios: Audio files directly passed to run()
|
|
40
|
+
files: Files directly passed to run()
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
input_content: Union[str, List, Dict, Message, BaseModel, List[Message]]
|
|
44
|
+
images: Optional[Sequence[Image]] = None
|
|
45
|
+
videos: Optional[Sequence[Video]] = None
|
|
46
|
+
audios: Optional[Sequence[Audio]] = None
|
|
47
|
+
files: Optional[Sequence[File]] = None
|
|
48
|
+
|
|
49
|
+
def input_content_string(self) -> str:
|
|
50
|
+
import json
|
|
51
|
+
|
|
52
|
+
if isinstance(self.input_content, (str)):
|
|
53
|
+
return self.input_content
|
|
54
|
+
elif isinstance(self.input_content, BaseModel):
|
|
55
|
+
return self.input_content.model_dump_json(exclude_none=True)
|
|
56
|
+
elif isinstance(self.input_content, Message):
|
|
57
|
+
return json.dumps(self.input_content.to_dict())
|
|
58
|
+
elif isinstance(self.input_content, list) and self.input_content and isinstance(self.input_content[0], Message):
|
|
59
|
+
return json.dumps([m.to_dict() for m in self.input_content])
|
|
60
|
+
else:
|
|
61
|
+
return str(self.input_content)
|
|
62
|
+
|
|
63
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
64
|
+
"""Convert to dictionary representation"""
|
|
65
|
+
result: Dict[str, Any] = {}
|
|
66
|
+
|
|
67
|
+
if self.input_content is not None:
|
|
68
|
+
if isinstance(self.input_content, (str)):
|
|
69
|
+
result["input_content"] = self.input_content
|
|
70
|
+
elif isinstance(self.input_content, BaseModel):
|
|
71
|
+
result["input_content"] = self.input_content.model_dump(exclude_none=True)
|
|
72
|
+
elif isinstance(self.input_content, Message):
|
|
73
|
+
result["input_content"] = self.input_content.to_dict()
|
|
74
|
+
|
|
75
|
+
# Handle input_content provided as a list of Message objects
|
|
76
|
+
elif (
|
|
77
|
+
isinstance(self.input_content, list)
|
|
78
|
+
and self.input_content
|
|
79
|
+
and isinstance(self.input_content[0], Message)
|
|
80
|
+
):
|
|
81
|
+
result["input_content"] = [m.to_dict() for m in self.input_content]
|
|
82
|
+
|
|
83
|
+
# Handle input_content provided as a list of dicts
|
|
84
|
+
elif (
|
|
85
|
+
isinstance(self.input_content, list) and self.input_content and isinstance(self.input_content[0], dict)
|
|
86
|
+
):
|
|
87
|
+
for content in self.input_content:
|
|
88
|
+
# Handle media input
|
|
89
|
+
if isinstance(content, dict):
|
|
90
|
+
if content.get("images"):
|
|
91
|
+
content["images"] = [
|
|
92
|
+
img.to_dict() if isinstance(img, Image) else img for img in content["images"]
|
|
93
|
+
]
|
|
94
|
+
if content.get("videos"):
|
|
95
|
+
content["videos"] = [
|
|
96
|
+
vid.to_dict() if isinstance(vid, Video) else vid for vid in content["videos"]
|
|
97
|
+
]
|
|
98
|
+
if content.get("audios"):
|
|
99
|
+
content["audios"] = [
|
|
100
|
+
aud.to_dict() if isinstance(aud, Audio) else aud for aud in content["audios"]
|
|
101
|
+
]
|
|
102
|
+
if content.get("files"):
|
|
103
|
+
content["files"] = [
|
|
104
|
+
file.to_dict() if isinstance(file, File) else file for file in content["files"]
|
|
105
|
+
]
|
|
106
|
+
result["input_content"] = self.input_content
|
|
107
|
+
else:
|
|
108
|
+
result["input_content"] = self.input_content
|
|
109
|
+
|
|
110
|
+
if self.images:
|
|
111
|
+
result["images"] = [img.to_dict() for img in self.images]
|
|
112
|
+
if self.videos:
|
|
113
|
+
result["videos"] = [vid.to_dict() for vid in self.videos]
|
|
114
|
+
if self.audios:
|
|
115
|
+
result["audios"] = [aud.to_dict() for aud in self.audios]
|
|
116
|
+
if self.files:
|
|
117
|
+
result["files"] = [file.to_dict() for file in self.files]
|
|
118
|
+
|
|
119
|
+
return result
|
|
120
|
+
|
|
121
|
+
@classmethod
|
|
122
|
+
def from_dict(cls, data: Dict[str, Any]) -> "RunInput":
|
|
123
|
+
"""Create RunInput from dictionary"""
|
|
124
|
+
images = reconstruct_images(data.get("images"))
|
|
125
|
+
videos = reconstruct_videos(data.get("videos"))
|
|
126
|
+
audios = reconstruct_audio_list(data.get("audios"))
|
|
127
|
+
files = reconstruct_files(data.get("files"))
|
|
128
|
+
|
|
129
|
+
return cls(
|
|
130
|
+
input_content=data.get("input_content", ""), images=images, videos=videos, audios=audios, files=files
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
class RunEvent(str, Enum):
|
|
135
|
+
"""Events that can be sent by the run() functions"""
|
|
136
|
+
|
|
137
|
+
run_started = "RunStarted"
|
|
138
|
+
run_content = "RunContent"
|
|
139
|
+
run_content_completed = "RunContentCompleted"
|
|
140
|
+
run_intermediate_content = "RunIntermediateContent"
|
|
141
|
+
run_completed = "RunCompleted"
|
|
142
|
+
run_error = "RunError"
|
|
143
|
+
run_cancelled = "RunCancelled"
|
|
144
|
+
|
|
145
|
+
run_paused = "RunPaused"
|
|
146
|
+
run_continued = "RunContinued"
|
|
147
|
+
|
|
148
|
+
pre_hook_started = "PreHookStarted"
|
|
149
|
+
pre_hook_completed = "PreHookCompleted"
|
|
150
|
+
|
|
151
|
+
post_hook_started = "PostHookStarted"
|
|
152
|
+
post_hook_completed = "PostHookCompleted"
|
|
153
|
+
|
|
154
|
+
tool_call_started = "ToolCallStarted"
|
|
155
|
+
tool_call_completed = "ToolCallCompleted"
|
|
156
|
+
|
|
157
|
+
reasoning_started = "ReasoningStarted"
|
|
158
|
+
reasoning_step = "ReasoningStep"
|
|
159
|
+
reasoning_completed = "ReasoningCompleted"
|
|
160
|
+
|
|
161
|
+
memory_update_started = "MemoryUpdateStarted"
|
|
162
|
+
memory_update_completed = "MemoryUpdateCompleted"
|
|
163
|
+
|
|
164
|
+
session_summary_started = "SessionSummaryStarted"
|
|
165
|
+
session_summary_completed = "SessionSummaryCompleted"
|
|
166
|
+
|
|
167
|
+
parser_model_response_started = "ParserModelResponseStarted"
|
|
168
|
+
parser_model_response_completed = "ParserModelResponseCompleted"
|
|
169
|
+
|
|
170
|
+
output_model_response_started = "OutputModelResponseStarted"
|
|
171
|
+
output_model_response_completed = "OutputModelResponseCompleted"
|
|
172
|
+
|
|
173
|
+
custom_event = "CustomEvent"
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
@dataclass
|
|
177
|
+
class BaseAgentRunEvent(BaseRunOutputEvent):
|
|
178
|
+
created_at: int = field(default_factory=lambda: int(time()))
|
|
179
|
+
event: str = ""
|
|
180
|
+
agent_id: str = ""
|
|
181
|
+
agent_name: str = ""
|
|
182
|
+
run_id: Optional[str] = None
|
|
183
|
+
parent_run_id: Optional[str] = None
|
|
184
|
+
session_id: Optional[str] = None
|
|
185
|
+
|
|
186
|
+
# Step context for workflow execution
|
|
187
|
+
workflow_id: Optional[str] = None
|
|
188
|
+
workflow_run_id: Optional[str] = None
|
|
189
|
+
step_id: Optional[str] = None
|
|
190
|
+
step_name: Optional[str] = None
|
|
191
|
+
step_index: Optional[int] = None
|
|
192
|
+
tools: Optional[List[ToolExecution]] = None
|
|
193
|
+
|
|
194
|
+
# For backwards compatibility
|
|
195
|
+
content: Optional[Any] = None
|
|
196
|
+
|
|
197
|
+
@property
|
|
198
|
+
def tools_requiring_confirmation(self):
|
|
199
|
+
return [t for t in self.tools if t.requires_confirmation] if self.tools else []
|
|
200
|
+
|
|
201
|
+
@property
|
|
202
|
+
def tools_requiring_user_input(self):
|
|
203
|
+
return [t for t in self.tools if t.requires_user_input] if self.tools else []
|
|
204
|
+
|
|
205
|
+
@property
|
|
206
|
+
def tools_awaiting_external_execution(self):
|
|
207
|
+
return [t for t in self.tools if t.external_execution_required] if self.tools else []
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
@dataclass
|
|
211
|
+
class RunStartedEvent(BaseAgentRunEvent):
|
|
212
|
+
"""Event sent when the run starts"""
|
|
213
|
+
|
|
214
|
+
event: str = RunEvent.run_started.value
|
|
215
|
+
model: str = ""
|
|
216
|
+
model_provider: str = ""
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
@dataclass
|
|
220
|
+
class RunContentEvent(BaseAgentRunEvent):
|
|
221
|
+
"""Main event for each delta of the RunOutput"""
|
|
222
|
+
|
|
223
|
+
event: str = RunEvent.run_content.value
|
|
224
|
+
content: Optional[Any] = None
|
|
225
|
+
workflow_agent: bool = (
|
|
226
|
+
False # Used by consumers of the events to distinguish between workflow agent and regular agent
|
|
227
|
+
)
|
|
228
|
+
content_type: str = "str"
|
|
229
|
+
reasoning_content: Optional[str] = None
|
|
230
|
+
model_provider_data: Optional[Dict[str, Any]] = None
|
|
231
|
+
citations: Optional[Citations] = None
|
|
232
|
+
response_audio: Optional[Audio] = None # Model audio response
|
|
233
|
+
image: Optional[Image] = None # Image attached to the response
|
|
234
|
+
references: Optional[List[MessageReferences]] = None
|
|
235
|
+
additional_input: Optional[List[Message]] = None
|
|
236
|
+
reasoning_steps: Optional[List[ReasoningStep]] = None
|
|
237
|
+
reasoning_messages: Optional[List[Message]] = None
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
@dataclass
|
|
241
|
+
class RunContentCompletedEvent(BaseAgentRunEvent):
|
|
242
|
+
event: str = RunEvent.run_content_completed.value
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
@dataclass
|
|
246
|
+
class IntermediateRunContentEvent(BaseAgentRunEvent):
|
|
247
|
+
event: str = RunEvent.run_intermediate_content.value
|
|
248
|
+
content: Optional[Any] = None
|
|
249
|
+
content_type: str = "str"
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
@dataclass
|
|
253
|
+
class RunCompletedEvent(BaseAgentRunEvent):
|
|
254
|
+
event: str = RunEvent.run_completed.value
|
|
255
|
+
content: Optional[Any] = None
|
|
256
|
+
content_type: str = "str"
|
|
257
|
+
reasoning_content: Optional[str] = None
|
|
258
|
+
citations: Optional[Citations] = None
|
|
259
|
+
model_provider_data: Optional[Dict[str, Any]] = None
|
|
260
|
+
images: Optional[List[Image]] = None # Images attached to the response
|
|
261
|
+
videos: Optional[List[Video]] = None # Videos attached to the response
|
|
262
|
+
audio: Optional[List[Audio]] = None # Audio attached to the response
|
|
263
|
+
response_audio: Optional[Audio] = None # Model audio response
|
|
264
|
+
references: Optional[List[MessageReferences]] = None
|
|
265
|
+
additional_input: Optional[List[Message]] = None
|
|
266
|
+
reasoning_steps: Optional[List[ReasoningStep]] = None
|
|
267
|
+
reasoning_messages: Optional[List[Message]] = None
|
|
268
|
+
metadata: Optional[Dict[str, Any]] = None
|
|
269
|
+
metrics: Optional[Metrics] = None
|
|
270
|
+
session_state: Optional[Dict[str, Any]] = None
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
@dataclass
|
|
274
|
+
class RunPausedEvent(BaseAgentRunEvent):
|
|
275
|
+
event: str = RunEvent.run_paused.value
|
|
276
|
+
tools: Optional[List[ToolExecution]] = None
|
|
277
|
+
requirements: Optional[List[RunRequirement]] = None
|
|
278
|
+
|
|
279
|
+
@property
|
|
280
|
+
def is_paused(self):
|
|
281
|
+
return True
|
|
282
|
+
|
|
283
|
+
@property
|
|
284
|
+
def active_requirements(self) -> List[RunRequirement]:
|
|
285
|
+
if not self.requirements:
|
|
286
|
+
return []
|
|
287
|
+
return [requirement for requirement in self.requirements if not requirement.is_resolved()]
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
@dataclass
|
|
291
|
+
class RunContinuedEvent(BaseAgentRunEvent):
|
|
292
|
+
event: str = RunEvent.run_continued.value
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
@dataclass
|
|
296
|
+
class RunErrorEvent(BaseAgentRunEvent):
|
|
297
|
+
event: str = RunEvent.run_error.value
|
|
298
|
+
content: Optional[str] = None
|
|
299
|
+
|
|
300
|
+
# From exceptions
|
|
301
|
+
error_type: Optional[str] = None
|
|
302
|
+
error_id: Optional[str] = None
|
|
303
|
+
additional_data: Optional[Dict[str, Any]] = None
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
@dataclass
|
|
307
|
+
class RunCancelledEvent(BaseAgentRunEvent):
|
|
308
|
+
event: str = RunEvent.run_cancelled.value
|
|
309
|
+
reason: Optional[str] = None
|
|
310
|
+
|
|
311
|
+
@property
|
|
312
|
+
def is_cancelled(self):
|
|
313
|
+
return True
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
@dataclass
|
|
317
|
+
class PreHookStartedEvent(BaseAgentRunEvent):
|
|
318
|
+
event: str = RunEvent.pre_hook_started.value
|
|
319
|
+
pre_hook_name: Optional[str] = None
|
|
320
|
+
run_input: Optional[RunInput] = None
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
@dataclass
|
|
324
|
+
class PreHookCompletedEvent(BaseAgentRunEvent):
|
|
325
|
+
event: str = RunEvent.pre_hook_completed.value
|
|
326
|
+
pre_hook_name: Optional[str] = None
|
|
327
|
+
run_input: Optional[RunInput] = None
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
@dataclass
|
|
331
|
+
class PostHookStartedEvent(BaseAgentRunEvent):
|
|
332
|
+
event: str = RunEvent.post_hook_started.value
|
|
333
|
+
post_hook_name: Optional[str] = None
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
@dataclass
|
|
337
|
+
class PostHookCompletedEvent(BaseAgentRunEvent):
|
|
338
|
+
event: str = RunEvent.post_hook_completed.value
|
|
339
|
+
post_hook_name: Optional[str] = None
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
@dataclass
|
|
343
|
+
class MemoryUpdateStartedEvent(BaseAgentRunEvent):
|
|
344
|
+
event: str = RunEvent.memory_update_started.value
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
@dataclass
|
|
348
|
+
class MemoryUpdateCompletedEvent(BaseAgentRunEvent):
|
|
349
|
+
event: str = RunEvent.memory_update_completed.value
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
@dataclass
|
|
353
|
+
class SessionSummaryStartedEvent(BaseAgentRunEvent):
|
|
354
|
+
event: str = RunEvent.session_summary_started.value
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
@dataclass
|
|
358
|
+
class SessionSummaryCompletedEvent(BaseAgentRunEvent):
|
|
359
|
+
event: str = RunEvent.session_summary_completed.value
|
|
360
|
+
session_summary: Optional["SessionSummary"] = None
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
@dataclass
|
|
364
|
+
class ReasoningStartedEvent(BaseAgentRunEvent):
|
|
365
|
+
event: str = RunEvent.reasoning_started.value
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
@dataclass
|
|
369
|
+
class ReasoningStepEvent(BaseAgentRunEvent):
|
|
370
|
+
event: str = RunEvent.reasoning_step.value
|
|
371
|
+
content: Optional[Any] = None
|
|
372
|
+
content_type: str = "str"
|
|
373
|
+
reasoning_content: str = ""
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
@dataclass
|
|
377
|
+
class ReasoningCompletedEvent(BaseAgentRunEvent):
|
|
378
|
+
event: str = RunEvent.reasoning_completed.value
|
|
379
|
+
content: Optional[Any] = None
|
|
380
|
+
content_type: str = "str"
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
@dataclass
|
|
384
|
+
class ToolCallStartedEvent(BaseAgentRunEvent):
|
|
385
|
+
event: str = RunEvent.tool_call_started.value
|
|
386
|
+
tool: Optional[ToolExecution] = None
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
@dataclass
|
|
390
|
+
class ToolCallCompletedEvent(BaseAgentRunEvent):
|
|
391
|
+
event: str = RunEvent.tool_call_completed.value
|
|
392
|
+
tool: Optional[ToolExecution] = None
|
|
393
|
+
content: Optional[Any] = None
|
|
394
|
+
images: Optional[List[Image]] = None # Images produced by the tool call
|
|
395
|
+
videos: Optional[List[Video]] = None # Videos produced by the tool call
|
|
396
|
+
audio: Optional[List[Audio]] = None # Audio produced by the tool call
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
@dataclass
|
|
400
|
+
class ParserModelResponseStartedEvent(BaseAgentRunEvent):
|
|
401
|
+
event: str = RunEvent.parser_model_response_started.value
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
@dataclass
|
|
405
|
+
class ParserModelResponseCompletedEvent(BaseAgentRunEvent):
|
|
406
|
+
event: str = RunEvent.parser_model_response_completed.value
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
@dataclass
|
|
410
|
+
class OutputModelResponseStartedEvent(BaseAgentRunEvent):
|
|
411
|
+
event: str = RunEvent.output_model_response_started.value
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
@dataclass
|
|
415
|
+
class OutputModelResponseCompletedEvent(BaseAgentRunEvent):
|
|
416
|
+
event: str = RunEvent.output_model_response_completed.value
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
@dataclass
|
|
420
|
+
class CustomEvent(BaseAgentRunEvent):
|
|
421
|
+
event: str = RunEvent.custom_event.value
|
|
422
|
+
|
|
423
|
+
def __init__(self, **kwargs):
|
|
424
|
+
# Store arbitrary attributes directly on the instance
|
|
425
|
+
for key, value in kwargs.items():
|
|
426
|
+
setattr(self, key, value)
|
|
427
|
+
|
|
428
|
+
|
|
429
|
+
RunOutputEvent = Union[
|
|
430
|
+
RunStartedEvent,
|
|
431
|
+
RunContentEvent,
|
|
432
|
+
IntermediateRunContentEvent,
|
|
433
|
+
RunContentCompletedEvent,
|
|
434
|
+
RunCompletedEvent,
|
|
435
|
+
RunErrorEvent,
|
|
436
|
+
RunCancelledEvent,
|
|
437
|
+
RunPausedEvent,
|
|
438
|
+
RunContinuedEvent,
|
|
439
|
+
PreHookStartedEvent,
|
|
440
|
+
PreHookCompletedEvent,
|
|
441
|
+
PostHookStartedEvent,
|
|
442
|
+
PostHookCompletedEvent,
|
|
443
|
+
ReasoningStartedEvent,
|
|
444
|
+
ReasoningStepEvent,
|
|
445
|
+
ReasoningCompletedEvent,
|
|
446
|
+
MemoryUpdateStartedEvent,
|
|
447
|
+
MemoryUpdateCompletedEvent,
|
|
448
|
+
SessionSummaryStartedEvent,
|
|
449
|
+
SessionSummaryCompletedEvent,
|
|
450
|
+
ToolCallStartedEvent,
|
|
451
|
+
ToolCallCompletedEvent,
|
|
452
|
+
ParserModelResponseStartedEvent,
|
|
453
|
+
ParserModelResponseCompletedEvent,
|
|
454
|
+
OutputModelResponseStartedEvent,
|
|
455
|
+
OutputModelResponseCompletedEvent,
|
|
456
|
+
CustomEvent,
|
|
457
|
+
]
|
|
458
|
+
|
|
459
|
+
|
|
460
|
+
# Map event string to dataclass
|
|
461
|
+
RUN_EVENT_TYPE_REGISTRY = {
|
|
462
|
+
RunEvent.run_started.value: RunStartedEvent,
|
|
463
|
+
RunEvent.run_content.value: RunContentEvent,
|
|
464
|
+
RunEvent.run_content_completed.value: RunContentCompletedEvent,
|
|
465
|
+
RunEvent.run_intermediate_content.value: IntermediateRunContentEvent,
|
|
466
|
+
RunEvent.run_completed.value: RunCompletedEvent,
|
|
467
|
+
RunEvent.run_error.value: RunErrorEvent,
|
|
468
|
+
RunEvent.run_cancelled.value: RunCancelledEvent,
|
|
469
|
+
RunEvent.run_paused.value: RunPausedEvent,
|
|
470
|
+
RunEvent.run_continued.value: RunContinuedEvent,
|
|
471
|
+
RunEvent.pre_hook_started.value: PreHookStartedEvent,
|
|
472
|
+
RunEvent.pre_hook_completed.value: PreHookCompletedEvent,
|
|
473
|
+
RunEvent.post_hook_started.value: PostHookStartedEvent,
|
|
474
|
+
RunEvent.post_hook_completed.value: PostHookCompletedEvent,
|
|
475
|
+
RunEvent.reasoning_started.value: ReasoningStartedEvent,
|
|
476
|
+
RunEvent.reasoning_step.value: ReasoningStepEvent,
|
|
477
|
+
RunEvent.reasoning_completed.value: ReasoningCompletedEvent,
|
|
478
|
+
RunEvent.memory_update_started.value: MemoryUpdateStartedEvent,
|
|
479
|
+
RunEvent.memory_update_completed.value: MemoryUpdateCompletedEvent,
|
|
480
|
+
RunEvent.session_summary_started.value: SessionSummaryStartedEvent,
|
|
481
|
+
RunEvent.session_summary_completed.value: SessionSummaryCompletedEvent,
|
|
482
|
+
RunEvent.tool_call_started.value: ToolCallStartedEvent,
|
|
483
|
+
RunEvent.tool_call_completed.value: ToolCallCompletedEvent,
|
|
484
|
+
RunEvent.parser_model_response_started.value: ParserModelResponseStartedEvent,
|
|
485
|
+
RunEvent.parser_model_response_completed.value: ParserModelResponseCompletedEvent,
|
|
486
|
+
RunEvent.output_model_response_started.value: OutputModelResponseStartedEvent,
|
|
487
|
+
RunEvent.output_model_response_completed.value: OutputModelResponseCompletedEvent,
|
|
488
|
+
RunEvent.custom_event.value: CustomEvent,
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
|
|
492
|
+
def run_output_event_from_dict(data: dict) -> BaseRunOutputEvent:
|
|
493
|
+
event_type = data.get("event", "")
|
|
494
|
+
cls = RUN_EVENT_TYPE_REGISTRY.get(event_type)
|
|
495
|
+
if not cls:
|
|
496
|
+
raise ValueError(f"Unknown event type: {event_type}")
|
|
497
|
+
return cls.from_dict(data) # type: ignore
|
|
498
|
+
|
|
499
|
+
|
|
500
|
+
@dataclass
|
|
501
|
+
class RunOutput:
|
|
502
|
+
"""Response returned by Agent.run() or Workflow.run() functions"""
|
|
503
|
+
|
|
504
|
+
run_id: Optional[str] = None
|
|
505
|
+
agent_id: Optional[str] = None
|
|
506
|
+
agent_name: Optional[str] = None
|
|
507
|
+
session_id: Optional[str] = None
|
|
508
|
+
parent_run_id: Optional[str] = None
|
|
509
|
+
workflow_id: Optional[str] = None
|
|
510
|
+
user_id: Optional[str] = None
|
|
511
|
+
|
|
512
|
+
# Input media and messages from user
|
|
513
|
+
input: Optional[RunInput] = None
|
|
514
|
+
|
|
515
|
+
content: Optional[Any] = None
|
|
516
|
+
content_type: str = "str"
|
|
517
|
+
|
|
518
|
+
reasoning_content: Optional[str] = None
|
|
519
|
+
reasoning_steps: Optional[List[ReasoningStep]] = None
|
|
520
|
+
reasoning_messages: Optional[List[Message]] = None
|
|
521
|
+
|
|
522
|
+
model_provider_data: Optional[Dict[str, Any]] = None
|
|
523
|
+
|
|
524
|
+
model: Optional[str] = None
|
|
525
|
+
model_provider: Optional[str] = None
|
|
526
|
+
messages: Optional[List[Message]] = None
|
|
527
|
+
metrics: Optional[Metrics] = None
|
|
528
|
+
additional_input: Optional[List[Message]] = None
|
|
529
|
+
|
|
530
|
+
tools: Optional[List[ToolExecution]] = None
|
|
531
|
+
|
|
532
|
+
images: Optional[List[Image]] = None # Images attached to the response
|
|
533
|
+
videos: Optional[List[Video]] = None # Videos attached to the response
|
|
534
|
+
audio: Optional[List[Audio]] = None # Audio attached to the response
|
|
535
|
+
files: Optional[List[File]] = None # Files attached to the response
|
|
536
|
+
response_audio: Optional[Audio] = None # Model audio response
|
|
537
|
+
|
|
538
|
+
citations: Optional[Citations] = None
|
|
539
|
+
references: Optional[List[MessageReferences]] = None
|
|
540
|
+
|
|
541
|
+
metadata: Optional[Dict[str, Any]] = None
|
|
542
|
+
session_state: Optional[Dict[str, Any]] = None
|
|
543
|
+
|
|
544
|
+
created_at: int = field(default_factory=lambda: int(time()))
|
|
545
|
+
|
|
546
|
+
events: Optional[List[RunOutputEvent]] = None
|
|
547
|
+
|
|
548
|
+
status: RunStatus = RunStatus.running
|
|
549
|
+
|
|
550
|
+
# User control flow (HITL) requirements to continue a run when paused, in order of arrival
|
|
551
|
+
requirements: Optional[list[RunRequirement]] = None
|
|
552
|
+
|
|
553
|
+
# === FOREIGN KEY RELATIONSHIPS ===
|
|
554
|
+
# These fields establish relationships to parent workflow/step structures
|
|
555
|
+
# and should be treated as foreign keys for data integrity
|
|
556
|
+
workflow_step_id: Optional[str] = None # FK: Points to StepOutput.step_id
|
|
557
|
+
|
|
558
|
+
@property
|
|
559
|
+
def active_requirements(self) -> list[RunRequirement]:
|
|
560
|
+
if not self.requirements:
|
|
561
|
+
return []
|
|
562
|
+
return [requirement for requirement in self.requirements if not requirement.is_resolved()]
|
|
563
|
+
|
|
564
|
+
@property
|
|
565
|
+
def is_paused(self):
|
|
566
|
+
return self.status == RunStatus.paused
|
|
567
|
+
|
|
568
|
+
@property
|
|
569
|
+
def is_cancelled(self):
|
|
570
|
+
return self.status == RunStatus.cancelled
|
|
571
|
+
|
|
572
|
+
@property
|
|
573
|
+
def tools_requiring_confirmation(self):
|
|
574
|
+
return [t for t in self.tools if t.requires_confirmation] if self.tools else []
|
|
575
|
+
|
|
576
|
+
@property
|
|
577
|
+
def tools_requiring_user_input(self):
|
|
578
|
+
return [t for t in self.tools if t.requires_user_input] if self.tools else []
|
|
579
|
+
|
|
580
|
+
@property
|
|
581
|
+
def tools_awaiting_external_execution(self):
|
|
582
|
+
return [t for t in self.tools if t.external_execution_required] if self.tools else []
|
|
583
|
+
|
|
584
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
585
|
+
_dict = {
|
|
586
|
+
k: v
|
|
587
|
+
for k, v in asdict(self).items()
|
|
588
|
+
if v is not None
|
|
589
|
+
and k
|
|
590
|
+
not in [
|
|
591
|
+
"messages",
|
|
592
|
+
"metrics",
|
|
593
|
+
"tools",
|
|
594
|
+
"metadata",
|
|
595
|
+
"images",
|
|
596
|
+
"videos",
|
|
597
|
+
"audio",
|
|
598
|
+
"files",
|
|
599
|
+
"response_audio",
|
|
600
|
+
"input",
|
|
601
|
+
"citations",
|
|
602
|
+
"events",
|
|
603
|
+
"additional_input",
|
|
604
|
+
"reasoning_steps",
|
|
605
|
+
"reasoning_messages",
|
|
606
|
+
"references",
|
|
607
|
+
"requirements",
|
|
608
|
+
]
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
if self.metrics is not None:
|
|
612
|
+
_dict["metrics"] = self.metrics.to_dict() if isinstance(self.metrics, Metrics) else self.metrics
|
|
613
|
+
|
|
614
|
+
if self.events is not None:
|
|
615
|
+
_dict["events"] = [e.to_dict() for e in self.events]
|
|
616
|
+
|
|
617
|
+
if self.status is not None:
|
|
618
|
+
_dict["status"] = self.status.value if isinstance(self.status, RunStatus) else self.status
|
|
619
|
+
|
|
620
|
+
if self.messages is not None:
|
|
621
|
+
_dict["messages"] = [m.to_dict() for m in self.messages]
|
|
622
|
+
|
|
623
|
+
if self.metadata is not None:
|
|
624
|
+
_dict["metadata"] = self.metadata
|
|
625
|
+
|
|
626
|
+
if self.additional_input is not None:
|
|
627
|
+
_dict["additional_input"] = [m.to_dict() for m in self.additional_input]
|
|
628
|
+
|
|
629
|
+
if self.reasoning_messages is not None:
|
|
630
|
+
_dict["reasoning_messages"] = [m.to_dict() for m in self.reasoning_messages]
|
|
631
|
+
|
|
632
|
+
if self.reasoning_steps is not None:
|
|
633
|
+
_dict["reasoning_steps"] = [rs.model_dump() for rs in self.reasoning_steps]
|
|
634
|
+
|
|
635
|
+
if self.references is not None:
|
|
636
|
+
_dict["references"] = [r.model_dump() for r in self.references]
|
|
637
|
+
|
|
638
|
+
if self.images is not None:
|
|
639
|
+
_dict["images"] = []
|
|
640
|
+
for img in self.images:
|
|
641
|
+
if isinstance(img, Image):
|
|
642
|
+
_dict["images"].append(img.to_dict())
|
|
643
|
+
else:
|
|
644
|
+
_dict["images"].append(img)
|
|
645
|
+
|
|
646
|
+
if self.videos is not None:
|
|
647
|
+
_dict["videos"] = []
|
|
648
|
+
for vid in self.videos:
|
|
649
|
+
if isinstance(vid, Video):
|
|
650
|
+
_dict["videos"].append(vid.to_dict())
|
|
651
|
+
else:
|
|
652
|
+
_dict["videos"].append(vid)
|
|
653
|
+
|
|
654
|
+
if self.audio is not None:
|
|
655
|
+
_dict["audio"] = []
|
|
656
|
+
for aud in self.audio:
|
|
657
|
+
if isinstance(aud, Audio):
|
|
658
|
+
_dict["audio"].append(aud.to_dict())
|
|
659
|
+
else:
|
|
660
|
+
_dict["audio"].append(aud)
|
|
661
|
+
|
|
662
|
+
if self.files is not None:
|
|
663
|
+
_dict["files"] = []
|
|
664
|
+
for file in self.files:
|
|
665
|
+
if isinstance(file, File):
|
|
666
|
+
_dict["files"].append(file.to_dict())
|
|
667
|
+
else:
|
|
668
|
+
_dict["files"].append(file)
|
|
669
|
+
|
|
670
|
+
if self.response_audio is not None:
|
|
671
|
+
if isinstance(self.response_audio, Audio):
|
|
672
|
+
_dict["response_audio"] = self.response_audio.to_dict()
|
|
673
|
+
else:
|
|
674
|
+
_dict["response_audio"] = self.response_audio
|
|
675
|
+
|
|
676
|
+
if self.citations is not None:
|
|
677
|
+
if isinstance(self.citations, Citations):
|
|
678
|
+
_dict["citations"] = self.citations.model_dump(exclude_none=True)
|
|
679
|
+
else:
|
|
680
|
+
_dict["citations"] = self.citations
|
|
681
|
+
|
|
682
|
+
if self.content and isinstance(self.content, BaseModel):
|
|
683
|
+
_dict["content"] = self.content.model_dump(exclude_none=True, mode="json")
|
|
684
|
+
|
|
685
|
+
if self.tools is not None:
|
|
686
|
+
_dict["tools"] = []
|
|
687
|
+
for tool in self.tools:
|
|
688
|
+
if isinstance(tool, ToolExecution):
|
|
689
|
+
_dict["tools"].append(tool.to_dict())
|
|
690
|
+
else:
|
|
691
|
+
_dict["tools"].append(tool)
|
|
692
|
+
|
|
693
|
+
if self.requirements is not None:
|
|
694
|
+
_dict["requirements"] = [req.to_dict() if hasattr(req, "to_dict") else req for req in self.requirements]
|
|
695
|
+
|
|
696
|
+
if self.input is not None:
|
|
697
|
+
_dict["input"] = self.input.to_dict()
|
|
698
|
+
|
|
699
|
+
return _dict
|
|
700
|
+
|
|
701
|
+
def to_json(self, separators=(", ", ": "), indent: Optional[int] = 2) -> str:
|
|
702
|
+
import json
|
|
703
|
+
|
|
704
|
+
try:
|
|
705
|
+
_dict = self.to_dict()
|
|
706
|
+
except Exception:
|
|
707
|
+
logger.error("Failed to convert response to json", exc_info=True)
|
|
708
|
+
raise
|
|
709
|
+
|
|
710
|
+
if indent is None:
|
|
711
|
+
return json.dumps(_dict, separators=separators)
|
|
712
|
+
else:
|
|
713
|
+
return json.dumps(_dict, indent=indent, separators=separators)
|
|
714
|
+
|
|
715
|
+
@classmethod
|
|
716
|
+
def from_dict(cls, data: Dict[str, Any]) -> "RunOutput":
|
|
717
|
+
if "run" in data:
|
|
718
|
+
data = data.pop("run")
|
|
719
|
+
|
|
720
|
+
events = data.pop("events", None)
|
|
721
|
+
final_events = []
|
|
722
|
+
for event in events or []:
|
|
723
|
+
if "agent_id" in event:
|
|
724
|
+
event = run_output_event_from_dict(event)
|
|
725
|
+
else:
|
|
726
|
+
# Use the factory from response.py for agent events
|
|
727
|
+
from agno.run.team import team_run_output_event_from_dict
|
|
728
|
+
|
|
729
|
+
event = team_run_output_event_from_dict(event)
|
|
730
|
+
final_events.append(event)
|
|
731
|
+
events = final_events
|
|
732
|
+
|
|
733
|
+
messages = data.pop("messages", None)
|
|
734
|
+
messages = [Message.from_dict(message) for message in messages] if messages else None
|
|
735
|
+
|
|
736
|
+
citations = data.pop("citations", None)
|
|
737
|
+
citations = Citations.model_validate(citations) if citations else None
|
|
738
|
+
|
|
739
|
+
tools = data.pop("tools", [])
|
|
740
|
+
tools = [ToolExecution.from_dict(tool) for tool in tools] if tools else None
|
|
741
|
+
|
|
742
|
+
# Handle requirements
|
|
743
|
+
requirements_data = data.pop("requirements", None)
|
|
744
|
+
requirements: Optional[List[RunRequirement]] = None
|
|
745
|
+
if requirements_data is not None:
|
|
746
|
+
requirements_list: List[RunRequirement] = []
|
|
747
|
+
for item in requirements_data:
|
|
748
|
+
if isinstance(item, RunRequirement):
|
|
749
|
+
requirements_list.append(item)
|
|
750
|
+
elif isinstance(item, dict):
|
|
751
|
+
requirements_list.append(RunRequirement.from_dict(item))
|
|
752
|
+
requirements = requirements_list if requirements_list else None
|
|
753
|
+
|
|
754
|
+
images = reconstruct_images(data.pop("images", []))
|
|
755
|
+
videos = reconstruct_videos(data.pop("videos", []))
|
|
756
|
+
audio = reconstruct_audio_list(data.pop("audio", []))
|
|
757
|
+
files = reconstruct_files(data.pop("files", []))
|
|
758
|
+
response_audio = reconstruct_response_audio(data.pop("response_audio", None))
|
|
759
|
+
|
|
760
|
+
input_data = data.pop("input", None)
|
|
761
|
+
input_obj = None
|
|
762
|
+
if input_data:
|
|
763
|
+
input_obj = RunInput.from_dict(input_data)
|
|
764
|
+
|
|
765
|
+
metrics = data.pop("metrics", None)
|
|
766
|
+
if metrics:
|
|
767
|
+
metrics = Metrics(**metrics)
|
|
768
|
+
|
|
769
|
+
additional_input = data.pop("additional_input", None)
|
|
770
|
+
|
|
771
|
+
if additional_input is not None:
|
|
772
|
+
additional_input = [Message.from_dict(message) for message in additional_input]
|
|
773
|
+
|
|
774
|
+
reasoning_steps = data.pop("reasoning_steps", None)
|
|
775
|
+
if reasoning_steps is not None:
|
|
776
|
+
reasoning_steps = [ReasoningStep.model_validate(step) for step in reasoning_steps]
|
|
777
|
+
|
|
778
|
+
reasoning_messages = data.pop("reasoning_messages", None)
|
|
779
|
+
if reasoning_messages is not None:
|
|
780
|
+
reasoning_messages = [Message.from_dict(message) for message in reasoning_messages]
|
|
781
|
+
|
|
782
|
+
references = data.pop("references", None)
|
|
783
|
+
if references is not None:
|
|
784
|
+
references = [MessageReferences.model_validate(reference) for reference in references]
|
|
785
|
+
|
|
786
|
+
# Filter data to only include fields that are actually defined in the RunOutput dataclass
|
|
787
|
+
from dataclasses import fields
|
|
788
|
+
|
|
789
|
+
supported_fields = {f.name for f in fields(cls)}
|
|
790
|
+
filtered_data = {k: v for k, v in data.items() if k in supported_fields}
|
|
791
|
+
|
|
792
|
+
return cls(
|
|
793
|
+
messages=messages,
|
|
794
|
+
metrics=metrics,
|
|
795
|
+
citations=citations,
|
|
796
|
+
tools=tools,
|
|
797
|
+
images=images,
|
|
798
|
+
audio=audio,
|
|
799
|
+
videos=videos,
|
|
800
|
+
files=files,
|
|
801
|
+
response_audio=response_audio,
|
|
802
|
+
input=input_obj,
|
|
803
|
+
events=events,
|
|
804
|
+
additional_input=additional_input,
|
|
805
|
+
reasoning_steps=reasoning_steps,
|
|
806
|
+
reasoning_messages=reasoning_messages,
|
|
807
|
+
references=references,
|
|
808
|
+
requirements=requirements,
|
|
809
|
+
**filtered_data,
|
|
810
|
+
)
|
|
811
|
+
|
|
812
|
+
def get_content_as_string(self, **kwargs) -> str:
|
|
813
|
+
import json
|
|
814
|
+
|
|
815
|
+
from pydantic import BaseModel
|
|
816
|
+
|
|
817
|
+
if isinstance(self.content, str):
|
|
818
|
+
return self.content
|
|
819
|
+
elif isinstance(self.content, BaseModel):
|
|
820
|
+
return self.content.model_dump_json(exclude_none=True, **kwargs)
|
|
821
|
+
else:
|
|
822
|
+
return json.dumps(self.content, **kwargs)
|