Maka Session States Explained: Lifecycle vs. CUA Statuses
Maka sessions operate in two distinct state dimensions: three durable lifecycle states (absent, live, terminal) that track graph-level existence, and seven CUA statuses (unobserved, active, intervention_debounce, reobserve_required, screen_locked, blocked_url, user_stopped) that govern UI interaction permissions.
The apache/maka repository defines a dual-layer state model that separates long-term session persistence from real-time UI observation. Understanding how these Maka session states interact is critical for building reliable AI agents that can gracefully handle interruptions, policy violations, and completion events. The runtime coordinates these states through specific TypeScript classes found in the packages/runtime/src directory.
Session Lifecycle States: Absent, Live, and Terminal
At the durable graph level, every Maka session maintains a lifecycle state stored in the session header. The AgentGraphCoordinator class exposes this through the readSessionState() method, which returns one of three possible values.
In packages/runtime/src/stream-graph-coordinator.ts (lines 23-33), the implementation distinguishes:
absent: The session header does not exist. This indicates either a brand-new session that has not been initialized or a previously deleted session.live: The session is currently active and its graph can be reconciled. Only live sessions accept new actions or observations.terminal: The session has reached a finished or stopped state and will no longer produce new graph activity. Terminal sessions are immutable.
This lifecycle state determines whether the runtime should attempt to drive the session forward or treat it as complete.
CUA Session Statuses: The UI Observation Layer
While the lifecycle state tracks existence, the CUA (Computer-Use-Agent) session status tracks the fine-grained UI state required for desktop automation. Defined in packages/runtime/src/cua-session-state.ts (lines 20-28) within the CUA_SESSION_STATUSES constant, these seven statuses control when actions are permitted:
unobserved: The session has not yet captured a UI frame. No actions can be taken until the first observation.active: Normal operation. The runtime may execute actions and observations.intervention_debounce: User intervention was detected. A short cooldown period must elapse before re-observing to avoid racing with human input.reobserve_required: The UI has changed significantly and must be refreshed before further actions.screen_locked: The host machine's screen is locked, preventing UI interaction.blocked_url: A policy-blocked URL was detected. This is a terminal status that stops the session.user_stopped: The user explicitly terminated the session. This is also a terminal status.
The CuaSessionState class encapsulates these transitions and validates every action through its beforeAction() and beforeObservation() methods.
How Lifecycle and CUA States Interact
The two state systems operate in a hierarchy. The lifecycle state answers "Does this session exist and can it run?" while the CUA status answers "Is the UI ready for the next action?"
When a session is live at the lifecycle level, the runtime continuously monitors the CUA status. If the CUA status transitions to a terminal condition—specifically blocked_url or user_stopped—the AgentGraphCoordinator propagates this to the lifecycle layer. As implemented in #readSessionStateForGraph, this promotion causes the durable session header to update to terminal, ensuring the session stops permanently even if the CUA object is garbage collected.
Non-terminal CUA statuses like intervention_debounce or screen_locked do not affect the lifecycle state; they merely pause execution until the condition clears.
Querying Maka Session States in Code
You can inspect both state dimensions programmatically using the runtime API.
Query the Durable Lifecycle State
Use AgentGraphCoordinator.readSessionState() to check graph-level existence:
// Assume coordinator is an AgentGraphCoordinator instance
const rootSessionId = 'sess-123';
const state = await coordinator.readSessionState(rootSessionId);
// state: 'absent' | 'live' | 'terminal'
if (state === 'live') {
// Proceed with graph reconciliation
} else if (state === 'terminal') {
// Session completed or stopped
}
Inspect CUA Session Status
Create a CuaSessionState instance to monitor UI-level readiness:
import { CuaSessionState } from '@maka/runtime';
const cua = new CuaSessionState('sess-123');
const snap = cua.snapshot(); // { status: 'active', generation: 4 }
// Validate before executing an action
const leaseResult = cua.beforeAction();
if (leaseResult.ok) {
console.log('Action lease granted:', leaseResult.lease.generation);
} else {
console.warn('Action blocked:', leaseResult.reason); // e.g., 'screen_locked'
}
Handle Terminal Transitions
Detect policy violations or user stops and verify lifecycle propagation:
// Simulate a policy block
cua.blockedUrlDetected();
// CUA status immediately reflects the block
console.log(cua.snapshot().status); // -> 'blocked_url'
// Lifecycle eventually synchronizes to terminal
const lifecycle = await coordinator.readSessionState('sess-123');
console.log(lifecycle); // -> 'terminal'
Key Implementation Files
The complete state model spans several packages:
packages/runtime/src/stream-graph-coordinator.ts: ImplementsreadSessionState()and the lifecycle transition logic forabsent,live, andterminal.packages/runtime/src/cua-session-state.ts: DefinesCUA_SESSION_STATUSESand theCuaSessionStateclass that manages UI observation state.packages/storage/src/session-repository.ts: Persists durableSessionStateobjects to storage, backing the coordinator's queries.packages/runtime/src/session-manager.ts: Exposes higher-level APIs likegetPlanState()that aggregate both lifecycle and CUA information.
Summary
- Maka uses two complementary state systems: durable lifecycle states (
absent,live,terminal) and transient CUA statuses (unobservedthroughuser_stopped). - The lifecycle state persists in the session header and determines if a graph can be driven.
- CUA statuses control real-time UI interaction permissions and are checked before every action.
- Terminal CUA statuses (
blocked_url,user_stopped) automatically promote the lifecycle toterminal. - Query states via
AgentGraphCoordinator.readSessionState()for persistence andCuaSessionState.snapshot()for UI readiness.
Frequently Asked Questions
What is the difference between lifecycle states and CUA statuses in Maka?
Lifecycle states (absent, live, terminal) are durable properties stored in the session header that indicate whether a graph exists and can accept new operations. CUA statuses (active, screen_locked, etc.) are runtime UI observation states managed by the CuaSessionState class that determine if the specific action can execute right now. A session can be live at the lifecycle level but temporarily screen_locked at the CUA level.
How do I check if a Maka session is still active programmatically?
Call await coordinator.readSessionState(sessionId) where coordinator is an AgentGraphCoordinator instance. If the returned value is 'live', the session accepts new graph operations. For UI-specific readiness, instantiate CuaSessionState and call snapshot().status to verify it equals 'active' before attempting interactions.
What causes a Maka session to enter the terminal state?
A session becomes terminal either through explicit user action (user_stopped CUA status), policy enforcement (blocked_url CUA status), or natural completion of all tasks. According to the source code in stream-graph-coordinator.ts, both blocked_url and user_stopped CUA statuses trigger an immediate transition of the durable lifecycle to terminal.
Where are Maka session states stored and managed?
The durable lifecycle state persists in the storage layer via packages/storage/src/session-repository.ts, while the ephemeral CUA status resides in memory within the CuaSessionState class. The AgentGraphCoordinator bridges these layers, reading from storage to determine absent/live/terminal and querying the in-memory CUA object for UI-level status during active sessions.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →