hurui200320 dd6c20df5d
CI / dead_code (pull_request) Successful in 43s
CI / typecheck (pull_request) Successful in 1m13s
CI / unit_tests (pull_request) Successful in 1m11s
CI / lint (pull_request) Successful in 1m16s
CI / security (pull_request) Successful in 1m15s
CI / coverage (pull_request) Successful in 1m16s
CI / build (pull_request) Successful in 26s
CI / typecheck (push) Successful in 1m3s
CI / unit_tests (push) Successful in 1m2s
CI / lint (push) Successful in 1m6s
CI / dead_code (push) Successful in 27s
CI / security (push) Successful in 57s
CI / coverage (push) Successful in 59s
CI / build (push) Successful in 37s
fix(compiler): thread actor-level system_prompt into graph node metadata
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
2026-05-22 06:05:16 +00:00

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.

S
Description
CleverActors — pure Python library for declarative actor definitions: YAML schema, Jinja2 preprocessing, validation, and LangGraph compilation. Extracted from cleveragents-core.
Readme 4 MiB
Languages
Python 81.4%
Gherkin 16.3%
RobotFramework 2%
Shell 0.3%