[build-system] requires = ["hatchling"] build-backend = "hatchling.build" [project] name = "camel-ai" version = "0.2.91a7" description = "Communicative Agents for AI Society Study" authors = [{ name = "CAMEL-AI.org" }] requires-python = ">=3.10,<3.15" readme = "README.md" license = "Apache-2.0" keywords = [ "communicative-ai", "ai-societies", "artificial-intelligence", "deep-learning", "multi-agent-systems", "cooperative-ai", "natural-language-processing", "large-language-models", ] dependencies = [ "mcp>=1.3.0,<2", "tiktoken>=0.7.0,<=0.12", "colorama>=0.4.6,<0.5", "jsonschema>=4,<5", "docstring-parser>=0.17.0,<0.18", "pydantic>=2.10.6,<=2.12.0", "httpx>=0.28.0,<1.0.0dev", "psutil>=5.9.8,<6", "openai>=1.86.0,<3", "websockets>=13.0,<15.1", "astor>=0.8.1", "pillow>=10.0.0", "google-search-results>=2.4.2", "pyyaml>=6.0.3", ] [tool.uv] upgrade = false [project.dependency-groups] test = ["pytest>=7,<8", "mock>=5,<6", "pytest-asyncio>=0.23.0,<0.24"] [project.optional-dependencies] dev = [ "ruff>=0.7,<0.8", "mypy>=1.5.1,<2", "toml>=0.10.2", "pre-commit>=3,<4", "pytest>=7,<8", "pytest-cov>=4,<5", "pytest-asyncio>=0.23.0,<0.24", "setuptools>=78.1.1,<79", "gradio>=3,<4", "mock>=5,<6", "types-colorama>=0.4.15,<0.5", "types-PyYAML>=6.0.12,<7", "types-mock>=5.1.0,<6", "types-tqdm>=4.66.0,<5", "types-requests>=2.31.0,<3", "types-setuptools>=75.8.0,<76", "uv>=0.7.0,<0.8", "Flask>=2.0", ] docs = [ "sphinx>=7,<8", "sphinx_book_theme", "docutils<0.20.0", "myst-parser", "nbsphinx", "sphinxext-rediraffe>=0.2.7,<0.3", ] rag = [ "numpy>=1.2,<=2.2", "qdrant-client>=1.9.0,<2", "pymilvus>=2.4.0,<3", "pytidb>=0.0.13", "faiss-cpu>=1.7.2,<2", "weaviate-client>=4.15.0", "protobuf>=6.0.0", "grpcio>=1.72.0", "neo4j>=5.18.0,<6", "nebula3-python==3.8.2", "rank-bm25>=0.2.2,<0.3", "cohere>=5.11.0,<6", "unstructured==0.16.20; python_version < '3.13'", "crawl4ai>=0.3.745", "pyobvector>=0.2.22; python_version < '3.13'", "sqlglot>=26.0.1,<30; python_version < '3.13'", "google-genai>=1.13.0", "chunkr-ai>=0.0.50, <0.1.0", "chromadb>=0.6.0,<1.0.0", ] web_tools = [ "ddgs>=9.0.0,<10", "wikipedia>=1,<2", "firecrawl-py>=4.0.0,<5", "apify_client>=1.8.1,<2", "linkup-sdk>=0.2.1,<0.3", "wolframalpha>=5.0.0,<6", "tavily-python>=0.5.0,<0.6", "dappier>=0.3.3,<0.4", "pyowm>=3.3.0,<4", "googlemaps>=4.10.0,<5", "requests_oauthlib>=1.3.1,<2", "google-api-python-client==2.166.0", "google-auth>=2.0.0,<3.0.0", "google-auth-httplib2==0.2.0", "google-auth-oauthlib==1.2.1", "sympy>=1.13.3,<2", "fastapi>=0.115.11", "playwright>=1.50.0", "html2text>=2024.2.26", "beautifulsoup4>=4,<5", "exa-py>=1.10.0,<2", "scrapegraph-py>=1.12.0,<2", "websockets>=13.0,<15.1", ] document_tools = [ "numpy>=1.2,<=2.2", "beautifulsoup4>=4,<5", "docx2txt>=0.8,<0.9", "PyMuPDF>=1.22.5,<2", "unstructured==0.16.20; python_version < '3.13'", "prance>=23.6.21.0,<24", "openapi-spec-validator>=0.7.1,<0.8", "xls2xlsx>=0.2.0", "tabulate>=0.9.0", "openpyxl>=3.1.5", "docx>=0.2.4", "crawl4ai>=0.3.745", "markitdown>=0.1.1; python_version >= '3.13'", "pylatex>=1.4.2", "chunkr-ai>=0.0.50, <0.1.0", "python-pptx>=1.0.2", "reportlab>=4.4.2", "onnxruntime<=1.19.2", ] media_tools = [ "imageio[pyav]>=2.34.2,<3", "pydub>=0.25.1,<0.26", "yt-dlp>=2024.11.4,<2025", "ffmpeg-python>=0.2.0,<0.3", "scenedetect>=0.6.5.2", "pytesseract>=0.3.13", "av<16", "twelvelabs>=1.2.8,<2", ] communication_tools = [ "slack-sdk>=3.27.2,<4", "slack-bolt>=1.20.1,<2", "pygithub>=2.6.0,<3", "pyTelegramBotAPI>=4.18.0,<5", "discord.py>=2.3.2,<3", "notion-client>=2.2.1,<3", "praw>=7.7.1,<8", "resend>=2.0.0,<3", "plivo>=4.61.0,<5", "azure-identity>=1.25.1,<2", "msgraph-sdk>=1.46.0,<2", "msal>=1.34.0,<2" ] data_tools = [ "datacommons-client[pandas]>=2.1.5", "numpy>=1.2,<=2.2", "pandas>=2", "textblob>=0.17.1,<0.18", "rouge>=1.0.1,<2", "aiosqlite>=0.20.0,<0.21", "stripe>=11.3.0,<12", "networkx>=3.4.2,<4", "math-verify>=0.7.0,<0.8", ] research_tools = [ "arxiv>=2.1.3,<3", "arxiv2text>=0.1.14,<0.2", "scholarly[tor]==1.7.11", ] dev_tools = [ "docker>=7.1.0,<8", "jupyter_client>=8.6.2,<9", "ipykernel>=6.0.0,<7", "agentops>=0.3.21,<0.4", "e2b-code-interpreter>=1.0.3,<2", "microsandbox>=0.1.8,<0.2", "tree-sitter-python>=0.23.6,<0.24", "tree-sitter>=0.23.2,<0.24", "typer>=0.15.2", "mcp>=1.3.0,<2", "daytona-sdk>=0.20.0", "aci-sdk>=1.0.0b1", "langfuse>=2.60.5", ] model_platforms = [ "litellm>=1.38.1,<1.80.12", "mistralai>=1.1.0,<2", "reka-api>=3.0.8,<4", "anthropic>=0.89.0,<0.90.0", "cohere>=5.11.0,<6", "fish-audio-sdk>=1.0.0", "ibm-watsonx-ai>=1.3.11", "boto3>=1.42.64", "xai_sdk>=1.11.0", ] huggingface = [ "transformers>=5,<6", "diffusers>=0.38.0", "datasets>=3,<4", "soundfile>=0.13,<0.14", "safetensors>=0.8.0rc0", "sentencepiece>=0.2,<0.3", "huggingface-hub>=1.0", ] storage = [ "qdrant-client>=1.9.0,<2", "pymilvus>=2.4.0,<3", "pytidb>=0.0.13", "faiss-cpu>=1.7.2,<2", "neo4j>=5.18.0,<6", "nebula3-python==3.8.2", "redis>=5.0.6,<6", "azure-storage-blob>=12.21.0,<13", "google-cloud-storage>=2.18.0,<3", "boto3>=1.42.64", "mem0ai>=0.1.73", "pyobvector>=0.2.22; python_version < '3.13'", "sqlglot>=26.0.1,<30; python_version < '3.13'", "weaviate-client>=4.15.0", "protobuf>=6.0.0", "grpcio>=1.72.0", "psycopg[binary]>=3.1.18,<4", "pgvector>=0.2.4,<0.3", "surrealdb>=1.0.6", "chromadb>=0.6.0,<1.0.0", "duckdb>=1.4.3", ] owl = [ "numpy>=1.2,<=2.2", "chunkr-ai>=0.0.41", "mcp-simple-arxiv==0.2.2", "mcp-server-fetch==2025.1.17", "python-dotenv>=1.0.0,<2", "transformers>=5,<6", "sentencepiece>=0.2,<0.3", "anthropic>=0.89.0,<0.90.0", "datasets>=3,<4", "soundfile>=0.13,<0.14", "pydub>=0.25.1,<0.26", "ffmpeg-python>=0.2.0,<0.3", "imageio[pyav]>=2.34.2,<3", "yt-dlp>=2024.11.4,<2025", "scenedetect>=0.6.5.2", "twelvelabs>=1.2.8,<2", "beautifulsoup4>=4,<5", "docx2txt>=0.8,<0.9", "PyMuPDF>=1.22.5,<2", "unstructured==0.16.20; python_version < '3.13'", "prance>=23.6.21.0,<24", "openapi-spec-validator>=0.7.1,<0.8", "xls2xlsx>=0.2.0", "tabulate>=0.9.0", "openpyxl>=3.1.5", "docx>=0.2.4", "ddgs>=9.0.0,<10", "wikipedia>=1,<2", "playwright>=1.50.0", "html2text>=2024.2.26", "requests_oauthlib>=1.3.1,<2", "websockets>=13.0,<15.1", "e2b-code-interpreter>=1.0.3,<2", "typer>=0.15.2", "tree-sitter-python>=0.23.6,<0.24", "tree-sitter>=0.23.2,<0.24", "pandas>=2", "rouge>=1.0.1,<2", "crawl4ai>=0.3.745", "scrapegraph-py>=1.12.0,<2", "pyautogui>=0.9.54,<0.10", "aci-sdk>=1.0.0b1", "pylatex>=1.4.2", "chunkr-ai>=0.0.50, <0.1.0", "python-pptx>=1.0.2", "pytesseract>=0.3.13", "markitdown>=0.1.1; python_version >= '3.13'", "exa-py>=1.10.0,<2", "reportlab>=4.4.2", "onnxruntime<=1.19.2", "av<16", ] eigent = [ "numpy>=1.2,<=2.2", "mcp-simple-arxiv==0.2.2", "mcp-server-fetch==2025.1.17", "python-dotenv>=1.0.0,<2", "anthropic>=0.89.0,<0.90.0", "datasets>=3,<4", "pydub>=0.25.1,<0.26", "ffmpeg-python>=0.2.0,<0.3", "imageio[pyav]>=2.34.2,<3", "yt-dlp>=2024.11.4,<2025", "scenedetect>=0.6.5.2", "xls2xlsx>=0.2.0", "tabulate>=0.9.0", "openpyxl>=3.1.5", "docx>=0.2.4", "wikipedia>=1,<2", "requests_oauthlib>=1.3.1,<2", "websockets>=13.0,<15.1", "pandas>=2", "pylatex>=1.4.2", "python-pptx>=1.0.2", "pytesseract>=0.3.13", "markitdown[all]>=0.1.1; python_version < '3.13'", "markitdown>=0.1.1; python_version >= '3.13'", "exa-py>=1.10.0,<2", "reportlab>=4.4.2", "onnxruntime<=1.19.2", "slack-sdk>=3.27.2,<4", "google-api-python-client==2.166.0", "google-auth-httplib2==0.2.0", "google-auth-oauthlib==1.2.1", "httplib2>=0.31.0", "av<16", "mistralai>=1.1.0,<2", "boto3>=1.42.64", ] all = [ "numpy>=1.2,<=2.2", "transformers>=5,<6", "diffusers>=0.38.0", "datasets>=3,<4", "soundfile>=0.13,<0.14", "safetensors>=0.8.0rc0", "sentencepiece>=0.2,<0.3", "beautifulsoup4>=4,<5", "docx2txt>=0.8,<0.9", "PyMuPDF>=1.22.5,<2", "unstructured==0.16.20; python_version < '3.13'", "wikipedia>=1,<2", "linkup-sdk>=0.2.1,<0.3", "ddgs>=9.0.0,<10", "wolframalpha>=5.0.0,<6", "sympy>=1.13.3,<2", "pyowm>=3.3.0,<4", "googlemaps>=4.10.0,<5", "google-api-python-client==2.166.0", "google-auth>=2.0.0,<3.0.0", "google-auth-httplib2==0.2.0", "google-auth-oauthlib==1.2.1", "requests_oauthlib>=1.3.1,<2", "fastapi>=0.115.11", "prance>=23.6.21.0,<24", "openapi-spec-validator>=0.7.1,<0.8", "rouge>=1.0.1,<2", "aiosqlite>=0.20.0,<0.21", "e2b-code-interpreter>=1.0.3,<2", "microsandbox>=0.1.8,<0.2", "firecrawl-py>=4.0.0,<5", "arxiv>=2.1.3,<3", "arxiv2text>=0.1.14,<0.2", "imageio[pyav]>=2.34.2,<3", "slack-sdk>=3.27.2,<4", "slack-bolt>=1.20.1,<2", "pydub>=0.25.1,<0.26", "pygithub>=2.6.0,<3", "pyTelegramBotAPI>=4.18.0,<5", "discord.py>=2.3.2,<3", "docker>=7.1.0,<8", "jupyter_client>=8.6.2,<9", "ipykernel>=6.0.0,<7", "agentops>=0.3.21,<0.4", "praw>=7.7.1,<8", "resend>=2.0.0,<3", "plivo>=4.61.0,<5", "azure-identity>=1.25.1,<2", "msgraph-sdk>=1.46.0,<2", "msal>=1.34.0,<2", "textblob>=0.17.1,<0.18", "scholarly[tor]==1.7.11", "notion-client>=2.2.1,<3", "yt-dlp>=2024.11.4,<2025", "ffmpeg-python>=0.2.0,<0.3", "datacommons-client[pandas]>=2.1.5", "tavily-python>=0.5.0,<0.6", "apify_client>=1.8.1,<2", "stripe>=11.3.0,<12", "pandas>=2", "tree-sitter-python>=0.23.6,<0.24", "tree-sitter>=0.23.2,<0.24", "networkx>=3.4.2,<4", "qdrant-client>=1.9.0,<2", "pymilvus>=2.4.0,<3", "pytidb>=0.0.13", "faiss-cpu>=1.7.2,<2", "cohere>=5.11.0,<6", "neo4j>=5.18.0,<6", "markitdown>=0.1.1; python_version >= '3.13'", "nebula3-python==3.8.2", "rank-bm25>=0.2.2,<0.3", "litellm>=1.38.1,<1.80.12", "mistralai>=1.1.0,<2", "fish-audio-sdk>=1.0.0", "anthropic>=0.89.0,<0.90.0", "reka-api>=3.0.8,<4", "redis>=5.0.6,<6", "azure-storage-blob>=12.21.0,<13", "google-cloud-storage>=2.18.0,<3", "boto3>=1.42.64", "dappier>=0.3.3,<0.4", "mypy>=1.5.1,<2", "pre-commit>=3,<4", "types-colorama>=0.4.15,<0.5", "types-PyYAML>=6.0.12,<7", "types-mock>=5.1.0,<6", "types-tqdm>=4.66.0,<5", "types-requests>=2.31.0,<3", "types-setuptools>=75.8.0,<76", "pytest>=7,<8", "pytest-cov>=4,<5", "pytest-asyncio>=0.23.0,<0.24", "setuptools>=78.1.1,<79", "gradio>=3,<4", "mock>=5,<6", "xls2xlsx>=0.2.0", "tabulate>=0.9.0", "openpyxl>=3.1.5", "scenedetect>=0.6.5.2", "twelvelabs>=1.2.8,<2", "playwright>=1.50.0", "html2text>=2024.2.26", "docx>=0.2.4", "websockets>=13.0,<15.1", "mcp>=1.3.0,<2", "typer>=0.15.2", "mem0ai>=0.1.67", "math-verify>=0.7.0,<0.8", "exa-py>=1.10.0,<2", "crawl4ai>=0.4.0", "pyautogui>=0.9.54,<0.10", "pyobvector>=0.2.22; python_version < '3.13'", "sqlglot>=26.0.1,<30; python_version < '3.13'", "scrapegraph-py>=1.12.0,<2", "daytona-sdk>=0.20.0", "ibm-watsonx-ai>=1.3.11", "google-genai>=1.13.0", "aci-sdk>=1.0.0b1", "pylatex>=1.4.2", "chunkr-ai>=0.0.50, <0.1.0", "weaviate-client>=4.15.0", "protobuf>=6.0.0", "grpcio>=1.72.0", "python-pptx>=1.0.2", "langfuse>=2.60.5", "Flask>=2.0", "rlcard>=1.0.0,<1.3.0", "pytesseract>=0.3.13", "psycopg[binary]>=3.1.18,<4", "pgvector>=0.2.4,<0.3", "surrealdb>=1.0.6", "chromadb>=0.6.0,<1.0.0", "reportlab>=4.4.2", "onnxruntime<=1.19.2", "google-cloud-aiplatform>=1.111.0", "httplib2>=0.31.0", "duckdb>=1.4.3", "opencv-python>=4.11.0.86", "rasterio>=1.4.4", "ruptures>=1.1.10", "scikit-image>=0.25.2", "scipy>=1.15.3", "statsmodels>=0.14.6", "av<16", "xai_sdk>=1.11.0", ] earth-science = [ "numpy>=1.2,<=2.2", "pandas>=2", "matplotlib>=3.10.7", "opencv-python>=4.11.0.86", "rasterio>=1.4.4", "ruptures>=1.1.10", "scikit-image>=0.25.2", "scipy>=1.15.3", "statsmodels>=0.14.6", # Note: GDAL/osgeo requires system-level installation # Install via: brew install gdal (macOS) or apt-get install gdal-bin libgdal-dev (Linux) # Then: pip install gdal==$(gdal-config --version) ] [project.urls] Homepage = "https://www.camel-ai.org/" Repository = "https://github.com/camel-ai/camel" Documentation = "https://docs.camel-ai.org" [tool.hatch.build.targets.sdist] include = [ "camel", "camel/toolkits/hybrid_browser_toolkit/ts/package.json", "camel/toolkits/hybrid_browser_toolkit/ts/package-lock.json", "camel/toolkits/hybrid_browser_toolkit/ts/tsconfig.json", "camel/toolkits/hybrid_browser_toolkit/ts/src/**/*", "camel/toolkits/hybrid_browser_toolkit/ts/websocket-server.js", ] exclude = ["camel/toolkits/hybrid_browser_toolkit/ts/node_modules/**/*"] [tool.hatch.build.targets.wheel] include = [ "camel", "camel/toolkits/hybrid_browser_toolkit/ts/package.json", "camel/toolkits/hybrid_browser_toolkit/ts/package-lock.json", "camel/toolkits/hybrid_browser_toolkit/ts/tsconfig.json", "camel/toolkits/hybrid_browser_toolkit/ts/src/**/*", "camel/toolkits/hybrid_browser_toolkit/ts/dist/**/*", "camel/toolkits/hybrid_browser_toolkit/ts/websocket-server.js", ] exclude = ["camel/toolkits/hybrid_browser_toolkit/ts/node_modules/**/*"] [tool.hatch.metadata] allow-direct-references = true [tool.ruff] line-length = 79 fix = true target-version = "py310" [tool.ruff.format] quote-style = "preserve" [tool.ruff.lint] extend-select = [ "I", # isort "B", # flake8-bugbear "C4", # flake8-comprehensions "PGH", # pygrep-hooks "RUF", # ruff "E", ] ignore = [ "B028", # Warning without stacklevel "B904", # use 'raise ... from err' "B905", # use explicit 'strict=' parameter with 'zip()' "N818", # Exception name should be named with an Error suffix "C416", # I think comprehension is more clear https://docs.astral.sh/ruff/rules/unnecessary-comprehension/ "C408", # we have used lots of dict(...) instead of literal ] [tool.ruff.lint.pydocstyle] convention = "google" [tool.ruff.lint.isort] known-first-party = ["camel"] [tool.ruff.lint.per-file-ignores] "camel/toolkits/search_toolkit.py" = ["E501"] [tool.pytest.ini_options] pythonpath = ["."] addopts = ["--strict-markers"] markers = [ "asyncio: mark a test as asyncio-based.", "very_slow: mark a very slow test to run only in full test mode", "model_backend: for tests that require OpenAI API key or a local LLM", "heavy_dependency: mark a test as requiring heavy optional dependencies", ] [tool.coverage.report] include_namespace_packages = true [tool.mypy] exclude = [ '\.venv/.*', # exclude .venv directory 'site-packages/.*', # exclude site-packages ] [[tool.mypy.overrides]] module = [ "transformers.*", "packaging.*", "tiktoken", "openai", "openai.error", "anthropic", "pytest", "psutil", "_pytest.config", "_pytest.nodes", "numpy", "sqlalchemy", "google.cloud.sql.connector", "gradio", "database_connection", "huggingface_hub", "huggingface_hub.utils._errors", "huggingface_hub.errors", "wikipedia", "linkup-sdk", "ddgs", "newspaper", "wolframalpha", "pyowm", "googlemaps", "requests_oauthlib", "fastapi", "prance", "xls2xlsx", "tabulate", "openpyxl", "openapi-spec-validator", "jsonschema.*", "bs4.*", "docx2txt", "PyMuPDF", "fitz", "qdrant_client.*", "unstructured.*", "rouge", "aiosqlite", "e2b_code_interpreter", "firecrawl", "imageio", "rank_bm25", "cohere", "fish_audio_sdk", "pymilvus", "pytidb.schema", "faiss", "pillow", "slack-sdk", "slack-bolt", "pydub", "pygithub", "litellm", "pyTelegramBotAPI", "dappier", "discord.py", "docker.*", "google.*", "google_generativeai", "google_auth_oauthlib.flow", "googleapiclient.discovery", "mistralai.*", "cohere", "fish-audio-sdk", "reka-api", "agentops", "boto3", "boto3.*", "botocore", "botocore.*", "arxiv", "arxiv2text", "praw", "resend", "plivo", "textblob", "tavily-python", "scholarly", "notion-client", "ffmpeg", "yt_dlp", "datasets", "datacommons_client", "pandas", "tree-sitter-python", "tree-sitter", "networkx", "sklearn.metrics.pairwise", "sympy.*", "astor", "tqdm", "colorama", "yaml", "mock", "uvicorn", "xls2xlsx", "tabulate", "openpyxl", "scenedetect", "scenedetect.detectors", "twelvelabs", "twelvelabs.*", "playwright", "html2text", "docx", "reportlab", "mcp", "typer", "mem0", "math_verify.*", "exa_py", "crawl4ai.*", "pyautogui", "pyobvector.*", "daytona_sdk", "scrapegraph_py.*", "ibm_watsonx_ai.*", "google_genai", "aci-sdk.*", "pylatex.*", "bohrium.*", "chunkr_ai.*", "langfuse.*", "outlines.*", "torch.*", "cv2", "matplotlib.*", "rasterio", "rasterio.*", "ruptures", "osgeo", "osgeo.*", "scipy.*", "skimage.*", "statsmodels.*", "rlcard.*", "pytesseract", "psycopg.*", "pgvecto.*", "pgvector.*", "reportlab.*", "surrealdb.*", "microsandbox.*", "sentence_transformers.*", "markitdown", "httplib2", "serpapi.*", "xai_sdk", ] ignore_missing_imports = true [tool.codespell] # Ref: https://github.com/codespell-project/codespell#using-a-config-file # the .py file needs to be listed twice since pre-commit and codespell treat # that path differently. skip = '.git*,*.pdf,*.svg,*.lock,*.css,examples/toolkits/semantic_scholar_toolkit.py,./examples/toolkits/semantic_scholar_toolkit.py' check-hidden = true # Ignore long lines as usually some kind of base64 encodings e.g. in ipynb ignore-regex = '^\s*"image/\S+": ".*|^.{300,}|\b(NotIn|Unsupport)\b' ignore-words-list = 'ans,datas,rouge,doubleClick,OCE,ACI,aci,Pinter,SoM,SOM,checkin,ND,'