Documentation / guides
Live Loop Controller
Describe the public loop.Handle and loop.Controller surfaces bound to a live loop.
The runtime exposes a read-only view and a trusted mutation surface:
type Handle interface {
ID() uuid.UUID
Mode() ModeName
Model() model.Model
}
type Controller interface {
Handle
SetMode(context.Context, ModeName) error
Change(context.Context, ...Change) error
Interrupt(context.Context) error
}
Handle is safe to hand to read-only UI code. It identifies one live loop and
reports the active mode and model snapshot. It does not expose tools, journal
writes, actor channels, or internal runtime types.
Handle
ID() is the loop UUID assigned for the session. Mode() returns the empty
name for the base mode. Model() returns the effective model for the selected
mode and current runtime changes. The value is a snapshot; read it again after
a successful controller change instead of caching it as authority.
func render(handle loop.Handle) string {
return fmt.Sprintf("loop=%s mode=%q model=%s",
handle.ID(), handle.Mode(), handle.Model().Name)
}
Controller
SetMode accepts only predeclared names and commits at a turn boundary.
Change accepts the sealed ChangeModel and ChangeEffort values and applies
the full batch atomically. Interrupt cancels the loop’s current turn and the
entire delegate subtree. It holds admission until the subtree is idle, so a
parent waiting for a delegate cannot immediately start a replacement step.
The controller is trusted by design. Expose it only to the component that owns
session control, not to model-facing tool code. Session-wide interruption is a
different operation on session.Session; controller interruption is one loop
subtree.
%%{init: {"theme":"dark"}}%%
stateDiagram-v2
[*] --> idle
idle --> running: Session submits input
running --> idle: turn commits terminal
running --> interrupting: Controller.Interrupt
interrupting --> idle: subtree drained
idle --> changing: SetMode / Change
changing --> idle: durable boundary commit
changing --> idle: ChangeError
idle --> [*]: Session shutdown
Ownership
Controller belongs to the session runtime and is invalid after shutdown.
Every call takes a context; cancellation before the actor commits yields
ChangeContextDone. Do not call Shutdown through this interface. The owning
session.SessionController closes subscriptions, sessions, and all loop
actors in the documented lifecycle order.