OpenMAIC Agent Execution Events: Complete Guide to Director Graph Event Emission

OpenMAIC emits seven distinct StatelessEvent types during agent execution in its director graph, streamed from two core nodes to enable real‑time multi‑agent orchestration.

The OpenMAIC director graph is a LangGraph‑based state machine that coordinates agent conversations. During each request, it streams granular progress updates via StatelessEvent objects, allowing clients to render typing indicators, partial responses, and tool invocations as they occur. This guide breaks down every event emitted during the execution lifecycle, with source‑level precision from the THU‑MAIC/OpenMAIC repository.

Events Emitted by the Director Node

Located in lib/orchestration/director-graph.ts, the director node manages conversation flow and routing decisions. It emits two event families:

thinking Events

The director signals its internal reasoning through thinking events with distinct stage values:

  • agent_loading — Emitted when the director selects a single agent (fast‑path) or trigger agent. Payload includes agentId. Sourced at lines 20‑33.
  • director — Emitted immediately before the LLM call that determines the next speaker in multi‑agent mode. Sourced at lines 59‑71.

cue_user Event

When the director determines the user should speak—either after the sole agent responds or as a deliberate handoff—it emits cue_user with an optional fromAgentId field indicating which agent yielded control. Sourced at lines 59‑71.

Events Emitted by the Agent Generate Node

The agent generate node handles actual LLM streaming and tool execution. It emits five event types, all defined in lib/orchestration/director-graph.ts between lines 60‑197:

Event Purpose Key Payload Fields Source Lines
agent_start Signals generation beginning messageId, agentId, agentName, agentAvatar, agentColor 60‑70
text_delta Streams incremental text output content, messageId 78‑87
action Delivers structured tool commands actionId, actionName, params, agentId, messageId 123‑130
error Captures generation failures message 165‑176
agent_end Marks generation completion messageId, agentId 190‑197

The text_delta and action events are produced by parsing LLM chunks in lib/orchestration/stateless-generate.ts, which structures streamed responses into ordered sequences that the graph then emits as discrete events.

Complete Event Handling Example

Client applications consume these events through a LangGraph writer stream. Here is a type‑safe handler implementation:

import type { StatelessEvent } from '@/lib/types/chat';

function handleEvent(event: StatelessEvent) {
  switch (event.type) {
    case 'thinking':
      console.log(`Director stage: ${event.data.stage}`, event.data);
      // Render loading indicator or "AI is thinking" UI
      break;
    case 'cue_user':
      console.log('User input requested', event.data.fromAgentId);
      // Activate chat input field
      break;
    case 'agent_start':
      console.log('Agent initialized', event.data.agentName);
      // Display agent avatar and color
      break;
    case 'text_delta':
      process.stdout.write(event.data.content);
      // Append to streaming message buffer
      break;
    case 'action':
      console.log('Executing action', event.data.actionName, event.data.params);
      // Route to whiteboard or tool handler
      break;
    case 'error':
      console.error('Stream failed:', event.data.message);
      // Surface error to user with retry option
      break;
    case 'agent_end':
      console.log('Generation complete', event.data.messageId);
      // Finalize message rendering
      break;
  }
}

Event Payload Type Definitions

The StatelessEvent union type in lib/types/chat.d.ts enforces the following discriminated structure:

  • Base fields: type, data
  • thinking.data: { stage: 'agent_loading' | 'director', agentId?: string }
  • cue_user.data: { fromAgentId?: string }
  • agent_start.data: { messageId: string, agentId: string, agentName: string, agentAvatar: string, agentColor: string }
  • text_delta.data: { content: string, messageId: string }
  • action.data: { actionId: string, actionName: string, params: Record<string, unknown>, agentId: string, messageId: string }
  • error.data: { message: string }
  • agent_end.data: { messageId: string, agentId: string }

Key Source Files for OpenMAIC Agent Events

File Role in Event Lifecycle
lib/orchestration/director-graph.ts Core LangGraph implementation; all seven event types are written here via writer() calls
lib/orchestration/director-prompt.ts Constructs director LLM prompts that precede the thinking‑director event
lib/orchestration/stateless-generate.ts Parses raw LLM streams into text_delta and action sequences
lib/types/chat.d.ts Source of truth for StatelessEvent type definitions

Summary

  • OpenMAIC agent execution emits seven StatelessEvent types across two graph nodes.
  • Director node handles routing with thinking and cue_user events.
  • Agent generate node handles streaming with agent_start, text_delta, action, error, and agent_end events.
  • All events are defined and emitted in lib/orchestration/director-graph.ts via LangGraph's writer API.
  • Client handlers should switch on event.type and destructure event.data according to the discriminated union defined in lib/types/chat.d.ts.

Frequently Asked Questions

What triggers the thinking event with stage: 'director'?

This event fires immediately before the director LLM receives its prompt to select the next speaker. According to the source at lib/orchestration/director-graph.ts lines 59‑71, it precedes the generateDirectResponse call in multi‑agent conversations, providing a hook for UI loading states.

How does OpenMAIC distinguish between text and action outputs from the LLM?

The stateless-generate.ts parser inspects each streamed chunk for structural markers. Plain text becomes text_delta events; detected command structures trigger action events with full parameter serialization. Both route through the same agent generate node in director-graph.ts.

Can custom events be added to the OpenMAIC director graph?

The current StatelessEvent union in lib/types/chat.d.ts is fixed. To extend event types, you must modify the type definition and add corresponding writer() calls in director-graph.ts. The LangGraph architecture supports arbitrary event shapes through its streaming interface.

What happens to agent_end if an error event was previously emitted?

agent_end fires unconditionally after generation terminates, regardless of success or failure. Per lines 190‑197, it executes in a finally block, ensuring clients can clean up rendering state even when errors interrupt the stream.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →