Skip to documentation
Documentation navigation

Documentation navigation

Documentation / guides

Delegation Policy

Describe the delegates a loop definition may address and the policy that limits them.

developer

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.

Source and proof

← back to documentation