Files
cleveragents-core/docs/reference/di.md
T
freemo 120274da99 feat(di): wire decision services
Create DecisionService application-layer service that wraps
DecisionRepository with structured logging and UnitOfWork transaction
management. Wire DecisionService and PlanLifecycleService into the DI
container as Factory providers.

Inject DecisionService into PlanLifecycleService so that phase
transitions automatically record decisions: start_strategize records a
strategy_choice decision and start_execute records an
implementation_choice decision. Decision recording is optional and
never blocks lifecycle transitions.

Add Behave feature (5 scenarios), Robot Framework smoke tests (2 test
cases), ASV benchmarks (3 benchmark classes), and DI reference
documentation.

ISSUES CLOSED: #173
2026-02-27 02:33:42 +00:00

109 lines
4.4 KiB
Markdown

# Dependency Injection Reference
The CleverAgents DI container is built on `dependency-injector`'s
`DeclarativeContainer`. All service registrations live in
`src/cleveragents/application/container.py`.
## Container Overview
| Provider | Type | Description |
|-------------------------------|-----------|-----------------------------------------|
| `settings` | Singleton | Application settings |
| `provider_registry` | Singleton | AI provider registry |
| `database_url` | Callable | Database URL resolution |
| `unit_of_work` | Factory | Unit of Work (new per request) |
| `ai_provider` | Singleton | AI provider instance |
| `project_service` | Factory | Project management service |
| `vector_store_service` | Factory | Vector store operations |
| `context_service` | Factory | Context management service |
| `actor_service` | Factory | Actor configuration service |
| `actor_registry` | Factory | Actor registry with provider binding |
| `plan_service` | Factory | Legacy plan management (deprecated) |
| **`decision_service`** | Factory | Decision tree recording service |
| **`plan_lifecycle_service`** | Factory | V3 four-phase plan lifecycle |
| `resource_registry_service` | Factory | Resource registry operations |
| `namespaced_project_repo` | Factory | Namespaced project repository |
| `project_resource_link_repo` | Factory | Project-resource link repository |
| `stream_router` | Singleton | Reactive stream routing |
| `langgraph_bridge` | Singleton | LangGraph integration bridge |
| `route_bridge` | Singleton | Reactive route bridge |
## Decision Service Registration
The `DecisionService` is registered as a **Factory** provider, meaning
each resolution returns a new instance. It depends on:
- `settings` — Application settings (Singleton)
- `unit_of_work` — Unit of Work (Factory)
```python
decision_service = providers.Factory(
DecisionService,
settings=settings,
unit_of_work=unit_of_work,
)
```
`DecisionService` wraps `DecisionRepository` (accessible via
`UnitOfWorkContext.decisions`) and provides:
| Method | Description |
|-------------------------|--------------------------------------------|
| `record_decision()` | Persist a new decision |
| `get_decision()` | Retrieve a decision by ID |
| `get_decisions_for_plan()` | Get all decisions for a plan |
| `get_decision_tree()` | BFS traversal of the decision tree |
| `get_path_to_root()` | Walk from a decision up to the root |
| `mark_superseded()` | Mark a decision as superseded |
| `list_by_type()` | List decisions by type for a plan |
## Plan Lifecycle Service Registration
The `PlanLifecycleService` is registered as a **Factory** provider
with the `DecisionService` injected:
```python
plan_lifecycle_service = providers.Factory(
PlanLifecycleService,
settings=settings,
unit_of_work=unit_of_work,
decision_service=decision_service,
)
```
When a `DecisionService` is wired, the lifecycle service automatically
records decisions during phase transitions:
- **start_strategize** → records a `strategy_choice` decision
- **start_execute** → records an `implementation_choice` decision
If no `DecisionService` is provided (e.g. in legacy tests), decision
recording is silently skipped.
## Usage Example
```python
from cleveragents.application.container import get_container
container = get_container()
# Resolve services
decision_svc = container.decision_service()
lifecycle_svc = container.plan_lifecycle_service()
# Record a decision manually
from cleveragents.domain.models.core.decision import Decision, DecisionType
decision = Decision(
plan_id="01HV...",
sequence_number=0,
decision_type=DecisionType.STRATEGY_CHOICE,
question="Which approach?",
chosen_option="Approach A",
)
decision_svc.record_decision(decision)
# Retrieve decisions
decisions = decision_svc.get_decisions_for_plan("01HV...")
```