一键导入
ai-server
// Conventions for the opentrons-ai-server FastAPI service — project structure, uv dependency management, settings, testing, Docker, and deployment. Use when working with files in opentrons-ai-server/ or discussing the AI server API.
// Conventions for the opentrons-ai-server FastAPI service — project structure, uv dependency management, settings, testing, Docker, and deployment. Use when working with files in opentrons-ai-server/ or discussing the AI server API.
| name | ai-server |
| description | Conventions for the opentrons-ai-server FastAPI service — project structure, uv dependency management, settings, testing, Docker, and deployment. Use when working with files in opentrons-ai-server/ or discussing the AI server API. |
opentrons-ai-server is a standalone FastAPI service for Opentrons AI — protocol generation, chat completions, and related AI features. It is not part of the monorepo build system; it has its own dependency management, CI workflows, and deployment pipeline.
Deployed environments: staging (staging.opentrons.ai) and prod (ai.opentrons.com), running on AWS ECS Fargate behind CloudFront.
The server exposes four chat endpoints that return JSON responses:
| Endpoint | Purpose |
|---|---|
POST /api/chat/completion | General chat (no file attachments) |
POST /api/chat/completion-multipart | Chat with file attachments (multipart form) |
POST /api/chat/create-protocol | Generate a new protocol |
POST /api/chat/update-protocol | Update an existing protocol |
All endpoints require a Bearer token in Authorization. Setting "fake": true in the request body bypasses the LLM and returns a canned response from api/domain/fake_responses.py — useful for local development without Anthropic API calls.
This project uses uv for Python dependency management (not pipenv, pip-tools, or poetry).
| File | Role | Committed? |
|---|---|---|
pyproject.toml | Single source of truth for dependencies AND all tool config | Yes |
uv.lock | Locked dependency graph | Yes |
requirements.txt | Generated pip-format file for Docker builds | No (gitignored) |
.venv/ | Local virtual environment created by uv sync | No (gitignored) |
make setup # Install all deps (uv sync --frozen)
uv add <package> # Add production dep
uv add --dev <package> # Add dev-only dep
uv remove <package> # Remove dep
uv lock # Re-resolve after manual pyproject.toml edits
uv run <command> # Run inside the managed venv
After changing deps, commit both pyproject.toml and uv.lock.
opentrons-ai-server/
├── api/ # Application source code
│ ├── handler/ # FastAPI app, routes, middleware (fast.py entrypoint)
│ ├── domain/ # Business logic — LLM prediction (Anthropic, OpenAI)
│ ├── models/ # Pydantic request/response models
│ ├── services/ # File processing and other services
│ ├── integration/ # External integrations (Auth0, Google Sheets, AWS)
│ ├── constants/ # Shared constants
│ ├── data/ # Static data files
│ ├── storage/ # Stored API docs, indexes
│ ├── utils/ # Markdown conversion, index creation
│ └── settings.py # Pydantic Settings — all env vars and secrets
├── tests/
│ ├── conftest.py # Pytest fixtures and --env option
│ ├── helpers/ # Client, token helpers for live testing
│ └── test\_\*.py # Unit and live tests
├── deploy.py # ECS Fargate deployment script
├── Dockerfile
├── Makefile
├── pyproject.toml
└── uv.lock
All runtime configuration lives in api/settings.py via pydantic-settings:
.env file (gitignored)deploy.pySettings classSecretStr type; non-secret vars are plain strings with defaultsget_settings() singleton (not Settings() directly) to avoid re-parsing .env on every importNotable settings:
allowed_origins — comma-separated CORS origins (must be explicit; wildcard * is invalid with allow_credentials=True)request_timeout_seconds — request timeout in seconds (default "300"); production proxies must be configured to allow at least this durationanthropic_max_tokens — stored as a string, cast to int when usedGenerate a template .env from defaults: make gen-env
All config is in pyproject.toml — no separate config files:
| Tool | Section | Purpose |
|---|---|---|
| ruff | [tool.ruff], [tool.ruff.lint], [tool.ruff.format] | Linting AND formatting |
| mypy | [tool.mypy], [[tool.mypy.overrides]] | Strict type checking with pydantic plugin |
| pytest | [tool.pytest.ini_options] | Test runner config, markers: unit, live |
Line length: 140. Target: Python 3.12. Mypy is in strict mode.
All targets run from opentrons-ai-server/.
| Target | Description |
|---|---|
make setup | Install all deps (uv sync --frozen --extra dev) |
make teardown | Delete .venv/ |
make format | Auto-fix lint + format with ruff, then prettier for .md/.json |
make lint | Check lint (ruff) + type check (mypy) — no auto-fix |
make prep | format then lint then unit-test |
make unit-test | Run unit tests (pytest tests -m unit) |
| Target | Description |
|---|---|
make local-run | Run FastAPI with uvicorn (hot reload, no Docker) |
make build | Generate requirements.txt, build Docker image |
make run | Run the Docker container (requires .env file) |
make rebuild | clean + build + run |
make live-test | Run live tests against a running server (ENV=local default) |
make live-client | Interactive client for testing the API |
| Target | Description |
|---|---|
make gen-requirements | Export uv.lock to requirements.txt (production deps only) |
make deploy ENV=staging | Build, push to ECR, update ECS service |
make dry-deploy ENV=staging | Retrieve AWS data but make no changes |
make build-only ENV=staging | Build Docker image only, no push/deploy |
The container does not use uv internally:
make build calls make gen-requirements → uv export --no-hashes --no-dev -o requirements.txtpipapi/ source and Opentrons API docsuvicorn api.handler.fast:app (3 workers, port 8000)Docker build context is the repo root (not opentrons-ai-server/) so the Dockerfile can copy api/docs/v2 from the sibling api/ package.
@pytest.mark.unit): run offline → make unit-test@pytest.mark.live): run against a real server → make live-test ENV=local--env pytest option selects the target environment (local/staging/prod)tests/helpers/ handle Auth0 token caching and HTTP client setupAuth0 JWT verification via api/integration/auth.py. Config: auth0_domain, auth0_api_audience, auth0_issuer, auth0_algorithms in Settings.
make format to auto-fixapi/models/)structlogI rule (isort-compatible)Settings class in api/settings.py (use SecretStr for secrets).env fileCSS Modules conventions, Stylelint rules, design tokens (spacing, colors, typography, border-radius), and patterns for the Opentrons monorepo. Use when working with .module.css files or styling React components in app/, components/, protocol-visualization/, protocol-designer/, or other JS packages.
Conventions for the analyses snapshot testing framework in analyses-snapshot-testing/. Use when working with protocol analysis snapshots, adding protocols, updating snapshots, or running snapshot tests.
Vite demo and Playwright + Applitools tests for packed @opentrons JS packages in js-package-testing/. Covers components, shared-data, step-generation, and protocol-visualization. Use for integration testing, package linking, or visual testing.
TypeScript conventions, React patterns, testing, styling, and import rules for the Opentrons monorepo JS/TS packages. Use when working with TypeScript or React files in app/, components/, shared-data/, step-generation/, protocol-designer/, protocol-visualization/, opentrons-ai-client/, or other JS/TS packages.
Protocol Designer (PD) application architecture, Redux slices, step/timeline system, domain concepts, and dev workflow. Use when working with files in protocol-designer/ or discussing PD features, steps, timelines, or protocol design.
Component creation checklist and ai-client-specific patterns for React .tsx files in opentrons-ai-client/ and protocol-designer/. Use when creating new React components in these packages.