Files
temp/docs/reference/actor_config.md
aditya e476d2de0e feat(actor): extend hierarchical actor YAML schema and loader
Extend actor YAML schema to support hierarchical graphs with explicit
node types (agent, tool, conditional, subgraph), per-node LSP bindings
(lsp_binding with server, languages, auto, capabilities), and tool-source
references (skills, mcp_servers, agent_skills).

Add schema validation for namespaced actor references, duplicate node IDs,
edge target existence, and graph reachability — all nodes must be reachable
from entry_node via explicit edges or conditional node routing targets.

Update loader to report YAML parse errors with precise line/column positions
and schema validation errors with dotted field paths and remediation hints
pointing to docs/reference/actor_config.md.

Add docs/reference/actor_config.md as the practical configuration reference
covering hierarchical graph examples, node type table, topology rules, and
common error cases with fix guidance.

Refresh examples/actors/graph_workflow.yaml to replace deprecated actor_path
with actor_ref. Add benchmarks/actor_yaml_bench.py for schema load overhead.

Tests: 95 Behave scenarios, 10 Robot smoke tests (including hierarchical
loader smoke test), security scan clean, coverage 99% (threshold 97%).

ISSUES CLOSED: #157
2026-02-25 10:30:42 +00:00

311 lines
7.1 KiB
Markdown

# Actor Configuration Reference
Practical guide to writing actor YAML configuration files with hierarchical
graph examples and common error cases.
**Module:** `cleveragents.actor.schema` / `cleveragents.actor.loader`
Related references:
- [Actor YAML Schema](actors_schema.md) — full field listing
- [Actor Hierarchy Extensions](actor_hierarchy.md) — LSP bindings and tool sources
- [Actor Loader](actors_loading.md) — discovery and caching
---
## Table of Contents
- [Actor Configuration Reference](#actor-configuration-reference)
- [Basic Structure](#basic-structure)
- [Hierarchical Graph Example](#hierarchical-graph-example)
- [Node Types](#node-types)
- [Graph Topology Rules](#graph-topology-rules)
- [Error Cases](#error-cases)
---
## Basic Structure
Every actor YAML file must include `name`, `type`, and `description`.
The `name` must follow the `namespace/identifier` format.
```yaml
name: local/my-actor # Required — namespaced
type: llm # Required — llm | tool | graph
description: What it does # Required
version: "1.0" # Optional
model: gpt-4 # Required for llm and graph types
```
---
## Hierarchical Graph Example
A graph actor defines a multi-node workflow with conditional routing,
per-node LSP bindings, and tool-source references.
```yaml
name: workflows/dev-pipeline
type: graph
description: Multi-agent development pipeline
version: "1.0"
model: gpt-4
# Actor-level skill and LSP declarations
skills:
- local/file-ops
- local/git-ops
lsp:
- local/pyright
route:
nodes:
- id: planner
type: agent
name: Planner
description: Plans the implementation strategy
config:
model: gpt-4
prompt: "Analyze requirements and create a plan."
# Per-node LSP binding (overrides actor-level default)
lsp_binding:
server: local/pyright
languages:
- python
capabilities:
- diagnostics
# Per-node tool sources
tool_sources:
- type: skill
name: local/file-ops
- id: implementer
type: agent
name: Implementer
description: Implements the plan
config:
model: gpt-4
prompt: "Implement the changes per the plan."
lsp_binding:
auto: true
tool_sources:
- type: skill
name: local/file-ops
- type: skill
name: local/git-ops
- type: mcp
name: local/filesystem
- id: reviewer
type: subgraph
name: Code Reviewer
description: Delegates to the code-review actor
actor_ref: local/code-reviewer # namespaced reference to another actor
- id: gate
type: conditional
name: Quality Gate
description: Routes to reviewer or re-plans based on lint result
config:
conditions:
- check: "state.get('lint_ok') == True"
route_to: reviewer
- check: "state.get('lint_ok') == False"
route_to: planner
edges:
- from_node: planner
to_node: implementer
- from_node: implementer
to_node: gate
- from_node: gate
to_node: planner # explicit back-edge for retry path
- from_node: gate
to_node: reviewer
entry_node: planner
exit_nodes:
- reviewer
```
---
## Node Types
| Type | Purpose | Key config fields |
|------|---------|-------------------|
| `agent` | LLM-driven reasoning node | `model`, `prompt`, `tools` |
| `tool` | Runs a specific tool call | `tool_name`, `parameters` |
| `conditional` | Routes to different nodes based on state | `conditions[].check`, `conditions[].route_to` |
| `subgraph` | Delegates to another actor entirely | `actor_ref` |
### Conditional Node Routing
Conditional nodes use Python expressions over `state` to route the workflow.
The `route_to` targets are counted as reachable even without explicit edges.
```yaml
- id: branch
type: conditional
name: Branch
description: Decides next step
config:
conditions:
- check: "state.get('success') == True"
route_to: done
- check: "state.get('success') == False"
route_to: retry
```
### Subgraph Node
Subgraph nodes delegate execution to another actor by namespaced name.
Use `actor_ref` (not `config.actor_path`).
```yaml
- id: review_step
type: subgraph
name: Review
description: Runs the review sub-workflow
actor_ref: local/reviewer # correct: namespaced actor reference
```
---
## Graph Topology Rules
The loader enforces these constraints on every graph actor:
| Rule | Error trigger |
|------|--------------|
| Unique node IDs | Two nodes share the same `id` |
| Entry node exists | `entry_node` references an `id` not in `nodes` |
| Exit nodes exist | Any `exit_nodes` entry references a missing `id` |
| Edge targets exist | `from_node` or `to_node` reference a missing `id` |
| Nodes are reachable | A node has no path from `entry_node` via edges or conditional routing |
| No cycles | A non-conditional cycle exists in the edge graph |
---
## Error Cases
### Naming Errors
**Actor name missing namespace:**
```yaml
name: my-actor # wrong — must be namespace/name
```
Error: `name must be in 'namespace/name' format`
Fix: use a namespaced name like `local/my-actor` or `workflows/my-actor`.
---
### LLM Actor Without Model
```yaml
name: local/my-actor
type: llm
description: Assistant
# model: missing
```
Error: `llm and graph types require 'model'`
---
### GRAPH Actor Without Route
```yaml
name: local/pipeline
type: graph
description: Pipeline
model: gpt-4
# route: missing
```
Error: `graph type requires 'route'`
---
### Duplicate Node IDs
```yaml
nodes:
- id: step_a
...
- id: step_a # duplicate
...
```
Error: `Duplicate node IDs: 'step_a'`
Fix: give each node a unique `id`.
---
### Missing Entry Node
```yaml
route:
nodes:
- id: node_a
...
entry_node: node_x # node_x does not exist
```
Error: `Entry node 'node_x' not found in route.entry_node`
---
### Invalid Edge Target
```yaml
edges:
- from_node: node_a
to_node: node_z # node_z does not exist
```
Error: `Edge to_node 'node_z' not found at route.edges[0]`
---
### Unreachable Node
```yaml
nodes:
- id: node_a
- id: node_b
- id: node_c # no edge or conditional route_to points here
edges:
- from_node: node_a
to_node: node_b
entry_node: node_a
```
Error: `route: nodes 'node_c' are unreachable from entry node 'node_a'`
Fix: add an edge from a reachable node to `node_c`, or remove `node_c` from
`nodes` if it is not needed.
---
### YAML Parse Error
A malformed YAML file produces a parse error with the location:
```
Invalid YAML in bad.yaml at line 3, column 5: mapping values are not allowed here
```
Fix: check the indicated line and correct the YAML syntax.
---
### Schema Validation Error Format
When a YAML file is syntactically valid but fails schema validation, the
loader reports precise field paths:
```
Schema validation failed for actor.yaml:
type: Input should be 'llm', 'tool' or 'graph'
route.nodes.0.id: String should match pattern '^[a-zA-Z0-9_-]+$'
Hint: see docs/reference/actor_config.md for the correct schema format.
```
Each line shows the dotted field path and the validation message.