-
Notifications
You must be signed in to change notification settings - Fork 0
Execution Model
How work moves through stud-cli. Turns, stages, concurrency, cancellation, backpressure.
This page is the why and how-they-relate. The stage sequence itself lives in Message Loop.
A turn is one user-visible pass of the message loop: input comes in, a request is composed and dispatched to a Provider, the response is streamed, tool calls are executed, output is rendered. Turns start and end at clear boundaries.
| Boundary | What triggers it |
|---|---|
| Turn start | A RECEIVE_INPUT event: user text or an incoming command; or, for an attached SM, a sequential stage execution beginning Setup; or the scheduler spawning a parallel fan-out group (siblings + optional join — one SessionTurnStart for the whole compound turn). |
| Turn end | The RENDER stage completes for the last response of the turn; or (sequential SM turn) the stage's Exit runs; or (parallel SM fan-out turn) the last sibling's Exit runs when no join is declared, or the join stage's Exit runs when one is. |
A session is a sequence of turns. See Session Lifecycle.
Each turn walks through a fixed sequence of turn stages. These are the kernel's ABI for the message loop; extensions attach via Hooks.
stateDiagram-v2
[*] --> RECEIVE_INPUT: turn start
RECEIVE_INPUT --> COMPOSE_REQUEST: input ready
COMPOSE_REQUEST --> SEND_REQUEST: request built
SEND_REQUEST --> STREAM_RESPONSE: dispatched
STREAM_RESPONSE --> TOOL_CALL: tool emitted
STREAM_RESPONSE --> RENDER: no tool
TOOL_CALL --> COMPOSE_REQUEST: continuation
TOOL_CALL --> RENDER: terminal
RENDER --> [*]: turn end
Per-stage responsibilities — names and intent only — are detailed in Message Loop.
Every turn stage has pre and post hook points. Three sub-kinds of hook are allowed: transform, observer, guard. See Hook Taxonomy.
Turn stage ≠ SM stage. The five turn stages above (
RECEIVE_INPUT…RENDER) are the kernel message-loop stages, unrelated to an SM's Stage pipeline. When an SM is attached, each sequential SM stage execution walks through these turn stages as its own session turn; a parallel fan-out group bundles its siblings (and the optionaljoin) into a single compound session turn. See Stage Executions § Turn boundary and persistence.
At each turn stage's boundary core runs, in order:
-
Pre-stage guards. Any
guardhook attached to the stage's pre point votes. A single deny blocks the stage. - Stage body. Core runs the stage. Transform hooks rewrite payloads in order; observers fire.
Post-stage hooks fire only after the stage body completes. If a stage is blocked at step 1, its post hooks do not fire either (there was no body to observe).
The attached SM does not vote on each turn stage boundary. Its authority is concentrated at two places:
-
Turn definition. When an SM stage execution is the turn, the stage's rendered body is the system prompt, the tool manifest is
allowedToolsplus the injected completion channel, andturnCapbounds how many LLM turnsActmay issue. See Stage Executions. -
Tool-call approval inside
TOOL_CALL. The stage'sallowedTools(plus any matchinggrantStageTooltoken) determines whether a proposed call runs, is refused, or auto-issues an interaction request for a grant. This is the SM precedence axis in Tool Approvals. Consuming a grant token is SM-approve; the security-mode gate is bypassed; guard hooks still run.
Invariant. For gated tool calls, SM authority runs before the mode gate and before guards (guard-deny still wins in any mode). Hooks observe or transform what core allowed to happen; they do not reorder SM authority.
Most of a turn is sequential. Concurrency appears in a few well-defined places.
The provider may emit multiple tool calls in one response. Core dispatches them with bounded parallelism. Each tool call runs its own pre/post hooks and, where applicable, its own approval prompt.
Approval prompts are serialized by core in tool-call order. Each prompt then fans out through the active interactors, and the first response wins — a single UI never faces two approval dialogs at once. See Parallel Tool Approvals flow.
For continuation accounting, that whole batch still belongs to the same continuation round. The round count advances only if core sends the tool results back to the provider and the provider emits another tool-calling response.
STREAM_RESPONSE overlaps with downstream consumers through the event bus: tokens are published as they arrive. Tool calls emitted mid-stream are buffered until the provider signals the call is complete, then dispatched to TOOL_CALL.
Hooks within a stage run in ordering-manifest order (see Extension Discovery). Transform hooks pass their output to the next transform hook's input. Observer hooks run concurrently with each other and must not mutate state observable to others. Guard hooks run in order and short-circuit on first deny.
Cancellation propagates downward. Three scopes:
| Scope | Cancels | Triggered by |
|---|---|---|
| Session | All active turns in the session | Session close, fatal error, user quit |
| Turn | The current turn and every stage/tool inside it | User interrupt (Ctrl-C), guard deny, provider failure. turnCap is not a turn-cancel trigger — it ends Act with capHit: true on a normal Act-ending branch (see Message Loop — Continuation loop). |
| Tool | One tool call; the rest of the parallel group continues | User denies one approval; hook guard denies one tool; tool-level timeout |
A cancelled scope fires cancel via the Host API cancellation token that scope created. Downstream extensions are responsible for observing the token and winding down cooperatively.
See Concurrency and Cancellation for the detailed propagation rules and retry semantics.
The LLM produces tokens faster than downstream consumers can render, log, or persist. Core applies backpressure at three points:
- Event bus. Publishers write into a bounded queue per subscriber. A slow subscriber sees its queue fill; it drops observer events (never authoritative messages) and emits a diagnostic. See Event Bus.
- Interaction protocol. Requests block the requester until a response arrives. There is no timeout by default; an SM may enforce one. See Interaction Protocol.
- Tool execution. Tools emit progress through observer events; core does not drain these faster than the slowest observer. Tool bodies that block the process block the turn — this is a design choice, not a bug. Heavy tools should use the Host API's cancellation token and yield.
stud-cli is single-session-at-a-time in v1. Inside a session:
-
Turns do not overlap. A new turn cannot start until the current turn's
RENDERhas fired (non-SM turn) or the current stage execution / fan-out group has finished itsSessionTurnEnd(SM-driven turn). -
Parallel fan-out runs as one compound turn. When an attached SM's
Next()returnsexecution: "parallel", every sibling plus the optionaljoinrun under a singleSessionTurnStart/SessionTurnEndpair. Individual siblingExits do not fire session turn events. See Stage Executions § Turn boundary and persistence. - Commands can run concurrently with a turn — they act on the main session but do not gate turns, and the turn does not gate them. See Command Model. Commands that mutate session state use Host API session accessors which serialize mutations.
- Hot reload holds at stage boundaries. A reload request waits for the current stage (or current compound fan-out turn, when one is active) to complete, swaps the extension set, and revises the session manifest. Some categories cannot reload mid-turn; see Extension Reloading.
| Surface | Role in the execution model |
|---|---|
| State Machines | Author the pipeline. A sequential SM stage execution is itself a turn; a parallel fan-out group (siblings + optional join) runs as a single compound turn. See Stage Executions § Turn boundary and persistence. Authoritative for tool-call approval via the stage's allowedTools + grantStageTool tokens. |
| Hooks | Turn-stage-scoped interception: transform (rewrite), observer (witness), guard (vote). |
| Commands | Orthogonal to turns. Act on the main session via Host API session accessors. |
| Event Bus | Projection channel. Tokens, stage transitions, audit events. Never authoritative. |
| Interaction Protocol | Typed request/response where core blocks until an active interactor answers. |
| Providers | Own the SEND_REQUEST and STREAM_RESPONSE bodies on behalf of core. |
| Tools | Run inside the TOOL_CALL stage. Local or remote (MCP). |
Stage order is deterministic. Hook order within a stage is deterministic (ordering manifest). Approval-prompt order is deterministic (tool-call emission order).
Non-deterministic sources visible in the execution model:
- Sampling inside the provider.
- Retries on provider or tool failure.
- Compaction (if the turn crosses the compaction threshold). See Compaction and Memory.
- User approvals (wall-clock timing, user decision).
- Clock and time.
A State Machine aiming for replay-level determinism should structure its session to avoid these surfaces or handle them explicitly. See Determinism and Ordering for the full list.
- Execution Model
- Message Loop
- Concurrency and Cancellation
- Error Model
- Event and Command Ordering
- Event Bus
- Command Model
- Interaction Protocol
- Hook Taxonomy
- Host API
- Extension Lifecycle
- Env Provider
- Prompt Registry
- Resource Registry
- Session Lifecycle
- Session Manifest
- Persistence and Recovery
- Stage Executions
- Subagent Sessions
- Contract Pattern
- Versioning and Compatibility
- Deprecation Policy
- Capability Negotiation
- Dependency Resolution
- Validation Pipeline
- Cardinality and Activation
- Extension State
- Conformance and Testing
- Providers
- Provider Params
- Tools
- Hooks
- UI
- Loggers
- State Machines
- SM Stage Lifecycle
- Stage Definitions
- Commands
- Session Store
- Context Providers
- Settings Shape
- Trust Model
- Project Trust
- Extension Isolation
- Extension Integrity
- LLM Context Isolation
- Secrets Hygiene
- Security Modes
- Tool Approvals
- MCP Trust
- Sandboxing
- Configuration Scopes
- Project Root
- Extension Discovery
- Extension Installation
- Extension Reloading
- Headless and Interactor
- Determinism and Ordering
- Launch Arguments
- Network Policy
- Platform Integration
Tools
UI
Session Stores
Loggers
Providers
Hooks
Context Providers
Commands
- First Run
- Default Chat
- Tool Call Cycle
- Hook Interception
- Guard Deny Reproposal
- State Machine Workflow
- SM Stage Retry
- Hot Model Switch
- Capability Mismatch Switch
- Session Resume
- Session Resume Drift
- Approval and Auth
- Interaction Timeout
- Headless Run
- Parallel Tool Approvals
- Subagent Delegation
- Scope Layering
- Project First-Run Trust
- Reload Mid-Turn
- Compaction Warning
- MCP Remote Tool Call
- MCP Prompt Consume
- MCP Resource Bind
- MCP Reconnect