Component Playbook
Use this when deciding which Akka SDK component to create and how to keep it clean.
Decision Table
| Need | Prefer | Clean-Code Rule |
|---|---|---|
| Public JSON API | HTTP endpoint | Endpoint translates; domain decides |
| Durable state by id | Key Value Entity | State is immutable and has an explicit empty state |
| Auditable state history | Event Sourced Entity | Events are business facts with stable type names |
| Long-running process | Workflow | Steps are named business transitions |
| Query by attributes | View | Model the read access pattern explicitly |
| External event ingestion | Consumer | Handler is idempotent |
| Scheduled action | Timer | Time is part of the business model |
| LLM-backed reasoning | Agent | Non-determinism is isolated and evaluated |
HTTP Endpoints
Clean endpoint checklist:
- Route path is named after a resource or business action.
- ACL/auth decision is visible at the class or method boundary.
- Request DTOs are public contracts, not entity state.
- Endpoint calls one application-level operation per route.
- Expected failures are translated into public errors.
- No durable state is stored in endpoint fields.
Bad endpoint names:
@HttpEndpoint("/api")
class ApiEndpoint {}Good endpoint names:
@HttpEndpoint("/carts")
class ShoppingCartEndpoint {}Entities
Clean entity checklist:
@Component(id = "...")is stable and business-named.emptyState()exists for key value entities.- State records are immutable.
- Command names are verbs in the business language.
- Read-only handlers use read-only effects.
- Domain calculations are delegated to domain objects.
- External side effects are deliberate and protected from duplicate execution.
Entity smell:
public Effect<Done> update(UpdateCommand command)Better:
public Effect<Done> reserveInventory(ReserveInventory command)Event Sourced Entities
Clean event checklist:
- Events are facts that already happened.
- Event names are past tense:
OrderPaid,InventoryReserved. - Event payloads are minimal but sufficient to rebuild state.
- Type names are stable.
- Command validation happens before events are persisted.
- Event handlers are deterministic and side-effect free.
Bad event:
record UpdateOrder(String field, String value) implements OrderEvent {}Good events:
record ShippingAddressChanged(Address address) implements OrderEvent {}
record OrderPaid(PaymentReference paymentReference) implements OrderEvent {}Workflows
Clean workflow checklist:
- Workflow id maps to one business process instance.
- Steps are named after business transitions.
- State records what operators need to understand progress.
- Waiting states are explicit.
- Timeouts and retries are part of the design.
- Compensation is modeled, not hidden in catch blocks.
- Human intervention paths are command handlers with clear guards.
Workflow smell:
private StepEffect step2() { ... }Better:
@StepName("capture-payment")
private StepEffect capturePayment(CapturePayment input) { ... }Views
Clean view checklist:
- View name describes the query:
orders-by-customer. - Query method names describe the access pattern.
- Row model is a projection, not a leaked aggregate unless deliberate.
- The endpoint using the view documents eventual consistency when relevant.
- Incompatible query or table changes are treated as migrations.
Consumers
Clean consumer checklist:
- Message source is obvious from the annotation and class name.
- Handler is idempotent.
- Poison-message behavior is explicit.
- External side effects can survive retries.
- Business correlation ids are logged.
Agents
Clean agent checklist:
- Agent role is narrow.
- Prompt construction is named and tested where possible.
- Tool calls are explicit and bounded.
- Session memory semantics are documented.
- Deterministic business rules stay outside the agent.
- Evaluation cases cover expected model behavior.
Agent smell:
class BusinessRulesAgent extends Agent { ... }Better:
class SupportIntentClassifierAgent extends Agent { ... }Timers
Clean timer checklist:
- Timer name says why time matters.
- Scheduling command is separate from the action being scheduled.
- Repeated timers are idempotent.
- Cancellation path is explicit.
- Time values are constants or configuration, not magic numbers.