Skip to documentation
Documentation navigation

Documentation navigation

Documentation / guides

Cancel queued input

Cancel admitted input that has not begun its Turn.

developer

CancelQueuedInput retracts a submit that was admitted to a loop inbox but has not begun a Turn. It is resolved by the target loop actor, which owns the queue; the session does not inspect and remove an item from the queue itself. That actor ownership avoids a session-side time-of-check/time-of-use race.

Command shape

type CancelQueuedInput struct {
	Header
	identity.Coordinates
	TargetCommandID uuid.UUID `json:"target_command_id,omitzero"`
}

Coordinates.SessionID and Coordinates.LoopID select the owning loop. The TargetCommandID is the original UserInput or SubagentResult header ID, which is also present in the admitting event.InputQueued.Cause.CommandID. There is no Ack; the result is observed through events.

// The runtime normally constructs this command. A consumer should prefer its
// session/delegation API, but this is the exact shape a journal adapter sees.
cmd := command.CancelQueuedInput{
	Header: command.Header{CommandID: cancelID},
	Coordinates: identity.Coordinates{SessionID: sessionID, LoopID: loopID},
	TargetCommandID: queuedInputID,
}
if err := command.ValidateCommand(cmd); err != nil {
	var invalid *command.CommandValidationError
	if errors.As(err, &invalid) {
		log.Printf("cannot retract %s: %s", invalid.Field, invalid.Rule)
	}
	return err
}

Validation requires all three coordinates/IDs plus the universal command ID. Missing SessionID, LoopID, or TargetCommandID returns a typed *command.CommandValidationError with RuleRequired.

Outcome semantics

If the target is still in the actor-owned inbox, the loop publishes an enduring event.InputCancelled with Reason: event.CancelClientRetracted and the target command ID in its cause. If it already started, folded, was returned, or was never known, the retract is a no-op. The caller infers that state from the resolution event it already observed; a no-op is not an error.

%%{init: {"theme":"dark"}}%%
sequenceDiagram
    participant App as Cancellation owner
    participant L as Target loop
    participant E as Event fan-in

    App->>L: CancelQueuedInput{TargetCommandID}
    L->>L: inspect actor-owned inbox
    alt still queued
        L->>L: remove exact command ID
        L->>E: InputCancelled{CancelClientRetracted}
    else started, folded, or unknown
        L-->>App: no point reply; no-op
    end

The cancellation command itself can be appended for audit. Its transient transport has no channel and restore can safely replay it because the actor’s queue lookup is idempotent. The target input’s own durable record is not erased; the cancellation event is the authoritative resolution.

The source is pkg/command/cancel_queued_input.go. The queue ownership and event behavior are proved by the loop managed-queue tests and pkg/command/cancel_queued_input_test.go. This page documents an internal command shape; ordinary applications should use the higher-level delegation/session operation that owns the original request.

Source and proof

← back to documentation