# OpenMAIC Streaming Interface Event Types: Complete SSE Reference Guide

> Explore OpenMAIC's 25 distinct Server-Sent Events (SSE) covering host lifecycle signals, compatibility frames, and Pi-AI runtime messages. Get the complete SSE reference.

- Repository: [MAIC/OpenMAIC](https://github.com/THU-MAIC/OpenMAIC)
- Tags: api-reference
- Published: 2026-09-03

---

**OpenMAIC emits 25 distinct Server-Sent Events (SSE) through its streaming interface, aggregating host lifecycle signals, legacy compatibility frames, and Pi-AI runtime messages into the `WORKBENCH_EVENT_TYPES` array consumed by the React frontend.**

The **THU-MAIC/OpenMAIC** repository delivers live AI workbench updates via a Server-Sent Events stream, where each named frame type must be explicitly registered to prevent silent data loss. Understanding the complete taxonomy of **OpenMAIC streaming interface event types** is essential for debugging session flows, replaying historic logs, and building responsive UI components that react to real-time agent state changes.

## The Three Categories of OpenMAIC Streaming Events

The SSE client defined in [`lib/workbench/use-workbench-session.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/workbench/use-workbench-session.ts) concatenates three distinct source arrays to build the definitive `WORKBENCH_EVENT_TYPES` constant. Missing any entry from this aggregate list results in the EventSource API silently dropping those frames before they reach your application code.

### Host Lifecycle Events

Defined in [`lib/agent-runtime/lifecycle.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/agent-runtime/lifecycle.ts), these events track high-level session state and user interactions within the OpenMAIC workbench:

- `session_start`, `session_resumed`, `checkpoint`, `session_end`, `session_interrupted`
- `user_message`, `trace`, `thinking_end`
- `material_extraction`, `user_question`, `stage_link`
- `library_changed`, `media_ready`

These constants represent the primary lifecycle signals emitted by the host runtime during an AI-assisted session.

### Legacy Compatibility Events

Maintained in [`lib/workbench/use-workbench-session.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/workbench/use-workbench-session.ts) to ensure backward compatibility with archived session logs:

- `course_link`
- `active_stage_changed`

These legacy names prevent data loss when replaying historic sessions recorded before lifecycle constants were renamed.

### Pi-AI Runtime Events

Raw message types emitted directly by the Pi-AI agent, also defined in [`lib/workbench/use-workbench-session.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/workbench/use-workbench-session.ts):

- `message_start`, `message_update`, `message_end`
- `tool_execution_start`, `tool_execution_update`, `tool_execution_end`
- `turn_start`, `turn_end`, `agent_start`, `agent_end`

These low-level events correspond to the granular "assistant" message stream and are folded into the chat UI by the workbench reducer.

## Event Registration and the EventSource API

The frontend constructs the complete event taxonomy by spreading the three source arrays into `WORKBENCH_EVENT_TYPES`:

```typescript
// lib/workbench/use-workbench-session.ts
export const LEGACY_WORKBENCH_EVENT_TYPES = [
  'course_link',
  'active_stage_changed',
] as const;

export const WORKBENCH_EVENT_TYPES = [
  ...Object.values(LIFECYCLE),   // host lifecycle (lib/agent-runtime/lifecycle.ts)
  ...LEGACY_WORKBENCH_EVENT_TYPES,
  ...PI_EVENT_TYPES,             // raw Pi-AI messages
];

```

The `useWorkbenchStream` hook iterates over this array to register a dedicated listener for each type:

```typescript
const source = new EventSource(
  `/api/agent/sessions/${encodeURIComponent(sessionId)}/events?lastEventId=${from}`
);

for (const type of WORKBENCH_EVENT_TYPES) {
  source.addEventListener(type, onAny as EventListener);
}

```

**Critical implementation detail:** The EventSource API only dispatches frames to listeners registered for the exact `event:` name. Early versions of OpenMAIC omitted `user_question` from the aggregate list, causing a subtle bug where question cards were silently dropped before any UI code could process them (see the comment at lines 66-71 of [`use-workbench-session.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/use-workbench-session.ts)).

## Practical Implementation: Consuming OpenMAIC SSE Events

### Attaching to a Session Stream

The following pattern establishes the connection and prepares the event routing infrastructure:

```typescript
// lib/workbench/use-workbench-session.ts (excerpt)
export function useWorkbenchStream(sessionId: string | null): void {
  const applyEvent = useWorkbenchStore(s => s.applyEvent);
  const setAttached = useWorkbenchStore(s => s.setAttached);
  const source = new EventSource(
    `/api/agent/sessions/${encodeURIComponent(sessionId)}/events?lastEventId=${from}`
  );

  for (const type of WORKBENCH_EVENT_TYPES) {
    source.addEventListener(type, onAny as EventListener);
  }
  // Handler implementation omitted for brevity
}

```

### Dispatching Events by Type

Within the `onAny` callback, parse the event data and route based on the type discriminator:

```typescript
// Inside the onAny callback from lib/workbench/use-workbench-session.ts
if (parsed.type === LIFECYCLE.mediaReady) {
  const frame = parseMediaReadyFrame(parsed.data);
  if (frame) applyMediaReadyFrame(frame);
}

```

### Listening to Specific Events

For isolated components that only care about particular signals, attach a targeted listener:

```typescript
const source = new EventSource(url);
source.addEventListener('user_question', (e: MessageEvent) => {
  const payload = JSON.parse(e.data);   // { question: string, options?: … }
  // Show a modal, log analytics, etc.
});

```

### TypeScript Type Safety for Event Types

Derive a strict union type from the constant array to ensure exhaustive switch statements:

```typescript
import { WORKBENCH_EVENT_TYPES } from '@/lib/workbench/use-workbench-session';

type WorkbenchEventType = typeof WORKBENCH_EVENT_TYPES[number];
// WorkbenchEventType is now a union of all 25 string literals

```

## Summary

- **25 distinct event types** comprise the complete OpenMAIC streaming interface, divided into host lifecycle (13), legacy (2), and Pi-AI runtime (10) categories.
- **`WORKBENCH_EVENT_TYPES`** in [`lib/workbench/use-workbench-session.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/workbench/use-workbench-session.ts) aggregates all valid event names; omissions cause the EventSource API to silently drop frames.
- **Host lifecycle events** originate in [`lib/agent-runtime/lifecycle.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/lib/agent-runtime/lifecycle.ts) and track session-level state changes like `session_start` and `media_ready`.
- **Legacy names** ensure backward compatibility for replaying archived logs after constant renames.
- **Pi-AI events** provide granular visibility into the AI agent's message generation and tool execution cycles.

## Frequently Asked Questions

### What happens if an event type is not included in WORKBENCH_EVENT_TYPES?

The EventSource API dispatches SSE frames only to registered listeners. If a type is missing from the `WORKBENCH_EVENT_TYPES` array, the browser receives the frame but drops it silently, causing "invisible" events that never reach your handlers. This mechanism caused an early bug where `user_question` events were lost (documented at lines 66-71 of [`use-workbench-session.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/use-workbench-session.ts)).

### Why does OpenMAIC maintain legacy event types?

The `course_link` and `active_stage_changed` legacy names ensure historic session logs remain replayable after lifecycle constants were renamed in subsequent versions, preventing data loss across version migrations of the THU-MAIC/OpenMAIC codebase.

### How do Pi-AI runtime events differ from host lifecycle events?

Pi-AI runtime events (`message_start`, `tool_execution_end`, etc.) represent low-level assistant message streams and tool execution granularities emitted directly by the AI agent, while host lifecycle events (`session_start`, `media_ready`, etc.) track high-level session state and user interactions managed by the OpenMAIC workbench runtime.

### Can I register a listener for only one specific event type?

Yes. While the workbench registers all types automatically to ensure completeness, you can create a standalone `EventSource` connection and call `source.addEventListener('user_question', handler)` to isolate specific signals without processing the full event stream or loading the entire `WORKBENCH_EVENT_TYPES` registry.