agno 1.8.2__py3-none-any.whl → 2.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agno/agent/__init__.py +19 -27
- agno/agent/agent.py +3143 -4170
- agno/api/agent.py +11 -67
- agno/api/api.py +5 -46
- agno/api/evals.py +8 -19
- agno/api/os.py +17 -0
- agno/api/routes.py +6 -41
- agno/api/schemas/__init__.py +9 -0
- agno/api/schemas/agent.py +5 -21
- agno/api/schemas/evals.py +7 -16
- agno/api/schemas/os.py +14 -0
- agno/api/schemas/team.py +5 -21
- agno/api/schemas/utils.py +21 -0
- agno/api/schemas/workflows.py +11 -7
- agno/api/settings.py +53 -0
- agno/api/team.py +11 -66
- 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/db/__init__.py +24 -0
- agno/db/base.py +245 -0
- agno/db/dynamo/__init__.py +3 -0
- agno/db/dynamo/dynamo.py +1743 -0
- agno/db/dynamo/schemas.py +278 -0
- agno/db/dynamo/utils.py +684 -0
- agno/db/firestore/__init__.py +3 -0
- agno/db/firestore/firestore.py +1432 -0
- agno/db/firestore/schemas.py +130 -0
- agno/db/firestore/utils.py +278 -0
- agno/db/gcs_json/__init__.py +3 -0
- agno/db/gcs_json/gcs_json_db.py +1001 -0
- agno/db/gcs_json/utils.py +194 -0
- agno/db/in_memory/__init__.py +3 -0
- agno/db/in_memory/in_memory_db.py +882 -0
- agno/db/in_memory/utils.py +172 -0
- agno/db/json/__init__.py +3 -0
- agno/db/json/json_db.py +1045 -0
- agno/db/json/utils.py +196 -0
- agno/db/migrations/v1_to_v2.py +162 -0
- agno/db/mongo/__init__.py +3 -0
- agno/db/mongo/mongo.py +1416 -0
- agno/db/mongo/schemas.py +77 -0
- agno/db/mongo/utils.py +204 -0
- agno/db/mysql/__init__.py +3 -0
- agno/db/mysql/mysql.py +1719 -0
- agno/db/mysql/schemas.py +124 -0
- agno/db/mysql/utils.py +297 -0
- agno/db/postgres/__init__.py +3 -0
- agno/db/postgres/postgres.py +1710 -0
- agno/db/postgres/schemas.py +124 -0
- agno/db/postgres/utils.py +280 -0
- agno/db/redis/__init__.py +3 -0
- agno/db/redis/redis.py +1367 -0
- agno/db/redis/schemas.py +109 -0
- agno/db/redis/utils.py +288 -0
- agno/db/schemas/__init__.py +3 -0
- agno/db/schemas/evals.py +33 -0
- agno/db/schemas/knowledge.py +40 -0
- agno/db/schemas/memory.py +46 -0
- agno/db/singlestore/__init__.py +3 -0
- agno/db/singlestore/schemas.py +116 -0
- agno/db/singlestore/singlestore.py +1712 -0
- agno/db/singlestore/utils.py +326 -0
- agno/db/sqlite/__init__.py +3 -0
- agno/db/sqlite/schemas.py +119 -0
- agno/db/sqlite/sqlite.py +1676 -0
- agno/db/sqlite/utils.py +268 -0
- agno/db/utils.py +88 -0
- agno/eval/__init__.py +14 -0
- agno/eval/accuracy.py +154 -48
- agno/eval/performance.py +88 -23
- agno/eval/reliability.py +73 -20
- agno/eval/utils.py +23 -13
- agno/integrations/discord/__init__.py +3 -0
- agno/{app → integrations}/discord/client.py +10 -10
- agno/knowledge/__init__.py +2 -2
- agno/{document → knowledge}/chunking/agentic.py +2 -2
- agno/{document → knowledge}/chunking/document.py +2 -2
- agno/{document → knowledge}/chunking/fixed.py +3 -3
- agno/{document → knowledge}/chunking/markdown.py +2 -2
- agno/{document → knowledge}/chunking/recursive.py +2 -2
- agno/{document → knowledge}/chunking/row.py +2 -2
- agno/knowledge/chunking/semantic.py +59 -0
- agno/knowledge/chunking/strategy.py +121 -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/{embedder → knowledge/embedder}/aws_bedrock.py +127 -1
- agno/{embedder → knowledge/embedder}/azure_openai.py +65 -1
- agno/{embedder → knowledge/embedder}/base.py +6 -0
- agno/{embedder → knowledge/embedder}/cohere.py +72 -1
- agno/{embedder → knowledge/embedder}/fastembed.py +17 -1
- agno/{embedder → knowledge/embedder}/fireworks.py +1 -1
- agno/{embedder → knowledge/embedder}/google.py +74 -1
- agno/{embedder → knowledge/embedder}/huggingface.py +36 -2
- agno/{embedder → knowledge/embedder}/jina.py +48 -2
- agno/knowledge/embedder/langdb.py +22 -0
- agno/knowledge/embedder/mistral.py +139 -0
- agno/{embedder → knowledge/embedder}/nebius.py +1 -1
- agno/{embedder → knowledge/embedder}/ollama.py +54 -3
- agno/knowledge/embedder/openai.py +223 -0
- agno/{embedder → knowledge/embedder}/sentence_transformer.py +16 -1
- agno/{embedder → knowledge/embedder}/together.py +1 -1
- agno/{embedder → knowledge/embedder}/voyageai.py +49 -1
- agno/knowledge/knowledge.py +1551 -0
- agno/knowledge/reader/__init__.py +7 -0
- agno/{document → knowledge}/reader/arxiv_reader.py +32 -4
- agno/knowledge/reader/base.py +88 -0
- agno/{document → knowledge}/reader/csv_reader.py +47 -65
- agno/knowledge/reader/docx_reader.py +83 -0
- agno/{document → knowledge}/reader/firecrawl_reader.py +42 -21
- agno/{document → knowledge}/reader/json_reader.py +30 -9
- agno/{document → knowledge}/reader/markdown_reader.py +58 -9
- agno/{document → knowledge}/reader/pdf_reader.py +71 -126
- agno/knowledge/reader/reader_factory.py +268 -0
- agno/knowledge/reader/s3_reader.py +101 -0
- agno/{document → knowledge}/reader/text_reader.py +31 -10
- agno/knowledge/reader/url_reader.py +128 -0
- agno/knowledge/reader/web_search_reader.py +366 -0
- agno/{document → knowledge}/reader/website_reader.py +37 -10
- agno/knowledge/reader/wikipedia_reader.py +59 -0
- agno/knowledge/reader/youtube_reader.py +78 -0
- agno/knowledge/remote_content/remote_content.py +88 -0
- agno/{reranker → knowledge/reranker}/base.py +1 -1
- agno/{reranker → knowledge/reranker}/cohere.py +2 -2
- agno/{reranker → knowledge/reranker}/infinity.py +2 -2
- agno/{reranker → knowledge/reranker}/sentence_transformer.py +2 -2
- agno/knowledge/types.py +30 -0
- agno/knowledge/utils.py +169 -0
- agno/media.py +269 -268
- agno/memory/__init__.py +2 -10
- agno/memory/manager.py +1003 -148
- agno/models/aimlapi/__init__.py +2 -2
- agno/models/aimlapi/aimlapi.py +6 -6
- agno/models/anthropic/claude.py +128 -72
- agno/models/aws/bedrock.py +107 -175
- agno/models/aws/claude.py +64 -18
- agno/models/azure/ai_foundry.py +73 -23
- agno/models/base.py +346 -290
- agno/models/cerebras/cerebras.py +84 -27
- agno/models/cohere/chat.py +106 -98
- agno/models/google/gemini.py +105 -46
- agno/models/groq/groq.py +97 -35
- agno/models/huggingface/huggingface.py +92 -27
- agno/models/ibm/watsonx.py +72 -13
- agno/models/litellm/chat.py +85 -13
- agno/models/message.py +46 -151
- agno/models/meta/llama.py +85 -49
- agno/models/metrics.py +120 -0
- agno/models/mistral/mistral.py +90 -21
- agno/models/ollama/__init__.py +0 -2
- agno/models/ollama/chat.py +85 -47
- agno/models/openai/chat.py +154 -37
- agno/models/openai/responses.py +178 -105
- agno/models/perplexity/perplexity.py +26 -2
- agno/models/portkey/portkey.py +0 -7
- agno/models/response.py +15 -9
- agno/models/utils.py +20 -0
- agno/models/vercel/__init__.py +2 -2
- agno/models/vercel/v0.py +1 -1
- agno/models/vllm/__init__.py +2 -2
- agno/models/vllm/vllm.py +3 -3
- agno/models/xai/xai.py +10 -10
- agno/os/__init__.py +3 -0
- agno/os/app.py +497 -0
- agno/os/auth.py +47 -0
- agno/os/config.py +103 -0
- agno/os/interfaces/agui/__init__.py +3 -0
- agno/os/interfaces/agui/agui.py +31 -0
- agno/{app/agui/async_router.py → os/interfaces/agui/router.py} +16 -16
- agno/{app → os/interfaces}/agui/utils.py +65 -28
- agno/os/interfaces/base.py +21 -0
- agno/os/interfaces/slack/__init__.py +3 -0
- agno/{app/slack/async_router.py → os/interfaces/slack/router.py} +3 -5
- agno/os/interfaces/slack/slack.py +32 -0
- agno/os/interfaces/whatsapp/__init__.py +3 -0
- agno/{app/whatsapp/async_router.py → os/interfaces/whatsapp/router.py} +4 -7
- agno/os/interfaces/whatsapp/whatsapp.py +29 -0
- agno/os/mcp.py +235 -0
- agno/os/router.py +1400 -0
- agno/os/routers/__init__.py +3 -0
- agno/os/routers/evals/__init__.py +3 -0
- agno/os/routers/evals/evals.py +393 -0
- agno/os/routers/evals/schemas.py +142 -0
- agno/os/routers/evals/utils.py +161 -0
- agno/os/routers/knowledge/__init__.py +3 -0
- agno/os/routers/knowledge/knowledge.py +850 -0
- agno/os/routers/knowledge/schemas.py +118 -0
- agno/os/routers/memory/__init__.py +3 -0
- agno/os/routers/memory/memory.py +410 -0
- agno/os/routers/memory/schemas.py +58 -0
- agno/os/routers/metrics/__init__.py +3 -0
- agno/os/routers/metrics/metrics.py +178 -0
- agno/os/routers/metrics/schemas.py +47 -0
- agno/os/routers/session/__init__.py +3 -0
- agno/os/routers/session/session.py +536 -0
- agno/os/schema.py +945 -0
- agno/{app/playground → os}/settings.py +7 -15
- agno/os/utils.py +270 -0
- agno/reasoning/azure_ai_foundry.py +4 -4
- agno/reasoning/deepseek.py +4 -4
- agno/reasoning/default.py +6 -11
- agno/reasoning/groq.py +4 -4
- agno/reasoning/helpers.py +4 -6
- agno/reasoning/ollama.py +4 -4
- agno/reasoning/openai.py +4 -4
- agno/run/agent.py +633 -0
- agno/run/base.py +53 -77
- agno/run/cancel.py +81 -0
- agno/run/team.py +243 -96
- agno/run/workflow.py +550 -12
- agno/session/__init__.py +10 -0
- agno/session/agent.py +244 -0
- agno/session/summary.py +225 -0
- agno/session/team.py +262 -0
- agno/{storage/session/v2 → session}/workflow.py +47 -24
- agno/team/__init__.py +15 -16
- agno/team/team.py +3260 -4824
- agno/tools/agentql.py +14 -5
- agno/tools/airflow.py +9 -4
- agno/tools/api.py +7 -3
- agno/tools/apify.py +2 -46
- agno/tools/arxiv.py +8 -3
- agno/tools/aws_lambda.py +7 -5
- agno/tools/aws_ses.py +7 -1
- agno/tools/baidusearch.py +4 -1
- agno/tools/bitbucket.py +4 -4
- agno/tools/brandfetch.py +14 -11
- agno/tools/bravesearch.py +4 -1
- agno/tools/brightdata.py +43 -23
- agno/tools/browserbase.py +13 -4
- agno/tools/calcom.py +12 -10
- agno/tools/calculator.py +10 -27
- agno/tools/cartesia.py +20 -17
- agno/tools/{clickup_tool.py → clickup.py} +12 -25
- agno/tools/confluence.py +8 -8
- agno/tools/crawl4ai.py +7 -1
- agno/tools/csv_toolkit.py +9 -8
- agno/tools/dalle.py +22 -12
- agno/tools/daytona.py +13 -16
- agno/tools/decorator.py +6 -3
- agno/tools/desi_vocal.py +17 -8
- agno/tools/discord.py +11 -8
- agno/tools/docker.py +30 -42
- agno/tools/duckdb.py +34 -53
- agno/tools/duckduckgo.py +8 -7
- agno/tools/e2b.py +62 -62
- agno/tools/eleven_labs.py +36 -29
- agno/tools/email.py +4 -1
- agno/tools/evm.py +7 -1
- agno/tools/exa.py +19 -14
- agno/tools/fal.py +30 -30
- agno/tools/file.py +9 -8
- agno/tools/financial_datasets.py +25 -44
- agno/tools/firecrawl.py +17 -18
- agno/tools/function.py +127 -18
- agno/tools/giphy.py +23 -11
- agno/tools/github.py +48 -126
- agno/tools/gmail.py +45 -61
- agno/tools/google_bigquery.py +7 -6
- agno/tools/google_maps.py +11 -26
- agno/tools/googlesearch.py +7 -2
- agno/tools/googlesheets.py +21 -17
- agno/tools/hackernews.py +9 -5
- agno/tools/jina.py +5 -4
- agno/tools/jira.py +18 -9
- agno/tools/knowledge.py +31 -32
- agno/tools/linear.py +18 -33
- agno/tools/linkup.py +5 -1
- agno/tools/local_file_system.py +8 -5
- agno/tools/lumalab.py +32 -20
- agno/tools/mcp.py +1 -2
- agno/tools/mem0.py +18 -12
- agno/tools/memori.py +14 -10
- agno/tools/mlx_transcribe.py +3 -2
- agno/tools/models/azure_openai.py +33 -15
- agno/tools/models/gemini.py +59 -32
- agno/tools/models/groq.py +30 -23
- agno/tools/models/nebius.py +28 -12
- agno/tools/models_labs.py +40 -16
- agno/tools/moviepy_video.py +7 -6
- agno/tools/neo4j.py +10 -8
- agno/tools/newspaper.py +7 -2
- agno/tools/newspaper4k.py +8 -3
- agno/tools/openai.py +58 -32
- agno/tools/openbb.py +12 -11
- agno/tools/opencv.py +63 -47
- agno/tools/openweather.py +14 -12
- agno/tools/pandas.py +11 -3
- agno/tools/postgres.py +4 -12
- agno/tools/pubmed.py +4 -1
- agno/tools/python.py +9 -22
- agno/tools/reasoning.py +35 -27
- agno/tools/reddit.py +11 -26
- agno/tools/replicate.py +55 -42
- agno/tools/resend.py +4 -1
- agno/tools/scrapegraph.py +15 -14
- agno/tools/searxng.py +10 -23
- agno/tools/serpapi.py +6 -3
- agno/tools/serper.py +13 -4
- agno/tools/shell.py +9 -2
- agno/tools/slack.py +12 -11
- agno/tools/sleep.py +3 -2
- agno/tools/spider.py +24 -4
- agno/tools/sql.py +7 -6
- agno/tools/tavily.py +6 -4
- agno/tools/telegram.py +12 -4
- agno/tools/todoist.py +11 -31
- agno/tools/toolkit.py +1 -1
- agno/tools/trafilatura.py +22 -6
- agno/tools/trello.py +9 -22
- agno/tools/twilio.py +10 -3
- agno/tools/user_control_flow.py +6 -1
- agno/tools/valyu.py +34 -5
- agno/tools/visualization.py +19 -28
- agno/tools/webbrowser.py +4 -3
- agno/tools/webex.py +11 -7
- agno/tools/website.py +15 -46
- agno/tools/webtools.py +12 -4
- agno/tools/whatsapp.py +5 -9
- agno/tools/wikipedia.py +20 -13
- agno/tools/x.py +14 -13
- agno/tools/yfinance.py +13 -40
- agno/tools/youtube.py +26 -20
- agno/tools/zendesk.py +7 -2
- agno/tools/zep.py +10 -7
- agno/tools/zoom.py +10 -9
- agno/utils/common.py +1 -19
- agno/utils/events.py +100 -123
- agno/utils/gemini.py +1 -1
- agno/utils/knowledge.py +29 -0
- agno/utils/log.py +54 -4
- agno/utils/mcp.py +68 -10
- agno/utils/media.py +39 -0
- agno/utils/message.py +12 -1
- agno/utils/models/aws_claude.py +1 -1
- agno/utils/models/claude.py +6 -12
- agno/utils/models/cohere.py +1 -1
- agno/utils/models/mistral.py +8 -7
- agno/utils/models/schema_utils.py +3 -3
- agno/utils/models/watsonx.py +1 -1
- agno/utils/openai.py +1 -1
- agno/utils/pprint.py +33 -32
- agno/utils/print_response/agent.py +779 -0
- agno/utils/print_response/team.py +1669 -0
- agno/utils/print_response/workflow.py +1451 -0
- agno/utils/prompts.py +14 -14
- agno/utils/reasoning.py +87 -0
- agno/utils/response.py +42 -42
- agno/utils/streamlit.py +481 -0
- agno/utils/string.py +8 -22
- agno/utils/team.py +50 -0
- agno/utils/timer.py +2 -2
- agno/vectordb/base.py +33 -21
- agno/vectordb/cassandra/cassandra.py +287 -23
- agno/vectordb/chroma/chromadb.py +482 -59
- agno/vectordb/clickhouse/clickhousedb.py +270 -63
- agno/vectordb/couchbase/couchbase.py +309 -29
- agno/vectordb/lancedb/lance_db.py +360 -21
- agno/vectordb/langchaindb/__init__.py +5 -0
- agno/vectordb/langchaindb/langchaindb.py +145 -0
- agno/vectordb/lightrag/__init__.py +5 -0
- agno/vectordb/lightrag/lightrag.py +374 -0
- agno/vectordb/llamaindex/llamaindexdb.py +127 -0
- agno/vectordb/milvus/milvus.py +242 -32
- agno/vectordb/mongodb/mongodb.py +200 -24
- agno/vectordb/pgvector/pgvector.py +319 -37
- agno/vectordb/pineconedb/pineconedb.py +221 -27
- agno/vectordb/qdrant/qdrant.py +334 -14
- agno/vectordb/singlestore/singlestore.py +286 -29
- agno/vectordb/surrealdb/surrealdb.py +187 -7
- agno/vectordb/upstashdb/upstashdb.py +342 -26
- agno/vectordb/weaviate/weaviate.py +227 -165
- agno/workflow/__init__.py +17 -13
- agno/workflow/{v2/condition.py → condition.py} +135 -32
- agno/workflow/{v2/loop.py → loop.py} +115 -28
- agno/workflow/{v2/parallel.py → parallel.py} +138 -108
- agno/workflow/{v2/router.py → router.py} +133 -32
- agno/workflow/{v2/step.py → step.py} +207 -49
- agno/workflow/{v2/steps.py → steps.py} +147 -66
- agno/workflow/types.py +482 -0
- agno/workflow/workflow.py +2410 -696
- agno-2.0.0.dist-info/METADATA +494 -0
- agno-2.0.0.dist-info/RECORD +515 -0
- agno-2.0.0.dist-info/licenses/LICENSE +201 -0
- agno/agent/metrics.py +0 -110
- agno/api/app.py +0 -35
- agno/api/playground.py +0 -92
- agno/api/schemas/app.py +0 -12
- agno/api/schemas/playground.py +0 -22
- agno/api/schemas/user.py +0 -35
- agno/api/schemas/workspace.py +0 -46
- agno/api/user.py +0 -160
- agno/api/workflows.py +0 -33
- agno/api/workspace.py +0 -175
- agno/app/agui/__init__.py +0 -3
- agno/app/agui/app.py +0 -17
- agno/app/agui/sync_router.py +0 -120
- agno/app/base.py +0 -186
- agno/app/discord/__init__.py +0 -3
- agno/app/fastapi/__init__.py +0 -3
- agno/app/fastapi/app.py +0 -107
- agno/app/fastapi/async_router.py +0 -457
- agno/app/fastapi/sync_router.py +0 -448
- agno/app/playground/app.py +0 -228
- agno/app/playground/async_router.py +0 -1053
- agno/app/playground/deploy.py +0 -249
- agno/app/playground/operator.py +0 -183
- agno/app/playground/schemas.py +0 -223
- agno/app/playground/serve.py +0 -55
- agno/app/playground/sync_router.py +0 -1045
- agno/app/playground/utils.py +0 -46
- agno/app/settings.py +0 -15
- agno/app/slack/__init__.py +0 -3
- agno/app/slack/app.py +0 -19
- agno/app/slack/sync_router.py +0 -92
- agno/app/utils.py +0 -54
- agno/app/whatsapp/__init__.py +0 -3
- agno/app/whatsapp/app.py +0 -15
- agno/app/whatsapp/sync_router.py +0 -197
- agno/cli/auth_server.py +0 -249
- agno/cli/config.py +0 -274
- agno/cli/console.py +0 -88
- agno/cli/credentials.py +0 -23
- agno/cli/entrypoint.py +0 -571
- agno/cli/operator.py +0 -357
- agno/cli/settings.py +0 -96
- agno/cli/ws/ws_cli.py +0 -817
- agno/constants.py +0 -13
- agno/document/__init__.py +0 -5
- agno/document/chunking/semantic.py +0 -45
- agno/document/chunking/strategy.py +0 -31
- agno/document/reader/__init__.py +0 -5
- agno/document/reader/base.py +0 -47
- agno/document/reader/docx_reader.py +0 -60
- agno/document/reader/gcs/pdf_reader.py +0 -44
- agno/document/reader/s3/pdf_reader.py +0 -59
- agno/document/reader/s3/text_reader.py +0 -63
- agno/document/reader/url_reader.py +0 -59
- agno/document/reader/youtube_reader.py +0 -58
- agno/embedder/__init__.py +0 -5
- agno/embedder/langdb.py +0 -80
- agno/embedder/mistral.py +0 -82
- agno/embedder/openai.py +0 -78
- agno/file/__init__.py +0 -5
- 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 -702
- agno/knowledge/arxiv.py +0 -33
- agno/knowledge/combined.py +0 -36
- agno/knowledge/csv.py +0 -144
- agno/knowledge/csv_url.py +0 -124
- agno/knowledge/document.py +0 -223
- agno/knowledge/docx.py +0 -137
- agno/knowledge/firecrawl.py +0 -34
- agno/knowledge/gcs/__init__.py +0 -0
- agno/knowledge/gcs/base.py +0 -39
- agno/knowledge/gcs/pdf.py +0 -125
- agno/knowledge/json.py +0 -137
- agno/knowledge/langchain.py +0 -71
- agno/knowledge/light_rag.py +0 -273
- agno/knowledge/llamaindex.py +0 -66
- agno/knowledge/markdown.py +0 -154
- agno/knowledge/pdf.py +0 -164
- agno/knowledge/pdf_bytes.py +0 -42
- agno/knowledge/pdf_url.py +0 -148
- agno/knowledge/s3/__init__.py +0 -0
- agno/knowledge/s3/base.py +0 -64
- agno/knowledge/s3/pdf.py +0 -33
- agno/knowledge/s3/text.py +0 -34
- agno/knowledge/text.py +0 -141
- agno/knowledge/url.py +0 -46
- agno/knowledge/website.py +0 -179
- agno/knowledge/wikipedia.py +0 -32
- agno/knowledge/youtube.py +0 -35
- agno/memory/agent.py +0 -423
- agno/memory/classifier.py +0 -104
- agno/memory/db/__init__.py +0 -5
- 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 -22
- agno/memory/row.py +0 -36
- agno/memory/summarizer.py +0 -201
- agno/memory/summary.py +0 -19
- agno/memory/team.py +0 -415
- agno/memory/v2/__init__.py +0 -2
- agno/memory/v2/db/__init__.py +0 -1
- agno/memory/v2/db/base.py +0 -42
- agno/memory/v2/db/firestore.py +0 -339
- agno/memory/v2/db/mongodb.py +0 -196
- agno/memory/v2/db/postgres.py +0 -214
- agno/memory/v2/db/redis.py +0 -187
- agno/memory/v2/db/schema.py +0 -54
- agno/memory/v2/db/sqlite.py +0 -209
- agno/memory/v2/manager.py +0 -437
- agno/memory/v2/memory.py +0 -1097
- agno/memory/v2/schema.py +0 -55
- agno/memory/v2/summarizer.py +0 -215
- agno/memory/workflow.py +0 -38
- agno/models/ollama/tools.py +0 -430
- agno/models/qwen/__init__.py +0 -5
- agno/playground/__init__.py +0 -10
- agno/playground/deploy.py +0 -3
- agno/playground/playground.py +0 -3
- agno/playground/serve.py +0 -3
- agno/playground/settings.py +0 -3
- agno/reranker/__init__.py +0 -0
- agno/run/response.py +0 -467
- agno/run/v2/__init__.py +0 -0
- agno/run/v2/workflow.py +0 -567
- agno/storage/__init__.py +0 -0
- agno/storage/agent/__init__.py +0 -0
- agno/storage/agent/dynamodb.py +0 -1
- agno/storage/agent/json.py +0 -1
- agno/storage/agent/mongodb.py +0 -1
- agno/storage/agent/postgres.py +0 -1
- agno/storage/agent/singlestore.py +0 -1
- agno/storage/agent/sqlite.py +0 -1
- agno/storage/agent/yaml.py +0 -1
- agno/storage/base.py +0 -60
- agno/storage/dynamodb.py +0 -673
- agno/storage/firestore.py +0 -297
- agno/storage/gcs_json.py +0 -261
- agno/storage/in_memory.py +0 -234
- agno/storage/json.py +0 -237
- agno/storage/mongodb.py +0 -328
- agno/storage/mysql.py +0 -685
- agno/storage/postgres.py +0 -682
- agno/storage/redis.py +0 -336
- agno/storage/session/__init__.py +0 -16
- agno/storage/session/agent.py +0 -64
- agno/storage/session/team.py +0 -63
- agno/storage/session/v2/__init__.py +0 -5
- agno/storage/session/workflow.py +0 -61
- agno/storage/singlestore.py +0 -606
- agno/storage/sqlite.py +0 -646
- agno/storage/workflow/__init__.py +0 -0
- agno/storage/workflow/mongodb.py +0 -1
- agno/storage/workflow/postgres.py +0 -1
- agno/storage/workflow/sqlite.py +0 -1
- agno/storage/yaml.py +0 -241
- agno/tools/thinking.py +0 -73
- 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/workflow/v2/__init__.py +0 -21
- agno/workflow/v2/types.py +0 -357
- agno/workflow/v2/workflow.py +0 -3313
- agno/workspace/__init__.py +0 -0
- agno/workspace/config.py +0 -325
- agno/workspace/enums.py +0 -6
- agno/workspace/helpers.py +0 -52
- agno/workspace/operator.py +0 -757
- agno/workspace/settings.py +0 -158
- agno-1.8.2.dist-info/METADATA +0 -982
- agno-1.8.2.dist-info/RECORD +0 -566
- agno-1.8.2.dist-info/entry_points.txt +0 -3
- agno-1.8.2.dist-info/licenses/LICENSE +0 -375
- /agno/{app → db/migrations}/__init__.py +0 -0
- /agno/{app/playground/__init__.py → db/schemas/metrics.py} +0 -0
- /agno/{cli → integrations}/__init__.py +0 -0
- /agno/{cli/ws → knowledge/chunking}/__init__.py +0 -0
- /agno/{document/chunking → knowledge/remote_content}/__init__.py +0 -0
- /agno/{document/reader/gcs → knowledge/reranker}/__init__.py +0 -0
- /agno/{document/reader/s3 → os/interfaces}/__init__.py +0 -0
- /agno/{app → os/interfaces}/slack/security.py +0 -0
- /agno/{app → os/interfaces}/whatsapp/security.py +0 -0
- /agno/{file/local → utils/print_response}/__init__.py +0 -0
- /agno/{infra → vectordb/llamaindex}/__init__.py +0 -0
- {agno-1.8.2.dist-info → agno-2.0.0.dist-info}/WHEEL +0 -0
- {agno-1.8.2.dist-info → agno-2.0.0.dist-info}/top_level.txt +0 -0
agno/os/config.py
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"""Schemas related to the AgentOS configuration"""
|
|
2
|
+
|
|
3
|
+
from typing import Generic, List, Optional, TypeVar
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel, field_validator
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class EvalsDomainConfig(BaseModel):
|
|
9
|
+
"""Configuration for the Evals domain of the AgentOS"""
|
|
10
|
+
|
|
11
|
+
display_name: Optional[str] = None
|
|
12
|
+
available_models: Optional[List[str]] = None
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class SessionDomainConfig(BaseModel):
|
|
16
|
+
"""Configuration for the Session domain of the AgentOS"""
|
|
17
|
+
|
|
18
|
+
display_name: Optional[str] = None
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class KnowledgeDomainConfig(BaseModel):
|
|
22
|
+
"""Configuration for the Knowledge domain of the AgentOS"""
|
|
23
|
+
|
|
24
|
+
display_name: Optional[str] = None
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class MetricsDomainConfig(BaseModel):
|
|
28
|
+
"""Configuration for the Metrics domain of the AgentOS"""
|
|
29
|
+
|
|
30
|
+
display_name: Optional[str] = None
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class MemoryDomainConfig(BaseModel):
|
|
34
|
+
"""Configuration for the Memory domain of the AgentOS"""
|
|
35
|
+
|
|
36
|
+
display_name: Optional[str] = None
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
DomainConfigType = TypeVar("DomainConfigType")
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class DatabaseConfig(BaseModel, Generic[DomainConfigType]):
|
|
43
|
+
"""Configuration for a domain when used with the contextual database"""
|
|
44
|
+
|
|
45
|
+
db_id: str
|
|
46
|
+
domain_config: Optional[DomainConfigType] = None
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class EvalsConfig(EvalsDomainConfig):
|
|
50
|
+
"""Configuration for the Evals domain of the AgentOS"""
|
|
51
|
+
|
|
52
|
+
dbs: Optional[List[DatabaseConfig[EvalsDomainConfig]]] = None
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class SessionConfig(SessionDomainConfig):
|
|
56
|
+
"""Configuration for the Session domain of the AgentOS"""
|
|
57
|
+
|
|
58
|
+
dbs: Optional[List[DatabaseConfig[SessionDomainConfig]]] = None
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class MemoryConfig(MemoryDomainConfig):
|
|
62
|
+
"""Configuration for the Memory domain of the AgentOS"""
|
|
63
|
+
|
|
64
|
+
dbs: Optional[List[DatabaseConfig[MemoryDomainConfig]]] = None
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class KnowledgeConfig(KnowledgeDomainConfig):
|
|
68
|
+
"""Configuration for the Knowledge domain of the AgentOS"""
|
|
69
|
+
|
|
70
|
+
dbs: Optional[List[DatabaseConfig[KnowledgeDomainConfig]]] = None
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class MetricsConfig(MetricsDomainConfig):
|
|
74
|
+
"""Configuration for the Metrics domain of the AgentOS"""
|
|
75
|
+
|
|
76
|
+
dbs: Optional[List[DatabaseConfig[MetricsDomainConfig]]] = None
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class ChatConfig(BaseModel):
|
|
80
|
+
"""Configuration for the Chat page of the AgentOS"""
|
|
81
|
+
|
|
82
|
+
quick_prompts: dict[str, list[str]]
|
|
83
|
+
|
|
84
|
+
# Limit the number of quick prompts to 3 (per agent/team/workflow)
|
|
85
|
+
@field_validator("quick_prompts")
|
|
86
|
+
@classmethod
|
|
87
|
+
def limit_lists(cls, v):
|
|
88
|
+
for key, lst in v.items():
|
|
89
|
+
if len(lst) > 3:
|
|
90
|
+
raise ValueError(f"Too many quick prompts for '{key}', maximum allowed is 3")
|
|
91
|
+
return v
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class AgentOSConfig(BaseModel):
|
|
95
|
+
"""General configuration for an AgentOS instance"""
|
|
96
|
+
|
|
97
|
+
available_models: Optional[List[str]] = None
|
|
98
|
+
chat: Optional[ChatConfig] = None
|
|
99
|
+
evals: Optional[EvalsConfig] = None
|
|
100
|
+
knowledge: Optional[KnowledgeConfig] = None
|
|
101
|
+
memory: Optional[MemoryConfig] = None
|
|
102
|
+
session: Optional[SessionConfig] = None
|
|
103
|
+
metrics: Optional[MetricsConfig] = None
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""Main class for the AG-UI app, used to expose an Agno Agent or Team in an AG-UI compatible format."""
|
|
2
|
+
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
from fastapi.routing import APIRouter
|
|
6
|
+
|
|
7
|
+
from agno.agent import Agent
|
|
8
|
+
from agno.os.interfaces.agui.router import attach_routes
|
|
9
|
+
from agno.os.interfaces.base import BaseInterface
|
|
10
|
+
from agno.team import Team
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class AGUI(BaseInterface):
|
|
14
|
+
type = "agui"
|
|
15
|
+
|
|
16
|
+
router: APIRouter
|
|
17
|
+
|
|
18
|
+
def __init__(self, agent: Optional[Agent] = None, team: Optional[Team] = None):
|
|
19
|
+
self.agent = agent
|
|
20
|
+
self.team = team
|
|
21
|
+
|
|
22
|
+
if not self.agent and not self.team:
|
|
23
|
+
raise ValueError("AGUI requires an agent and a team")
|
|
24
|
+
|
|
25
|
+
def get_router(self, **kwargs) -> APIRouter:
|
|
26
|
+
# Cannot be overridden
|
|
27
|
+
self.router = APIRouter(tags=["AGUI"])
|
|
28
|
+
|
|
29
|
+
self.router = attach_routes(router=self.router, agent=self.agent, team=self.team)
|
|
30
|
+
|
|
31
|
+
return self.router
|
|
@@ -16,7 +16,10 @@ from fastapi import APIRouter
|
|
|
16
16
|
from fastapi.responses import StreamingResponse
|
|
17
17
|
|
|
18
18
|
from agno.agent.agent import Agent
|
|
19
|
-
from agno.
|
|
19
|
+
from agno.os.interfaces.agui.utils import (
|
|
20
|
+
async_stream_agno_response_as_agui_events,
|
|
21
|
+
convert_agui_messages_to_agno_messages,
|
|
22
|
+
)
|
|
20
23
|
from agno.team.team import Team
|
|
21
24
|
|
|
22
25
|
logger = logging.getLogger(__name__)
|
|
@@ -32,8 +35,8 @@ async def run_agent(agent: Agent, run_input: RunAgentInput) -> AsyncIterator[Bas
|
|
|
32
35
|
yield RunStartedEvent(type=EventType.RUN_STARTED, thread_id=run_input.thread_id, run_id=run_id)
|
|
33
36
|
|
|
34
37
|
# Request streaming response from agent
|
|
35
|
-
response_stream =
|
|
36
|
-
|
|
38
|
+
response_stream = agent.arun(
|
|
39
|
+
input=messages,
|
|
37
40
|
session_id=run_input.thread_id,
|
|
38
41
|
stream=True,
|
|
39
42
|
stream_intermediate_steps=True,
|
|
@@ -41,7 +44,9 @@ async def run_agent(agent: Agent, run_input: RunAgentInput) -> AsyncIterator[Bas
|
|
|
41
44
|
|
|
42
45
|
# Stream the response content in AG-UI format
|
|
43
46
|
async for event in async_stream_agno_response_as_agui_events(
|
|
44
|
-
response_stream=response_stream,
|
|
47
|
+
response_stream=response_stream, # type: ignore
|
|
48
|
+
thread_id=run_input.thread_id,
|
|
49
|
+
run_id=run_id,
|
|
45
50
|
):
|
|
46
51
|
yield event
|
|
47
52
|
|
|
@@ -60,8 +65,8 @@ async def run_team(team: Team, input: RunAgentInput) -> AsyncIterator[BaseEvent]
|
|
|
60
65
|
yield RunStartedEvent(type=EventType.RUN_STARTED, thread_id=input.thread_id, run_id=run_id)
|
|
61
66
|
|
|
62
67
|
# Request streaming response from team
|
|
63
|
-
response_stream =
|
|
64
|
-
|
|
68
|
+
response_stream = team.arun(
|
|
69
|
+
input=messages,
|
|
65
70
|
session_id=input.thread_id,
|
|
66
71
|
stream=True,
|
|
67
72
|
stream_intermediate_steps=True,
|
|
@@ -78,15 +83,14 @@ async def run_team(team: Team, input: RunAgentInput) -> AsyncIterator[BaseEvent]
|
|
|
78
83
|
yield RunErrorEvent(type=EventType.RUN_ERROR, message=str(e))
|
|
79
84
|
|
|
80
85
|
|
|
81
|
-
def
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
raise ValueError("One of 'agent' or 'team' must be provided.")
|
|
86
|
+
def attach_routes(router: APIRouter, agent: Optional[Agent] = None, team: Optional[Team] = None) -> APIRouter:
|
|
87
|
+
if agent is None and team is None:
|
|
88
|
+
raise ValueError("Either agent or team must be provided.")
|
|
85
89
|
|
|
86
|
-
router = APIRouter()
|
|
87
90
|
encoder = EventEncoder()
|
|
88
91
|
|
|
89
|
-
|
|
92
|
+
@router.post("/agui")
|
|
93
|
+
async def run_agent_agui(run_input: RunAgentInput):
|
|
90
94
|
async def event_generator():
|
|
91
95
|
if agent:
|
|
92
96
|
async for event in run_agent(agent, run_input):
|
|
@@ -109,10 +113,6 @@ def get_async_agui_router(agent: Optional[Agent] = None, team: Optional[Team] =
|
|
|
109
113
|
},
|
|
110
114
|
)
|
|
111
115
|
|
|
112
|
-
@router.post("/agui")
|
|
113
|
-
async def run_agent_agui(run_input: RunAgentInput):
|
|
114
|
-
return await _run(run_input)
|
|
115
|
-
|
|
116
116
|
@router.get("/status")
|
|
117
117
|
async def get_status():
|
|
118
118
|
return {"status": "available"}
|
|
@@ -24,9 +24,9 @@ from ag_ui.core import (
|
|
|
24
24
|
from ag_ui.core.types import Message as AGUIMessage
|
|
25
25
|
|
|
26
26
|
from agno.models.message import Message
|
|
27
|
-
from agno.run.
|
|
28
|
-
from agno.run.team import
|
|
29
|
-
from agno.run.team import TeamRunEvent,
|
|
27
|
+
from agno.run.agent import RunContentEvent, RunEvent, RunOutputEvent, RunPausedEvent
|
|
28
|
+
from agno.run.team import RunContentEvent as TeamRunContentEvent
|
|
29
|
+
from agno.run.team import TeamRunEvent, TeamRunOutputEvent
|
|
30
30
|
from agno.utils.message import get_text_from_message
|
|
31
31
|
|
|
32
32
|
|
|
@@ -90,18 +90,18 @@ def convert_agui_messages_to_agno_messages(messages: List[AGUIMessage]) -> List[
|
|
|
90
90
|
return result
|
|
91
91
|
|
|
92
92
|
|
|
93
|
-
def extract_team_response_chunk_content(response:
|
|
93
|
+
def extract_team_response_chunk_content(response: TeamRunContentEvent) -> str:
|
|
94
94
|
"""Given a response stream chunk, find and extract the content."""
|
|
95
95
|
|
|
96
96
|
# Handle Team members' responses
|
|
97
97
|
members_content = []
|
|
98
98
|
if hasattr(response, "member_responses") and response.member_responses: # type: ignore
|
|
99
99
|
for member_resp in response.member_responses: # type: ignore
|
|
100
|
-
if isinstance(member_resp,
|
|
100
|
+
if isinstance(member_resp, RunContentEvent):
|
|
101
101
|
member_content = extract_response_chunk_content(member_resp)
|
|
102
102
|
if member_content:
|
|
103
103
|
members_content.append(f"Team member: {member_content}")
|
|
104
|
-
elif isinstance(member_resp,
|
|
104
|
+
elif isinstance(member_resp, TeamRunContentEvent):
|
|
105
105
|
member_content = extract_team_response_chunk_content(member_resp)
|
|
106
106
|
if member_content:
|
|
107
107
|
members_content.append(f"Team member: {member_content}")
|
|
@@ -113,7 +113,7 @@ def extract_team_response_chunk_content(response: TeamRunResponseContentEvent) -
|
|
|
113
113
|
return main_content + members_response
|
|
114
114
|
|
|
115
115
|
|
|
116
|
-
def extract_response_chunk_content(response:
|
|
116
|
+
def extract_response_chunk_content(response: RunContentEvent) -> str:
|
|
117
117
|
"""Given a response stream chunk, find and extract the content."""
|
|
118
118
|
|
|
119
119
|
if hasattr(response, "messages") and response.messages: # type: ignore
|
|
@@ -127,7 +127,7 @@ def extract_response_chunk_content(response: RunResponseContentEvent) -> str:
|
|
|
127
127
|
|
|
128
128
|
|
|
129
129
|
def _create_events_from_chunk(
|
|
130
|
-
chunk: Union[
|
|
130
|
+
chunk: Union[RunOutputEvent, TeamRunOutputEvent],
|
|
131
131
|
message_id: str,
|
|
132
132
|
message_started: bool,
|
|
133
133
|
event_buffer: EventBuffer,
|
|
@@ -139,9 +139,9 @@ def _create_events_from_chunk(
|
|
|
139
139
|
events_to_emit: List[BaseEvent] = []
|
|
140
140
|
|
|
141
141
|
# Extract content if the contextual event is a content event
|
|
142
|
-
if chunk.event == RunEvent.
|
|
142
|
+
if chunk.event == RunEvent.run_content:
|
|
143
143
|
content = extract_response_chunk_content(chunk) # type: ignore
|
|
144
|
-
elif chunk.event == TeamRunEvent.
|
|
144
|
+
elif chunk.event == TeamRunEvent.run_content:
|
|
145
145
|
content = extract_team_response_chunk_content(chunk) # type: ignore
|
|
146
146
|
else:
|
|
147
147
|
content = None
|
|
@@ -165,7 +165,7 @@ def _create_events_from_chunk(
|
|
|
165
165
|
message_id=message_id,
|
|
166
166
|
delta=content,
|
|
167
167
|
)
|
|
168
|
-
events_to_emit.append(content_event)
|
|
168
|
+
events_to_emit.append(content_event) # type: ignore
|
|
169
169
|
|
|
170
170
|
# Handle starting a new tool call
|
|
171
171
|
elif chunk.event == RunEvent.tool_call_started:
|
|
@@ -184,7 +184,7 @@ def _create_events_from_chunk(
|
|
|
184
184
|
tool_call_id=tool_call.tool_call_id, # type: ignore
|
|
185
185
|
delta=json.dumps(tool_call.tool_args),
|
|
186
186
|
)
|
|
187
|
-
events_to_emit.append(args_event)
|
|
187
|
+
events_to_emit.append(args_event) # type: ignore
|
|
188
188
|
|
|
189
189
|
# Handle tool call completion
|
|
190
190
|
elif chunk.event == RunEvent.tool_call_completed:
|
|
@@ -195,7 +195,7 @@ def _create_events_from_chunk(
|
|
|
195
195
|
type=EventType.TOOL_CALL_END,
|
|
196
196
|
tool_call_id=tool_call.tool_call_id, # type: ignore
|
|
197
197
|
)
|
|
198
|
-
events_to_emit.append(end_event)
|
|
198
|
+
events_to_emit.append(end_event) # type: ignore
|
|
199
199
|
|
|
200
200
|
if tool_call.result is not None:
|
|
201
201
|
result_event = ToolCallResultEvent(
|
|
@@ -205,21 +205,31 @@ def _create_events_from_chunk(
|
|
|
205
205
|
role="tool",
|
|
206
206
|
message_id=str(uuid.uuid4()),
|
|
207
207
|
)
|
|
208
|
-
events_to_emit.append(result_event)
|
|
208
|
+
events_to_emit.append(result_event) # type: ignore
|
|
209
|
+
|
|
210
|
+
if tool_call.result is not None:
|
|
211
|
+
result_event = ToolCallResultEvent(
|
|
212
|
+
type=EventType.TOOL_CALL_RESULT,
|
|
213
|
+
tool_call_id=tool_call.tool_call_id, # type: ignore
|
|
214
|
+
content=str(tool_call.result),
|
|
215
|
+
role="tool",
|
|
216
|
+
message_id=str(uuid.uuid4()),
|
|
217
|
+
)
|
|
218
|
+
events_to_emit.append(result_event) # type: ignore
|
|
209
219
|
|
|
210
220
|
# Handle reasoning
|
|
211
221
|
elif chunk.event == RunEvent.reasoning_started:
|
|
212
|
-
step_started_event = StepStartedEvent(type=EventType.STEP_STARTED, step_name="reasoning")
|
|
213
|
-
events_to_emit.append(step_started_event)
|
|
222
|
+
step_started_event = StepStartedEvent(type=EventType.STEP_STARTED, step_name="reasoning") # type: ignore
|
|
223
|
+
events_to_emit.append(step_started_event) # type: ignore
|
|
214
224
|
elif chunk.event == RunEvent.reasoning_completed:
|
|
215
|
-
|
|
216
|
-
events_to_emit.append(
|
|
225
|
+
step_started_event = StepFinishedEvent(type=EventType.STEP_FINISHED, step_name="reasoning") # type: ignore
|
|
226
|
+
events_to_emit.append(step_started_event) # type: ignore
|
|
217
227
|
|
|
218
|
-
return events_to_emit, message_started
|
|
228
|
+
return events_to_emit, message_started # type: ignore
|
|
219
229
|
|
|
220
230
|
|
|
221
231
|
def _create_completion_events(
|
|
222
|
-
chunk: Union[
|
|
232
|
+
chunk: Union[RunOutputEvent, TeamRunOutputEvent],
|
|
223
233
|
event_buffer: EventBuffer,
|
|
224
234
|
message_started: bool,
|
|
225
235
|
message_id: str,
|
|
@@ -241,10 +251,10 @@ def _create_completion_events(
|
|
|
241
251
|
# End the message and run, denoting the end of the session
|
|
242
252
|
if message_started:
|
|
243
253
|
end_message_event = TextMessageEndEvent(type=EventType.TEXT_MESSAGE_END, message_id=message_id)
|
|
244
|
-
events_to_emit.append(end_message_event)
|
|
254
|
+
events_to_emit.append(end_message_event) # type: ignore
|
|
245
255
|
|
|
246
256
|
# emit frontend tool calls, i.e. external_execution=True
|
|
247
|
-
if isinstance(chunk,
|
|
257
|
+
if isinstance(chunk, RunPausedEvent) and chunk.tools is not None:
|
|
248
258
|
for tool in chunk.tools:
|
|
249
259
|
if tool.tool_call_id is None or tool.tool_name is None:
|
|
250
260
|
continue
|
|
@@ -255,14 +265,14 @@ def _create_completion_events(
|
|
|
255
265
|
tool_call_name=tool.tool_name,
|
|
256
266
|
parent_message_id=message_id,
|
|
257
267
|
)
|
|
258
|
-
events_to_emit.append(start_event)
|
|
268
|
+
events_to_emit.append(start_event) # type: ignore
|
|
259
269
|
|
|
260
270
|
args_event = ToolCallArgsEvent(
|
|
261
271
|
type=EventType.TOOL_CALL_ARGS,
|
|
262
272
|
tool_call_id=tool.tool_call_id,
|
|
263
273
|
delta=json.dumps(tool.tool_args),
|
|
264
274
|
)
|
|
265
|
-
events_to_emit.append(args_event)
|
|
275
|
+
events_to_emit.append(args_event) # type: ignore
|
|
266
276
|
|
|
267
277
|
end_event = ToolCallEndEvent(
|
|
268
278
|
type=EventType.TOOL_CALL_END,
|
|
@@ -270,10 +280,37 @@ def _create_completion_events(
|
|
|
270
280
|
)
|
|
271
281
|
events_to_emit.append(end_event)
|
|
272
282
|
|
|
283
|
+
# emit frontend tool calls, i.e. external_execution=True
|
|
284
|
+
if isinstance(chunk, RunPausedEvent) and chunk.tools is not None:
|
|
285
|
+
for tool in chunk.tools:
|
|
286
|
+
if tool.tool_call_id is None or tool.tool_name is None:
|
|
287
|
+
continue
|
|
288
|
+
|
|
289
|
+
start_event = ToolCallStartEvent(
|
|
290
|
+
type=EventType.TOOL_CALL_START,
|
|
291
|
+
tool_call_id=tool.tool_call_id,
|
|
292
|
+
tool_call_name=tool.tool_name,
|
|
293
|
+
parent_message_id=message_id,
|
|
294
|
+
)
|
|
295
|
+
events_to_emit.append(start_event) # type: ignore
|
|
296
|
+
|
|
297
|
+
args_event = ToolCallArgsEvent(
|
|
298
|
+
type=EventType.TOOL_CALL_ARGS,
|
|
299
|
+
tool_call_id=tool.tool_call_id,
|
|
300
|
+
delta=json.dumps(tool.tool_args),
|
|
301
|
+
)
|
|
302
|
+
events_to_emit.append(args_event) # type: ignore
|
|
303
|
+
|
|
304
|
+
end_event = ToolCallEndEvent(
|
|
305
|
+
type=EventType.TOOL_CALL_END,
|
|
306
|
+
tool_call_id=tool.tool_call_id,
|
|
307
|
+
)
|
|
308
|
+
events_to_emit.append(end_event) # type: ignore
|
|
309
|
+
|
|
273
310
|
run_finished_event = RunFinishedEvent(type=EventType.RUN_FINISHED, thread_id=thread_id, run_id=run_id)
|
|
274
|
-
events_to_emit.append(run_finished_event)
|
|
311
|
+
events_to_emit.append(run_finished_event) # type: ignore
|
|
275
312
|
|
|
276
|
-
return events_to_emit
|
|
313
|
+
return events_to_emit # type: ignore
|
|
277
314
|
|
|
278
315
|
|
|
279
316
|
def _emit_event_logic(event: BaseEvent, event_buffer: EventBuffer) -> List[BaseEvent]:
|
|
@@ -327,7 +364,7 @@ def _emit_event_logic(event: BaseEvent, event_buffer: EventBuffer) -> List[BaseE
|
|
|
327
364
|
|
|
328
365
|
|
|
329
366
|
def stream_agno_response_as_agui_events(
|
|
330
|
-
response_stream: Iterator[Union[
|
|
367
|
+
response_stream: Iterator[Union[RunOutputEvent, TeamRunOutputEvent]], thread_id: str, run_id: str
|
|
331
368
|
) -> Iterator[BaseEvent]:
|
|
332
369
|
"""Map the Agno response stream to AG-UI format, handling event ordering constraints."""
|
|
333
370
|
message_id = str(uuid.uuid4())
|
|
@@ -362,7 +399,7 @@ def stream_agno_response_as_agui_events(
|
|
|
362
399
|
|
|
363
400
|
# Async version - thin wrapper
|
|
364
401
|
async def async_stream_agno_response_as_agui_events(
|
|
365
|
-
response_stream: AsyncIterator[Union[
|
|
402
|
+
response_stream: AsyncIterator[Union[RunOutputEvent, TeamRunOutputEvent]],
|
|
366
403
|
thread_id: str,
|
|
367
404
|
run_id: str,
|
|
368
405
|
) -> AsyncIterator[BaseEvent]:
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
from fastapi import APIRouter
|
|
5
|
+
|
|
6
|
+
from agno.agent import Agent
|
|
7
|
+
from agno.team import Team
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class BaseInterface(ABC):
|
|
11
|
+
type: str
|
|
12
|
+
version: str = "1.0"
|
|
13
|
+
router_prefix: str = ""
|
|
14
|
+
agent: Optional[Agent] = None
|
|
15
|
+
team: Optional[Team] = None
|
|
16
|
+
|
|
17
|
+
router: APIRouter
|
|
18
|
+
|
|
19
|
+
@abstractmethod
|
|
20
|
+
def get_router(self, use_async: bool = True, **kwargs) -> APIRouter:
|
|
21
|
+
pass
|
|
@@ -3,15 +3,13 @@ from typing import Optional
|
|
|
3
3
|
from fastapi import APIRouter, BackgroundTasks, HTTPException, Request
|
|
4
4
|
|
|
5
5
|
from agno.agent.agent import Agent
|
|
6
|
-
from agno.
|
|
6
|
+
from agno.os.interfaces.slack.security import verify_slack_signature
|
|
7
7
|
from agno.team.team import Team
|
|
8
8
|
from agno.tools.slack import SlackTools
|
|
9
9
|
from agno.utils.log import log_info
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
def
|
|
13
|
-
router = APIRouter()
|
|
14
|
-
|
|
12
|
+
def attach_routes(router: APIRouter, agent: Optional[Agent] = None, team: Optional[Team] = None) -> APIRouter:
|
|
15
13
|
@router.post("/slack/events")
|
|
16
14
|
async def slack_events(request: Request, background_tasks: BackgroundTasks):
|
|
17
15
|
body = await request.body()
|
|
@@ -44,7 +42,7 @@ def get_async_router(agent: Optional[Agent] = None, team: Optional[Team] = None)
|
|
|
44
42
|
async def _process_slack_event(event: dict):
|
|
45
43
|
if event.get("type") == "message":
|
|
46
44
|
user = None
|
|
47
|
-
message_text = event.get("text")
|
|
45
|
+
message_text = event.get("text", "")
|
|
48
46
|
channel_id = event.get("channel", "")
|
|
49
47
|
user = event.get("user")
|
|
50
48
|
if event.get("thread_ts"):
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
from fastapi.routing import APIRouter
|
|
5
|
+
|
|
6
|
+
from agno.agent.agent import Agent
|
|
7
|
+
from agno.os.interfaces.base import BaseInterface
|
|
8
|
+
from agno.os.interfaces.slack.router import attach_routes
|
|
9
|
+
from agno.team.team import Team
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger(__name__)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Slack(BaseInterface):
|
|
15
|
+
type = "slack"
|
|
16
|
+
|
|
17
|
+
router: APIRouter
|
|
18
|
+
|
|
19
|
+
def __init__(self, agent: Optional[Agent] = None, team: Optional[Team] = None):
|
|
20
|
+
self.agent = agent
|
|
21
|
+
self.team = team
|
|
22
|
+
|
|
23
|
+
if not self.agent and not self.team:
|
|
24
|
+
raise ValueError("Slack requires an agent and a team")
|
|
25
|
+
|
|
26
|
+
def get_router(self, **kwargs) -> APIRouter:
|
|
27
|
+
# Cannot be overridden
|
|
28
|
+
self.router = APIRouter(prefix="/slack", tags=["Slack"])
|
|
29
|
+
|
|
30
|
+
self.router = attach_routes(router=self.router, agent=self.agent, team=self.team)
|
|
31
|
+
|
|
32
|
+
return self.router
|
|
@@ -15,9 +15,7 @@ from agno.utils.whatsapp import get_media_async, send_image_message_async, typin
|
|
|
15
15
|
from .security import validate_webhook_signature
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
def
|
|
19
|
-
router = APIRouter()
|
|
20
|
-
|
|
18
|
+
def attach_routes(router: APIRouter, agent: Optional[Agent] = None, team: Optional[Team] = None) -> APIRouter:
|
|
21
19
|
if agent is None and team is None:
|
|
22
20
|
raise ValueError("Either agent or team must be provided.")
|
|
23
21
|
|
|
@@ -128,7 +126,7 @@ def get_async_router(agent: Optional[Agent] = None, team: Optional[Team] = None)
|
|
|
128
126
|
audio=[Audio(content=await get_media_async(message_audio))] if message_audio else None,
|
|
129
127
|
)
|
|
130
128
|
elif team:
|
|
131
|
-
response = await team.arun(
|
|
129
|
+
response = await team.arun( # type: ignore
|
|
132
130
|
message_text,
|
|
133
131
|
user_id=phone_number,
|
|
134
132
|
files=[File(content=await get_media_async(message_doc))] if message_doc else None,
|
|
@@ -167,9 +165,8 @@ def get_async_router(agent: Optional[Agent] = None, team: Optional[Team] = None)
|
|
|
167
165
|
log_warning(
|
|
168
166
|
f"Could not process image content for user {phone_number}. Type: {type(image_content)}"
|
|
169
167
|
)
|
|
170
|
-
await _send_whatsapp_message(phone_number, response.content) #
|
|
171
|
-
|
|
172
|
-
await _send_whatsapp_message(phone_number, response.content)
|
|
168
|
+
await _send_whatsapp_message(phone_number, response.content) # type: ignore
|
|
169
|
+
await _send_whatsapp_message(phone_number, response.content) # type: ignore
|
|
173
170
|
|
|
174
171
|
except Exception as e:
|
|
175
172
|
log_error(f"Error processing message: {str(e)}")
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
from fastapi.routing import APIRouter
|
|
4
|
+
|
|
5
|
+
from agno.agent import Agent
|
|
6
|
+
from agno.os.interfaces.base import BaseInterface
|
|
7
|
+
from agno.os.interfaces.whatsapp.router import attach_routes
|
|
8
|
+
from agno.team import Team
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Whatsapp(BaseInterface):
|
|
12
|
+
type = "whatsapp"
|
|
13
|
+
|
|
14
|
+
router: APIRouter
|
|
15
|
+
|
|
16
|
+
def __init__(self, agent: Optional[Agent] = None, team: Optional[Team] = None):
|
|
17
|
+
self.agent = agent
|
|
18
|
+
self.team = team
|
|
19
|
+
|
|
20
|
+
if not self.agent and not self.team:
|
|
21
|
+
raise ValueError("Whatsapp requires an agent and a team")
|
|
22
|
+
|
|
23
|
+
def get_router(self, **kwargs) -> APIRouter:
|
|
24
|
+
# Cannot be overridden
|
|
25
|
+
self.router = APIRouter(prefix="/whatsapp", tags=["Whatsapp"])
|
|
26
|
+
|
|
27
|
+
self.router = attach_routes(router=self.router, agent=self.agent, team=self.team)
|
|
28
|
+
|
|
29
|
+
return self.router
|