Files
cleveragents-core/docs/reference/actor_compiler.md
T
freemo c47e6445d0 feat(actor): compile hierarchical actor configs to LangGraph
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
2026-02-24 17:57:18 +00:00

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

  1. Input validation — The compiler accepts an ActorConfigSchema with type=GRAPH and a populated route field. Non-GRAPH types are rejected with ActorCompilationError.

  2. Reference validation — All node IDs referenced in edges, entry, and exit points are checked against the declared node set.

  3. Intra-graph cycle detection — The route's detect_cycles() method verifies the node graph is acyclic.

  4. Cross-actor subgraph cycle detection — When an optional actor_resolver is provided, the compiler follows SUBGRAPH node references recursively and detects cycles across actor boundaries (e.g. actor A → actor B → actor A).

  5. Node mapping — Each NodeDefinition is mapped to a LangGraph NodeConfig with the appropriate NodeType (AGENT, TOOL, CONDITIONAL, SUBGRAPH).

  6. Edge mapping — Each EdgeDefinition is mapped to a LangGraph Edge. Conditional expressions are preserved in edge.condition.

  7. LSP binding extraction — Per-node lsp_bindings config entries are extracted into LspBinding objects and stored in compilation metadata.

  8. Metadata assembly — The compiler returns a CompiledActor containing the node map, edge list, entry point, and a CompilationMetadata object 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 be ActorType.GRAPH).
  • actor_resolver — Optional callable (name: str) -> ActorConfigSchema | None for 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