Skip to content

symfonic.capabilities.delegation.depth

depth

How deep delegation may go, and what happens at the bottom.

Depth is the only thing standing between "an agent may delegate" and an unbounded tree of agents delegating to each other, so the arithmetic is worth stating once, in one place, rather than inline at each call site as it was.

Two rules, and both are easy to get subtly wrong:

  • The ceiling is on the child, not on the parent. max_depth=2 means a grandchild may run; it does not mean a parent at depth 2 may delegate. The test that pins this is the one that catches an off-by-one, because both readings are self-consistent — they just differ by one level of agents.
  • A depth arriving from outside is coerced, never trusted. It reaches the runtime through a state-override mapping an adopter can write, so a string, a float, None, or a negative number are all reachable. A depth that failed to parse must land at zero (a top-level run) rather than propagate as garbage that compares oddly against the ceiling.

DepthPolicy dataclass

DepthPolicy(max_depth: int)

The delegation ceiling, and the arithmetic around it.

Attributes:

Name Type Description
max_depth int

The deepest a child may run at. 0 disables delegation entirely — a supported configuration, not a misconfiguration: an operator switching delegation off for a tenant should not have to unwire the roster to do it.

admits

admits(parent_depth: Any) -> bool

True if a run at parent_depth may delegate one level down.

Source code in src/symfonic/capabilities/delegation/depth.py
def admits(self, parent_depth: Any) -> bool:
    """``True`` if a run at ``parent_depth`` may delegate one level down."""
    return self.child_depth(parent_depth) <= self.max_depth

child_depth

child_depth(parent_depth: Any) -> int

The depth a child of a run at parent_depth would run at.

Source code in src/symfonic/capabilities/delegation/depth.py
def child_depth(self, parent_depth: Any) -> int:
    """The depth a child of a run at ``parent_depth`` would run at."""
    return coerce_depth(parent_depth) + 1

refusal

refusal() -> str

The message a model gets when the ceiling stops it.

Prose, and returned rather than raised, because this is a conversational fact: the model asked for something the deployment does not allow, and it needs to read that and route around it. An exception here would end the parent's run over a decision the parent made.

Source code in src/symfonic/capabilities/delegation/depth.py
def refusal(self) -> str:
    """The message a model gets when the ceiling stops it.

    Prose, and returned rather than raised, because this is a
    conversational fact: the model asked for something the deployment does
    not allow, and it needs to read that and route around it. An exception
    here would end the parent's run over a decision the parent made.
    """
    return (
        f"Delegation refused: maximum sub-agent depth ({self.max_depth}) "
        "reached; cannot delegate further."
    )

coerce_depth

coerce_depth(value: Any) -> int

Read value as a run depth: a non-negative int, always.

Anything unparseable is zero. Failing the other way — raising, or keeping the raw value — turns an adopter's typo in a state override into either a crashed run or a comparison whose result nobody can predict.

Source code in src/symfonic/capabilities/delegation/depth.py
def coerce_depth(value: Any) -> int:
    """Read ``value`` as a run depth: a non-negative ``int``, always.

    Anything unparseable is zero. Failing the other way — raising, or keeping
    the raw value — turns an adopter's typo in a state override into either a
    crashed run or a comparison whose result nobody can predict.
    """
    try:
        return max(0, int(value))
    except (TypeError, ValueError):
        return 0