Defines coding conventions, error handling patterns, async practices, logging standards, API response formats, and testing workflows for the Order Service — a FastAPI/Python microservice. Covers typed exception classes with FastAPI exception handler registration, structlog structured logging, Pydantic request/response models, and pytest-asyncio endpoint tests. Use when writing or modifying order endpoints, implementing order processing logic, adding error handling, or working with any file matching app/**/*.py or tests/**/*.py in the Order Service.
87%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Passed
No findings from the security scan
app/
main.py - FastAPI app, exception handlers
orders.py - Order endpoints
models.py - Pydantic request/response models
tests/
conftest.py - Shared fixtures (client, sample_order)
test_*.py - Async endpoint testsUse typed exception classes. Never use bare try/except at the endpoint level.
Define exceptions per domain:
class OrderNotFoundError(Exception):
def __init__(self, order_id: str):
self.order_id = order_id
super().__init__(f"Order {order_id} not found")Register exception handlers on the FastAPI app in main.py:
from fastapi.responses import JSONResponse
@app.exception_handler(OrderNotFoundError)
async def handle_order_not_found(request, exc):
return JSONResponse(
status_code=404,
content={
"error": "OrderNotFound",
"order_id": exc.order_id,
"message": str(exc),
},
)In endpoints, raise the exception and let the handler deal with it:
if order_id not in _orders:
raise OrderNotFoundError(order_id){
"error": "ErrorTypeName",
"order_id": "the-resource-id",
"message": "Human-readable description"
}All endpoint handlers are async. All I/O operations use async/await. Never use synchronous blocking calls inside an endpoint.
External service calls (database, third-party APIs) must be awaited.
Use structlog for all logging. Never use print().
import structlog
logger = structlog.get_logger()
logger.info("order_confirmed", order_id=order_id)
logger.error("order_not_found", order_id=order_id)All successful mutation endpoints return the resource ID and new status:
return {"order_id": order_id, "status": "confirmed"}Include additional fields when the endpoint triggers side effects.
pytest with pytest-asyncio (asyncio_mode = auto)httpx.AsyncClient with ASGITransport for endpoint testsclient and sample_order fixtures from conftest.pyunittest.mock.AsyncMockclient and sample_order fixtures from conftest.py.AsyncMock before invoking the endpoint.AsyncClient.AsyncMock vs MagicMock), then re-run until all assertions pass.Run tests:
python -m pytest tests/ -vArchitectural decisions are stored in .memory/decisions/:
.memory/decisions/
YYYY-MM-DD-short-description.mdEach file:
# Decision: [short title]
Date: YYYY-MM-DD
Status: accepted
## Context
[Why this decision was needed]
## Decision
[What was decided]
## Consequences
[What this means for the codebase]jbaruch/qcon-london-2026-300-tokens
b4eb766
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.