agno 1.8.1__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 +2778 -4123
- 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/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/google/gemini.py +100 -42
- 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 +121 -23
- 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 +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 +2961 -4253
- 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 +8 -8
- 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 +61 -61
- 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 +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 +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 +10 -8
- 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/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 +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} +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 -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/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.1.dist-info/METADATA +0 -982
- agno-1.8.1.dist-info/RECORD +0 -566
- agno-1.8.1.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.1.dist-info → agno-2.0.0a1.dist-info}/WHEEL +0 -0
- {agno-1.8.1.dist-info → agno-2.0.0a1.dist-info}/licenses/LICENSE +0 -0
- {agno-1.8.1.dist-info → agno-2.0.0a1.dist-info}/top_level.txt +0 -0
agno/models/xai/xai.py
CHANGED
|
@@ -65,7 +65,7 @@ class xAI(OpenAILike):
|
|
|
65
65
|
|
|
66
66
|
return request_params
|
|
67
67
|
|
|
68
|
-
def
|
|
68
|
+
def _parse_provider_response(
|
|
69
69
|
self,
|
|
70
70
|
response: ChatCompletion,
|
|
71
71
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
@@ -73,21 +73,21 @@ class xAI(OpenAILike):
|
|
|
73
73
|
"""
|
|
74
74
|
Parse the xAI response into a ModelResponse.
|
|
75
75
|
"""
|
|
76
|
-
model_response = super().
|
|
76
|
+
model_response = super()._parse_provider_response(response, response_format)
|
|
77
77
|
|
|
78
|
-
if hasattr(response, "citations") and response.citations:
|
|
78
|
+
if hasattr(response, "citations") and response.citations: # type: ignore
|
|
79
79
|
citations = Citations()
|
|
80
80
|
url_citations = []
|
|
81
|
-
for citation_url in response.citations:
|
|
81
|
+
for citation_url in response.citations: # type: ignore
|
|
82
82
|
url_citations.append(UrlCitation(url=str(citation_url)))
|
|
83
83
|
|
|
84
84
|
citations.urls = url_citations
|
|
85
|
-
citations.raw = response.citations
|
|
85
|
+
citations.raw = response.citations # type: ignore
|
|
86
86
|
model_response.citations = citations
|
|
87
87
|
|
|
88
88
|
return model_response
|
|
89
89
|
|
|
90
|
-
def
|
|
90
|
+
def _parse_provider_response_delta(self, response_delta: ChatCompletionChunk) -> ModelResponse:
|
|
91
91
|
"""
|
|
92
92
|
Parse the xAI streaming response.
|
|
93
93
|
|
|
@@ -97,16 +97,16 @@ class xAI(OpenAILike):
|
|
|
97
97
|
Returns:
|
|
98
98
|
ModelResponse: Parsed response data
|
|
99
99
|
"""
|
|
100
|
-
model_response = super().
|
|
100
|
+
model_response = super()._parse_provider_response_delta(response_delta)
|
|
101
101
|
|
|
102
|
-
if hasattr(response_delta, "citations") and response_delta.citations:
|
|
102
|
+
if hasattr(response_delta, "citations") and response_delta.citations: # type: ignore
|
|
103
103
|
citations = Citations()
|
|
104
104
|
url_citations = []
|
|
105
|
-
for citation_url in response_delta.citations:
|
|
105
|
+
for citation_url in response_delta.citations: # type: ignore
|
|
106
106
|
url_citations.append(UrlCitation(url=str(citation_url)))
|
|
107
107
|
|
|
108
108
|
citations.urls = url_citations
|
|
109
|
-
citations.raw = response_delta.citations
|
|
109
|
+
citations.raw = response_delta.citations # type: ignore
|
|
110
110
|
model_response.citations = citations
|
|
111
111
|
|
|
112
112
|
return model_response
|
agno/os/__init__.py
ADDED
agno/os/app.py
ADDED
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
from os import getenv
|
|
2
|
+
from typing import Any, Dict, List, Optional, Tuple, Union
|
|
3
|
+
from uuid import uuid4
|
|
4
|
+
|
|
5
|
+
from fastapi import FastAPI, HTTPException
|
|
6
|
+
from fastapi.responses import JSONResponse
|
|
7
|
+
from rich import box
|
|
8
|
+
from rich.panel import Panel
|
|
9
|
+
from starlette.middleware.cors import CORSMiddleware
|
|
10
|
+
from starlette.requests import Request
|
|
11
|
+
|
|
12
|
+
from agno.agent.agent import Agent
|
|
13
|
+
from agno.os.config import (
|
|
14
|
+
AgentOSConfig,
|
|
15
|
+
DatabaseConfig,
|
|
16
|
+
EvalsConfig,
|
|
17
|
+
EvalsDomainConfig,
|
|
18
|
+
KnowledgeConfig,
|
|
19
|
+
KnowledgeDomainConfig,
|
|
20
|
+
MemoryConfig,
|
|
21
|
+
MemoryDomainConfig,
|
|
22
|
+
MetricsConfig,
|
|
23
|
+
MetricsDomainConfig,
|
|
24
|
+
SessionConfig,
|
|
25
|
+
SessionDomainConfig,
|
|
26
|
+
)
|
|
27
|
+
from agno.os.interfaces.base import BaseInterface
|
|
28
|
+
from agno.os.router import get_base_router
|
|
29
|
+
from agno.os.routers.evals import get_eval_router
|
|
30
|
+
from agno.os.routers.knowledge import get_knowledge_router
|
|
31
|
+
from agno.os.routers.memory import get_memory_router
|
|
32
|
+
from agno.os.routers.metrics import get_metrics_router
|
|
33
|
+
from agno.os.routers.session import get_session_router
|
|
34
|
+
from agno.os.settings import AgnoAPISettings
|
|
35
|
+
from agno.os.utils import generate_id
|
|
36
|
+
from agno.team.team import Team
|
|
37
|
+
from agno.workflow.workflow import Workflow
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class AgentOS:
|
|
41
|
+
host_url: Optional[str] = None
|
|
42
|
+
|
|
43
|
+
def __init__(
|
|
44
|
+
self,
|
|
45
|
+
os_id: Optional[str] = None,
|
|
46
|
+
description: Optional[str] = None,
|
|
47
|
+
agents: Optional[List[Agent]] = None,
|
|
48
|
+
teams: Optional[List[Team]] = None,
|
|
49
|
+
workflows: Optional[List[Workflow]] = None,
|
|
50
|
+
interfaces: Optional[List[BaseInterface]] = None,
|
|
51
|
+
config: Optional[Union[str, AgentOSConfig]] = None,
|
|
52
|
+
settings: Optional[AgnoAPISettings] = None,
|
|
53
|
+
fastapi_app: Optional[FastAPI] = None,
|
|
54
|
+
telemetry: bool = True,
|
|
55
|
+
):
|
|
56
|
+
if not agents and not workflows and not teams:
|
|
57
|
+
raise ValueError("Either agents, teams or workflows must be provided.")
|
|
58
|
+
|
|
59
|
+
self.config = self._load_yaml_config(config) if isinstance(config, str) else config
|
|
60
|
+
self.description = description
|
|
61
|
+
|
|
62
|
+
self.agents: Optional[List[Agent]] = agents
|
|
63
|
+
self.workflows: Optional[List[Workflow]] = workflows
|
|
64
|
+
self.teams: Optional[List[Team]] = teams
|
|
65
|
+
self.interfaces = interfaces or []
|
|
66
|
+
|
|
67
|
+
self.settings: AgnoAPISettings = settings or AgnoAPISettings()
|
|
68
|
+
self.fastapi_app: Optional[FastAPI] = fastapi_app
|
|
69
|
+
|
|
70
|
+
self.interfaces = interfaces or []
|
|
71
|
+
|
|
72
|
+
self.os_id: Optional[str] = os_id
|
|
73
|
+
self.description = description
|
|
74
|
+
|
|
75
|
+
self.telemetry = telemetry
|
|
76
|
+
|
|
77
|
+
self.interfaces_loaded: List[Tuple[str, str]] = []
|
|
78
|
+
|
|
79
|
+
if self.agents:
|
|
80
|
+
for agent in self.agents:
|
|
81
|
+
agent.initialize_agent()
|
|
82
|
+
|
|
83
|
+
# Required for the built-in routes to work
|
|
84
|
+
agent.store_events = True
|
|
85
|
+
|
|
86
|
+
if self.teams:
|
|
87
|
+
for team in self.teams:
|
|
88
|
+
team.initialize_team()
|
|
89
|
+
|
|
90
|
+
# Required for the built-in routes to work
|
|
91
|
+
team.store_events = True
|
|
92
|
+
|
|
93
|
+
for member in team.members:
|
|
94
|
+
if isinstance(member, Agent):
|
|
95
|
+
member.team_id = None
|
|
96
|
+
member.initialize_agent()
|
|
97
|
+
elif isinstance(member, Team):
|
|
98
|
+
member.initialize_team()
|
|
99
|
+
|
|
100
|
+
if self.workflows:
|
|
101
|
+
for workflow in self.workflows:
|
|
102
|
+
if not workflow.id:
|
|
103
|
+
workflow.id = generate_id(workflow.name)
|
|
104
|
+
|
|
105
|
+
if self.telemetry:
|
|
106
|
+
from agno.api.os import OSLaunch, log_os_telemetry
|
|
107
|
+
|
|
108
|
+
log_os_telemetry(launch=OSLaunch(os_id=self.os_id, data=self._get_telemetry_data()))
|
|
109
|
+
|
|
110
|
+
def _get_telemetry_data(self) -> Dict[str, Any]:
|
|
111
|
+
"""Get the telemetry data for the OS"""
|
|
112
|
+
return {
|
|
113
|
+
"agents": [agent.id for agent in self.agents] if self.agents else None,
|
|
114
|
+
"teams": [team.id for team in self.teams] if self.teams else None,
|
|
115
|
+
"workflows": [workflow.id for workflow in self.workflows] if self.workflows else None,
|
|
116
|
+
"interfaces": [interface.type for interface in self.interfaces] if self.interfaces else None,
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
def _load_yaml_config(self, config_file_path: str) -> AgentOSConfig:
|
|
120
|
+
"""Load a YAML config file and return the configuration as an AgentOSConfig instance."""
|
|
121
|
+
from pathlib import Path
|
|
122
|
+
|
|
123
|
+
import yaml
|
|
124
|
+
|
|
125
|
+
# Validate that the path points to a YAML file
|
|
126
|
+
path = Path(config_file_path)
|
|
127
|
+
if path.suffix.lower() not in [".yaml", ".yml"]:
|
|
128
|
+
raise ValueError(f"Config file must have a .yaml or .yml extension, got: {config_file_path}")
|
|
129
|
+
|
|
130
|
+
# Load the YAML file
|
|
131
|
+
with open(config_file_path, "r") as f:
|
|
132
|
+
return AgentOSConfig.model_validate(yaml.safe_load(f))
|
|
133
|
+
|
|
134
|
+
def _auto_discover_databases(self) -> None:
|
|
135
|
+
"""Auto-discover the databases used by all contextual agents, teams and workflows."""
|
|
136
|
+
dbs = {}
|
|
137
|
+
|
|
138
|
+
for agent in self.agents or []:
|
|
139
|
+
if agent.db:
|
|
140
|
+
dbs[agent.db.id] = agent.db
|
|
141
|
+
if agent.knowledge and agent.knowledge.contents_db:
|
|
142
|
+
dbs[agent.knowledge.contents_db.id] = agent.knowledge.contents_db
|
|
143
|
+
|
|
144
|
+
for team in self.teams or []:
|
|
145
|
+
if team.db:
|
|
146
|
+
dbs[team.db.id] = team.db
|
|
147
|
+
if team.knowledge and team.knowledge.contents_db:
|
|
148
|
+
dbs[team.knowledge.contents_db.id] = team.knowledge.contents_db
|
|
149
|
+
|
|
150
|
+
for workflow in self.workflows or []:
|
|
151
|
+
if workflow.db:
|
|
152
|
+
dbs[workflow.db.id] = workflow.db
|
|
153
|
+
|
|
154
|
+
for interface in self.interfaces or []:
|
|
155
|
+
if interface.agent and interface.agent.db:
|
|
156
|
+
dbs[interface.agent.db.id] = interface.agent.db
|
|
157
|
+
elif interface.team and interface.team.db:
|
|
158
|
+
dbs[interface.team.db.id] = interface.team.db
|
|
159
|
+
|
|
160
|
+
self.dbs = dbs
|
|
161
|
+
|
|
162
|
+
def _auto_discover_knowledge_instances(self) -> None:
|
|
163
|
+
"""Auto-discover the knowledge instances used by all contextual agents, teams and workflows."""
|
|
164
|
+
knowledge_instances = []
|
|
165
|
+
for agent in self.agents or []:
|
|
166
|
+
if agent.knowledge:
|
|
167
|
+
knowledge_instances.append(agent.knowledge)
|
|
168
|
+
|
|
169
|
+
for team in self.teams or []:
|
|
170
|
+
if team.knowledge:
|
|
171
|
+
knowledge_instances.append(team.knowledge)
|
|
172
|
+
|
|
173
|
+
self.knowledge_instances = knowledge_instances
|
|
174
|
+
|
|
175
|
+
def _get_session_config(self) -> SessionConfig:
|
|
176
|
+
session_config = self.config.session if self.config and self.config.session else SessionConfig()
|
|
177
|
+
|
|
178
|
+
if session_config.dbs is None:
|
|
179
|
+
session_config.dbs = []
|
|
180
|
+
|
|
181
|
+
multiple_dbs: bool = len(self.dbs.keys()) > 1
|
|
182
|
+
dbs_with_specific_config = [db.db_id for db in session_config.dbs]
|
|
183
|
+
|
|
184
|
+
for db_id in self.dbs.keys():
|
|
185
|
+
if db_id not in dbs_with_specific_config:
|
|
186
|
+
session_config.dbs.append(
|
|
187
|
+
DatabaseConfig(
|
|
188
|
+
db_id=db_id,
|
|
189
|
+
domain_config=SessionDomainConfig(
|
|
190
|
+
display_name="Sessions" if not multiple_dbs else "Sessions " + db_id
|
|
191
|
+
),
|
|
192
|
+
)
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
return session_config
|
|
196
|
+
|
|
197
|
+
def _get_memory_config(self) -> MemoryConfig:
|
|
198
|
+
memory_config = self.config.memory if self.config and self.config.memory else MemoryConfig()
|
|
199
|
+
|
|
200
|
+
if memory_config.dbs is None:
|
|
201
|
+
memory_config.dbs = []
|
|
202
|
+
|
|
203
|
+
multiple_dbs: bool = len(self.dbs.keys()) > 1
|
|
204
|
+
dbs_with_specific_config = [db.db_id for db in memory_config.dbs]
|
|
205
|
+
|
|
206
|
+
for db_id in self.dbs.keys():
|
|
207
|
+
if db_id not in dbs_with_specific_config:
|
|
208
|
+
memory_config.dbs.append(
|
|
209
|
+
DatabaseConfig(
|
|
210
|
+
db_id=db_id,
|
|
211
|
+
domain_config=MemoryDomainConfig(
|
|
212
|
+
display_name="Memory" if not multiple_dbs else "Memory " + db_id
|
|
213
|
+
),
|
|
214
|
+
)
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
return memory_config
|
|
218
|
+
|
|
219
|
+
def _get_knowledge_config(self) -> KnowledgeConfig:
|
|
220
|
+
knowledge_config = self.config.knowledge if self.config and self.config.knowledge else KnowledgeConfig()
|
|
221
|
+
|
|
222
|
+
if knowledge_config.dbs is None:
|
|
223
|
+
knowledge_config.dbs = []
|
|
224
|
+
|
|
225
|
+
multiple_dbs: bool = len(self.dbs.keys()) > 1
|
|
226
|
+
dbs_with_specific_config = [db.db_id for db in knowledge_config.dbs]
|
|
227
|
+
|
|
228
|
+
for db_id in self.dbs.keys():
|
|
229
|
+
if db_id not in dbs_with_specific_config:
|
|
230
|
+
knowledge_config.dbs.append(
|
|
231
|
+
DatabaseConfig(
|
|
232
|
+
db_id=db_id,
|
|
233
|
+
domain_config=KnowledgeDomainConfig(
|
|
234
|
+
display_name="Knowledge" if not multiple_dbs else "Knowledge " + db_id
|
|
235
|
+
),
|
|
236
|
+
)
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
return knowledge_config
|
|
240
|
+
|
|
241
|
+
def _get_metrics_config(self) -> MetricsConfig:
|
|
242
|
+
metrics_config = self.config.metrics if self.config and self.config.metrics else MetricsConfig()
|
|
243
|
+
|
|
244
|
+
if metrics_config.dbs is None:
|
|
245
|
+
metrics_config.dbs = []
|
|
246
|
+
|
|
247
|
+
multiple_dbs: bool = len(self.dbs.keys()) > 1
|
|
248
|
+
dbs_with_specific_config = [db.db_id for db in metrics_config.dbs]
|
|
249
|
+
|
|
250
|
+
for db_id in self.dbs.keys():
|
|
251
|
+
if db_id not in dbs_with_specific_config:
|
|
252
|
+
metrics_config.dbs.append(
|
|
253
|
+
DatabaseConfig(
|
|
254
|
+
db_id=db_id,
|
|
255
|
+
domain_config=MetricsDomainConfig(
|
|
256
|
+
display_name="Metrics" if not multiple_dbs else "Metrics " + db_id
|
|
257
|
+
),
|
|
258
|
+
)
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
return metrics_config
|
|
262
|
+
|
|
263
|
+
def _get_evals_config(self) -> EvalsConfig:
|
|
264
|
+
evals_config = self.config.evals if self.config and self.config.evals else EvalsConfig()
|
|
265
|
+
|
|
266
|
+
if evals_config.dbs is None:
|
|
267
|
+
evals_config.dbs = []
|
|
268
|
+
|
|
269
|
+
multiple_dbs: bool = len(self.dbs.keys()) > 1
|
|
270
|
+
dbs_with_specific_config = [db.db_id for db in evals_config.dbs]
|
|
271
|
+
|
|
272
|
+
for db_id in self.dbs.keys():
|
|
273
|
+
if db_id not in dbs_with_specific_config:
|
|
274
|
+
evals_config.dbs.append(
|
|
275
|
+
DatabaseConfig(
|
|
276
|
+
db_id=db_id,
|
|
277
|
+
domain_config=EvalsDomainConfig(display_name="Evals" if not multiple_dbs else "Evals " + db_id),
|
|
278
|
+
)
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
return evals_config
|
|
282
|
+
|
|
283
|
+
def _setup_routers(self) -> None:
|
|
284
|
+
"""Add all routers to the FastAPI app."""
|
|
285
|
+
if not self.dbs or not self.fastapi_app:
|
|
286
|
+
return
|
|
287
|
+
|
|
288
|
+
routers = [
|
|
289
|
+
get_session_router(dbs=self.dbs),
|
|
290
|
+
get_memory_router(dbs=self.dbs),
|
|
291
|
+
get_eval_router(dbs=self.dbs, agents=self.agents, teams=self.teams),
|
|
292
|
+
get_metrics_router(dbs=self.dbs),
|
|
293
|
+
get_knowledge_router(knowledge_instances=self.knowledge_instances),
|
|
294
|
+
]
|
|
295
|
+
|
|
296
|
+
for router in routers:
|
|
297
|
+
self.fastapi_app.include_router(router)
|
|
298
|
+
|
|
299
|
+
def set_os_id(self) -> str:
|
|
300
|
+
# If os_id is already set, keep it instead of overriding with UUID
|
|
301
|
+
if self.os_id is None:
|
|
302
|
+
self.os_id = str(uuid4())
|
|
303
|
+
|
|
304
|
+
return self.os_id
|
|
305
|
+
|
|
306
|
+
def get_app(self) -> FastAPI:
|
|
307
|
+
if not self.fastapi_app:
|
|
308
|
+
self.fastapi_app = FastAPI(
|
|
309
|
+
title=self.settings.title,
|
|
310
|
+
docs_url="/docs" if self.settings.docs_enabled else None,
|
|
311
|
+
redoc_url="/redoc" if self.settings.docs_enabled else None,
|
|
312
|
+
openapi_url="/openapi.json" if self.settings.docs_enabled else None,
|
|
313
|
+
)
|
|
314
|
+
|
|
315
|
+
if not self.fastapi_app:
|
|
316
|
+
raise Exception("API App could not be created.")
|
|
317
|
+
|
|
318
|
+
@self.fastapi_app.exception_handler(HTTPException)
|
|
319
|
+
async def http_exception_handler(request: Request, exc: HTTPException) -> JSONResponse:
|
|
320
|
+
return JSONResponse(
|
|
321
|
+
status_code=exc.status_code,
|
|
322
|
+
content={"detail": str(exc.detail)},
|
|
323
|
+
)
|
|
324
|
+
|
|
325
|
+
async def general_exception_handler(request: Request, call_next):
|
|
326
|
+
try:
|
|
327
|
+
return await call_next(request)
|
|
328
|
+
except Exception as e:
|
|
329
|
+
return JSONResponse(
|
|
330
|
+
status_code=e.status_code if hasattr(e, "status_code") else 500, # type: ignore
|
|
331
|
+
content={"detail": str(e)},
|
|
332
|
+
)
|
|
333
|
+
|
|
334
|
+
self.fastapi_app.middleware("http")(general_exception_handler)
|
|
335
|
+
|
|
336
|
+
self.fastapi_app.include_router(get_base_router(self, settings=self.settings))
|
|
337
|
+
|
|
338
|
+
for interface in self.interfaces:
|
|
339
|
+
interface_router = interface.get_router()
|
|
340
|
+
self.fastapi_app.include_router(interface_router)
|
|
341
|
+
self.interfaces_loaded.append((interface.type, interface.router_prefix))
|
|
342
|
+
|
|
343
|
+
self._auto_discover_databases()
|
|
344
|
+
self._auto_discover_knowledge_instances()
|
|
345
|
+
self._setup_routers()
|
|
346
|
+
|
|
347
|
+
self.fastapi_app.add_middleware(
|
|
348
|
+
CORSMiddleware,
|
|
349
|
+
allow_origins=self.settings.cors_origin_list, # type: ignore
|
|
350
|
+
allow_credentials=True,
|
|
351
|
+
allow_methods=["*"],
|
|
352
|
+
allow_headers=["*"],
|
|
353
|
+
expose_headers=["*"],
|
|
354
|
+
)
|
|
355
|
+
|
|
356
|
+
return self.fastapi_app
|
|
357
|
+
|
|
358
|
+
def serve(
|
|
359
|
+
self,
|
|
360
|
+
app: Union[str, FastAPI],
|
|
361
|
+
*,
|
|
362
|
+
host: str = "localhost",
|
|
363
|
+
port: int = 7777,
|
|
364
|
+
reload: bool = False,
|
|
365
|
+
**kwargs,
|
|
366
|
+
):
|
|
367
|
+
import uvicorn
|
|
368
|
+
|
|
369
|
+
if getenv("AGNO_API_RUNTIME", "").lower() == "stg":
|
|
370
|
+
public_endpoint = "https://os-stg.agno.com/"
|
|
371
|
+
else:
|
|
372
|
+
public_endpoint = "https://os.agno.com/"
|
|
373
|
+
|
|
374
|
+
# Create a terminal panel to announce OS initialization and provide useful info
|
|
375
|
+
from rich.align import Align
|
|
376
|
+
from rich.console import Console, Group
|
|
377
|
+
|
|
378
|
+
aligned_endpoint = Align.center(f"[bold cyan]{public_endpoint}[/bold cyan]")
|
|
379
|
+
connection_endpoint = f"\n\n[bold dark_orange]Running on:[/bold dark_orange] http://{host}:{port}"
|
|
380
|
+
|
|
381
|
+
console = Console()
|
|
382
|
+
console.print(
|
|
383
|
+
Panel(
|
|
384
|
+
Group(aligned_endpoint, connection_endpoint),
|
|
385
|
+
title="AgentOS",
|
|
386
|
+
expand=False,
|
|
387
|
+
border_style="dark_orange",
|
|
388
|
+
box=box.DOUBLE_EDGE,
|
|
389
|
+
padding=(2, 2),
|
|
390
|
+
)
|
|
391
|
+
)
|
|
392
|
+
|
|
393
|
+
uvicorn.run(app=app, host=host, port=port, reload=reload, **kwargs)
|
agno/os/auth.py
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
from fastapi import Header, HTTPException
|
|
4
|
+
from fastapi.security import HTTPBearer
|
|
5
|
+
|
|
6
|
+
from agno.os.settings import AgnoAPISettings
|
|
7
|
+
|
|
8
|
+
# Create a global HTTPBearer instance
|
|
9
|
+
security = HTTPBearer(auto_error=False)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def get_authentication_dependency(settings: AgnoAPISettings):
|
|
13
|
+
"""
|
|
14
|
+
Create an authentication dependency function for FastAPI routes.
|
|
15
|
+
|
|
16
|
+
Args:
|
|
17
|
+
settings: The API settings containing the security key
|
|
18
|
+
|
|
19
|
+
Returns:
|
|
20
|
+
A dependency function that can be used with FastAPI's Depends()
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
def auth_dependency(authorization: Optional[str] = Header(None)) -> bool:
|
|
24
|
+
# If no security key is set, skip authentication entirely
|
|
25
|
+
if not settings or not settings.os_security_key:
|
|
26
|
+
return True
|
|
27
|
+
|
|
28
|
+
# If security is enabled but no authorization header provided, fail
|
|
29
|
+
if not authorization:
|
|
30
|
+
raise HTTPException(status_code=401, detail="Authorization header required")
|
|
31
|
+
|
|
32
|
+
# Check if the authorization header starts with "Bearer "
|
|
33
|
+
if not authorization.startswith("Bearer "):
|
|
34
|
+
raise HTTPException(
|
|
35
|
+
status_code=401, detail="Invalid authorization header format. Expected 'Bearer <token>'"
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
# Extract the token from the authorization header
|
|
39
|
+
token = authorization[7:] # Remove "Bearer " prefix
|
|
40
|
+
|
|
41
|
+
# Verify the token
|
|
42
|
+
if token != settings.os_security_key:
|
|
43
|
+
raise HTTPException(status_code=401, detail="Invalid authentication token")
|
|
44
|
+
|
|
45
|
+
return True
|
|
46
|
+
|
|
47
|
+
return auth_dependency
|
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
|