Compare commits

...

1 Commits

Author SHA1 Message Date
HAL9000 4dafe25343 docs: add action module API reference, update CHANGELOG and nav
- Add docs/api/action.md: full API reference for ActionConfigSchema and ActionArgumentSchema — field tables, factory methods, camelCase compat mapping, env-var interpolation, database integrity note, and complete YAML example
- Update docs/api/index.md: add cleveragents.action entry to module index
- Update mkdocs.yml: add 'Action Schema: api/action.md' to the API Reference nav
- Update CHANGELOG.md [Unreleased] Fixed: document plan use UNIQUE constraint violation fix (#4174, #4197)
- Clarify from_yaml_file ValueError semantics, document inputs_schema type as dict[str, Any] | None, and update A2A ASV benchmarks to pass method= requests after JSON-RPC migration

ISSUES CLOSED: #7472
2026-04-17 16:05:49 +00:00
6 changed files with 302 additions and 7 deletions
+7
View File
@@ -107,6 +107,13 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
### Fixed
- **`plan use` UNIQUE constraint violation** (`ActionRepository.update`): Replaced the
`.clear()` + `.append()` SQLAlchemy pattern with explicit `sa_delete()` + `session.flush()`
before re-inserting `action_arguments` and `action_invariants` child rows. Added
`session.expire()` to force collection reload, preventing stale identity-map references
that caused `sqlite3.IntegrityError: UNIQUE constraint failed` when re-using an action
that already had arguments registered. (#4174, #4197)
- **Robot Framework TDD Listener Guards** (#5436): Added three guard conditions to the
`tdd_expected_fail_listener` `end_test()` function to prevent blindly inverting ALL test
failures to passes, which was masking infrastructure errors and causing flaky CI behavior.
+4 -4
View File
@@ -40,11 +40,11 @@ class FacadeDispatchSuite:
def setup(self) -> None:
self.facade = A2aLocalFacade()
self.session_req = A2aRequest(operation="session.create")
self.session_req = A2aRequest(method="session.create", params={})
self.plan_req = A2aRequest(
operation="plan.execute", params={"plan_id": "BENCH001"}
method="plan.execute", params={"plan_id": "BENCH001"}
)
self.context_req = A2aRequest(operation="context.get")
self.context_req = A2aRequest(method="context.get", params={})
def time_dispatch_session_create(self) -> None:
self.facade.dispatch(self.session_req)
@@ -57,7 +57,7 @@ class FacadeDispatchSuite:
def time_dispatch_all_operations(self) -> None:
for op in self.facade.list_operations():
req = A2aRequest(operation=op)
req = A2aRequest(method=op, params={})
self.facade.dispatch(req)
def time_list_operations(self) -> None:
+3 -3
View File
@@ -50,17 +50,17 @@ class M6FacadeDispatchSuite:
def time_session_create(self) -> None:
"""Benchmark session.create dispatch."""
self._facade.dispatch(A2aRequest(operation="session.create", params={}))
self._facade.dispatch(A2aRequest(method="session.create", params={}))
def time_plan_create(self) -> None:
"""Benchmark plan.create dispatch."""
self._facade.dispatch(A2aRequest(operation="plan.create", params={}))
self._facade.dispatch(A2aRequest(method="plan.create", params={}))
def time_plan_execute(self) -> None:
"""Benchmark plan.execute dispatch."""
self._facade.dispatch(
A2aRequest(
operation="plan.execute",
method="plan.execute",
params={"plan_id": "01M6SM0KE00000000000000001"},
)
)
+283
View File
@@ -0,0 +1,283 @@
# `cleveragents.action` — Action Configuration Schema
The `action` package provides the YAML configuration schema, validation, and
loading utilities for CleverAgents action definitions.
Actions are the top-level automation units in CleverAgents: each action binds
lifecycle actors, typed arguments, invariants, and completion criteria into a
named, reusable workflow template.
See the [Action Configuration Files](../schema/action.schema.yaml) schema and
`examples/actions/` for reference examples.
---
## Quick Start
```python
from cleveragents.action.schema import ActionConfigSchema
# Parse from a YAML string
config = ActionConfigSchema.from_yaml("""
name: local/my-action
description: "Refactor a Python module"
strategy_actor: openai/gpt-4o
execution_actor: openai/gpt-4o-mini
definition_of_done: "All tests pass and coverage >= 90%"
arguments:
- name: target_module
type: string
required: true
description: "Module path to refactor"
invariants:
- "Do not modify public API signatures"
""")
print(config.name) # "local/my-action"
print(config.arguments[0]) # ActionArgumentSchema(name='target_module', ...)
# Load from a file
config = ActionConfigSchema.from_yaml_file("examples/actions/refactor.yaml")
```
---
## `ActionConfigSchema`
```python
from cleveragents.action.schema import ActionConfigSchema
```
Pydantic model that validates a complete action YAML configuration.
### Factory Methods
#### `ActionConfigSchema.from_yaml(yaml_string: str) → ActionConfigSchema`
Parse and validate an action YAML string.
| Parameter | Type | Description |
|-----------|------|-------------|
| `yaml_string` | `str` | Raw YAML content |
**Returns:** Validated `ActionConfigSchema` instance.
**Raises:**
- `ValueError` — if the YAML is empty, `None`, or not a mapping
- `pydantic.ValidationError` — if schema validation fails
**Processing pipeline:**
1. Parse YAML with `yaml.safe_load`
2. Normalize camelCase keys → snake_case (with deprecation warnings)
3. Interpolate `${ENV_VAR}` placeholders from environment variables
4. Validate with Pydantic
---
#### `ActionConfigSchema.from_yaml_file(path: str | Path) → ActionConfigSchema`
Load and validate an action YAML file from disk.
| Parameter | Type | Description |
|-----------|------|-------------|
| `path` | `str \| Path` | Path to the YAML file |
**Returns:** Validated `ActionConfigSchema` instance.
**Raises:**
- `FileNotFoundError` — if the file does not exist
- `ValueError` — if the path is `None` or does not point to a regular file
- `pydantic.ValidationError` — if schema validation fails
---
### Fields
#### Identity
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `schema_version` | `str` | No (default: `"1"`) | Schema version for forward compatibility |
| `name` | `str` | **Yes** | Namespaced action name — `namespace/name` format |
| `description` | `str` | **Yes** | Short description of the action |
| `long_description` | `str \| None` | No | Detailed multi-line description |
The `name` field must match `^[a-z0-9][a-z0-9_-]*/[a-z0-9][a-z0-9_-]*$`.
Examples: `local/my-action`, `builtin/refactor`.
#### Lifecycle Actors
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `strategy_actor` | `str` | **Yes** | Actor for the Strategize phase |
| `execution_actor` | `str` | **Yes** | Actor for the Execute phase |
| `estimation_actor` | `str \| None` | No | Optional actor for cost/risk estimation |
| `review_actor` | `str \| None` | No | Optional actor for code review / QA |
| `apply_actor` | `str \| None` | No | Optional actor for the Apply phase |
| `invariant_actor` | `str \| None` | No | Optional actor for invariant reconciliation |
All actor names must follow the `namespace/name` format.
#### Completion Criteria
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `definition_of_done` | `str` | **Yes** | Testable criteria defining task completion |
#### Behaviour
| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `reusable` | `bool` | `True` | Whether the action persists after use |
| `read_only` | `bool` | `False` | Restrict the action to read-only operations |
| `state` | `str` | `"available"` | Action state: `available` or `archived` |
#### Arguments
| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `arguments` | `list[ActionArgumentSchema]` | `[]` | Typed arguments accepted by the action |
#### Automation & Invariants
| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `automation_profile` | `str \| None` | `None` | Default automation profile for derived plans |
| `invariants` | `list[str]` | `[]` | Constraints carried as plan-level invariants |
| `inputs_schema` | `dict[str, Any] \| None` | `None` | Optional JSON Schema for advanced input validation |
Invariants are automatically trimmed, de-duplicated, and blank entries are
dropped during validation.
---
## `ActionArgumentSchema`
```python
from cleveragents.action.schema import ActionArgumentSchema
```
Pydantic model for a single typed action argument. Arguments are values
supplied by the user at plan-use time (`agents plan use --arg name=value`).
### Fields
| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `name` | `str` | **Required** | Argument name (164 chars, valid identifier) |
| `type` | `str` | `"string"` | Data type: `string`, `integer`, `float`, `boolean`, `list` |
| `required` | `bool` | `False` | Whether the argument must be provided |
| `description` | `str` | `""` | Human-readable description (max 500 chars) |
| `default` | `str \| int \| float \| bool \| list[str] \| None` | `None` | Default value when argument is not provided |
| `validation_pattern` | `str \| None` | `None` | Regex pattern for string argument validation |
| `min_value` | `float \| None` | `None` | Minimum value for numeric arguments |
| `max_value` | `float \| None` | `None` | Maximum value for numeric arguments |
The `name` field must be a valid Python identifier (alphanumeric, underscores,
or hyphens).
---
## camelCase Compatibility
The schema accepts both `snake_case` and `camelCase` keys for backward
compatibility. camelCase keys are automatically normalized with a deprecation
warning:
| camelCase | snake_case |
|-----------|------------|
| `strategyActor` | `strategy_actor` |
| `executionActor` | `execution_actor` |
| `definitionOfDone` | `definition_of_done` |
| `longDescription` | `long_description` |
| `estimationActor` | `estimation_actor` |
| `reviewActor` | `review_actor` |
| `applyActor` | `apply_actor` |
| `invariantActor` | `invariant_actor` |
| `readOnly` | `read_only` |
| `automationProfile` | `automation_profile` |
| `inputsSchema` | `inputs_schema` |
| `validationPattern` | `validation_pattern` |
| `minValue` | `min_value` |
| `maxValue` | `max_value` |
| `schemaVersion` | `schema_version` |
---
## Environment Variable Interpolation
String values in the YAML may reference environment variables using
`${VAR_NAME}` syntax. Missing variables are left as-is (no error):
```yaml
name: local/deploy
description: "Deploy to ${TARGET_ENV}"
strategy_actor: openai/gpt-4o
execution_actor: openai/gpt-4o-mini
definition_of_done: "Deployment to ${TARGET_ENV} verified"
```
```python
import os
os.environ["TARGET_ENV"] = "staging"
config = ActionConfigSchema.from_yaml(yaml_string)
# config.description == "Deploy to staging"
```
---
## Database Integrity Note
When updating an action that already has arguments or invariants registered,
`ActionRepository.update()` uses explicit `sa_delete()` + `session.flush()`
before re-inserting child rows. This avoids the SQLAlchemy `.clear()` +
`.append()` pattern that could trigger a `UNIQUE constraint failed` error
on `(action_name, name)` pairs. See [#4197](https://git.cleverthis.com/cleveragents/cleveragents-core/pulls/4197).
---
## Complete Example
```yaml
# examples/actions/refactor.yaml
schema_version: "1"
name: local/refactor
description: "Refactor a Python module to improve code quality"
long_description: |
Analyses the target module for code smells, applies refactoring
patterns, and ensures all tests continue to pass.
strategy_actor: openai/gpt-4o
execution_actor: openai/gpt-4o-mini
review_actor: anthropic/claude-4-sonnet
estimation_actor: local/estimator
definition_of_done: |
- All existing tests pass
- Coverage >= 90%
- No new linting errors
- Public API unchanged
reusable: true
read_only: false
state: available
arguments:
- name: target_module
type: string
required: true
description: "Python module path to refactor (e.g. src/myapp/utils.py)"
- name: max_complexity
type: integer
required: false
default: 10
description: "Maximum cyclomatic complexity threshold"
min_value: 1
max_value: 50
invariants:
- "Do not modify public API signatures"
- "Preserve all existing test assertions"
automation_profile: standard
```
+1
View File
@@ -10,6 +10,7 @@ classes, functions, and exceptions with signatures and usage examples.
|--------|-------------|
| [`cleveragents.core`](core.md) | Exception hierarchy, error handling, retry patterns, async cleanup |
| [`cleveragents.a2a`](a2a.md) | Agent-to-Agent (A2A) protocol facade, transport, models, and events |
| [`cleveragents.action`](action.md) | Action YAML configuration schema, validation, argument types, and env-var interpolation |
| [`cleveragents.actor`](actor.md) | Actor registry, configuration, loader, and compiler |
| [`cleveragents.skills`](skills.md) | Skill framework — schema, protocol, registry, discovery, and inline executor |
| [`cleveragents.tool`](tool.md) | Tool runtime, lifecycle, registry, router, and container executor |
+4
View File
@@ -23,10 +23,13 @@ nav:
- Configuration: api/config.md
- AI Providers: api/providers.md
- TUI: api/tui.md
- ACMS / UKO: api/acms.md
- Modules:
- Shell Safety: modules/shell-safety.md
- UKO Provenance Tracking: modules/uko-provenance.md
- Invariant Reconciliation: modules/invariant-reconciliation.md
- ACMS Context Hydration: modules/context-hydration.md
- Git Worktree Sandbox: modules/git-worktree-sandbox.md
- Development:
- Agent System Specification: development/agent-system-specification.md
- CI/CD Pipeline: development/ci-cd.md
@@ -38,6 +41,7 @@ nav:
- System Watchdog: development/system-watchdog.md
- Automation Tracking: development/automation-tracking.md
- Custom Sandbox Strategy: development/custom_sandbox_strategy.md
- Documentation Writer: development/docs-writer.md
- Implementation Timeline: timeline.md
- FAQ: faq.md
- Reference: reference/