Files
cleveragents-core/docs/reference/action_model.md
T
freemo fd6d41b371
CI / lint (pull_request) Successful in 14s
CI / typecheck (pull_request) Successful in 26s
CI / security (pull_request) Successful in 21s
CI / quality (pull_request) Successful in 16s
CI / integration_tests (pull_request) Successful in 4m15s
CI / build (pull_request) Successful in 16s
CI / unit_tests (pull_request) Successful in 7m41s
CI / docker (pull_request) Successful in 39s
CI / lint (push) Successful in 13s
CI / coverage (pull_request) Successful in 5m38s
CI / typecheck (push) Successful in 26s
CI / security (push) Successful in 22s
CI / quality (push) Successful in 15s
CI / integration_tests (push) Successful in 4m10s
CI / build (push) Successful in 15s
CI / unit_tests (push) Successful in 8m17s
CI / docker (push) Successful in 41s
CI / coverage (push) Successful in 5m30s
feat(domain): align action model with spec
2026-02-13 09:41:28 -05:00

295 lines
12 KiB
Markdown

# Action Domain Model
The `Action` is a YAML-defined, reusable plan template in CleverAgents.
It specifies actors, typed arguments, completion criteria, and optional
invariants. Actions are project-agnostic until bound to one or more
projects via `agents plan use`, which instantiates a Plan in Strategize phase.
Actions are created via CLI with a required `--config` YAML file:
```
agents action create --config ./actions/code-coverage.yaml
```
## State Lifecycle
Actions have only two states with no draft phase:
| State | Description |
|-------------|--------------------------------------------------|
| AVAILABLE | Default state; action can be used to create plans |
| ARCHIVED | Action is retired and cannot create new plans |
There is no draft state. Actions are created directly in `available` state
from a validated YAML config file.
## Fields Reference
### Identity
| Field | Type | Required | Description |
|--------------------|------------------|----------|------------------------------------------|
| `namespaced_name` | `NamespacedName` | Yes | Unique identifier (`[server:][namespace/]<name>`) |
The namespaced name is the sole identity for an action -- there is no
separate ULID. This enables cross-server action references.
### Descriptions
| Field | Type | Required | Description |
|---------------------|--------------|----------|------------------------------------------|
| `description` | `str` | Yes | Short description (min 1 char) |
| `long_description` | `str \| None`| No | Detailed description for reusable actions|
| `definition_of_done`| `str` | Yes | Explicit, testable completion criteria |
### Actor References
| Field | Type | Required | Description |
|--------------------|---------------|----------|--------------------------------------|
| `strategy_actor` | `str` | Yes | Actor for the Strategize phase |
| `execution_actor` | `str` | Yes | Actor for the Execute phase |
| `review_actor` | `str \| None` | No | Actor for reviewing results |
| `apply_actor` | `str \| None` | No | Actor for the Apply phase |
| `estimation_actor` | `str \| None` | No | Actor for effort/cost estimation |
| `invariant_actor` | `str \| None` | No | Actor for invariant reconciliation |
`strategy_actor` and `execution_actor` are required. All actor fields accept
namespaced names.
### Behavior Flags
| Field | Type | Default | Description |
|-------------|--------|---------|------------------------------------------|
| `reusable` | `bool` | `True` | If true, action remains available after use |
| `read_only` | `bool` | `False` | If true, action only performs read operations |
### Metadata
| Field | Type | Description |
|--------------|---------------|--------------------------------|
| `created_at` | `datetime` | Creation timestamp |
| `updated_at` | `datetime` | Last update timestamp |
| `created_by` | `str \| None` | User/session that created the action |
| `tags` | `list[str]` | Tags for organization |
## Arguments System
Actions accept typed arguments defined as `ActionArgument` instances.
Arguments are injected into description/definition-of-done templates and
passed into actor context. Users supply values via `--arg name=value`.
### ActionArgument Fields
| Field | Type | Default | Description |
|----------------------|-------------------------------|------------|--------------------------------------|
| `name` | `str` | -- | Valid Python identifier (1-64 chars) |
| `arg_type` | `ArgumentType` | `STRING` | Type of the argument |
| `requirement` | `ArgumentRequirement` | `REQUIRED` | Required or optional |
| `description` | `str` | `""` | Human-readable description (max 500) |
| `default_value` | `str\|int\|float\|bool\|list\|None` | `None` | Default for optional arguments |
| `validation_pattern` | `str \| None` | `None` | Regex pattern for string validation |
| `min_value` | `float \| None` | `None` | Minimum value for numeric arguments |
| `max_value` | `float \| None` | `None` | Maximum value for numeric arguments |
### Argument Types
| Type | Python Type | Description |
|-----------|-------------|------------------------|
| `string` | `str` | Text value |
| `integer` | `int` | Whole number |
| `float` | `float` | Decimal number |
| `boolean` | `bool` | True/false value |
| `list` | `list[str]` | Comma-separated values |
Legacy short names (`str`, `int`, `bool`) are accepted and mapped to their
full equivalents via `ArgumentType._missing_()`.
### Argument Requirement
| Value | Description |
|------------|--------------------------------------------|
| `required` | Must be provided when using the action |
| `optional` | May be omitted; default_value used if set |
### Parsing: CLI String Format
`ActionArgument.parse()` accepts colon-delimited strings:
```
name:type:required|optional[:description]
```
Examples:
```
target_coverage:integer:required:Target coverage percentage
test_framework:string:optional:Test framework to use
```
### Parsing: YAML Mapping
`ActionArgument.from_mapping()` builds an argument from a YAML dict:
```yaml
name: target_coverage
type: integer
required: true
description: Target coverage percentage
default: 80
min_value: 0
max_value: 100
```
The `required` key is a boolean (default `false`). The `type` key is
case-insensitive and supports legacy short names.
### Type Coercion: CLI Values
`ActionArgument.coerce_value(raw)` converts a raw CLI string to the
declared type:
| Type | Coercion Behavior |
|-----------|-----------------------------------------------------------|
| `string` | Returned as-is |
| `integer` | `int(raw)`; raises `ValueError` on failure |
| `float` | `float(raw)`; raises `ValueError` on failure |
| `boolean` | Truthy: `true`, `1`, `yes`, `on`. Falsy: `false`, `0`, `no`, `off` |
| `list` | Split on `,`, strip whitespace, drop empty items |
### Argument Validation
`Action.validate_arguments(provided_args)` checks provided values against
the action's argument schema and returns a list of error messages (empty
if valid). Checks performed:
1. Missing required arguments
2. Unknown argument names
3. Type mismatches (including `min_value`/`max_value` for integers)
Convenience properties:
- `action.required_arguments` -- list of arguments where requirement is `REQUIRED`
- `action.optional_arguments` -- list of arguments where requirement is `OPTIONAL`
## YAML-First Configuration
Actions are loaded from YAML config dicts via `Action.from_config(config)`.
### Required Config Keys
| Key | Description |
|---------------------|--------------------------------------|
| `name` | Namespaced name (parsed via `NamespacedName.parse()`) |
| `description` | Short description |
| `definition_of_done`| Completion criteria |
| `strategy_actor` | Strategize phase actor |
| `execution_actor` | Execute phase actor |
Missing any of these raises `ValueError`.
### Optional Config Keys
| Key | Default | Description |
|----------------------|---------------|------------------------------------|
| `long_description` | `None` | Detailed description |
| `review_actor` | `None` | Review actor |
| `apply_actor` | `None` | Apply phase actor |
| `estimation_actor` | `None` | Estimation actor |
| `invariant_actor` | `None` | Invariant reconciliation actor |
| `arguments` | `[]` | List of argument mappings |
| `inputs_schema` | `None` | JSON Schema dict |
| `reusable` | `True` | Whether action persists after use |
| `read_only` | `False` | Read-only mode |
| `state` | `"available"` | Initial state |
| `automation_profile` | `None` | Default automation profile name |
| `invariants` | `[]` | List of invariant strings |
| `tags` | `[]` | Organization tags |
| `created_by` | `None` | Creator identifier |
## Automation Profile
Actions can specify a default automation profile via the `automation_profile`
field. This is a namespaced name string resolved at plan-use time.
Cross-field validation trims the value and converts empty/whitespace-only
strings to `None`.
## Invariants
Actions carry a list of invariant constraint strings (`invariants: list[str]`).
When the action is used to create a plan, these are carried forward as
plan-level invariants with `ACTION` scope.
### Sanitization
The `invariants` field is sanitized on assignment via a Pydantic
`field_validator` (mode `"before"`):
1. **Trim** -- leading/trailing whitespace stripped from each entry
2. **Blank rejection** -- empty strings after trimming are dropped
3. **Deduplication** -- duplicate entries removed while preserving insertion order
4. **None coercion** -- `None` input is normalized to an empty list
## inputs_schema
An optional `dict[str, Any]` field for advanced input validation via
JSON Schema. Validated on assignment to ensure the value is a `dict`
(or `None`). This provides a schema-based alternative to the typed
`arguments` list for complex input structures.
## CLI Rendering
`Action.as_cli_dict()` returns a stable-ordered dict for deterministic
CLI output. Key ordering:
1. `name`, `description`, `state`
2. `strategy_actor`, `execution_actor`
3. `long_description` (if set)
4. `definition_of_done`
5. Optional actors: `review_actor`, `apply_actor`, `estimation_actor`, `invariant_actor` (if set)
6. `arguments` (if non-empty) -- each as `{name, type, required, description}`
7. `reusable`, `read_only`
8. `automation_profile` (if set), `invariants` (if non-empty)
9. `created_at`
10. `tags` (if non-empty)
## Templating
Actions support `${placeholder}` syntax (Python `string.Template`) for
injecting argument values into text fields.
### render_template(template_text, args)
Core method. Scans for `${name}` and `$name` placeholders, verifies all
are present in the `args` dict, and substitutes using `safe_substitute`.
Raises `ValueError` if any placeholder is missing from `args`.
### render_description(args)
Shorthand for `render_template(self.description, args)`.
### render_definition_of_done(args)
Shorthand for `render_template(self.definition_of_done, args)`.
### Example
Given an action with:
```yaml
description: "Increase test coverage to ${target_coverage}%"
definition_of_done: "All modules have >= ${target_coverage}% line coverage"
```
Calling `render_description({"target_coverage": "90"})` produces:
```
Increase test coverage to 90%
```
## Source Location
- Model: `src/cleveragents/domain/models/core/action.py`
- Plan model: `src/cleveragents/domain/models/core/plan.py`
- Plan lifecycle service: `src/cleveragents/application/services/plan_lifecycle_service.py`