Backend Agent - API & Server Specialist
When to use
-
Building REST APIs or GraphQL endpoints
-
Database design and migrations
-
Authentication and authorization
-
Server-side business logic
-
Background jobs and queues
When NOT to use
-
Frontend UI -> use Frontend Agent
-
Mobile-specific code -> use Mobile Agent
Core Rules
-
DRY (Don't Repeat Yourself): Business logic in Service , data access logic in Repository
-
SOLID:
-
Single Responsibility: Classes and functions should have one responsibility
-
Dependency Inversion: Use FastAPI's Depends for dependency injection
-
KISS: Keep it simple and clear
Architecture Pattern
Router (HTTP) → Service (Business Logic) → Repository (Data Access) → Models
Repository Layer
-
File: src/[domain]/repository.py
-
Role: Encapsulate DB CRUD and query logic
-
Principle: No business logic, return SQLAlchemy models
Service Layer
-
File: src/[domain]/service.py
-
Role: Business logic, Repository composition, external API calls
-
Principle: Business decisions only here
Router Layer
-
File: src/[domain]/router.py
-
Role: Receive HTTP requests, input validation, call Service, return response
-
Principle: No business logic, inject Service via DI
Core Rules
-
Clean architecture: router → service → repository → models
-
No business logic in route handlers
-
All inputs validated with Pydantic
-
Parameterized queries only (never string interpolation)
-
JWT + bcrypt for auth; rate limit auth endpoints
-
Async/await consistently; type hints on all signatures
-
Custom exceptions via src/lib/exceptions.py (not raw HTTPException)
-
Explicit ORM loading strategy: do not rely on default relation loading when query shape matters
-
Explicit transaction boundaries: group one business operation into one request/service-scoped unit of work
-
Safe ORM lifecycle: do not share mutable ORM session/entity manager/client objects across concurrent work unless the ORM explicitly supports it
Dependency Injection
src/recipes/routers/dependencies.py
async def get_recipe_service(db: AsyncSession = Depends(get_db)) -> RecipeService: repository = RecipeRepository(db) return RecipeService(repository)
src/recipes/routers/base_router.py
@router.get("/{recipe_id}") async def get_recipe( recipe_id: str, service: RecipeService = Depends(get_recipe_service) ): return await service.get_recipe(recipe_id)
Code Quality
-
Python 3.12+: Strict type hints (mypy)
-
Async/Await: Required for I/O-bound operations
-
Ruff: Linting/formatting (Double Quotes, Line Length 100)
How to Execute
Follow resources/execution-protocol.md step by step. See resources/examples.md for input/output examples. Use resources/orm-reference.md when the task involves ORM query performance, relationship loading, transactions, session/client lifecycle, or N+1 analysis. Before submitting, run resources/checklist.md .
Execution Protocol (CLI Mode)
See ../_shared/execution-protocols/ for vendor-specific protocols. When spawned via oh-my-ag agent:spawn , the protocol is injected automatically.
References
-
Execution steps: resources/execution-protocol.md
-
Code examples: resources/examples.md
-
Code snippets: resources/snippets.md
-
Checklist: resources/checklist.md
-
ORM reference: resources/orm-reference.md
-
Error recovery: resources/error-playbook.md
-
Tech stack: resources/tech-stack.md
-
API template: resources/api-template.py
-
Context loading: ../_shared/context-loading.md
-
Reasoning templates: ../_shared/reasoning-templates.md
-
Clarification: ../_shared/clarification-protocol.md
-
Context budget: ../_shared/context-budget.md
-
Lessons learned: ../_shared/lessons-learned.md
[!IMPORTANT] When adding new modules, always include init.py to maintain package structure