Files
cleveragents-core/docs/reference/subplan_service.md
T
freemo c43e1f8260 feat(service): add subplan service and spawn workflow
Add SubplanService for building child plans from DecisionService spawn
entries and SubplanConfig. The service validates resource scopes, merge
strategies, and max_parallel bounds before spawning.

Key additions:
- SubplanService: Orchestrates child plan creation from spawn entries
- SpawnMetadata: Persisted metadata (spawn_decision_id, parent/root
  plan IDs, execution mode) for status output
- Spawn validation: Checks resource scopes, merge strategy, and
  parallelism bounds before spawning
- Documentation: subplan_service.md with spawn workflow and lifecycle

ISSUES CLOSED: #197
2026-03-02 09:41:25 -05:00

141 lines
5.6 KiB
Markdown

# Subplan Service: Spawn Workflow and Lifecycle
The `SubplanService` coordinates the spawning of child plans from
`DecisionService` spawn entries and `SubplanConfig`. It validates
resource scopes, merge strategies, and parallelism bounds before
creating child plan statuses.
## Overview
When a parent plan decides to decompose work into child plans (via
`subplan_spawn` or `subplan_parallel_spawn` decisions during Strategize),
the `SubplanService` handles the spawn workflow:
1. Extract spawn decisions from the `DecisionService`
2. Build `SpawnEntry` objects from those decisions
3. Validate the spawn request
4. Create `SubplanStatus` and `SpawnMetadata` for each entry
5. Return the result for the caller to persist on the parent plan
## Spawn Workflow
```
DecisionService SubplanService Parent Plan
| | |
| get_spawn_decisions | |
|<-----------------------| |
| [Decision, ...] | |
|----------------------->| |
| | build_spawn_entries |
| | validate_spawn |
| | spawn |
| |------------------------->|
| | SpawnResult |
| | (statuses + metadata) |
```
## Key Types
### SpawnMetadata
Persisted alongside each child plan for status output and provenance:
| Field | Type | Description |
|---------------------|--------|------------------------------------------|
| `spawn_decision_id` | `str` | ULID of the decision that triggered spawn|
| `parent_plan_id` | `str` | ULID of the parent plan |
| `root_plan_id` | `str` | ULID of the root plan in the hierarchy |
| `execution_mode` | `str` | How the subplan should be executed |
### SpawnEntry
A single spawn request derived from a decision:
| Field | Type | Description |
|--------------------|--------------|--------------------------------------|
| `decision` | `Decision` | The decision that triggered spawn |
| `action_name` | `str` | Namespaced action name for child plan|
| `target_resources` | `list[str]` | Resource IDs the child plan uses |
| `description` | `str` | Description/prompt for the child plan|
### SpawnResult
Result of spawning child plans:
| Field | Type | Description |
|--------------------|-------------------------------|--------------------------------|
| `spawned_statuses` | `list[SubplanStatus]` | Status for each child plan |
| `metadata` | `dict[str, SpawnMetadata]` | Metadata keyed by subplan_id |
| `total_spawned` | `int` | Number of child plans created |
| `execution_mode` | `str` | Execution mode from config |
## Spawn Validation
Before any child plan is created, `validate_spawn` checks:
1. **Resource scopes resolved**: All `target_resources` in each entry
exist in the `available_resources` set. Unresolved resources produce
a validation error.
2. **Merge strategy defined**: The `SubplanConfig.merge_strategy` must
not be `None`. Without a merge strategy, child plan results cannot
be combined.
3. **max_parallel bounds**: In `PARALLEL` execution mode, the number of
spawn entries must not exceed `config.max_parallel`.
4. **Valid action names**: Each entry must have a non-empty `action_name`.
5. **Correct decision types**: Each entry's decision must be either
`subplan_spawn` or `subplan_parallel_spawn`.
If any check fails, `SpawnValidationError` is raised with all errors.
## Integration with Other Services
- **DecisionService**: Provides spawn-type decisions via
`list_by_type(plan_id, "subplan_spawn")`.
- **SubplanExecutionService**: Executes the spawned child plans using
the `SubplanStatus` objects from `SpawnResult`.
- **SubplanMergeService**: Merges child plan outputs using the strategy
from `SubplanConfig`.
- **PlanLifecycleService**: Manages the parent plan's lifecycle,
persisting the updated `subplan_statuses` and `subplan_config`.
## Example Usage
```python
from cleveragents.application.services.subplan_service import (
SubplanService,
)
# Get spawn decisions for the parent plan
decisions = subplan_service.get_spawn_decisions(parent_plan.identity.plan_id)
# Build spawn entries from decisions
entries = subplan_service.build_spawn_entries(decisions)
# Spawn child plans (validates first)
result = subplan_service.spawn(
parent_plan=parent_plan,
config=parent_plan.subplan_config,
spawn_entries=entries,
available_resources=frozenset(known_resource_ids),
)
# Update the parent plan with spawned statuses
parent_plan.subplan_statuses = result.spawned_statuses
```
## Error Handling
| Error | When |
|--------------------------|---------------------------------------------|
| `ValueError` | `None` or empty required arguments |
| `SpawnValidationError` | Validation checks fail (resource scope, |
| | merge strategy, max_parallel, action name, |
| | or decision type) |
`SpawnValidationError` inherits from `ValidationError` and includes a
`validation_errors` list with detailed messages for each failure.