Files
temp/docs/reference/actor_compiler.md
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

107 lines
3.7 KiB
Markdown

# 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:
```yaml
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 |