Files
hurui200320 15e81e58f1
CI / dead_code (pull_request) Successful in 40s
CI / security (pull_request) Successful in 1m10s
CI / coverage (pull_request) Successful in 1m11s
CI / typecheck (pull_request) Successful in 1m19s
CI / unit_tests (pull_request) Successful in 1m18s
CI / lint (pull_request) Successful in 1m20s
CI / build (pull_request) Successful in 23s
CI / lint (push) Successful in 51s
CI / typecheck (push) Successful in 47s
CI / unit_tests (push) Successful in 49s
CI / coverage (push) Successful in 53s
CI / dead_code (push) Successful in 26s
CI / build (push) Successful in 26s
CI / security (push) Successful in 42s
fix: sync doc with extraction scope, remove boundary violation, add ProviderRegistryPort
Boundary fix:
- Delete src/cleveractors/acms/index.py (ACMSIndex, FileTraversalEngine,
  IndexEntry, FileType, TierLevel) — these are CLI/storage concerns that
  belong in cleveragents-core per ADR-001; the file already exists there
  at cleveragents/acms/index.py
- Clean src/cleveractors/acms/__init__.py: remove all index.py imports
  and re-exports; __all__ now derives purely from uko.__all__

ProviderRegistryPort (ADR-005):
- Add src/cleveractors/ports/provider_registry.py: ProviderRegistryPort
  Protocol with get(provider, model) -> Agent | None; structural typing,
  no host imports, mirrors the shape of ToolRegistryPort
- Update src/cleveractors/ports/__init__.py: export ProviderRegistryPort
  alongside ToolRegistryPort; update module docstring

Wire provider resolution into the node executor:
- compiler.py: _map_node now accepts actor_provider/actor_model defaults
  and merges them into AGENT node metadata (setdefault so per-node config
  values still win); compile_actor passes config.provider/config.model
- nodes.py: Node.__init__ gains optional provider_registry parameter;
  _execute_agent resolution order is now: (1) pre-resolved agents dict,
  (2) ProviderRegistryPort.get(provider, model) from node metadata,
  (3) graceful synthetic fallback — the ValueError guard for missing
  config.agent is removed since the registry is a valid alternative path

Documentation:
- Port ADR-003 (actor abstraction definition) from cleveragents-core ADR-031
- Port ADR-004 (Jinja2 YAML template preprocessing) from cleveragents-core
  ADR-032
- Add ADR-005 (Provider Registry Protocol) for the new provider_registry port
- Port five reference docs: actors_schema.md, actor_compiler.md,
  actor_config.md, actor_hierarchy.md, actors_examples.md
- Port API reference: api/actor.md
- Add provider field to all YAML examples in actors_examples.md,
  actor_hierarchy.md, and actor_config.md
- Update error messages in actor_config.md to match actual validator output
- Add graph-level provider/model propagation docs to actor_compiler.md
- Add ADR-005 cross-references to ADR-001, ADR-002, and actors_schema.md
- Fix ADR-005 status section to reflect that implementation is in this PR
- Fix ADR-004 to reference actual test files (smoke.feature, not phantom ones)
- Remove fabricated reserved-namespace constraint from ADR-003 Constraints
- Fix broken LICENSE link in docs/index.md for MkDocs rendering
- Add provider field to ActorConfigSchema table in api/actor.md
- Add internal modules section to docs/specification.md (ticket item 7)
- Fix markdown formatting in actors_schema.md provider field definition
- Add ADR-005 cross-reference to actors_schema.md provider field section

BDD coverage (7 scenarios, 30 steps):
- ProviderRegistryPort happy-path resolution
- Graceful fallback when provider registry returns None
- Graceful fallback when no provider registry is supplied
- Pre-resolved agents dict takes precedence over provider registry
- Compile a minimal graph actor, reject missing provider, render template

Post-review fixes applied in amend:
- actors_examples.md and actor_hierarchy.md: added provider to all examples
- ADR-003: removed fabricated reserved-namespace constraint
- ADR-004: corrected phantom test file references
- ADR-005: updated status to reflect implementation is included
- Added 'no registry' and 'agents dict precedence' BDD scenarios
- Added provider to api/actor.md ActorConfigSchema fields table
- ADR-001 and ADR-002: added ADR-005 cross-references
- actor_config.md: fixed error message to match validator
- actor_compiler.md: documented graph-level provider/model propagation
- index.md: fixed broken LICENSE link
- actors_schema.md: added ADR-005 cross-reference

ISSUES CLOSED: #4
2026-05-21 10:10:37 +00:00

7.9 KiB

cleveractors.actor — Actor System

The actor package provides the actor YAML configuration schema, loader, and compiler. Actors are the primary units parsed and compiled by this library — they encapsulate an LLM reference, a set of tool declarations, and a LangGraph execution graph.

See ADR-003 for the actor abstraction definition and ADR-001 for the library boundary decisions.

!!! note "Lazy imports" The actor package uses lazy imports to avoid pulling in heavy transitive dependencies (LangChain, LangSmith) when only lightweight submodules such as role_validation or schema are needed.


ActorConfigSchema

from cleveractors.actor.schema import ActorConfigSchema

Pydantic model representing a fully-parsed actor YAML file. Key fields:

Field Type Description
name str Actor identifier in namespace/name format
type ActorType llm, tool, or graph
description str Human-readable description
version str Schema version (default "1.0")
provider str | None LLM provider identifier (required for llm/graph; see ADR-005)
model str | None LLM model identifier (required for llm/graph)
system_prompt str | None System prompt; may contain Jinja2 templates
tools list Tool references and inline tool definitions
route RouteDefinition | None Graph topology (required for graph)
memory MemoryConfig | None Conversation memory settings
context ContextConfigSchema | None File inclusion settings
context_view ContextView | None Role-based context filtering hint
skills list[str] Skill references for capability acquisition
lsp ... | None Actor-level LSP server bindings

See Actor YAML Schema for the full field reference.


ActorConfiguration

from cleveractors.actor.config import ActorConfiguration

Pydantic model representing a fully-parsed actor YAML file with compiled graph configuration. Used internally by the compiler; surface-level consumers typically work with ActorConfigSchema and CompiledActor.

Field Type Description
name str Actor identifier (namespaced)
entry_node str Graph entry node name
nodes dict[str, NodeConfig] Node definitions
edges list[Edge] Graph edges
lsp_binding LspBinding | None Per-node LSP server binding
tool_sources list[str] Tool source references

ActorLoader

from cleveractors.actor.loader import ActorLoader
from pathlib import Path

loader = ActorLoader(
    search_roots=[Path("./actors/")],
    tool_registry=my_tool_registry,   # optional: ToolRegistryPort
)
configs = loader.discover()

Discovers and loads actor YAML files from a directory tree. Validates graph reachability (all nodes reachable from entry_node) and reports YAML line/column positions on error.

The optional tool_registry parameter accepts any object satisfying ToolRegistryPort. Unknown tool references produce warnings rather than errors, so the loader degrades gracefully when running without a fully populated tool registry.

Methods

Method Description
discover() Scan all search_roots for actor YAML files; returns list[ActorConfigSchema]
load(path) Load and validate a single actor YAML file
validate(config) Validate an ActorConfigSchema without loading from disk

compile_actor / CompiledActor

from cleveractors.actor.compiler import compile_actor, CompiledActor

compiled: CompiledActor = compile_actor(config)
# or, with subgraph cycle detection:
compiled = compile_actor(config, actor_resolver=my_registry.get)

Compiles an ActorConfigSchema into a CompiledActor by validating the graph, mapping nodes and edges to LangGraph data classes, and extracting LSP bindings. See Actor Compiler for the full pipeline description.

Parameters:

  • configActorConfigSchema (must be ActorType.GRAPH)
  • actor_resolver — Optional (name: str) -> ActorConfigSchema | None for cross-actor subgraph cycle detection

Returns: CompiledActor

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

Compilation Errors

from cleveractors.actor import (
    ActorCompilationError,
    MissingNodeError,
    InvalidEntryExitError,
    SubgraphCycleError,
)
Exception Description
ActorCompilationError General compilation failure (base class)
MissingNodeError Edge or entry/exit references a node not in the graph
InvalidEntryExitError Entry or exit node configuration is invalid
SubgraphCycleError Cycle detected within the graph or across subgraph references

Extension Points (Ports)

from cleveractors.ports import ToolRegistryPort, ProviderRegistryPort
Protocol Used by Purpose
ToolRegistryPort ActorLoader Verify tool references at load time
ProviderRegistryPort Node._execute_agent() Resolve (provider, model) to an Agent instance at execution time

See ADR-002 and ADR-005 for the design rationale behind each port.


Supporting Types

LspBinding

from cleveractors.lsp.models import LspBinding

Data class describing an LSP server binding extracted during compilation. Consumed by the host application to start the appropriate language server.

VocabularyRegistry

from cleveractors.acms.uko import VocabularyRegistry

Registry of UKO (Universal Knowledge Ontology) vocabulary data used for context enrichment. Pure data; no I/O.

Agent

from cleveractors.agents.base import Agent

Minimal abstract base class for LLM-backed agents. Host applications subclass Agent to wrap their concrete LangChain model instances and return them from ProviderRegistryPort.get().

Error Types

from cleveractors.core import ValidationError, NotFoundError
Exception Description
ValidationError Schema or semantic validation failure
NotFoundError A named resource (actor, tool, skill) could not be found

Example: Loading and Compiling an Actor

from pathlib import Path
from cleveractors.actor.loader import ActorLoader
from cleveractors.actor.compiler import compile_actor
from cleveractors.ports import ToolRegistryPort

# Provide a tool registry (any object with .get(name) -> spec | None)
loader = ActorLoader(
    search_roots=[Path("actors/")],
    tool_registry=my_tool_registry,  # satisfies ToolRegistryPort
)

for config in loader.discover():
    compiled = compile_actor(config)
    # Hand compiled.nodes / compiled.edges to your LangGraph executor
    print(compiled.name, compiled.metadata.node_ids)