π€ AI Agent Quick Reference GuideΒΆ
Fast-track guide for AI agents to understand and work with the Neuroglia Python Framework
Read This First
Before using this guide, review the Documentation Philosophy to understand how to interpret patterns, evaluate trade-offs, and adapt examples to specific contexts. This is a toolbox, not a rulebook.
π― Framework OverviewΒΆ
Neuroglia is a clean architecture Python framework built on FastAPI that enforces separation of concerns, CQRS, dependency injection, and event-driven patterns for maintainable microservices.
ποΈ Core ArchitectureΒΆ
src/
βββ api/ # π Controllers, DTOs, Routes (FastAPI)
βββ application/ # πΌ Commands, Queries, Handlers, Services
βββ domain/ # ποΈ Entities, Value Objects, Business Rules
βββ integration/ # π Repositories, External APIs, Infrastructure
Dependency Rule: API β Application β Domain β Integration
β‘ Quick Start PatternsΒΆ
1. CQRS Command/Query PatternΒΆ
# Commands (Write operations)
@dataclass
class CreateOrderCommand(Command[Order]):
customer_id: str
items: List[OrderItemDto]
class CreateOrderHandler(CommandHandler[CreateOrderCommand, Order]):
async def handle_async(self, command: CreateOrderCommand) -> Order:
# Business logic here
return order
# Queries (Read operations)
@dataclass
class GetOrderQuery(Query[Optional[Order]]):
order_id: str
class GetOrderHandler(QueryHandler[GetOrderQuery, Optional[Order]]):
async def handle_async(self, query: GetOrderQuery) -> Optional[Order]:
return await self.repository.get_by_id_async(query.order_id)
2. API Controllers (FastAPI Integration)ΒΆ
from neuroglia.mvc import ControllerBase
from classy_fastapi.decorators import get, post
class OrdersController(ControllerBase):
@post("/", response_model=OrderDto, status_code=201)
async def create_order(self, dto: CreateOrderDto) -> OrderDto:
command = self.mapper.map(dto, CreateOrderCommand)
order = await self.mediator.execute_async(command)
return self.mapper.map(order, OrderDto)
@get("/{order_id}", response_model=OrderDto)
async def get_order(self, order_id: str) -> OrderDto:
query = GetOrderQuery(order_id=order_id)
order = await self.mediator.execute_async(query)
return self.mapper.map(order, OrderDto)
3. Repository PatternΒΆ
# Abstract repository
class OrderRepository(Repository[Order, str]):
async def get_by_customer_async(self, customer_id: str) -> List[Order]:
pass
# MongoDB implementation
class MongoOrderRepository(MongoRepository[Order, str]):
async def get_by_customer_async(self, customer_id: str) -> List[Order]:
cursor = self.collection.find({"customer_id": customer_id})
return [self._to_entity(doc) async for doc in cursor]
4. Dependency Injection & Application SetupΒΆ
from neuroglia.hosting.web import WebApplicationBuilder
from neuroglia.mediation import Mediator
from neuroglia.mapping import Mapper
def create_app():
builder = WebApplicationBuilder()
# Configure core services
Mediator.configure(builder, ["application.commands", "application.queries"])
Mapper.configure(builder, ["application.mapping", "api.dtos", "domain.entities"])
# Register custom services
builder.services.add_scoped(OrderRepository, MongoOrderRepository)
# Add SubApp with controllers
builder.add_sub_app(
SubAppConfig(
path="/api",
name="api",
controllers=["api.controllers"]
)
)
app = builder.build()
return app
5. Observability with OpenTelemetryΒΆ
from neuroglia.observability import configure_opentelemetry, get_tracer, trace_async
# Configure OpenTelemetry (in main.py)
configure_opentelemetry(
service_name="mario-pizzeria",
service_version="1.0.0",
otlp_endpoint="http://localhost:4317"
)
# Use in handlers
tracer = get_tracer(__name__)
class PlaceOrderHandler(CommandHandler):
@trace_async(name="place_order")
async def handle_async(self, command: PlaceOrderCommand):
with tracer.start_as_current_span("validate_order"):
# Business logic with automatic tracing
pass
6. Role-Based Access Control (RBAC)ΒΆ
from fastapi import Depends
from fastapi.security import HTTPBearer
security = HTTPBearer()
class OrdersController(ControllerBase):
@post("/", response_model=OrderDto)
async def create_order(
self,
dto: CreateOrderDto,
credentials: HTTPAuthorizationCredentials = Depends(security)
) -> OrderDto:
# Extract user info from JWT
user_info = self._decode_jwt(credentials.credentials)
# Pass to handler for RBAC check
command = CreateOrderCommand(
customer_id=dto.customer_id,
items=dto.items,
user_info=user_info # Handler checks roles/permissions
)
result = await self.mediator.execute_async(command)
return self.process(result)
# RBAC in handler (application layer)
class CreateOrderHandler(CommandHandler):
async def handle_async(self, command: CreateOrderCommand):
# Authorization check based on roles
if "customer" not in command.user_info.get("roles", []):
return self.forbidden("Insufficient permissions")
# Business logic
order = Order(command.customer_id, command.items)
await self.repository.save_async(order)
return self.created(order)
π§© Framework Modules ReferenceΒΆ
| Module | Purpose | Key Classes |
|---|---|---|
neuroglia.core |
Base types, utilities | OperationResult, Entity, ValueObject |
neuroglia.dependency_injection |
DI container | ServiceCollection, ServiceProvider, ServiceLifetime |
neuroglia.mediation |
CQRS patterns | Mediator, Command, Query, CommandHandler, QueryHandler |
neuroglia.mvc |
FastAPI controllers | ControllerBase, auto-discovery |
neuroglia.data |
Repository & persistence | Repository, MongoRepository, InMemoryRepository, EventStore |
neuroglia.data.resources |
Resource management | ResourceController, ResourceWatcher, Reconciler |
neuroglia.eventing |
Event handling | DomainEvent, EventHandler, EventBus |
neuroglia.eventing.cloud_events |
CloudEvents integration | CloudEvent, CloudEventPublisher, CloudEventIngestor |
neuroglia.mapping |
Object mapping | Mapper, convention-based mapping |
neuroglia.hosting |
App lifecycle | WebApplicationBuilder, WebApplication, HostedService |
neuroglia.serialization |
JSON/data serialization | JsonSerializer, JsonEncoder, TypeRegistry |
neuroglia.validation |
Business rule validation | BusinessRule, ValidationResult, PropertyValidator, EntityValidator |
neuroglia.reactive |
Reactive programming | Observable, Observer (RxPy integration) |
neuroglia.integration |
External services | HttpServiceClient, CacheRepository, BackgroundTaskScheduler |
neuroglia.utils |
Utility functions | CaseConversion, CamelModel, TypeFinder |
neuroglia.expressions |
Expression evaluation | JavaScriptExpressionTranslator |
neuroglia.observability |
OpenTelemetry integration | Tracing, metrics, logging with OTLP exporters |
π Sample ApplicationsΒΆ
The framework includes complete sample applications that demonstrate real-world usage:
π Mario's Pizzeria (samples/mario-pizzeria/)ΒΆ
- Full CQRS implementation with sophisticated domain models
- MongoDB repositories for orders, customers, pizzas
- Event-driven architecture with domain events
- Complete API with OpenAPI documentation
- OpenTelemetry observability with distributed tracing, metrics, and logging
Key Files:
domain/entities/:Order,Pizza,Customerwith business logicapplication/commands/:PlaceOrderCommand,CreatePizzaCommandapplication/queries/:GetOrderByIdQuery,GetMenuItemsQueryapi/controllers/:OrdersController,MenuController
π¦ OpenBank (samples/openbank/)ΒΆ
- Event sourcing with KurrentDB (EventStoreDB)
- CQRS with separate read/write models
- Complex domain modeling (accounts, transactions, persons)
- Banking business rules and validation
- Read model projections and eventual consistency
- Snapshot strategies for performance
π¨ Simple UI (samples/simple-ui/)ΒΆ
- SubApp pattern for UI/API separation
- Stateless JWT authentication without server-side sessions
- Role-Based Access Control (RBAC) at query/command level
- Bootstrap 5 frontend with Parcel bundler
- Clean separation of concerns between UI and API
ποΈ Desktop Controller (samples/desktop-controller/)ΒΆ
- Background services and scheduled tasks
- System integration patterns
- Resource management examples
π§ͺ Lab Resource Manager (samples/lab-resource-manager/)ΒΆ
- Resource-Oriented Architecture (ROA)
- Watcher/Controller patterns (like Kubernetes operators)
- Reconciliation loops for resource management
π API Gateway (samples/api-gateway/)ΒΆ
- Microservice gateway patterns
- AI/ML integration examples
- Service orchestration and routing
- Background task processing with Redis
π Where to Find InformationΒΆ
π Documentation Structure (docs/)ΒΆ
| Section | Purpose | Key Files |
|---|---|---|
getting-started.md |
Framework introduction | Quick start, core concepts |
features/ |
Feature documentation | One file per major feature |
patterns/ |
Architecture patterns | CQRS, Clean Architecture, Event Sourcing |
samples/ |
Sample walkthroughs | Detailed sample explanations |
references/ |
Technical references | Python best practices, 12-Factor App |
guides/ |
Step-by-step tutorials | Mario's Pizzeria tutorial |
π― Key Documentation FilesΒΆ
- Getting Started - Framework overview and quick start
- Mario's Pizzeria Tutorial - Complete walkthrough
- CQRS & Mediation - Command/Query patterns
- MVC Controllers - FastAPI controller patterns
- Data Access - Repository and persistence
- Dependency Injection - DI container usage
- Observability - OpenTelemetry tracing, metrics, logging
- RBAC & Authorization - Role-based access control patterns
- OpenTelemetry Integration - Infrastructure setup guide
- Python Typing Guide - Type hints & generics
π Additional ResourcesΒΆ
README.md- Project overview and installationpyproject.toml- Dependencies and build configurationsrc/neuroglia/- Complete framework source codetests/- Comprehensive test suite with examples
π‘ Common Patterns & Best PracticesΒΆ
β Do ThisΒΆ
# β
Use constructor injection
class OrderService:
def __init__(self, repository: OrderRepository, event_bus: EventBus):
self.repository = repository
self.event_bus = event_bus
# β
Separate commands and queries
class PlaceOrderCommand(Command[Order]): pass
class GetOrderQuery(Query[Optional[Order]]): pass
# β
Use domain events
class Order(Entity):
def place_order(self):
# Business logic
self.raise_event(OrderPlacedEvent(order_id=self.id))
# β
Type hints everywhere
async def handle_async(self, command: PlaceOrderCommand) -> Order:
return order
β Avoid ThisΒΆ
# β Direct database access in controllers
class OrderController:
def create_order(self):
# Don't access database directly
connection.execute("INSERT INTO...")
# β Mixing concerns
class OrderHandler:
def handle(self, command):
# Don't mix business logic with infrastructure
send_email() # Infrastructure concern
# β Missing type hints
def process_order(order): # What type is order?
return result # What type is result?
π Quick CommandsΒΆ
# Install framework (when available)
pip install neuroglia
# Run sample applications
cd samples/mario-pizzeria && python main.py
cd samples/openbank && python main.py
# Run tests
pytest tests/
# Generate documentation
mkdocs serve
# CLI tool (when available)
pyneuroctl --help
pyneuroctl samples list
pyneuroctl new myapp --template minimal
π― For AI Agents: Key TakeawaysΒΆ
- Architecture: Clean Architecture with strict dependency rules
- Patterns: CQRS, DI, Repository, Domain Events are core
- Code Style: Heavy use of type hints, dataclasses, async/await
- Framework Integration: Built on FastAPI, uses Pydantic extensively
- Sample Code: Always reference
samples/mario-pizzeria/for real examples - Documentation: Comprehensive docs in
docs/with practical examples - Testing: Full test coverage with patterns for all architectural layers
- Observability: OpenTelemetry integration for distributed tracing, metrics, and logging
- Security: RBAC patterns with JWT authentication at application layer
- Event Sourcing: Full support with KurrentDB (EventStoreDB) in OpenBank sample
When writing Neuroglia code:
- Follow the layered architecture strictly
- Use CQRS for all business operations
- Leverage dependency injection throughout
- Include comprehensive type hints
- Reference Mario's Pizzeria sample for patterns
- Maintain separation of concerns between layers
- Implement observability with OpenTelemetry decorators
- Handle authorization in handlers (application layer), not controllers
- Use SubApp pattern for clean UI/API separation
π€ Quick Framework Setup for AI AgentsΒΆ
# Minimal Neuroglia application setup
from neuroglia.hosting.web import WebApplicationBuilder
from neuroglia.mediation import Mediator
from neuroglia.mapping import Mapper
def create_app():
builder = WebApplicationBuilder()
# Configure essential services
Mediator.configure(builder, ["application.commands", "application.queries"])
Mapper.configure(builder, ["application.mapping", "api.dtos"])
# Add SubApp with controllers
builder.add_sub_app(
SubAppConfig(
path="/api",
name="api",
controllers=["api.controllers"]
)
)
# Build application
app = builder.build()
return app
if __name__ == "__main__":
app = create_app()
app.run()
Need more detail? Start with Getting Started then dive into specific feature documentation or explore the Mario's Pizzeria sample.