agno 1.8.0__py3-none-any.whl → 2.0.0a1__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 +19 -27
- agno/agent/agent.py +2781 -4126
- agno/api/agent.py +9 -65
- agno/api/api.py +5 -46
- agno/api/evals.py +6 -17
- 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 +9 -64
- 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 +1749 -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 +1438 -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 +888 -0
- agno/db/in_memory/utils.py +172 -0
- agno/db/json/__init__.py +3 -0
- agno/db/json/json_db.py +1051 -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 +1417 -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 +298 -0
- agno/db/postgres/__init__.py +3 -0
- agno/db/postgres/postgres.py +1720 -0
- agno/db/postgres/schemas.py +124 -0
- agno/db/postgres/utils.py +281 -0
- agno/db/redis/__init__.py +3 -0
- agno/db/redis/redis.py +1371 -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 +1722 -0
- agno/db/singlestore/utils.py +327 -0
- agno/db/sqlite/__init__.py +3 -0
- agno/db/sqlite/schemas.py +119 -0
- agno/db/sqlite/sqlite.py +1680 -0
- agno/db/sqlite/utils.py +269 -0
- agno/db/utils.py +88 -0
- agno/eval/__init__.py +14 -0
- agno/eval/accuracy.py +142 -43
- 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 +1515 -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 +68 -15
- agno/knowledge/reader/docx_reader.py +83 -0
- agno/{document → knowledge}/reader/firecrawl_reader.py +42 -21
- agno/knowledge/reader/gcs_reader.py +67 -0
- agno/{document → knowledge}/reader/json_reader.py +30 -9
- agno/{document → knowledge}/reader/markdown_reader.py +36 -9
- agno/{document → knowledge}/reader/pdf_reader.py +79 -21
- agno/knowledge/reader/reader_factory.py +275 -0
- agno/knowledge/reader/s3_reader.py +171 -0
- agno/{document → knowledge}/reader/text_reader.py +31 -10
- agno/knowledge/reader/url_reader.py +84 -0
- agno/knowledge/reader/web_search_reader.py +389 -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 +2 -2
- 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 +129 -82
- 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 +347 -287
- agno/models/cerebras/cerebras.py +84 -27
- agno/models/cohere/chat.py +106 -98
- agno/models/dashscope/dashscope.py +14 -5
- agno/models/google/gemini.py +123 -53
- 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 +38 -144
- 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 +84 -46
- agno/models/openai/chat.py +135 -27
- agno/models/openai/responses.py +233 -115
- agno/models/perplexity/perplexity.py +26 -2
- agno/models/portkey/portkey.py +0 -7
- agno/models/response.py +14 -8
- 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 +393 -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 +33 -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 +30 -0
- agno/os/router.py +843 -0
- agno/os/routers/__init__.py +3 -0
- agno/os/routers/evals/__init__.py +3 -0
- agno/os/routers/evals/evals.py +204 -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 +413 -0
- agno/os/routers/knowledge/schemas.py +118 -0
- agno/os/routers/memory/__init__.py +3 -0
- agno/os/routers/memory/memory.py +179 -0
- agno/os/routers/memory/schemas.py +58 -0
- agno/os/routers/metrics/__init__.py +3 -0
- agno/os/routers/metrics/metrics.py +58 -0
- agno/os/routers/metrics/schemas.py +47 -0
- agno/os/routers/session/__init__.py +3 -0
- agno/os/routers/session/session.py +163 -0
- agno/os/schema.py +892 -0
- agno/{app/playground → os}/settings.py +8 -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/{response.py → agent.py} +144 -72
- agno/run/base.py +44 -58
- agno/run/cancel.py +83 -0
- agno/run/team.py +133 -77
- agno/run/workflow.py +537 -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 +2967 -4243
- 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 +42 -22
- agno/tools/browserbase.py +13 -4
- agno/tools/calcom.py +12 -10
- agno/tools/calculator.py +10 -27
- agno/tools/cartesia.py +18 -13
- agno/tools/{clickup_tool.py → clickup.py} +12 -25
- agno/tools/confluence.py +71 -18
- agno/tools/crawl4ai.py +7 -1
- agno/tools/csv_toolkit.py +9 -8
- agno/tools/dalle.py +18 -11
- agno/tools/daytona.py +13 -16
- agno/tools/decorator.py +6 -3
- agno/tools/desi_vocal.py +16 -7
- 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 +35 -28
- agno/tools/email.py +4 -1
- agno/tools/evm.py +7 -1
- agno/tools/exa.py +19 -14
- agno/tools/fal.py +29 -29
- agno/tools/file.py +9 -8
- agno/tools/financial_datasets.py +25 -44
- agno/tools/firecrawl.py +22 -22
- agno/tools/function.py +68 -17
- agno/tools/giphy.py +22 -10
- agno/tools/github.py +48 -126
- agno/tools/gmail.py +46 -62
- 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 +31 -19
- 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 +32 -14
- agno/tools/models/gemini.py +58 -31
- agno/tools/models/groq.py +29 -20
- agno/tools/models/nebius.py +27 -11
- agno/tools/models_labs.py +39 -15
- agno/tools/moviepy_video.py +7 -6
- agno/tools/neo4j.py +134 -0
- agno/tools/newspaper.py +7 -2
- agno/tools/newspaper4k.py +8 -3
- agno/tools/openai.py +57 -26
- agno/tools/openbb.py +12 -11
- agno/tools/opencv.py +62 -46
- 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 +54 -41
- 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 +95 -118
- agno/utils/knowledge.py +29 -0
- agno/utils/location.py +2 -2
- agno/utils/log.py +2 -2
- agno/utils/mcp.py +11 -5
- agno/utils/media.py +39 -0
- agno/utils/message.py +12 -1
- agno/utils/models/claude.py +6 -4
- agno/utils/models/mistral.py +8 -7
- agno/utils/models/schema_utils.py +3 -3
- agno/utils/pprint.py +33 -32
- agno/utils/print_response/agent.py +779 -0
- agno/utils/print_response/team.py +1565 -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/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 +356 -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} +200 -42
- agno/workflow/{v2/steps.py → steps.py} +147 -66
- agno/workflow/types.py +482 -0
- agno/workflow/workflow.py +2394 -696
- agno-2.0.0a1.dist-info/METADATA +355 -0
- agno-2.0.0a1.dist-info/RECORD +514 -0
- agno/agent/metrics.py +0 -107
- 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 -1050
- agno/app/playground/deploy.py +0 -249
- agno/app/playground/operator.py +0 -183
- agno/app/playground/schemas.py +0 -220
- agno/app/playground/serve.py +0 -55
- agno/app/playground/sync_router.py +0 -1042
- 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 -698
- 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/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 -3312
- 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.0.dist-info/METADATA +0 -979
- agno-1.8.0.dist-info/RECORD +0 -565
- agno-1.8.0.dist-info/entry_points.txt +0 -3
- /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.0.dist-info → agno-2.0.0a1.dist-info}/WHEEL +0 -0
- {agno-1.8.0.dist-info → agno-2.0.0a1.dist-info}/licenses/LICENSE +0 -0
- {agno-1.8.0.dist-info → agno-2.0.0a1.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, use_async: bool = True, **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
|
|
|
31
31
|
|
|
32
32
|
@dataclass
|
|
@@ -89,18 +89,18 @@ def convert_agui_messages_to_agno_messages(messages: List[AGUIMessage]) -> List[
|
|
|
89
89
|
return result
|
|
90
90
|
|
|
91
91
|
|
|
92
|
-
def extract_team_response_chunk_content(response:
|
|
92
|
+
def extract_team_response_chunk_content(response: TeamRunContentEvent) -> str:
|
|
93
93
|
"""Given a response stream chunk, find and extract the content."""
|
|
94
94
|
|
|
95
95
|
# Handle Team members' responses
|
|
96
96
|
members_content = []
|
|
97
97
|
if hasattr(response, "member_responses") and response.member_responses: # type: ignore
|
|
98
98
|
for member_resp in response.member_responses: # type: ignore
|
|
99
|
-
if isinstance(member_resp,
|
|
99
|
+
if isinstance(member_resp, RunContentEvent):
|
|
100
100
|
member_content = extract_response_chunk_content(member_resp)
|
|
101
101
|
if member_content:
|
|
102
102
|
members_content.append(f"Team member: {member_content}")
|
|
103
|
-
elif isinstance(member_resp,
|
|
103
|
+
elif isinstance(member_resp, TeamRunContentEvent):
|
|
104
104
|
member_content = extract_team_response_chunk_content(member_resp)
|
|
105
105
|
if member_content:
|
|
106
106
|
members_content.append(f"Team member: {member_content}")
|
|
@@ -109,7 +109,7 @@ def extract_team_response_chunk_content(response: TeamRunResponseContentEvent) -
|
|
|
109
109
|
return str(response.content) + members_response
|
|
110
110
|
|
|
111
111
|
|
|
112
|
-
def extract_response_chunk_content(response:
|
|
112
|
+
def extract_response_chunk_content(response: RunContentEvent) -> str:
|
|
113
113
|
"""Given a response stream chunk, find and extract the content."""
|
|
114
114
|
if hasattr(response, "messages") and response.messages: # type: ignore
|
|
115
115
|
for msg in reversed(response.messages): # type: ignore
|
|
@@ -120,7 +120,7 @@ def extract_response_chunk_content(response: RunResponseContentEvent) -> str:
|
|
|
120
120
|
|
|
121
121
|
|
|
122
122
|
def _create_events_from_chunk(
|
|
123
|
-
chunk: Union[
|
|
123
|
+
chunk: Union[RunOutputEvent, TeamRunOutputEvent],
|
|
124
124
|
message_id: str,
|
|
125
125
|
message_started: bool,
|
|
126
126
|
event_buffer: EventBuffer,
|
|
@@ -132,9 +132,9 @@ def _create_events_from_chunk(
|
|
|
132
132
|
events_to_emit: List[BaseEvent] = []
|
|
133
133
|
|
|
134
134
|
# Extract content if the contextual event is a content event
|
|
135
|
-
if chunk.event == RunEvent.
|
|
135
|
+
if chunk.event == RunEvent.run_content:
|
|
136
136
|
content = extract_response_chunk_content(chunk) # type: ignore
|
|
137
|
-
elif chunk.event == TeamRunEvent.
|
|
137
|
+
elif chunk.event == TeamRunEvent.run_content:
|
|
138
138
|
content = extract_team_response_chunk_content(chunk) # type: ignore
|
|
139
139
|
else:
|
|
140
140
|
content = None
|
|
@@ -158,7 +158,7 @@ def _create_events_from_chunk(
|
|
|
158
158
|
message_id=message_id,
|
|
159
159
|
delta=content,
|
|
160
160
|
)
|
|
161
|
-
events_to_emit.append(content_event)
|
|
161
|
+
events_to_emit.append(content_event) # type: ignore
|
|
162
162
|
|
|
163
163
|
# Handle starting a new tool call
|
|
164
164
|
elif chunk.event == RunEvent.tool_call_started:
|
|
@@ -177,7 +177,7 @@ def _create_events_from_chunk(
|
|
|
177
177
|
tool_call_id=tool_call.tool_call_id, # type: ignore
|
|
178
178
|
delta=json.dumps(tool_call.tool_args),
|
|
179
179
|
)
|
|
180
|
-
events_to_emit.append(args_event)
|
|
180
|
+
events_to_emit.append(args_event) # type: ignore
|
|
181
181
|
|
|
182
182
|
# Handle tool call completion
|
|
183
183
|
elif chunk.event == RunEvent.tool_call_completed:
|
|
@@ -188,7 +188,7 @@ def _create_events_from_chunk(
|
|
|
188
188
|
type=EventType.TOOL_CALL_END,
|
|
189
189
|
tool_call_id=tool_call.tool_call_id, # type: ignore
|
|
190
190
|
)
|
|
191
|
-
events_to_emit.append(end_event)
|
|
191
|
+
events_to_emit.append(end_event) # type: ignore
|
|
192
192
|
|
|
193
193
|
if tool_call.result is not None:
|
|
194
194
|
result_event = ToolCallResultEvent(
|
|
@@ -198,21 +198,31 @@ def _create_events_from_chunk(
|
|
|
198
198
|
role="tool",
|
|
199
199
|
message_id=str(uuid.uuid4()),
|
|
200
200
|
)
|
|
201
|
-
events_to_emit.append(result_event)
|
|
201
|
+
events_to_emit.append(result_event) # type: ignore
|
|
202
|
+
|
|
203
|
+
if tool_call.result is not None:
|
|
204
|
+
result_event = ToolCallResultEvent(
|
|
205
|
+
type=EventType.TOOL_CALL_RESULT,
|
|
206
|
+
tool_call_id=tool_call.tool_call_id, # type: ignore
|
|
207
|
+
content=str(tool_call.result),
|
|
208
|
+
role="tool",
|
|
209
|
+
message_id=str(uuid.uuid4()),
|
|
210
|
+
)
|
|
211
|
+
events_to_emit.append(result_event) # type: ignore
|
|
202
212
|
|
|
203
213
|
# Handle reasoning
|
|
204
214
|
elif chunk.event == RunEvent.reasoning_started:
|
|
205
|
-
step_event = StepStartedEvent(type=EventType.STEP_STARTED, step_name="reasoning")
|
|
206
|
-
events_to_emit.append(step_event)
|
|
215
|
+
step_event = StepStartedEvent(type=EventType.STEP_STARTED, step_name="reasoning") # type: ignore
|
|
216
|
+
events_to_emit.append(step_event) # type: ignore
|
|
207
217
|
elif chunk.event == RunEvent.reasoning_completed:
|
|
208
|
-
step_event = StepFinishedEvent(type=EventType.STEP_FINISHED, step_name="reasoning")
|
|
209
|
-
events_to_emit.append(step_event)
|
|
218
|
+
step_event = StepFinishedEvent(type=EventType.STEP_FINISHED, step_name="reasoning") # type: ignore
|
|
219
|
+
events_to_emit.append(step_event) # type: ignore
|
|
210
220
|
|
|
211
|
-
return events_to_emit, message_started
|
|
221
|
+
return events_to_emit, message_started # type: ignore
|
|
212
222
|
|
|
213
223
|
|
|
214
224
|
def _create_completion_events(
|
|
215
|
-
chunk: Union[
|
|
225
|
+
chunk: Union[RunOutputEvent, TeamRunOutputEvent],
|
|
216
226
|
event_buffer: EventBuffer,
|
|
217
227
|
message_started: bool,
|
|
218
228
|
message_id: str,
|
|
@@ -234,10 +244,10 @@ def _create_completion_events(
|
|
|
234
244
|
# End the message and run, denoting the end of the session
|
|
235
245
|
if message_started:
|
|
236
246
|
end_message_event = TextMessageEndEvent(type=EventType.TEXT_MESSAGE_END, message_id=message_id)
|
|
237
|
-
events_to_emit.append(end_message_event)
|
|
247
|
+
events_to_emit.append(end_message_event) # type: ignore
|
|
238
248
|
|
|
239
249
|
# emit frontend tool calls, i.e. external_execution=True
|
|
240
|
-
if isinstance(chunk,
|
|
250
|
+
if isinstance(chunk, RunPausedEvent) and chunk.tools is not None:
|
|
241
251
|
for tool in chunk.tools:
|
|
242
252
|
if tool.tool_call_id is None or tool.tool_name is None:
|
|
243
253
|
continue
|
|
@@ -248,14 +258,14 @@ def _create_completion_events(
|
|
|
248
258
|
tool_call_name=tool.tool_name,
|
|
249
259
|
parent_message_id=message_id,
|
|
250
260
|
)
|
|
251
|
-
events_to_emit.append(start_event)
|
|
261
|
+
events_to_emit.append(start_event) # type: ignore
|
|
252
262
|
|
|
253
263
|
args_event = ToolCallArgsEvent(
|
|
254
264
|
type=EventType.TOOL_CALL_ARGS,
|
|
255
265
|
tool_call_id=tool.tool_call_id,
|
|
256
266
|
delta=json.dumps(tool.tool_args),
|
|
257
267
|
)
|
|
258
|
-
events_to_emit.append(args_event)
|
|
268
|
+
events_to_emit.append(args_event) # type: ignore
|
|
259
269
|
|
|
260
270
|
end_event = ToolCallEndEvent(
|
|
261
271
|
type=EventType.TOOL_CALL_END,
|
|
@@ -263,10 +273,37 @@ def _create_completion_events(
|
|
|
263
273
|
)
|
|
264
274
|
events_to_emit.append(end_event)
|
|
265
275
|
|
|
276
|
+
# emit frontend tool calls, i.e. external_execution=True
|
|
277
|
+
if isinstance(chunk, RunPausedEvent) and chunk.tools is not None:
|
|
278
|
+
for tool in chunk.tools:
|
|
279
|
+
if tool.tool_call_id is None or tool.tool_name is None:
|
|
280
|
+
continue
|
|
281
|
+
|
|
282
|
+
start_event = ToolCallStartEvent(
|
|
283
|
+
type=EventType.TOOL_CALL_START,
|
|
284
|
+
tool_call_id=tool.tool_call_id,
|
|
285
|
+
tool_call_name=tool.tool_name,
|
|
286
|
+
parent_message_id=message_id,
|
|
287
|
+
)
|
|
288
|
+
events_to_emit.append(start_event) # type: ignore
|
|
289
|
+
|
|
290
|
+
args_event = ToolCallArgsEvent(
|
|
291
|
+
type=EventType.TOOL_CALL_ARGS,
|
|
292
|
+
tool_call_id=tool.tool_call_id,
|
|
293
|
+
delta=json.dumps(tool.tool_args),
|
|
294
|
+
)
|
|
295
|
+
events_to_emit.append(args_event) # type: ignore
|
|
296
|
+
|
|
297
|
+
end_event = ToolCallEndEvent(
|
|
298
|
+
type=EventType.TOOL_CALL_END,
|
|
299
|
+
tool_call_id=tool.tool_call_id,
|
|
300
|
+
)
|
|
301
|
+
events_to_emit.append(end_event) # type: ignore
|
|
302
|
+
|
|
266
303
|
run_finished_event = RunFinishedEvent(type=EventType.RUN_FINISHED, thread_id=thread_id, run_id=run_id)
|
|
267
|
-
events_to_emit.append(run_finished_event)
|
|
304
|
+
events_to_emit.append(run_finished_event) # type: ignore
|
|
268
305
|
|
|
269
|
-
return events_to_emit
|
|
306
|
+
return events_to_emit # type: ignore
|
|
270
307
|
|
|
271
308
|
|
|
272
309
|
def _emit_event_logic(event: BaseEvent, event_buffer: EventBuffer) -> List[BaseEvent]:
|
|
@@ -320,7 +357,7 @@ def _emit_event_logic(event: BaseEvent, event_buffer: EventBuffer) -> List[BaseE
|
|
|
320
357
|
|
|
321
358
|
|
|
322
359
|
def stream_agno_response_as_agui_events(
|
|
323
|
-
response_stream: Iterator[Union[
|
|
360
|
+
response_stream: Iterator[Union[RunOutputEvent, TeamRunOutputEvent]], thread_id: str, run_id: str
|
|
324
361
|
) -> Iterator[BaseEvent]:
|
|
325
362
|
"""Map the Agno response stream to AG-UI format, handling event ordering constraints."""
|
|
326
363
|
message_id = str(uuid.uuid4())
|
|
@@ -355,7 +392,7 @@ def stream_agno_response_as_agui_events(
|
|
|
355
392
|
|
|
356
393
|
# Async version - thin wrapper
|
|
357
394
|
async def async_stream_agno_response_as_agui_events(
|
|
358
|
-
response_stream: AsyncIterator[Union[
|
|
395
|
+
response_stream: AsyncIterator[Union[RunOutputEvent, TeamRunOutputEvent]],
|
|
359
396
|
thread_id: str,
|
|
360
397
|
run_id: str,
|
|
361
398
|
) -> 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,33 @@
|
|
|
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, use_async: bool = True, **kwargs) -> APIRouter:
|
|
27
|
+
# Cannot be overridden
|
|
28
|
+
self.router_prefix = "/slack"
|
|
29
|
+
self.router = APIRouter(prefix=self.router_prefix, tags=["Slack"])
|
|
30
|
+
|
|
31
|
+
self.router = attach_routes(router=self.router, agent=self.agent, team=self.team)
|
|
32
|
+
|
|
33
|
+
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,30 @@
|
|
|
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, use_async: bool = True, **kwargs) -> APIRouter:
|
|
24
|
+
# Cannot be overridden
|
|
25
|
+
self.router_prefix = "/whatsapp"
|
|
26
|
+
self.router = APIRouter(prefix=self.router_prefix, tags=["Whatsapp"])
|
|
27
|
+
|
|
28
|
+
self.router = attach_routes(router=self.router, agent=self.agent, team=self.team)
|
|
29
|
+
|
|
30
|
+
return self.router
|