Skip to content

AgentStateMachine

Orchestrator state machine that derives a high-level AgentState from three underlying sub-machines: capture, playback, and processing.

Defined in: src/core/state/AgentStateMachine.ts:90

Orchestrator state machine that derives a high-level AgentState from three underlying sub-machines: capture, playback, and processing.

Remarks

The AgentStateMachine does not define its own explicit state transition graph. Instead, it subscribes to the three sub-machines provided via initialize() and re-derives its state every time any sub-machine emits a change. The derivation follows a strict priority order (see AgentStateMachine.calculateAgentState | calculateAgentState):

  1. error — If any sub-machine is in an error state, the agent is in error.
  2. speaking — If playback is playing or buffering, the agent is speaking.
  3. thinking — If processing is processing or streaming, the agent is thinking.
  4. listening — If capture is active, the agent is listening.
  5. ready — If all sub-machines are idle or capture is stopped/paused.
  6. idle — Initial state before initialize() is called, or after reset().

Example

import { AgentStateMachine } from './AgentStateMachine';

const agentSM = new AgentStateMachine(logger);

// Observe state changes
const unsubscribe = agentSM.onStateChange((newState, oldState) => {
  console.log(`Agent: ${oldState} -> ${newState}`);
});

// Initialize with the three sub-machines
agentSM.initialize(captureSM, playbackSM, processingSM);

// Query state at any time
console.log(agentSM.getState()); // e.g. 'ready'
console.log(agentSM.is('listening')); // false

// Clean up
unsubscribe();
agentSM.dispose();

Constructors

Constructor

new AgentStateMachine(logger?): AgentStateMachine;

Defined in: src/core/state/AgentStateMachine.ts:114

Creates a new AgentStateMachine.

Parameters

ParameterTypeDescription
logger?LoggerOptional Logger instance for diagnostic output. A child logger named 'AgentStateMachine' is created if provided.

Returns

AgentStateMachine

Remarks

The machine starts in the 'idle' state. Call initialize() with the three sub-machines to begin deriving state.

Methods

dispose()

dispose(): void;

Defined in: src/core/state/AgentStateMachine.ts:375

Disposes of the agent state machine by unsubscribing from all sub-machines and clearing all registered callbacks.

Returns

void

Remarks

After disposal, references to the sub-machines are released and no further state derivations will occur. This method is safe to call multiple times.


getDiagnostics()

getDiagnostics(): {
  agentState: AgentState;
  captureState: AudioCaptureState | null;
  playbackState: PlaybackState | null;
  processingState: ProcessingState | null;
};

Defined in: src/core/state/AgentStateMachine.ts:434

Returns diagnostic information about the current agent state and the states of all three sub-machines.

Returns

{
  agentState: AgentState;
  captureState: AudioCaptureState | null;
  playbackState: PlaybackState | null;
  processingState: ProcessingState | null;
}

An object containing the current agent state and the states of the capture, playback, and processing sub-machines.

NameTypeDefined in
agentStateAgentStatesrc/core/state/AgentStateMachine.ts:435
captureStateAudioCaptureState | nullsrc/core/state/AgentStateMachine.ts:436
playbackStatePlaybackState | nullsrc/core/state/AgentStateMachine.ts:437
processingStateProcessingState | nullsrc/core/state/AgentStateMachine.ts:438

Remarks

Useful for debugging and logging. If a sub-machine has not been set (i.e. initialize() was not called), its state is reported as null.

Example

const diag = agentSM.getDiagnostics();
console.log(diag);
// {
//   agentState: 'listening',
//   captureState: 'active',
//   playbackState: 'idle',
//   processingState: 'idle'
// }

getPreviousState()

getPreviousState(): AgentState;

Defined in: src/core/state/AgentStateMachine.ts:268

Returns the agent state that was active immediately before the most recent transition.

Returns

AgentState

The previous AgentState value.

Remarks

Before any transition has occurred, this returns 'idle' (the initial state).


getState()

getState(): AgentState;

Defined in: src/core/state/AgentStateMachine.ts:256

Returns the current derived agent state.

Returns

AgentState

The current AgentState value.


initialize()

initialize(
   captureStateMachine, 
   playbackStateMachine, 
   processingStateMachine): void;

Defined in: src/core/state/AgentStateMachine.ts:132

Subscribe to the three sub-machines and begin deriving agent state.

Parameters

ParameterTypeDescription
captureStateMachineSimpleAudioCaptureStateMachineThe audio capture sub-machine tracking microphone state.
playbackStateMachineSimpleAudioPlaybackStateMachineThe audio playback sub-machine tracking TTS output state.
processingStateMachineSimpleProcessingStateMachineThe processing sub-machine tracking LLM state.

Returns

void

Remarks

This method stores references to the sub-machines, subscribes to their onStateChange events, and performs an initial state derivation. It should be called exactly once after construction. Calling it again without first calling dispose() will add duplicate subscriptions.


is()

is(state): boolean;

Defined in: src/core/state/AgentStateMachine.ts:285

Checks whether the agent is currently in the specified state.

Parameters

ParameterTypeDescription
stateAgentStateThe AgentState to compare against.

Returns

boolean

true if the current state matches, false otherwise.

Example

if (agentSM.is('speaking')) {
  muteIndicator.show();
}

isIn()

isIn(...states): boolean;

Defined in: src/core/state/AgentStateMachine.ts:302

Checks whether the agent is currently in any of the specified states.

Parameters

ParameterTypeDescription
statesAgentState[]One or more AgentState values to check.

Returns

boolean

true if the current state matches any of the provided values.

Example

if (agentSM.isIn('thinking', 'speaking')) {
  interruptButton.enable();
}

onStateChange()

onStateChange(callback): () => void;

Defined in: src/core/state/AgentStateMachine.ts:328

Registers a callback that is invoked whenever the derived agent state changes.

Parameters

ParameterTypeDescription
callbackStateTransitionCallbackThe StateTransitionCallback to invoke on state changes.

Returns

An unsubscribe function. Call it to remove the callback.

(): void;
Returns

void

Remarks

Multiple callbacks can be registered. Each callback receives the new and old state values. Callbacks are invoked synchronously in registration order. Errors thrown by individual callbacks are caught and logged but do not prevent other callbacks from executing.

Example

const unsubscribe = agentSM.onStateChange((newState, oldState) => {
  updateUI(newState);
});

// Later, when no longer needed:
unsubscribe();

reset()

reset(): void;

Defined in: src/core/state/AgentStateMachine.ts:341

Resets the agent state to 'idle' regardless of the current sub-machine states.

Returns

void

Remarks

This forces a state change notification with 'idle' as the new state. It does not reset or modify the underlying sub-machines. Typically used when tearing down a session before calling dispose().


setError()

setError(): void;

Defined in: src/core/state/AgentStateMachine.ts:357

Forces the agent state to 'error'.

Returns

void

Remarks

This is intended for external error conditions that are not captured by any of the sub-machines (e.g. a network failure detected at a higher level). If the agent is already in the 'error' state, this method is a no-op.

© 2026 CompositeVoice. All rights reserved.

Font size
Contrast
Motion
Transparency