- README: add v3.7.0 highlights (first-run UX, estimation lifecycle, enriched domain events, correction attempts, devcontainer handler, A2A ValueError mapping); add What's New section; add doc links - CHANGELOG: merge 'Unreleased (pre-3.7.0)' into v3.7.0 as a subsection; clear [Unreleased] block - docs/reference/architecture_overview.md (new): high-level system layers, core abstractions, key services, protocols (A2A/MCP/LSP), estimation lifecycle, TUI architecture, server mode, observability - docs/reference/estimation_lifecycle.md (new): EstimationResult model reference, configuration, PLAN_ESTIMATION_COMPLETE event, plan.cost_estimate_usd, writing a custom estimation actor - docs/reference/correction_attempts.md (new): CorrectionAttemptRecord schema, state machine, CorrectionAttemptRepository API, DDL, CorrectionDryRunReport migration guide (removed redundant fields) - docs/reference/tui.md: add first-run experience section (ActorSelectionOverlay, is_first_run, create_default_persona_for_actor), session export/import TUI section, persona export/import TUI section; update architecture module table with first_run.py and actor_selection_overlay.py entries - mkdocs.yml: add Architecture Overview to top-level nav ISSUES CLOSED: #1310 #1087 #1242 #1241 #891 #996 #1001
5.4 KiB
Estimation Lifecycle
The estimation lifecycle is an optional hook that runs between the
Strategize and Execute phases of a plan. When configured, an
estimation actor analyses the plan's decision tree and produces an
EstimationResult containing cost, time, and risk forecasts.
Introduced in v3.7.0 (issue #1310). See also
plan_execute.md for the full plan lifecycle.
Module: cleveragents.application.services.plan_lifecycle_service
Overview
Strategize phase completes
│
▼
actor.default.estimation configured?
│
Yes │ No
│──────────────────► Execute phase begins immediately
▼
EstimationActor.run(plan)
│
├── EstimationResult stored on plan
├── plan.cost_estimate_usd populated
└── PLAN_ESTIMATION_COMPLETE event emitted
│
▼ (failure is informational — never blocks Execute)
Execute phase begins
Estimation failures are informational only. A failed or missing estimation actor never prevents the plan from advancing to Execute.
Configuration
Set the estimation actor via the actor.default.estimation config key:
agents config set actor.default.estimation anthropic/claude-4-sonnet
Or in ~/.config/cleveragents/config.yaml:
actor:
default:
estimation: anthropic/claude-4-sonnet
When this key is absent or empty, the estimation hook is skipped.
EstimationResult
Module: cleveragents.domain.models.core.estimation
All fields are optional. The estimation actor populates whichever metrics it can compute.
| Field | Type | Description |
|---|---|---|
estimated_cost_usd |
float | None |
Estimated LLM cost in USD (≥ 0) |
estimated_tokens |
int | None |
Estimated total token usage (≥ 0) |
estimated_steps |
int | None |
Expected number of execution steps (≥ 0) |
estimated_child_plans |
int | None |
Expected number of child plans |
estimated_time_seconds |
float | None |
Estimated execution time in seconds (≥ 0) |
risk_level |
"low" | "medium" | "high" | "critical" | None |
Risk assessment |
risk_factors |
tuple[str, ...] |
Identified risk factors (max 100 items) |
summary |
str |
Human-readable estimation summary (max 10 000 chars) |
raw_output |
str |
Raw actor output before parsing (max 100 000 chars) |
EstimationResult is a frozen Pydantic model. Instances are
immutable after construction.
Example
from cleveragents.domain.models.core.estimation import EstimationResult
result = EstimationResult(
estimated_cost_usd=0.42,
estimated_tokens=15_000,
estimated_steps=8,
risk_level="low",
risk_factors=("no external API calls", "read-only resources"),
summary="Low-risk plan with ~8 steps and minimal token usage.",
)
# Only non-empty fields for display
print(result.as_display_dict())
# {
# "estimated_cost_usd": 0.42,
# "estimated_tokens": 15000,
# "estimated_steps": 8,
# "risk_level": "low",
# "risk_factors": ["no external API calls", "read-only resources"],
# "summary": "Low-risk plan with ~8 steps and minimal token usage.",
# }
PLAN_ESTIMATION_COMPLETE Event
When estimation succeeds, PlanLifecycleService emits a
PLAN_ESTIMATION_COMPLETE domain event with the following details:
| Field | Value |
|---|---|
event_type |
EventType.PLAN_ESTIMATION_COMPLETE |
plan_id |
ID of the plan being estimated |
actor |
Name of the estimation actor |
estimated_cost_usd |
From EstimationResult.estimated_cost_usd |
risk_level |
From EstimationResult.risk_level |
summary |
From EstimationResult.summary |
The event is published to the event bus and picked up by the
AuditEventSubscriber for SEC7 audit logging.
plan.cost_estimate_usd
After a successful estimation, plan.cost_estimate_usd is set to
EstimationResult.estimated_cost_usd. This value is included in:
agents plan showoutput (when non-null)agents plan listtable (when non-null)- The
PLAN_APPLIEDevent's audit details
CLI Visibility
# Show plan details including cost estimate
agents plan show <PLAN_ID>
# Example output (with estimation configured)
# Plan: my-feature-plan
# Phase: Execute
# Cost estimate: $0.42
# Risk: low
# ...
Writing an Estimation Actor
An estimation actor is a standard CleverAgents actor. It receives the
plan's decision tree as context and should return a structured
EstimationResult-compatible response.
The actor is invoked with the plan's action description and decision
tree summary. It should return JSON that the lifecycle service parses
into an EstimationResult.
# Example custom estimation actor
name: my-estimator
namespace: local
provider: anthropic
model: claude-4-sonnet
system_prompt: |
You are a cost and risk estimation expert for AI automation plans.
Given a plan's action and decision tree, estimate:
- Total LLM cost in USD
- Total token usage
- Number of execution steps
- Risk level (low/medium/high/critical)
- Key risk factors
Return a JSON object matching the EstimationResult schema.