[project] name = "letta" version = "0.16.5" description = "Create LLM agents with long-term memory and custom tools" authors = [ {name = "Letta Team", email = "contact@letta.com"}, ] license = {text = "Apache License"} readme = "README.md" requires-python = "<3.14,>=3.11" dependencies = [ "typer>=0.15.2", "questionary>=2.0.1", "pytz>=2023.3.post1", "tqdm>=4.66.1", "black[jupyter]>=24.2.0", "setuptools>=70", "prettytable>=3.9.0", "docstring-parser>=0.16,<0.17", "httpx>=0.28.0", "numpy>=2.1.0", "demjson3>=3.0.6", "pyyaml>=6.0.1", "sqlalchemy-json>=0.7.0", "pydantic>=2.10.6", "html2text>=2020.1.16", "sqlalchemy[asyncio]>=2.0.41", "python-box>=7.1.1", "sqlmodel>=0.0.16", "python-multipart>=0.0.19", "sqlalchemy-utils>=0.41.2", "pydantic-settings>=2.2.1", "httpx-sse>=0.4.0", "nltk>=3.8.1", "alembic>=1.13.3", "pyhumps>=3.8.0", "pathvalidate>=3.2.1", "sentry-sdk[fastapi]==2.19.1", "rich>=13.9.4", "brotli>=1.1.0", "grpcio>=1.68.1", "grpcio-tools>=1.68.1", "llama-index>=0.12.2", "llama-index-embeddings-openai>=0.3.1", "anthropic>=0.75.0", "letta-client>=1.6.3", "openai>=2.11.0", "opentelemetry-api==1.30.0", "opentelemetry-sdk==1.30.0", "opentelemetry-instrumentation-requests==0.51b0", "opentelemetry-instrumentation-sqlalchemy==0.51b0", "opentelemetry-exporter-otlp==1.30.0", "faker>=36.1.0", "colorama>=0.4.6", "marshmallow-sqlalchemy>=1.4.1", "datamodel-code-generator[http]>=0.25.0", "mcp[cli]>=1.9.4", "exa-py>=1.15.4", "apscheduler>=3.11.0", "aiomultiprocess>=0.9.1", "matplotlib>=3.10.1", "tavily-python>=0.7.2", "temporalio>=1.8.0", "mistralai>=1.8.1", "structlog>=25.4.0", "certifi>=2025.6.15", "markitdown[docx,pdf,pptx]>=0.1.2", "orjson>=3.11.1", "ruff>=0.12.10", "ty>=0.0.17", "trafilatura", "readability-lxml", "google-genai>=1.52.0", "datadog>=0.49.1", "psutil>=5.9.0", "fastmcp>=2.12.5", "ddtrace>=4.2.1", "clickhouse-connect>=0.10.0", "aiofiles>=24.1.0", "async-lru>=2.0.5", ] [project.scripts] letta = "letta.main:app" [project.optional-dependencies] # ====== Databases ====== postgres = [ "pgvector>=0.2.3", "pg8000>=1.30.3", "psycopg2-binary>=2.9.10", "psycopg2>=2.9.10", "asyncpg>=0.30.0", ] redis = ["redis>=6.2.0"] pinecone = ["pinecone[asyncio]>=7.3.0"] sqlite = ["aiosqlite>=0.21.0", "sqlite-vec>=0.1.7a2"] # ====== Server ====== experimental = [ "uvloop>=0.21.0", "granian[uvloop,reload]>=2.3.2", ] server = [ "websockets", "fastapi>=0.115.6", "uvicorn==0.29.0", ] # ====== LLM Providers ====== bedrock = [ "boto3>=1.36.24", "aioboto3>=14.3.0", ] # ====== Development ====== dev = [ "pytest", "pytest-asyncio>=0.24.0", "pytest-order>=1.2.0", "pytest-mock>=3.14.0", "pytest-json-report>=1.5.0", "pexpect>=4.9.0", "pre-commit>=3.5.0", "pyright>=1.1.347", "ipykernel>=6.29.5", "ipdb>=0.13.13", ] # ====== Other ====== cloud-tool-sandbox = ["e2b-code-interpreter>=1.0.3"] # TODO: make this more explicitly e2b modal = ["modal>=1.1.0"] external-tools = [ "docker>=7.1.0", "langchain>=0.3.7", "wikipedia>=1.4.0", "langchain-community>=0.3.7", "exa-py>=1.15.4", "turbopuffer>=0.5.17", ] desktop = [ "websockets", "fastapi>=0.115.6", "uvicorn==0.29.0", "docker>=7.1.0", "langchain>=0.3.7", "wikipedia>=1.4.0", "langchain-community>=0.3.7", "locust>=2.31.5", "aiosqlite>=0.21.0", "sqlite-vec>=0.1.7a2", "pgvector>=0.2.3", "tiktoken>=0.11.0", "async-lru>=2.0.5", "magika>=0.6.2", #"pgserver>=0.1.4", ] profiling = [ "ddtrace>=4.2.1", ] [build-system] requires = ["hatchling"] build-backend = "hatchling.build" [tool.hatch.build.targets.wheel] packages = ["letta"] [tool.ruff] line-length = 140 target-version = "py312" extend-exclude = [ "examples/*", "tests/data/*", ] [tool.ruff.lint] select = [ "E", # pycodestyle errors "W", # pycodestyle warnings "F", # pyflakes "I", # isort "RUF", # ruff "FAST", # fastapi ] ignore = [ "E402", # module level import not at top of file "E501", # line too long (handled by formatter) "E711", # comparison to None (SQLAlchemy requires ==) "E712", # comparison to True/False (SQLAlchemy requires ==) "FAST002", # FastAPI dependency without Annotated (large migration) "RUF001", # ambiguous unicode character in string "RUF002", # ambiguous unicode character in docstring "RUF003", # ambiguous unicode character in comment "RUF010", # explicit conversion flag in f-string ] [tool.ty.rules] all = "ignore" unresolved-reference = "error" unresolved-import = "ignore" [tool.ty.src] exclude = ["examples/", "tests/data/"] [tool.ty.analysis] allowed-unresolved-imports = [ "letta_client.**", "cowsay", "transformers", "core.utils", "core.menu", "some_nonexistent_package", ] [tool.ruff.lint.isort] force-single-line = false combine-as-imports = true split-on-trailing-comma = true [tool.ruff.format] quote-style = "double" indent-style = "space" skip-magic-trailing-comma = false line-ending = "auto" [tool.pytest.ini_options] asyncio_mode = "auto"