Documentation / guides
Delegation Policy
Describe the delegates a loop definition may address and the policy that limits them.
Delegation has a policy value and an allowlist of names:
type DelegationStyle uint8
const (
DelegationSyncOnly DelegationStyle = iota
DelegationManaged
)
type Delegation struct{ Style DelegationStyle }
func WithDelegates(names ...identity.AgentName) Option
func WithDelegation(policy Delegation) Option
WithDelegates is additive and deduplicated when the definition freezes. Empty
or whitespace-only names are rejected. DelegationSyncOnly and
DelegationManaged are the only valid styles; an unknown numeric value is a
DefinitionInvalidDelegation error.
Graph validation
The loop definition only declares possible delegate names. The Rig is the composition root that verifies each name is registered and that every loop is reachable from at least one primer. This makes an unreachable worker an early definition error rather than dead configuration.
%%{init: {"theme":"dark"}}%%
flowchart TD
P[primer definitions] --> Q[reachable queue]
Q --> L{delegate name registered?}
L -->|no| E[rig.DefinitionError: invalid_loop]
L -->|yes| Q
Q --> R{all registered loops visited?}
R -->|no| E2[rig.DefinitionError: invalid_loop]
R -->|yes| OK[construct Rig]
DelegationSyncOnly permits only the synchronous model-facing action set. The
managed style is the one used by Harness’s lifecycle-aware delegation tools;
the Rig also injects the derived agent-tool definitions into every mode of a
delegate-capable loop during binding. The injected tools are included in the
frozen topology/tool fingerprint, so changing delegation topology is restore-
visible.
planner, err := loop.Define(
loop.WithName("planner"),
loop.WithInference(client, plannerModel),
loop.WithDelegates("worker"),
loop.WithDelegation(loop.Delegation{Style: loop.DelegationManaged}),
)
if err != nil {
return err
}
rigged, err := rig.Define(
rig.WithLoops(planner, worker),
rig.WithPrimers("planner"),
rig.WithDelegationLimits(rig.DelegationLimits{Depth: 2, Quota: 4}),
rig.WithSessionStore(store),
)
The exact method name is WithLoops, not a mutable registry method. A loop
cannot dynamically authorize an arbitrary child name from model output.