Hmbown/CodeWhale · error

Refusing {action} from agent '{caller}' to '{agent_id}'; a c

Error message

Refusing {action} from agent '{caller}' to '{agent_id}'; a child may control only its own descendants.

What it means

The sibling check of error 1200 in `ensure_caller_controls_descendant`: after passing the self-check, the guard walks the target's parent chain (worker_record_by_ref -> parent_run_id) looking for the caller. If it reaches "root" or an unknown parent record without ever meeting the caller, the action is refused — a child may control only its own strict descendants. This blocks lateral (sibling-to-sibling) and upward (child-to-ancestor) control.

Source

Thrown at crates/tui/src/tools/subagent/mod.rs:6813

                .parent_run_id
                .as_deref()
                .or(record.spec.parent_run_id.as_deref())
            else {
                break;
            };
            if parent_ref == caller {
                return Ok(agent_id);
            }
            if parent_ref == "root" {
                break;
            }
            let Some((parent_id, _)) = self.worker_record_by_ref(parent_ref) else {
                break;
            };
            cursor = parent_id;
        }

        Err(anyhow!(
            "Refusing {action} from agent '{caller}' to '{agent_id}'; a child may control only its own descendants."
        ))
    }

    pub(super) fn ensure_caller_controls_descendant_for_session(
        &self,
        active_session_id: &str,
        agent_ref: &str,
        caller_agent_id: Option<&str>,
        action: &str,
    ) -> Result<String> {
        let agent_id = self.resolve_agent_ref_for_session(active_session_id, agent_ref)?;
        if let Some(caller) = caller_agent_id
            .map(str::trim)
            .filter(|caller| !caller.is_empty() && *caller != "root")
        {
            self.resolve_agent_ref_for_session(active_session_id, caller)?;
        }

View on GitHub (pinned to 0c42157ee5)

Solutions

  1. Run cross-branch control actions from the root session instead of a child.
  2. Spawn the target agent under the calling child so it becomes a strict descendant.
  3. Before acting, verify the target's parent_run_id chain actually reaches the caller (no pruned records).
  4. If records were reaped, restart the affected branch from root rather than working around the guard.

Example fix

// before (child tries to stop a sibling)
manager.ensure_caller_controls_descendant(sibling_ref, Some(my_id), "stop")?; // Err 1201

// after: route cross-branch control through root
manager.ensure_caller_controls_descendant(sibling_ref, None, "stop")?; // root caller
Defensive patterns

Strategy: validation

Validate before calling

// Verify the target is a strict descendant before acting:
// walk parent_run_id links from target upward; the caller must appear before "root".
fn caller_owns(manager: &SubagentManager, target: &str, caller: &str) -> bool {
    let mut cursor = target.to_string();
    let mut seen = std::collections::HashSet::new();
    while seen.insert(cursor.clone()) {
        let Some((_, rec)) = manager.worker_record_by_ref(&cursor) else { return false };
        match rec.parent_run_id.as_deref() {
            Some(p) if p == caller => return true,
            Some("root") | None => return false,
            Some(p) => cursor = p.to_string(),
        }
    }
    false
}

Type guard

fn is_strict_descendant(manager: &SubagentManager, target: &str, caller: &str) -> bool {
    caller_owns(manager, target, caller)
}

Try / catch

match manager.ensure_caller_controls_descendant(&agent_ref, caller, action) {
    Err(e) if e.to_string().contains("only its own descendants") => {
        // re-route: either run from root or skip; do not retry unchanged
    }
    other => other?,
}

Prevention

When it happens

Trigger: A child agent issues a control action targeting a sibling spawned by the same parent, one of its own ancestors, or an unrelated agent; also fires when the parent_run_id chain is broken because intermediate worker records were pruned or expired.

Common situations: Fan-out orchestrators where one child tries to coordinate its peers; stale agent refs after parent records were reaped mid-run; root-level fleet commands replayed inside a child; adoption/re-parenting logic that breaks parent_run_id links.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@0c42157ee5 (2026-08-20). Data as JSON: /api/errors/185ef633b6a4f1e6. Report an issue: GitHub.