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
7.1 KiB
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 — full field listing
- Actor Hierarchy Extensions — LSP bindings and tool sources
- Actor Loader — discovery and caching
Table of Contents
Basic Structure
Every actor YAML file must include name, type, and description.
The name must follow the namespace/identifier format.
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.
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.
- 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).
- 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:
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
name: local/my-actor
type: llm
description: Assistant
# model: missing
Error: llm and graph types require 'model'
GRAPH Actor Without Route
name: local/pipeline
type: graph
description: Pipeline
model: gpt-4
# route: missing
Error: graph type requires 'route'
Duplicate Node IDs
nodes:
- id: step_a
...
- id: step_a # duplicate
...
Error: Duplicate node IDs: 'step_a'
Fix: give each node a unique id.
Missing Entry Node
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
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
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.