| name | phoenix-server |
| user-invocable | false |
| description | Backend development guide for the Phoenix AI observability platform (Strawberry GraphQL, SQLAlchemy async, FastAPI). Use this skill when writing or modifying Python server code in the phoenix repo — adding mutations, types, migrations, or tests. Trigger on any backend task touching src/phoenix/server/, src/phoenix/db/, or tests/unit/server/.
|
| metadata | {"internal":true} |
Phoenix Backend Development
Phoenix is an AI observability platform. The backend is Python: FastAPI serving a REST API and Strawberry
GraphQL API over an async SQLAlchemy ORM (PostgreSQL + SQLite).
Development Guide Index
Read DEVELOPMENT.md (env setup, uv, tests, debugpy, pre-commit, REST API conventions) and CONTRIBUTING.md (PR format, conventional commits, code review expectations) if you have not already.
Everyday Commands
make dev-backend
uv run pytest path/to/test -n auto
make test-python
make graphql
make format
make typecheck-python
Key Directories
src/phoenix/server/api/
mutations/ Domain-specific mutation mixins, composed in __init__.py
types/ GraphQL types with field resolvers
input_types/ Strawberry @input classes with validation
subscriptions.py Async generator subscriptions (streaming)
queries.py Root query type
context.py Request context: db, dataloaders, auth, event queue
dataloaders/ Batch loaders (prevent N+1 queries)
auth.py Permission classes (IsNotReadOnly, IsNotViewer, etc.)
routers/ REST API endpoints (v1/)
src/phoenix/db/
models.py SQLAlchemy ORM models (single file)
migrations/ Alembic migrations
tests/unit/server/api/
mutations/ Mutation tests
types/ Type resolver tests
conftest.py Fixtures: db, gql_client, test data factories
What Are You Doing?
| Task | Reference |
|---|
| Adding or modifying a mutation, type, subscription, or input | references/graphql-patterns.md |
| Writing or modifying tests | references/test-patterns.md |
| Writing tests for code that emits OpenInference spans (VCR cassettes, span attribute assertions) | references/llm-trace-tests.md |
| Adding a migration or modifying database models | references/database-patterns.md |
Hard Rules
- Side effects belong on
Mutation, not Query. A resolver that makes outbound
network calls, reads secrets, writes state, or accepts a user-supplied URL/host
MUST be a @strawberry.mutation with permission_classes=[...]. Query fields
bypass the make check-graphql-permissions CI guard and are reachable
unauthenticated by default — this has been exploited as an SSRF vector. See
references/graphql-patterns.md → "Query vs Mutation".
Naming
- Avoid acronyms and single/double-letter abbreviations for local variables.
Prefer the full noun:
session / project_session over ps, trace over t,
example / dataset_example over de. The cost of a longer identifier is trivial; the
cost of having to mentally expand an acronym while reading unfamiliar code is
not.
- Established domain acronyms used in the codebase (
db, gql, otel, llm)
are fine — they're vocabulary, not abbreviations of local nouns.
Docstrings
The project rule of "default to no comments" is about inline comments, not
docstrings. Public APIs should be documented.
- Document parameters and return values on public methods of reusable classes
(clients, services, factories, builders). Use Google-style
Args: / Returns:
/ Raises: blocks when the meaning isn't fully recoverable from the type
signature. Do not strip these during refactors — semantics outlive file moves.
- Describe behavior, not implementation. A method on a docs-search client
says "Invoke a backend tool and return its text result", not "Invoke a tool
on the MCP server" — the underlying transport is an implementation detail and
the docstring should survive a transport swap. Internal helpers (leading
_)
may reference the transport directly since their scope is bounded.
- One-liner docstrings are fine when the name and types fully convey intent
(
close(), is_backend_tool(name)). Don't pad them with restated signatures.
- Module docstrings belong at the top of any file that exposes public
surface (a client class, a router, a service module). One sentence on what
the module is for is enough.