agno 1.8.1__py3-none-any.whl → 2.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agno/__init__.py +8 -0
- agno/agent/__init__.py +19 -27
- agno/agent/agent.py +3143 -4170
- agno/api/agent.py +11 -67
- agno/api/api.py +5 -46
- agno/api/evals.py +8 -19
- agno/api/os.py +17 -0
- agno/api/routes.py +6 -41
- agno/api/schemas/__init__.py +9 -0
- agno/api/schemas/agent.py +5 -21
- agno/api/schemas/evals.py +7 -16
- agno/api/schemas/os.py +14 -0
- agno/api/schemas/team.py +5 -21
- agno/api/schemas/utils.py +21 -0
- agno/api/schemas/workflows.py +11 -7
- agno/api/settings.py +53 -0
- agno/api/team.py +11 -66
- agno/api/workflow.py +28 -0
- agno/cloud/aws/base.py +214 -0
- agno/cloud/aws/s3/__init__.py +2 -0
- agno/cloud/aws/s3/api_client.py +43 -0
- agno/cloud/aws/s3/bucket.py +195 -0
- agno/cloud/aws/s3/object.py +57 -0
- agno/db/__init__.py +24 -0
- agno/db/base.py +245 -0
- agno/db/dynamo/__init__.py +3 -0
- agno/db/dynamo/dynamo.py +1743 -0
- agno/db/dynamo/schemas.py +278 -0
- agno/db/dynamo/utils.py +684 -0
- agno/db/firestore/__init__.py +3 -0
- agno/db/firestore/firestore.py +1432 -0
- agno/db/firestore/schemas.py +130 -0
- agno/db/firestore/utils.py +278 -0
- agno/db/gcs_json/__init__.py +3 -0
- agno/db/gcs_json/gcs_json_db.py +1001 -0
- agno/db/gcs_json/utils.py +194 -0
- agno/db/in_memory/__init__.py +3 -0
- agno/db/in_memory/in_memory_db.py +882 -0
- agno/db/in_memory/utils.py +172 -0
- agno/db/json/__init__.py +3 -0
- agno/db/json/json_db.py +1045 -0
- agno/db/json/utils.py +196 -0
- agno/db/migrations/v1_to_v2.py +162 -0
- agno/db/mongo/__init__.py +3 -0
- agno/db/mongo/mongo.py +1416 -0
- agno/db/mongo/schemas.py +77 -0
- agno/db/mongo/utils.py +204 -0
- agno/db/mysql/__init__.py +3 -0
- agno/db/mysql/mysql.py +1719 -0
- agno/db/mysql/schemas.py +124 -0
- agno/db/mysql/utils.py +297 -0
- agno/db/postgres/__init__.py +3 -0
- agno/db/postgres/postgres.py +1710 -0
- agno/db/postgres/schemas.py +124 -0
- agno/db/postgres/utils.py +280 -0
- agno/db/redis/__init__.py +3 -0
- agno/db/redis/redis.py +1367 -0
- agno/db/redis/schemas.py +109 -0
- agno/db/redis/utils.py +288 -0
- agno/db/schemas/__init__.py +3 -0
- agno/db/schemas/evals.py +33 -0
- agno/db/schemas/knowledge.py +40 -0
- agno/db/schemas/memory.py +46 -0
- agno/db/singlestore/__init__.py +3 -0
- agno/db/singlestore/schemas.py +116 -0
- agno/db/singlestore/singlestore.py +1712 -0
- agno/db/singlestore/utils.py +326 -0
- agno/db/sqlite/__init__.py +3 -0
- agno/db/sqlite/schemas.py +119 -0
- agno/db/sqlite/sqlite.py +1676 -0
- agno/db/sqlite/utils.py +268 -0
- agno/db/utils.py +88 -0
- agno/eval/__init__.py +14 -0
- agno/eval/accuracy.py +154 -48
- agno/eval/performance.py +88 -23
- agno/eval/reliability.py +73 -20
- agno/eval/utils.py +23 -13
- agno/integrations/discord/__init__.py +3 -0
- agno/{app → integrations}/discord/client.py +15 -11
- agno/knowledge/__init__.py +2 -2
- agno/{document → knowledge}/chunking/agentic.py +2 -2
- agno/{document → knowledge}/chunking/document.py +2 -2
- agno/{document → knowledge}/chunking/fixed.py +3 -3
- agno/{document → knowledge}/chunking/markdown.py +2 -2
- agno/{document → knowledge}/chunking/recursive.py +2 -2
- agno/{document → knowledge}/chunking/row.py +2 -2
- agno/knowledge/chunking/semantic.py +59 -0
- agno/knowledge/chunking/strategy.py +121 -0
- agno/knowledge/content.py +74 -0
- agno/knowledge/document/__init__.py +5 -0
- agno/{document → knowledge/document}/base.py +12 -2
- agno/knowledge/embedder/__init__.py +5 -0
- agno/{embedder → knowledge/embedder}/aws_bedrock.py +127 -1
- agno/{embedder → knowledge/embedder}/azure_openai.py +65 -1
- agno/{embedder → knowledge/embedder}/base.py +6 -0
- agno/{embedder → knowledge/embedder}/cohere.py +72 -1
- agno/{embedder → knowledge/embedder}/fastembed.py +17 -1
- agno/{embedder → knowledge/embedder}/fireworks.py +1 -1
- agno/{embedder → knowledge/embedder}/google.py +74 -1
- agno/{embedder → knowledge/embedder}/huggingface.py +36 -2
- agno/{embedder → knowledge/embedder}/jina.py +48 -2
- agno/knowledge/embedder/langdb.py +22 -0
- agno/knowledge/embedder/mistral.py +139 -0
- agno/{embedder → knowledge/embedder}/nebius.py +1 -1
- agno/{embedder → knowledge/embedder}/ollama.py +54 -3
- agno/knowledge/embedder/openai.py +223 -0
- agno/{embedder → knowledge/embedder}/sentence_transformer.py +16 -1
- agno/{embedder → knowledge/embedder}/together.py +1 -1
- agno/{embedder → knowledge/embedder}/voyageai.py +49 -1
- agno/knowledge/knowledge.py +1551 -0
- agno/knowledge/reader/__init__.py +7 -0
- agno/{document → knowledge}/reader/arxiv_reader.py +32 -4
- agno/knowledge/reader/base.py +88 -0
- agno/{document → knowledge}/reader/csv_reader.py +47 -65
- agno/knowledge/reader/docx_reader.py +83 -0
- agno/{document → knowledge}/reader/firecrawl_reader.py +42 -21
- agno/{document → knowledge}/reader/json_reader.py +30 -9
- agno/{document → knowledge}/reader/markdown_reader.py +58 -9
- agno/{document → knowledge}/reader/pdf_reader.py +71 -126
- agno/knowledge/reader/reader_factory.py +268 -0
- agno/knowledge/reader/s3_reader.py +101 -0
- agno/{document → knowledge}/reader/text_reader.py +31 -10
- agno/knowledge/reader/url_reader.py +128 -0
- agno/knowledge/reader/web_search_reader.py +366 -0
- agno/{document → knowledge}/reader/website_reader.py +37 -10
- agno/knowledge/reader/wikipedia_reader.py +59 -0
- agno/knowledge/reader/youtube_reader.py +78 -0
- agno/knowledge/remote_content/remote_content.py +88 -0
- agno/{reranker → knowledge/reranker}/base.py +1 -1
- agno/{reranker → knowledge/reranker}/cohere.py +2 -2
- agno/{reranker → knowledge/reranker}/infinity.py +2 -2
- agno/{reranker → knowledge/reranker}/sentence_transformer.py +2 -2
- agno/knowledge/types.py +30 -0
- agno/knowledge/utils.py +169 -0
- agno/media.py +269 -268
- agno/memory/__init__.py +2 -10
- agno/memory/manager.py +1003 -148
- agno/models/aimlapi/__init__.py +2 -2
- agno/models/aimlapi/aimlapi.py +6 -6
- agno/models/anthropic/claude.py +131 -131
- agno/models/aws/bedrock.py +110 -182
- agno/models/aws/claude.py +64 -18
- agno/models/azure/ai_foundry.py +73 -23
- agno/models/base.py +346 -290
- agno/models/cerebras/cerebras.py +84 -27
- agno/models/cohere/chat.py +106 -98
- agno/models/google/gemini.py +105 -46
- agno/models/groq/groq.py +97 -35
- agno/models/huggingface/huggingface.py +92 -27
- agno/models/ibm/watsonx.py +72 -13
- agno/models/litellm/chat.py +85 -13
- agno/models/message.py +46 -151
- agno/models/meta/llama.py +85 -49
- agno/models/metrics.py +120 -0
- agno/models/mistral/mistral.py +90 -21
- agno/models/ollama/__init__.py +0 -2
- agno/models/ollama/chat.py +85 -47
- agno/models/openai/chat.py +154 -37
- agno/models/openai/responses.py +178 -105
- agno/models/perplexity/perplexity.py +26 -2
- agno/models/portkey/portkey.py +0 -7
- agno/models/response.py +15 -9
- agno/models/utils.py +20 -0
- agno/models/vercel/__init__.py +2 -2
- agno/models/vercel/v0.py +1 -1
- agno/models/vllm/__init__.py +2 -2
- agno/models/vllm/vllm.py +3 -3
- agno/models/xai/xai.py +10 -10
- agno/os/__init__.py +3 -0
- agno/os/app.py +497 -0
- agno/os/auth.py +47 -0
- agno/os/config.py +103 -0
- agno/os/interfaces/agui/__init__.py +3 -0
- agno/os/interfaces/agui/agui.py +31 -0
- agno/{app/agui/async_router.py → os/interfaces/agui/router.py} +16 -16
- agno/{app → os/interfaces}/agui/utils.py +77 -33
- agno/os/interfaces/base.py +21 -0
- agno/os/interfaces/slack/__init__.py +3 -0
- agno/{app/slack/async_router.py → os/interfaces/slack/router.py} +3 -5
- agno/os/interfaces/slack/slack.py +32 -0
- agno/os/interfaces/whatsapp/__init__.py +3 -0
- agno/{app/whatsapp/async_router.py → os/interfaces/whatsapp/router.py} +4 -7
- agno/os/interfaces/whatsapp/whatsapp.py +29 -0
- agno/os/mcp.py +235 -0
- agno/os/router.py +1400 -0
- agno/os/routers/__init__.py +3 -0
- agno/os/routers/evals/__init__.py +3 -0
- agno/os/routers/evals/evals.py +393 -0
- agno/os/routers/evals/schemas.py +142 -0
- agno/os/routers/evals/utils.py +161 -0
- agno/os/routers/knowledge/__init__.py +3 -0
- agno/os/routers/knowledge/knowledge.py +850 -0
- agno/os/routers/knowledge/schemas.py +118 -0
- agno/os/routers/memory/__init__.py +3 -0
- agno/os/routers/memory/memory.py +410 -0
- agno/os/routers/memory/schemas.py +58 -0
- agno/os/routers/metrics/__init__.py +3 -0
- agno/os/routers/metrics/metrics.py +178 -0
- agno/os/routers/metrics/schemas.py +47 -0
- agno/os/routers/session/__init__.py +3 -0
- agno/os/routers/session/session.py +536 -0
- agno/os/schema.py +945 -0
- agno/{app/playground → os}/settings.py +7 -15
- agno/os/utils.py +270 -0
- agno/reasoning/azure_ai_foundry.py +4 -4
- agno/reasoning/deepseek.py +4 -4
- agno/reasoning/default.py +6 -11
- agno/reasoning/groq.py +4 -4
- agno/reasoning/helpers.py +4 -6
- agno/reasoning/ollama.py +4 -4
- agno/reasoning/openai.py +4 -4
- agno/run/agent.py +633 -0
- agno/run/base.py +53 -77
- agno/run/cancel.py +81 -0
- agno/run/team.py +243 -96
- agno/run/workflow.py +550 -12
- agno/session/__init__.py +10 -0
- agno/session/agent.py +244 -0
- agno/session/summary.py +225 -0
- agno/session/team.py +262 -0
- agno/{storage/session/v2 → session}/workflow.py +47 -24
- agno/team/__init__.py +15 -16
- agno/team/team.py +3260 -4824
- agno/tools/agentql.py +14 -5
- agno/tools/airflow.py +9 -4
- agno/tools/api.py +7 -3
- agno/tools/apify.py +2 -46
- agno/tools/arxiv.py +8 -3
- agno/tools/aws_lambda.py +7 -5
- agno/tools/aws_ses.py +7 -1
- agno/tools/baidusearch.py +4 -1
- agno/tools/bitbucket.py +4 -4
- agno/tools/brandfetch.py +14 -11
- agno/tools/bravesearch.py +4 -1
- agno/tools/brightdata.py +43 -23
- agno/tools/browserbase.py +13 -4
- agno/tools/calcom.py +12 -10
- agno/tools/calculator.py +10 -27
- agno/tools/cartesia.py +20 -17
- agno/tools/{clickup_tool.py → clickup.py} +12 -25
- agno/tools/confluence.py +8 -8
- agno/tools/crawl4ai.py +7 -1
- agno/tools/csv_toolkit.py +9 -8
- agno/tools/dalle.py +22 -12
- agno/tools/daytona.py +13 -16
- agno/tools/decorator.py +6 -3
- agno/tools/desi_vocal.py +17 -8
- agno/tools/discord.py +11 -8
- agno/tools/docker.py +30 -42
- agno/tools/duckdb.py +34 -53
- agno/tools/duckduckgo.py +8 -7
- agno/tools/e2b.py +62 -62
- agno/tools/eleven_labs.py +36 -29
- agno/tools/email.py +4 -1
- agno/tools/evm.py +7 -1
- agno/tools/exa.py +19 -14
- agno/tools/fal.py +30 -30
- agno/tools/file.py +9 -8
- agno/tools/financial_datasets.py +25 -44
- agno/tools/firecrawl.py +22 -22
- agno/tools/function.py +127 -18
- agno/tools/giphy.py +23 -11
- agno/tools/github.py +48 -126
- agno/tools/gmail.py +45 -61
- agno/tools/google_bigquery.py +7 -6
- agno/tools/google_maps.py +11 -26
- agno/tools/googlesearch.py +7 -2
- agno/tools/googlesheets.py +21 -17
- agno/tools/hackernews.py +9 -5
- agno/tools/jina.py +5 -4
- agno/tools/jira.py +18 -9
- agno/tools/knowledge.py +31 -32
- agno/tools/linear.py +19 -34
- agno/tools/linkup.py +5 -1
- agno/tools/local_file_system.py +8 -5
- agno/tools/lumalab.py +32 -20
- agno/tools/mcp.py +1 -2
- agno/tools/mem0.py +18 -12
- agno/tools/memori.py +14 -10
- agno/tools/mlx_transcribe.py +3 -2
- agno/tools/models/azure_openai.py +33 -15
- agno/tools/models/gemini.py +59 -32
- agno/tools/models/groq.py +30 -23
- agno/tools/models/nebius.py +28 -12
- agno/tools/models_labs.py +40 -16
- agno/tools/moviepy_video.py +7 -6
- agno/tools/neo4j.py +10 -8
- agno/tools/newspaper.py +7 -2
- agno/tools/newspaper4k.py +8 -3
- agno/tools/openai.py +58 -32
- agno/tools/openbb.py +12 -11
- agno/tools/opencv.py +63 -47
- agno/tools/openweather.py +14 -12
- agno/tools/pandas.py +11 -3
- agno/tools/postgres.py +4 -12
- agno/tools/pubmed.py +4 -1
- agno/tools/python.py +9 -22
- agno/tools/reasoning.py +35 -27
- agno/tools/reddit.py +11 -26
- agno/tools/replicate.py +55 -42
- agno/tools/resend.py +4 -1
- agno/tools/scrapegraph.py +15 -14
- agno/tools/searxng.py +10 -23
- agno/tools/serpapi.py +6 -3
- agno/tools/serper.py +13 -4
- agno/tools/shell.py +9 -2
- agno/tools/slack.py +12 -11
- agno/tools/sleep.py +3 -2
- agno/tools/spider.py +24 -4
- agno/tools/sql.py +7 -6
- agno/tools/tavily.py +6 -4
- agno/tools/telegram.py +12 -4
- agno/tools/todoist.py +11 -31
- agno/tools/toolkit.py +1 -1
- agno/tools/trafilatura.py +22 -6
- agno/tools/trello.py +9 -22
- agno/tools/twilio.py +10 -3
- agno/tools/user_control_flow.py +6 -1
- agno/tools/valyu.py +34 -5
- agno/tools/visualization.py +19 -28
- agno/tools/webbrowser.py +4 -3
- agno/tools/webex.py +11 -7
- agno/tools/website.py +15 -46
- agno/tools/webtools.py +12 -4
- agno/tools/whatsapp.py +5 -9
- agno/tools/wikipedia.py +20 -13
- agno/tools/x.py +14 -13
- agno/tools/yfinance.py +13 -40
- agno/tools/youtube.py +26 -20
- agno/tools/zendesk.py +7 -2
- agno/tools/zep.py +10 -7
- agno/tools/zoom.py +10 -9
- agno/utils/common.py +1 -19
- agno/utils/events.py +100 -123
- agno/utils/gemini.py +32 -2
- agno/utils/knowledge.py +29 -0
- agno/utils/log.py +54 -4
- agno/utils/mcp.py +68 -10
- agno/utils/media.py +39 -0
- agno/utils/message.py +12 -1
- agno/utils/models/aws_claude.py +1 -1
- agno/utils/models/claude.py +47 -4
- agno/utils/models/cohere.py +1 -1
- agno/utils/models/mistral.py +8 -7
- agno/utils/models/schema_utils.py +3 -3
- agno/utils/models/watsonx.py +1 -1
- agno/utils/openai.py +1 -1
- agno/utils/pprint.py +33 -32
- agno/utils/print_response/agent.py +779 -0
- agno/utils/print_response/team.py +1669 -0
- agno/utils/print_response/workflow.py +1451 -0
- agno/utils/prompts.py +14 -14
- agno/utils/reasoning.py +87 -0
- agno/utils/response.py +42 -42
- agno/utils/streamlit.py +481 -0
- agno/utils/string.py +8 -22
- agno/utils/team.py +50 -0
- agno/utils/timer.py +2 -2
- agno/vectordb/base.py +33 -21
- agno/vectordb/cassandra/cassandra.py +287 -23
- agno/vectordb/chroma/chromadb.py +482 -59
- agno/vectordb/clickhouse/clickhousedb.py +270 -63
- agno/vectordb/couchbase/couchbase.py +309 -29
- agno/vectordb/lancedb/lance_db.py +360 -21
- agno/vectordb/langchaindb/__init__.py +5 -0
- agno/vectordb/langchaindb/langchaindb.py +145 -0
- agno/vectordb/lightrag/__init__.py +5 -0
- agno/vectordb/lightrag/lightrag.py +374 -0
- agno/vectordb/llamaindex/llamaindexdb.py +127 -0
- agno/vectordb/milvus/milvus.py +242 -32
- agno/vectordb/mongodb/mongodb.py +200 -24
- agno/vectordb/pgvector/pgvector.py +319 -37
- agno/vectordb/pineconedb/pineconedb.py +221 -27
- agno/vectordb/qdrant/qdrant.py +334 -14
- agno/vectordb/singlestore/singlestore.py +286 -29
- agno/vectordb/surrealdb/surrealdb.py +187 -7
- agno/vectordb/upstashdb/upstashdb.py +342 -26
- agno/vectordb/weaviate/weaviate.py +227 -165
- agno/workflow/__init__.py +17 -13
- agno/workflow/{v2/condition.py → condition.py} +135 -32
- agno/workflow/{v2/loop.py → loop.py} +115 -28
- agno/workflow/{v2/parallel.py → parallel.py} +138 -108
- agno/workflow/{v2/router.py → router.py} +133 -32
- agno/workflow/{v2/step.py → step.py} +207 -49
- agno/workflow/{v2/steps.py → steps.py} +147 -66
- agno/workflow/types.py +482 -0
- agno/workflow/workflow.py +2410 -696
- agno-2.0.0.dist-info/METADATA +494 -0
- agno-2.0.0.dist-info/RECORD +515 -0
- agno-2.0.0.dist-info/licenses/LICENSE +201 -0
- agno/agent/metrics.py +0 -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/response.py +0 -467
- agno/run/v2/__init__.py +0 -0
- agno/run/v2/workflow.py +0 -567
- agno/storage/__init__.py +0 -0
- agno/storage/agent/__init__.py +0 -0
- agno/storage/agent/dynamodb.py +0 -1
- agno/storage/agent/json.py +0 -1
- agno/storage/agent/mongodb.py +0 -1
- agno/storage/agent/postgres.py +0 -1
- agno/storage/agent/singlestore.py +0 -1
- agno/storage/agent/sqlite.py +0 -1
- agno/storage/agent/yaml.py +0 -1
- agno/storage/base.py +0 -60
- agno/storage/dynamodb.py +0 -673
- agno/storage/firestore.py +0 -297
- agno/storage/gcs_json.py +0 -261
- agno/storage/in_memory.py +0 -234
- agno/storage/json.py +0 -237
- agno/storage/mongodb.py +0 -328
- agno/storage/mysql.py +0 -685
- agno/storage/postgres.py +0 -682
- agno/storage/redis.py +0 -336
- agno/storage/session/__init__.py +0 -16
- agno/storage/session/agent.py +0 -64
- agno/storage/session/team.py +0 -63
- agno/storage/session/v2/__init__.py +0 -5
- agno/storage/session/workflow.py +0 -61
- agno/storage/singlestore.py +0 -606
- agno/storage/sqlite.py +0 -646
- agno/storage/workflow/__init__.py +0 -0
- agno/storage/workflow/mongodb.py +0 -1
- agno/storage/workflow/postgres.py +0 -1
- agno/storage/workflow/sqlite.py +0 -1
- agno/storage/yaml.py +0 -241
- agno/tools/thinking.py +0 -73
- agno/utils/defaults.py +0 -57
- agno/utils/filesystem.py +0 -39
- agno/utils/git.py +0 -52
- agno/utils/json_io.py +0 -30
- agno/utils/load_env.py +0 -19
- agno/utils/py_io.py +0 -19
- agno/utils/pyproject.py +0 -18
- agno/utils/resource_filter.py +0 -31
- agno/workflow/v2/__init__.py +0 -21
- agno/workflow/v2/types.py +0 -357
- agno/workflow/v2/workflow.py +0 -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-1.8.1.dist-info/licenses/LICENSE +0 -375
- /agno/{app → db/migrations}/__init__.py +0 -0
- /agno/{app/playground/__init__.py → db/schemas/metrics.py} +0 -0
- /agno/{cli → integrations}/__init__.py +0 -0
- /agno/{cli/ws → knowledge/chunking}/__init__.py +0 -0
- /agno/{document/chunking → knowledge/remote_content}/__init__.py +0 -0
- /agno/{document/reader/gcs → knowledge/reranker}/__init__.py +0 -0
- /agno/{document/reader/s3 → os/interfaces}/__init__.py +0 -0
- /agno/{app → os/interfaces}/slack/security.py +0 -0
- /agno/{app → os/interfaces}/whatsapp/security.py +0 -0
- /agno/{file/local → utils/print_response}/__init__.py +0 -0
- /agno/{infra → vectordb/llamaindex}/__init__.py +0 -0
- {agno-1.8.1.dist-info → agno-2.0.0.dist-info}/WHEEL +0 -0
- {agno-1.8.1.dist-info → agno-2.0.0.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,497 @@
|
|
|
1
|
+
from contextlib import asynccontextmanager
|
|
2
|
+
from functools import partial
|
|
3
|
+
from os import getenv
|
|
4
|
+
from typing import Any, Dict, List, Optional, Union
|
|
5
|
+
from uuid import uuid4
|
|
6
|
+
|
|
7
|
+
from fastapi import FastAPI, HTTPException
|
|
8
|
+
from fastapi.responses import JSONResponse
|
|
9
|
+
from rich import box
|
|
10
|
+
from rich.panel import Panel
|
|
11
|
+
from starlette.middleware.cors import CORSMiddleware
|
|
12
|
+
from starlette.requests import Request
|
|
13
|
+
|
|
14
|
+
from agno.agent.agent import Agent
|
|
15
|
+
from agno.os.config import (
|
|
16
|
+
AgentOSConfig,
|
|
17
|
+
DatabaseConfig,
|
|
18
|
+
EvalsConfig,
|
|
19
|
+
EvalsDomainConfig,
|
|
20
|
+
KnowledgeConfig,
|
|
21
|
+
KnowledgeDomainConfig,
|
|
22
|
+
MemoryConfig,
|
|
23
|
+
MemoryDomainConfig,
|
|
24
|
+
MetricsConfig,
|
|
25
|
+
MetricsDomainConfig,
|
|
26
|
+
SessionConfig,
|
|
27
|
+
SessionDomainConfig,
|
|
28
|
+
)
|
|
29
|
+
from agno.os.interfaces.base import BaseInterface
|
|
30
|
+
from agno.os.router import get_base_router
|
|
31
|
+
from agno.os.routers.evals import get_eval_router
|
|
32
|
+
from agno.os.routers.knowledge import get_knowledge_router
|
|
33
|
+
from agno.os.routers.memory import get_memory_router
|
|
34
|
+
from agno.os.routers.metrics import get_metrics_router
|
|
35
|
+
from agno.os.routers.session import get_session_router
|
|
36
|
+
from agno.os.settings import AgnoAPISettings
|
|
37
|
+
from agno.os.utils import generate_id
|
|
38
|
+
from agno.team.team import Team
|
|
39
|
+
from agno.tools.mcp import MCPTools, MultiMCPTools
|
|
40
|
+
from agno.workflow.workflow import Workflow
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@asynccontextmanager
|
|
44
|
+
async def mcp_lifespan(app, mcp_tools: List[Union[MCPTools, MultiMCPTools]]):
|
|
45
|
+
"""Manage MCP connection lifecycle inside a FastAPI app"""
|
|
46
|
+
# Startup logic: connect to all contextual MCP servers
|
|
47
|
+
for tool in mcp_tools:
|
|
48
|
+
await tool.connect()
|
|
49
|
+
|
|
50
|
+
yield
|
|
51
|
+
|
|
52
|
+
# Shutdown logic: Close all contextual MCP connections
|
|
53
|
+
for tool in mcp_tools:
|
|
54
|
+
await tool.close()
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
class AgentOS:
|
|
58
|
+
def __init__(
|
|
59
|
+
self,
|
|
60
|
+
os_id: Optional[str] = None,
|
|
61
|
+
name: Optional[str] = None,
|
|
62
|
+
description: Optional[str] = None,
|
|
63
|
+
version: Optional[str] = None,
|
|
64
|
+
agents: Optional[List[Agent]] = None,
|
|
65
|
+
teams: Optional[List[Team]] = None,
|
|
66
|
+
workflows: Optional[List[Workflow]] = None,
|
|
67
|
+
interfaces: Optional[List[BaseInterface]] = None,
|
|
68
|
+
config: Optional[Union[str, AgentOSConfig]] = None,
|
|
69
|
+
settings: Optional[AgnoAPISettings] = None,
|
|
70
|
+
fastapi_app: Optional[FastAPI] = None,
|
|
71
|
+
lifespan: Optional[Any] = None,
|
|
72
|
+
enable_mcp: bool = False,
|
|
73
|
+
telemetry: bool = True,
|
|
74
|
+
):
|
|
75
|
+
if not agents and not workflows and not teams:
|
|
76
|
+
raise ValueError("Either agents, teams or workflows must be provided.")
|
|
77
|
+
|
|
78
|
+
self.config = self._load_yaml_config(config) if isinstance(config, str) else config
|
|
79
|
+
|
|
80
|
+
self.agents: Optional[List[Agent]] = agents
|
|
81
|
+
self.workflows: Optional[List[Workflow]] = workflows
|
|
82
|
+
self.teams: Optional[List[Team]] = teams
|
|
83
|
+
self.interfaces = interfaces or []
|
|
84
|
+
|
|
85
|
+
self.settings: AgnoAPISettings = settings or AgnoAPISettings()
|
|
86
|
+
|
|
87
|
+
self._app_set = False
|
|
88
|
+
self.fastapi_app: Optional[FastAPI] = None
|
|
89
|
+
if fastapi_app:
|
|
90
|
+
self.fastapi_app = fastapi_app
|
|
91
|
+
self._app_set = True
|
|
92
|
+
|
|
93
|
+
self.interfaces = interfaces or []
|
|
94
|
+
|
|
95
|
+
self.os_id: Optional[str] = os_id
|
|
96
|
+
self.name = name
|
|
97
|
+
self.version = version
|
|
98
|
+
self.description = description
|
|
99
|
+
|
|
100
|
+
self.telemetry = telemetry
|
|
101
|
+
|
|
102
|
+
self.enable_mcp = enable_mcp
|
|
103
|
+
self.lifespan = lifespan
|
|
104
|
+
|
|
105
|
+
# List of all MCP tools used inside the AgentOS
|
|
106
|
+
self.mcp_tools: List[Union[MCPTools, MultiMCPTools]] = []
|
|
107
|
+
|
|
108
|
+
if self.agents:
|
|
109
|
+
for agent in self.agents:
|
|
110
|
+
# Track all MCP tools to later handle their connection
|
|
111
|
+
if agent.tools:
|
|
112
|
+
for tool in agent.tools:
|
|
113
|
+
if isinstance(tool, MCPTools) or isinstance(tool, MultiMCPTools):
|
|
114
|
+
self.mcp_tools.append(tool)
|
|
115
|
+
|
|
116
|
+
agent.initialize_agent()
|
|
117
|
+
|
|
118
|
+
# Required for the built-in routes to work
|
|
119
|
+
agent.store_events = True
|
|
120
|
+
|
|
121
|
+
if self.teams:
|
|
122
|
+
for team in self.teams:
|
|
123
|
+
# Track all MCP tools to later handle their connection
|
|
124
|
+
if team.tools:
|
|
125
|
+
for tool in team.tools:
|
|
126
|
+
if isinstance(tool, MCPTools) or isinstance(tool, MultiMCPTools):
|
|
127
|
+
self.mcp_tools.append(tool)
|
|
128
|
+
|
|
129
|
+
team.initialize_team()
|
|
130
|
+
|
|
131
|
+
# Required for the built-in routes to work
|
|
132
|
+
team.store_events = True
|
|
133
|
+
|
|
134
|
+
for member in team.members:
|
|
135
|
+
if isinstance(member, Agent):
|
|
136
|
+
member.team_id = None
|
|
137
|
+
member.initialize_agent()
|
|
138
|
+
elif isinstance(member, Team):
|
|
139
|
+
member.initialize_team()
|
|
140
|
+
|
|
141
|
+
if self.workflows:
|
|
142
|
+
for workflow in self.workflows:
|
|
143
|
+
# TODO: track MCP tools in workflow members
|
|
144
|
+
if not workflow.id:
|
|
145
|
+
workflow.id = generate_id(workflow.name)
|
|
146
|
+
|
|
147
|
+
if self.telemetry:
|
|
148
|
+
from agno.api.os import OSLaunch, log_os_telemetry
|
|
149
|
+
|
|
150
|
+
log_os_telemetry(launch=OSLaunch(os_id=self.os_id, data=self._get_telemetry_data()))
|
|
151
|
+
|
|
152
|
+
def _make_app(self, lifespan: Optional[Any] = None) -> FastAPI:
|
|
153
|
+
# Adjust the FastAPI app lifespan to handle MCP connections if relevant
|
|
154
|
+
app_lifespan = lifespan
|
|
155
|
+
if self.mcp_tools is not None:
|
|
156
|
+
mcp_tools_lifespan = partial(mcp_lifespan, mcp_tools=self.mcp_tools)
|
|
157
|
+
# If there is already a lifespan, combine it with the MCP lifespan
|
|
158
|
+
if lifespan is not None:
|
|
159
|
+
# Combine both lifespans
|
|
160
|
+
@asynccontextmanager
|
|
161
|
+
async def combined_lifespan(app: FastAPI):
|
|
162
|
+
# Run both lifespans
|
|
163
|
+
async with lifespan(app): # type: ignore
|
|
164
|
+
async with mcp_tools_lifespan(app): # type: ignore
|
|
165
|
+
yield
|
|
166
|
+
|
|
167
|
+
app_lifespan = combined_lifespan # type: ignore
|
|
168
|
+
else:
|
|
169
|
+
app_lifespan = mcp_tools_lifespan
|
|
170
|
+
|
|
171
|
+
return FastAPI(
|
|
172
|
+
title=self.name or "Agno AgentOS",
|
|
173
|
+
version=self.version or "1.0.0",
|
|
174
|
+
description=self.description or "An agent operating system.",
|
|
175
|
+
docs_url="/docs" if self.settings.docs_enabled else None,
|
|
176
|
+
redoc_url="/redoc" if self.settings.docs_enabled else None,
|
|
177
|
+
openapi_url="/openapi.json" if self.settings.docs_enabled else None,
|
|
178
|
+
lifespan=app_lifespan,
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
def get_app(self) -> FastAPI:
|
|
182
|
+
if not self.fastapi_app:
|
|
183
|
+
if self.enable_mcp:
|
|
184
|
+
from contextlib import asynccontextmanager
|
|
185
|
+
|
|
186
|
+
from agno.os.mcp import get_mcp_server
|
|
187
|
+
|
|
188
|
+
self.mcp_app = get_mcp_server(self)
|
|
189
|
+
|
|
190
|
+
final_lifespan = self.mcp_app.lifespan
|
|
191
|
+
if self.lifespan is not None:
|
|
192
|
+
# Combine both lifespans
|
|
193
|
+
@asynccontextmanager
|
|
194
|
+
async def combined_lifespan(app: FastAPI):
|
|
195
|
+
# Run both lifespans
|
|
196
|
+
async with self.lifespan(app): # type: ignore
|
|
197
|
+
async with self.mcp_app.lifespan(app): # type: ignore
|
|
198
|
+
yield
|
|
199
|
+
|
|
200
|
+
final_lifespan = combined_lifespan # type: ignore
|
|
201
|
+
|
|
202
|
+
self.fastapi_app = self._make_app(lifespan=final_lifespan)
|
|
203
|
+
else:
|
|
204
|
+
self.fastapi_app = self._make_app(lifespan=self.lifespan)
|
|
205
|
+
|
|
206
|
+
# Add routes
|
|
207
|
+
self.fastapi_app.include_router(get_base_router(self, settings=self.settings))
|
|
208
|
+
|
|
209
|
+
for interface in self.interfaces:
|
|
210
|
+
interface_router = interface.get_router()
|
|
211
|
+
self.fastapi_app.include_router(interface_router)
|
|
212
|
+
|
|
213
|
+
self._auto_discover_databases()
|
|
214
|
+
self._auto_discover_knowledge_instances()
|
|
215
|
+
self._setup_routers()
|
|
216
|
+
|
|
217
|
+
# Mount MCP if needed
|
|
218
|
+
if self.enable_mcp and self.mcp_app:
|
|
219
|
+
self.fastapi_app.mount("/", self.mcp_app)
|
|
220
|
+
|
|
221
|
+
# Add middleware (only if app is not set)
|
|
222
|
+
if not self._app_set:
|
|
223
|
+
|
|
224
|
+
@self.fastapi_app.exception_handler(HTTPException)
|
|
225
|
+
async def http_exception_handler(request: Request, exc: HTTPException) -> JSONResponse:
|
|
226
|
+
return JSONResponse(
|
|
227
|
+
status_code=exc.status_code,
|
|
228
|
+
content={"detail": str(exc.detail)},
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
async def general_exception_handler(request: Request, call_next):
|
|
232
|
+
try:
|
|
233
|
+
return await call_next(request)
|
|
234
|
+
except Exception as e:
|
|
235
|
+
return JSONResponse(
|
|
236
|
+
status_code=e.status_code if hasattr(e, "status_code") else 500, # type: ignore
|
|
237
|
+
content={"detail": str(e)},
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
self.fastapi_app.middleware("http")(general_exception_handler)
|
|
241
|
+
|
|
242
|
+
self.fastapi_app.add_middleware(
|
|
243
|
+
CORSMiddleware,
|
|
244
|
+
allow_origins=self.settings.cors_origin_list, # type: ignore
|
|
245
|
+
allow_credentials=True,
|
|
246
|
+
allow_methods=["*"],
|
|
247
|
+
allow_headers=["*"],
|
|
248
|
+
expose_headers=["*"],
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
return self.fastapi_app
|
|
252
|
+
|
|
253
|
+
def get_routes(self) -> List[Any]:
|
|
254
|
+
"""Retrieve all routes from the FastAPI app.
|
|
255
|
+
|
|
256
|
+
Returns:
|
|
257
|
+
List[Any]: List of routes included in the FastAPI app.
|
|
258
|
+
"""
|
|
259
|
+
app = self.get_app()
|
|
260
|
+
|
|
261
|
+
return app.routes
|
|
262
|
+
|
|
263
|
+
def _get_telemetry_data(self) -> Dict[str, Any]:
|
|
264
|
+
"""Get the telemetry data for the OS"""
|
|
265
|
+
return {
|
|
266
|
+
"agents": [agent.id for agent in self.agents] if self.agents else None,
|
|
267
|
+
"teams": [team.id for team in self.teams] if self.teams else None,
|
|
268
|
+
"workflows": [workflow.id for workflow in self.workflows] if self.workflows else None,
|
|
269
|
+
"interfaces": [interface.type for interface in self.interfaces] if self.interfaces else None,
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
def _load_yaml_config(self, config_file_path: str) -> AgentOSConfig:
|
|
273
|
+
"""Load a YAML config file and return the configuration as an AgentOSConfig instance."""
|
|
274
|
+
from pathlib import Path
|
|
275
|
+
|
|
276
|
+
import yaml
|
|
277
|
+
|
|
278
|
+
# Validate that the path points to a YAML file
|
|
279
|
+
path = Path(config_file_path)
|
|
280
|
+
if path.suffix.lower() not in [".yaml", ".yml"]:
|
|
281
|
+
raise ValueError(f"Config file must have a .yaml or .yml extension, got: {config_file_path}")
|
|
282
|
+
|
|
283
|
+
# Load the YAML file
|
|
284
|
+
with open(config_file_path, "r") as f:
|
|
285
|
+
return AgentOSConfig.model_validate(yaml.safe_load(f))
|
|
286
|
+
|
|
287
|
+
def _auto_discover_databases(self) -> None:
|
|
288
|
+
"""Auto-discover the databases used by all contextual agents, teams and workflows."""
|
|
289
|
+
dbs = {}
|
|
290
|
+
|
|
291
|
+
for agent in self.agents or []:
|
|
292
|
+
if agent.db:
|
|
293
|
+
dbs[agent.db.id] = agent.db
|
|
294
|
+
if agent.knowledge and agent.knowledge.contents_db:
|
|
295
|
+
dbs[agent.knowledge.contents_db.id] = agent.knowledge.contents_db
|
|
296
|
+
|
|
297
|
+
for team in self.teams or []:
|
|
298
|
+
if team.db:
|
|
299
|
+
dbs[team.db.id] = team.db
|
|
300
|
+
if team.knowledge and team.knowledge.contents_db:
|
|
301
|
+
dbs[team.knowledge.contents_db.id] = team.knowledge.contents_db
|
|
302
|
+
|
|
303
|
+
for workflow in self.workflows or []:
|
|
304
|
+
if workflow.db:
|
|
305
|
+
dbs[workflow.db.id] = workflow.db
|
|
306
|
+
|
|
307
|
+
for interface in self.interfaces or []:
|
|
308
|
+
if interface.agent and interface.agent.db:
|
|
309
|
+
dbs[interface.agent.db.id] = interface.agent.db
|
|
310
|
+
elif interface.team and interface.team.db:
|
|
311
|
+
dbs[interface.team.db.id] = interface.team.db
|
|
312
|
+
|
|
313
|
+
self.dbs = dbs
|
|
314
|
+
|
|
315
|
+
def _auto_discover_knowledge_instances(self) -> None:
|
|
316
|
+
"""Auto-discover the knowledge instances used by all contextual agents, teams and workflows."""
|
|
317
|
+
knowledge_instances = []
|
|
318
|
+
for agent in self.agents or []:
|
|
319
|
+
if agent.knowledge:
|
|
320
|
+
knowledge_instances.append(agent.knowledge)
|
|
321
|
+
|
|
322
|
+
for team in self.teams or []:
|
|
323
|
+
if team.knowledge:
|
|
324
|
+
knowledge_instances.append(team.knowledge)
|
|
325
|
+
|
|
326
|
+
self.knowledge_instances = knowledge_instances
|
|
327
|
+
|
|
328
|
+
def _get_session_config(self) -> SessionConfig:
|
|
329
|
+
session_config = self.config.session if self.config and self.config.session else SessionConfig()
|
|
330
|
+
|
|
331
|
+
if session_config.dbs is None:
|
|
332
|
+
session_config.dbs = []
|
|
333
|
+
|
|
334
|
+
multiple_dbs: bool = len(self.dbs.keys()) > 1
|
|
335
|
+
dbs_with_specific_config = [db.db_id for db in session_config.dbs]
|
|
336
|
+
|
|
337
|
+
for db_id in self.dbs.keys():
|
|
338
|
+
if db_id not in dbs_with_specific_config:
|
|
339
|
+
session_config.dbs.append(
|
|
340
|
+
DatabaseConfig(
|
|
341
|
+
db_id=db_id,
|
|
342
|
+
domain_config=SessionDomainConfig(
|
|
343
|
+
display_name="Sessions" if not multiple_dbs else "Sessions in database '" + db_id + "'"
|
|
344
|
+
),
|
|
345
|
+
)
|
|
346
|
+
)
|
|
347
|
+
|
|
348
|
+
return session_config
|
|
349
|
+
|
|
350
|
+
def _get_memory_config(self) -> MemoryConfig:
|
|
351
|
+
memory_config = self.config.memory if self.config and self.config.memory else MemoryConfig()
|
|
352
|
+
|
|
353
|
+
if memory_config.dbs is None:
|
|
354
|
+
memory_config.dbs = []
|
|
355
|
+
|
|
356
|
+
multiple_dbs: bool = len(self.dbs.keys()) > 1
|
|
357
|
+
dbs_with_specific_config = [db.db_id for db in memory_config.dbs]
|
|
358
|
+
|
|
359
|
+
for db_id in self.dbs.keys():
|
|
360
|
+
if db_id not in dbs_with_specific_config:
|
|
361
|
+
memory_config.dbs.append(
|
|
362
|
+
DatabaseConfig(
|
|
363
|
+
db_id=db_id,
|
|
364
|
+
domain_config=MemoryDomainConfig(
|
|
365
|
+
display_name="Memory" if not multiple_dbs else "Memory in database '" + db_id + "'"
|
|
366
|
+
),
|
|
367
|
+
)
|
|
368
|
+
)
|
|
369
|
+
|
|
370
|
+
return memory_config
|
|
371
|
+
|
|
372
|
+
def _get_knowledge_config(self) -> KnowledgeConfig:
|
|
373
|
+
knowledge_config = self.config.knowledge if self.config and self.config.knowledge else KnowledgeConfig()
|
|
374
|
+
|
|
375
|
+
if knowledge_config.dbs is None:
|
|
376
|
+
knowledge_config.dbs = []
|
|
377
|
+
|
|
378
|
+
multiple_dbs: bool = len(self.dbs.keys()) > 1
|
|
379
|
+
dbs_with_specific_config = [db.db_id for db in knowledge_config.dbs]
|
|
380
|
+
|
|
381
|
+
for db_id in self.dbs.keys():
|
|
382
|
+
if db_id not in dbs_with_specific_config:
|
|
383
|
+
knowledge_config.dbs.append(
|
|
384
|
+
DatabaseConfig(
|
|
385
|
+
db_id=db_id,
|
|
386
|
+
domain_config=KnowledgeDomainConfig(
|
|
387
|
+
display_name="Knowledge" if not multiple_dbs else "Knowledge in database " + db_id
|
|
388
|
+
),
|
|
389
|
+
)
|
|
390
|
+
)
|
|
391
|
+
|
|
392
|
+
return knowledge_config
|
|
393
|
+
|
|
394
|
+
def _get_metrics_config(self) -> MetricsConfig:
|
|
395
|
+
metrics_config = self.config.metrics if self.config and self.config.metrics else MetricsConfig()
|
|
396
|
+
|
|
397
|
+
if metrics_config.dbs is None:
|
|
398
|
+
metrics_config.dbs = []
|
|
399
|
+
|
|
400
|
+
multiple_dbs: bool = len(self.dbs.keys()) > 1
|
|
401
|
+
dbs_with_specific_config = [db.db_id for db in metrics_config.dbs]
|
|
402
|
+
|
|
403
|
+
for db_id in self.dbs.keys():
|
|
404
|
+
if db_id not in dbs_with_specific_config:
|
|
405
|
+
metrics_config.dbs.append(
|
|
406
|
+
DatabaseConfig(
|
|
407
|
+
db_id=db_id,
|
|
408
|
+
domain_config=MetricsDomainConfig(
|
|
409
|
+
display_name="Metrics" if not multiple_dbs else "Metrics in database '" + db_id + "'"
|
|
410
|
+
),
|
|
411
|
+
)
|
|
412
|
+
)
|
|
413
|
+
|
|
414
|
+
return metrics_config
|
|
415
|
+
|
|
416
|
+
def _get_evals_config(self) -> EvalsConfig:
|
|
417
|
+
evals_config = self.config.evals if self.config and self.config.evals else EvalsConfig()
|
|
418
|
+
|
|
419
|
+
if evals_config.dbs is None:
|
|
420
|
+
evals_config.dbs = []
|
|
421
|
+
|
|
422
|
+
multiple_dbs: bool = len(self.dbs.keys()) > 1
|
|
423
|
+
dbs_with_specific_config = [db.db_id for db in evals_config.dbs]
|
|
424
|
+
|
|
425
|
+
for db_id in self.dbs.keys():
|
|
426
|
+
if db_id not in dbs_with_specific_config:
|
|
427
|
+
evals_config.dbs.append(
|
|
428
|
+
DatabaseConfig(
|
|
429
|
+
db_id=db_id,
|
|
430
|
+
domain_config=EvalsDomainConfig(
|
|
431
|
+
display_name="Evals" if not multiple_dbs else "Evals in database '" + db_id + "'"
|
|
432
|
+
),
|
|
433
|
+
)
|
|
434
|
+
)
|
|
435
|
+
|
|
436
|
+
return evals_config
|
|
437
|
+
|
|
438
|
+
def _setup_routers(self) -> None:
|
|
439
|
+
"""Add all routers to the FastAPI app."""
|
|
440
|
+
if not self.dbs or not self.fastapi_app:
|
|
441
|
+
return
|
|
442
|
+
|
|
443
|
+
routers = [
|
|
444
|
+
get_session_router(dbs=self.dbs),
|
|
445
|
+
get_memory_router(dbs=self.dbs),
|
|
446
|
+
get_eval_router(dbs=self.dbs, agents=self.agents, teams=self.teams),
|
|
447
|
+
get_metrics_router(dbs=self.dbs),
|
|
448
|
+
get_knowledge_router(knowledge_instances=self.knowledge_instances),
|
|
449
|
+
]
|
|
450
|
+
|
|
451
|
+
for router in routers:
|
|
452
|
+
self.fastapi_app.include_router(router)
|
|
453
|
+
|
|
454
|
+
def set_os_id(self) -> str:
|
|
455
|
+
# If os_id is already set, keep it instead of overriding with UUID
|
|
456
|
+
if self.os_id is None:
|
|
457
|
+
self.os_id = str(uuid4())
|
|
458
|
+
|
|
459
|
+
return self.os_id
|
|
460
|
+
|
|
461
|
+
def serve(
|
|
462
|
+
self,
|
|
463
|
+
app: Union[str, FastAPI],
|
|
464
|
+
*,
|
|
465
|
+
host: str = "localhost",
|
|
466
|
+
port: int = 7777,
|
|
467
|
+
reload: bool = False,
|
|
468
|
+
workers: Optional[int] = None,
|
|
469
|
+
**kwargs,
|
|
470
|
+
):
|
|
471
|
+
import uvicorn
|
|
472
|
+
|
|
473
|
+
if getenv("AGNO_API_RUNTIME", "").lower() == "stg":
|
|
474
|
+
public_endpoint = "https://os-stg.agno.com/"
|
|
475
|
+
else:
|
|
476
|
+
public_endpoint = "https://os.agno.com/"
|
|
477
|
+
|
|
478
|
+
# Create a terminal panel to announce OS initialization and provide useful info
|
|
479
|
+
from rich.align import Align
|
|
480
|
+
from rich.console import Console, Group
|
|
481
|
+
|
|
482
|
+
aligned_endpoint = Align.center(f"[bold cyan]{public_endpoint}[/bold cyan]")
|
|
483
|
+
connection_endpoint = f"\n\n[bold dark_orange]Running on:[/bold dark_orange] http://{host}:{port}"
|
|
484
|
+
|
|
485
|
+
console = Console()
|
|
486
|
+
console.print(
|
|
487
|
+
Panel(
|
|
488
|
+
Group(aligned_endpoint, connection_endpoint),
|
|
489
|
+
title="AgentOS",
|
|
490
|
+
expand=False,
|
|
491
|
+
border_style="dark_orange",
|
|
492
|
+
box=box.DOUBLE_EDGE,
|
|
493
|
+
padding=(2, 2),
|
|
494
|
+
)
|
|
495
|
+
)
|
|
496
|
+
|
|
497
|
+
uvicorn.run(app=app, host=host, port=port, reload=reload, workers=workers, **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
|