actor/compiler.py:_map_node() already threaded provider and model from the
actor-level config into each AGENT node's merged_meta via setdefault, but
system_prompt was never added to the same pattern.
Three targeted additions across two files:
1. _map_node() in actor/compiler.py gains an actor_system_prompt parameter
and applies merged_meta.setdefault("system_prompt", actor_system_prompt)
inside the AGENT branch, directly after the existing provider/model calls.
setdefault semantics ensure per-node config.system_prompt overrides take
precedence, exactly matching the existing provider/model behaviour.
2. compile_actor() now passes actor_system_prompt=config.system_prompt to
_map_node() so the actor-level field reaches every AGENT node.
3. Node._execute_agent() in langgraph/nodes.py injects the node's
metadata["system_prompt"] into the context dict (before state.metadata
is merged) so host agents can read context.get("system_prompt") without
needing a direct reference to the raw ActorConfigSchema.
Seven BDD scenarios added in features/compiler_system_prompt.feature:
- Actor-level system_prompt is threaded into each AGENT node metadata.
- Per-node system_prompt takes precedence via setdefault semantics.
- process_message() receives system_prompt in the context dict.
- state.metadata["system_prompt"] overrides compiled default at runtime.
- Non-AGENT nodes (TOOL) do not receive system_prompt in metadata.
- Actor without system_prompt compiles metadata as None.
- Absent system_prompt is excluded from runtime context dict.
Bug fix: changed truthiness check from `if node_system_prompt:` to
`if node_system_prompt is not None:` in _execute_agent() to faithfully
pass empty-string system prompts into the context dict. Added explicit
`str | None` type annotation for node_system_prompt.
docs/reference/actor_compiler.md updated to document system_prompt
threading alongside provider and model in the Node Binding table.
Quality gates: lint, typecheck, unit_tests (14/14), coverage_report,
security_scan, dead_code, complexity all pass.
ISSUES CLOSED: #6
CleverActors Core
CleverActors is the declarative-actor library used by CleverAgents and CleverRouter.
It is the smallest possible Python module that lets a host application:
- Parse a CleverAgents v3 actor YAML file (with sandboxed Jinja2 + env-var preprocessing).
- Validate it against the Pydantic schema.
- Compile it into a LangGraph node + edge graph ready for execution.
The library carries no I/O concerns of its own — no databases, no HTTP, no CLI, no dependency-injection containers. Persistence, event publishing, and lifecycle management belong to whoever consumes it.
Origin
Extracted from cleveragents/cleveragents-core at commit 20ad9a46 in 2026.
The extraction preserves the customer-facing YAML format exactly; the host
application sees the same ActorConfigSchema and compile_actor() surface
as before, just at a different import path.
Install
pip install "cleveractors @ git+https://git.cleverthis.com/cleveragents/cleveractors-core@master"
Quick start
from cleveractors.actor import compile_actor
from cleveractors.actor.schema import ActorConfigSchema
from cleveractors.actor.yaml_loader import load_yaml_text
raw = load_yaml_text(open("my-actor.yaml").read())
config = ActorConfigSchema.model_validate(raw)
compiled = compile_actor(config)
print(compiled.metadata.node_ids)
The compiled GraphConfig is the LangGraph spec — feed it to a runtime
that understands cleveractors.langgraph.nodes.Node / Edge /
NodeConfig, which the library also provides.
What the library does NOT do
These belong to the host application (cleveragents-core, cleverrouter, your own integration) — not the library:
| Concern | Where it lives |
|---|---|
| Actor persistence (DB) | cleveragents.application.services.actor_service |
| Decision tree recording | cleveragents.application.services.decision_service |
| Invariant reconciliation runtime | cleveragents.actor.reconciliation |
| Reactive stream routing | cleveragents.reactive |
| LangChain provider lookups | cleveragents.providers.registry (or supply via cleveractors.ports.provider_registry) |
| LSP runtime | cleveragents.lsp (only the data models live here) |
| Plan lifecycle (Action / Strategize / Execute / Apply) | cleveragents.application |
License
MIT — see LICENSE.
See also CleverAgents Operations Code (CONTRIBUTING) for commit, PR, and testing conventions.