UAT: NodeDefinition.actor_ref field is ignored in actor compiler — SUBGRAPH node composition is broken #3568

Open
opened 2026-04-05 19:49:21 +00:00 by freemo · 1 comment
Owner

Metadata

  • Branch: fix/actor-compiler-subgraph-actor-ref
  • Commit Message: fix(actor-compiler): read node.actor_ref instead of config.get("actor_ref") for SUBGRAPH nodes
  • Milestone: None (backlog — see backlog note below)
  • Parent Epic: #392

Backlog note: This issue was discovered during autonomous operation
on milestone v3.2.0. It does not block milestone completion and has been
placed in the backlog for human review and future milestone assignment.


Background and Context

The specification defines hierarchical actor composition via SUBGRAPH nodes. A SUBGRAPH node embeds another actor as a nested workflow, enabling actors to be composed as a "composed LangGraph of actors and tool nodes." The NodeDefinition schema (at src/cleveragents/actor/schema.py) has a top-level actor_ref field that stores the namespaced actor reference for subgraph nodes.

However, the actor compiler (src/cleveragents/actor/compiler.py) reads config.get("actor_ref") from the node's config dict instead of reading node.actor_ref from the top-level field. Since actor_ref is a top-level field on NodeDefinition (not nested inside config), this lookup always returns None, making SUBGRAPH node composition completely non-functional.


Current Behavior

In src/cleveragents/actor/compiler.py, the _map_node function (line ~87):

subgraph=(config.get("actor_ref") if node.type == NodeType.SUBGRAPH else None),

reads actor_ref from node.config (a dict), but actor_ref is defined as a top-level field on NodeDefinition, not inside config.

Similarly, _detect_subgraph_cycles (line ~113):

ref_name = node.config.get("actor_ref", "")

has the same bug.

As a result:

  1. All SUBGRAPH nodes have subgraph=None in the compiled output
  2. subgraph_refs in CompilationMetadata is always empty for SUBGRAPH nodes
  3. Cross-actor subgraph cycle detection never fires (because ref_name is always empty)
  4. Hierarchical actor composition (actors calling other actors) is completely non-functional

Steps to Reproduce:

  1. Create a GRAPH actor YAML with a SUBGRAPH node that has actor_ref: local/my-sub-actor
  2. Call compile_actor(config) on the actor
  3. Observe that compiled.metadata.subgraph_refs is empty (should contain the actor_ref mapping)
  4. Observe that the compiled SUBGRAPH node has subgraph=None (should be the actor_ref string)

Expected Behavior

Per the specification, actors can be composed as a "composed LangGraph of actors and tool nodes." SUBGRAPH nodes should embed another actor as a nested workflow. The actor_ref field on NodeDefinition should be used to identify the referenced actor.

The fix is to read node.actor_ref (the top-level field) instead of node.config.get("actor_ref"):

# In _map_node:
subgraph=(node.actor_ref if node.type == NodeType.SUBGRAPH else None),

# In _detect_subgraph_cycles:
ref_name = node.actor_ref or ""

Acceptance Criteria

  • _map_node() reads node.actor_ref for SUBGRAPH nodes instead of node.config.get("actor_ref")
  • _detect_subgraph_cycles() reads node.actor_ref instead of node.config.get("actor_ref", "")
  • A GRAPH actor with a SUBGRAPH node correctly populates compiled.metadata.subgraph_refs
  • Cross-actor subgraph cycle detection works correctly when actor_ref is set
  • Existing tests pass; new regression tests added for SUBGRAPH node compilation

Supporting Information

Code Locations:

  • src/cleveragents/actor/compiler.py_map_node() function (~line 87): reads config.get("actor_ref") instead of node.actor_ref
  • src/cleveragents/actor/compiler.py_detect_subgraph_cycles() function (~line 113): reads node.config.get("actor_ref", "") instead of node.actor_ref or ""
  • src/cleveragents/actor/schema.pyNodeDefinition.actor_ref field (top-level, not inside config)

Related: Parent Epic #392 (Actor YAML & Compiler) covers the full actor compiler pipeline and hierarchical actor schema.


Subtasks

  • Locate _map_node() in src/cleveragents/actor/compiler.py and replace config.get("actor_ref") with node.actor_ref
  • Locate _detect_subgraph_cycles() in src/cleveragents/actor/compiler.py and replace node.config.get("actor_ref", "") with node.actor_ref or ""
  • Audit the rest of compiler.py for any other incorrect config.get("actor_ref") lookups
  • Write a unit test: GRAPH actor with a SUBGRAPH node → assert compiled.metadata.subgraph_refs is populated correctly
  • Write a unit test: GRAPH actor with a SUBGRAPH node → assert the compiled node has subgraph set to the actor_ref value
  • Write a unit test: cycle detection fires correctly when two actors reference each other via actor_ref
  • Verify coverage >= 97% via nox -s coverage_report
  • Run nox (all default sessions), fix any errors

Definition of Done

This issue is complete when:

  • All subtasks above are completed and checked off.
  • A Git commit is created where the first line of the commit message matches the Commit Message in Metadata exactly, followed by a blank line, then additional lines providing relevant details about the implementation.
  • The commit is pushed to the remote on the branch matching the Branch in Metadata exactly.
  • The commit is submitted as a pull request to master, reviewed, and merged before this issue is marked done.
  • All nox stages pass.
  • Coverage >= 97%.

Automated by CleverAgents Bot
Supervisor: Acting on behalf of: UAT Testing | Agent: ca-new-issue-creator

## Metadata - **Branch**: `fix/actor-compiler-subgraph-actor-ref` - **Commit Message**: `fix(actor-compiler): read node.actor_ref instead of config.get("actor_ref") for SUBGRAPH nodes` - **Milestone**: None (backlog — see backlog note below) - **Parent Epic**: #392 > **Backlog note:** This issue was discovered during autonomous operation > on milestone v3.2.0. It does not block milestone completion and has been > placed in the backlog for human review and future milestone assignment. --- ## Background and Context The specification defines hierarchical actor composition via SUBGRAPH nodes. A SUBGRAPH node embeds another actor as a nested workflow, enabling actors to be composed as a "composed LangGraph of actors and tool nodes." The `NodeDefinition` schema (at `src/cleveragents/actor/schema.py`) has a top-level `actor_ref` field that stores the namespaced actor reference for subgraph nodes. However, the actor compiler (`src/cleveragents/actor/compiler.py`) reads `config.get("actor_ref")` from the node's `config` dict instead of reading `node.actor_ref` from the top-level field. Since `actor_ref` is a top-level field on `NodeDefinition` (not nested inside `config`), this lookup always returns `None`, making SUBGRAPH node composition completely non-functional. --- ## Current Behavior In `src/cleveragents/actor/compiler.py`, the `_map_node` function (line ~87): ```python subgraph=(config.get("actor_ref") if node.type == NodeType.SUBGRAPH else None), ``` reads `actor_ref` from `node.config` (a dict), but `actor_ref` is defined as a top-level field on `NodeDefinition`, not inside `config`. Similarly, `_detect_subgraph_cycles` (line ~113): ```python ref_name = node.config.get("actor_ref", "") ``` has the same bug. As a result: 1. All SUBGRAPH nodes have `subgraph=None` in the compiled output 2. `subgraph_refs` in `CompilationMetadata` is always empty for SUBGRAPH nodes 3. Cross-actor subgraph cycle detection never fires (because `ref_name` is always empty) 4. Hierarchical actor composition (actors calling other actors) is completely non-functional **Steps to Reproduce:** 1. Create a GRAPH actor YAML with a SUBGRAPH node that has `actor_ref: local/my-sub-actor` 2. Call `compile_actor(config)` on the actor 3. Observe that `compiled.metadata.subgraph_refs` is empty (should contain the actor_ref mapping) 4. Observe that the compiled SUBGRAPH node has `subgraph=None` (should be the actor_ref string) --- ## Expected Behavior Per the specification, actors can be composed as a "composed LangGraph of actors and tool nodes." SUBGRAPH nodes should embed another actor as a nested workflow. The `actor_ref` field on `NodeDefinition` should be used to identify the referenced actor. The fix is to read `node.actor_ref` (the top-level field) instead of `node.config.get("actor_ref")`: ```python # In _map_node: subgraph=(node.actor_ref if node.type == NodeType.SUBGRAPH else None), # In _detect_subgraph_cycles: ref_name = node.actor_ref or "" ``` --- ## Acceptance Criteria - [ ] `_map_node()` reads `node.actor_ref` for SUBGRAPH nodes instead of `node.config.get("actor_ref")` - [ ] `_detect_subgraph_cycles()` reads `node.actor_ref` instead of `node.config.get("actor_ref", "")` - [ ] A GRAPH actor with a SUBGRAPH node correctly populates `compiled.metadata.subgraph_refs` - [ ] Cross-actor subgraph cycle detection works correctly when `actor_ref` is set - [ ] Existing tests pass; new regression tests added for SUBGRAPH node compilation --- ## Supporting Information **Code Locations:** - `src/cleveragents/actor/compiler.py` — `_map_node()` function (~line 87): reads `config.get("actor_ref")` instead of `node.actor_ref` - `src/cleveragents/actor/compiler.py` — `_detect_subgraph_cycles()` function (~line 113): reads `node.config.get("actor_ref", "")` instead of `node.actor_ref or ""` - `src/cleveragents/actor/schema.py` — `NodeDefinition.actor_ref` field (top-level, not inside `config`) **Related:** Parent Epic #392 (Actor YAML & Compiler) covers the full actor compiler pipeline and hierarchical actor schema. --- ## Subtasks - [ ] Locate `_map_node()` in `src/cleveragents/actor/compiler.py` and replace `config.get("actor_ref")` with `node.actor_ref` - [ ] Locate `_detect_subgraph_cycles()` in `src/cleveragents/actor/compiler.py` and replace `node.config.get("actor_ref", "")` with `node.actor_ref or ""` - [ ] Audit the rest of `compiler.py` for any other incorrect `config.get("actor_ref")` lookups - [ ] Write a unit test: GRAPH actor with a SUBGRAPH node → assert `compiled.metadata.subgraph_refs` is populated correctly - [ ] Write a unit test: GRAPH actor with a SUBGRAPH node → assert the compiled node has `subgraph` set to the `actor_ref` value - [ ] Write a unit test: cycle detection fires correctly when two actors reference each other via `actor_ref` - [ ] Verify coverage >= 97% via `nox -s coverage_report` - [ ] Run `nox` (all default sessions), fix any errors --- ## Definition of Done This issue is complete when: - All subtasks above are completed and checked off. - A Git commit is created where the **first line** of the commit message matches the Commit Message in Metadata exactly, followed by a blank line, then additional lines providing relevant details about the implementation. - The commit is pushed to the remote on the branch matching the **Branch** in Metadata exactly. - The commit is submitted as a **pull request** to `master`, reviewed, and **merged** before this issue is marked done. - All nox stages pass. - Coverage >= 97%. --- **Automated by CleverAgents Bot** Supervisor: Acting on behalf of: UAT Testing | Agent: ca-new-issue-creator
freemo added this to the v3.2.0 milestone 2026-04-05 20:04:16 +00:00
Author
Owner

Issue triaged by project owner:

  • State: Verified
  • Priority: High — SUBGRAPH node composition is completely non-functional. The actor compiler reads config.get("actor_ref") instead of node.actor_ref, causing all SUBGRAPH nodes to have subgraph=None. This breaks hierarchical actor composition entirely.
  • Milestone: v3.2.0
  • Story Points: 2 — S — Simple field reference fix in two locations (_map_node and _detect_subgraph_cycles), plus regression tests. The fix is clearly identified.
  • MoSCoW: Should Have — Hierarchical actor composition is a core spec feature ("composed LangGraph of actors and tool nodes"). While the fix is trivial, the feature it enables is architecturally significant. Not Must Have because the milestone can demo other actor functionality without subgraph composition.
  • Parent Epic: #392 (dependency link already exists)

Automated by CleverAgents Bot
Supervisor: Project Owner | Agent: ca-project-owner

Issue triaged by project owner: - **State**: Verified - **Priority**: High — SUBGRAPH node composition is completely non-functional. The actor compiler reads `config.get("actor_ref")` instead of `node.actor_ref`, causing all SUBGRAPH nodes to have `subgraph=None`. This breaks hierarchical actor composition entirely. - **Milestone**: v3.2.0 - **Story Points**: 2 — S — Simple field reference fix in two locations (`_map_node` and `_detect_subgraph_cycles`), plus regression tests. The fix is clearly identified. - **MoSCoW**: Should Have — Hierarchical actor composition is a core spec feature ("composed LangGraph of actors and tool nodes"). While the fix is trivial, the feature it enables is architecturally significant. Not Must Have because the milestone can demo other actor functionality without subgraph composition. - **Parent Epic**: #392 (dependency link already exists) --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: ca-project-owner
freemo removed this from the v3.2.0 milestone 2026-04-06 20:51:04 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Blocks
#392 Epic: Actor YAML & Compiler
cleveragents/cleveragents-core
Reference
cleveragents/cleveragents-core#3568
No description provided.