Add ActorCompiler module that translates GRAPH-type ActorConfigSchema definitions into LangGraph NodeConfig/Edge structures with LSP binding metadata. Includes subgraph resolution with cross-actor cycle detection, entry/exit validation, and CompilationMetadata for diagnostics. New files: - src/cleveragents/actor/compiler.py: Core compiler with compile_actor() - features/actor_compiler.feature: 13 Behave scenarios - features/steps/actor_compiler_steps.py: Step definitions - robot/actor_compiler.robot: 4 Robot smoke tests - benchmarks/actor_compiler_bench.py: ASV performance benchmarks - docs/reference/actor_compiler.md: Compilation pipeline reference Modified: - src/cleveragents/actor/__init__.py: Export compiler types - vulture_whitelist.py: Whitelist new public API ISSUES CLOSED: #158
3.7 KiB
Actor Compiler
The actor compiler translates hierarchical YAML-defined GRAPH actors into
LangGraph StateGraph node/edge structures that can be executed by the
CleverAgents runtime.
Compilation Pipeline
-
Input validation — The compiler accepts an
ActorConfigSchemawithtype=GRAPHand a populatedroutefield. Non-GRAPH types are rejected withActorCompilationError. -
Reference validation — All node IDs referenced in edges, entry, and exit points are checked against the declared node set.
-
Intra-graph cycle detection — The route's
detect_cycles()method verifies the node graph is acyclic. -
Cross-actor subgraph cycle detection — When an optional
actor_resolveris provided, the compiler followsSUBGRAPHnode references recursively and detects cycles across actor boundaries (e.g. actor A → actor B → actor A). -
Node mapping — Each
NodeDefinitionis mapped to a LangGraphNodeConfigwith the appropriateNodeType(AGENT, TOOL, CONDITIONAL, SUBGRAPH). -
Edge mapping — Each
EdgeDefinitionis mapped to a LangGraphEdge. Conditional expressions are preserved inedge.condition. -
LSP binding extraction — Per-node
lsp_bindingsconfig entries are extracted intoLspBindingobjects and stored in compilation metadata. -
Metadata assembly — The compiler returns a
CompiledActorcontaining the node map, edge list, entry point, and aCompilationMetadataobject for diagnostics and CLI inspection.
Node Binding
| Actor Node Type | LangGraph NodeType | Notes |
|---|---|---|
agent |
AGENT |
LLM invocation node |
tool |
TOOL |
Tool execution node |
conditional |
CONDITIONAL |
Routing node |
subgraph |
SUBGRAPH |
Nested actor reference |
LSP bindings are declared per-node in the config.lsp_bindings list:
nodes:
- id: coder
type: agent
name: Code Writer
description: Writes Python code
config:
agent: coder_agent
lsp_bindings:
- lsp_server_name: local/pyright
languages: [python]
auto_detect: true
Error Modes
| Error | Class | When |
|---|---|---|
| Non-GRAPH type | ActorCompilationError |
config.type != GRAPH |
| Missing route | ActorCompilationError |
config.route is None |
| Missing node | MissingNodeError |
Edge references unknown node |
| Invalid entry/exit | InvalidEntryExitError |
Entry/exit node not in graph |
| Intra-graph cycle | SubgraphCycleError |
Nodes form a cycle |
| Cross-actor cycle | SubgraphCycleError |
Subgraph refs form a cycle |
API Reference
compile_actor(config, *, actor_resolver=None) -> CompiledActor
Compile an ActorConfigSchema into a LangGraph-ready bundle.
Parameters:
config— The actor configuration (must beActorType.GRAPH).actor_resolver— Optional callable(name: str) -> ActorConfigSchema | Nonefor resolving subgraph references.
Returns: CompiledActor with nodes, edges, and metadata.
CompiledActor
| Field | Type | Description |
|---|---|---|
name |
str |
Actor name |
nodes |
dict[str, NodeConfig] |
LangGraph node configs |
edges |
list[Edge] |
LangGraph edges |
entry_point |
str |
Entry node ID |
metadata |
CompilationMetadata |
Diagnostic metadata |
CompilationMetadata
| Field | Type | Description |
|---|---|---|
node_ids |
list[str] |
All node IDs (sorted) |
tool_nodes |
list[str] |
Tool-type node IDs |
lsp_bindings |
list[LspBinding] |
Per-node LSP bindings |
subgraph_refs |
dict[str, str] |
Subgraph node → actor name |
entry_node |
str |
Entry point node ID |
exit_nodes |
list[str] |
Exit point node IDs |