How AgentRun and RuntimeKernel Handle Event Emission in Apache Maka

AgentRun orchestrates high‑level event emission while RuntimeKernel provides durable, ordered storage via RuntimeEventStore to guarantee authoritative audit trails.

In Apache Maka, the emission of events during an agent's execution turn relies on a strict separation between orchestration and persistence logic. The AgentRun class manages the lifecycle of a single turn—from user request to model response—emitting both runtime events for the system ledger and session events for the UI. It delegates the actual durable storage to the RuntimeKernel, which owns the authoritative RuntimeEventStore and enforces ordering, quiescence, and hand‑off semantics.

The Event Emission Architecture

AgentRun as the High‑Level Orchestrator

AgentRun represents a single turn of an agent conversation. Its primary responsibility is to generate runtime events (the low‑level ledger of what happened) and session events (the user‑visible transcript). Rather than writing directly to storage, the AgentRun buffers events and delegates persistence calls to the RuntimeKernel’s RuntimeEventStore. This design allows the kernel to enforce durability contracts while the run logic focuses on mapping model outputs to meaningful events.

RuntimeKernel as the Authoritative Ledger

The RuntimeKernel sits underneath the AgentRun and provides the authoritative event ledger (RuntimeEventStore). It guarantees durability, ordering, and hand‑off semantics. When the AgentRun decides something should be recorded, it invokes methods like appendRuntimeEvent on the kernel’s store. The kernel also enforces quiescence—a required quiet state—before allowing session snapshots, ensuring a consistent view of session state across hand‑offs.

Step‑by‑Step Event Flow

The interaction between AgentRun and RuntimeKernel follows a strict lifecycle during a single turn:

1. Turn Initialization with AgentRun.begin() When a turn starts, AgentRun.begin() creates an initial runtime event via recordInitialRuntimeEvent and immediately delegates to recordRuntimeEvents. The kernel’s appendRuntimeEvent persists this in the RuntimeEventStore, establishing the turn’s entry in the durable ledger.

2. Mapping UI Events via acceptMappedEvent() As the agent produces output, AgentRun.acceptMappedEvent() receives a SessionEvent (for the UI) and its corresponding RuntimeEvent (for the ledger). It forwards the runtime component to recordRuntimeEvents, where the kernel writes the event and optionally marks it as terminal or durable using flags like requireTerminalWrite and requireDurableWrite.

3. Partial Streaming and Buffering Non‑terminal model text (streaming tokens) is buffered internally in runtimePartialBuffer. The AgentRun periodically flushes these via flushRuntimePartialBuffer, where the RuntimeKernel batches partial events according to RUNTIME_PARTIAL_FLUSH_INTERVAL_MS and size limits, then appends them atomically to prevent ledger fragmentation.

4. Enforcing Quiescence Before Snapshots Before a session snapshot can be taken, the RuntimeKernel must enter a quiescent state. If a session attempts to snapshot prematurely, the kernel throws Runtime Kernel does not expose Session quiescence authority. The AgentRun checks hasCommittedHandoff() and settleStopTerminal() to verify the kernel has reached this stable state.

5. Handoff Coordination with requestHandoff() When pausing for compositional hand‑offs, AgentRun.requestHandoff() creates an AgentRunHandoffRequest. The kernel’s RunHandoffGate validates the boundary and records the pause as a runtime event with actions: { handoffPause: … }. The kernel ensures the run composition is durably committed before the handoff proceeds.

6. Finalization and Terminal Claims In AgentRun.finalize(), the method invokes recordRuntimeEvents for the terminal event and then calls commitMessageProjection. The kernel stores this terminal runtime event and updates the ledger’s terminal claim, signaling that the turn is complete for all subsequent readers.

Durability Guarantees and Failure Handling

The RuntimeKernel distinguishes between two durability modes that affect how AgentRun handles writes:

Canonical Durability When RuntimeEventStore operates with durability: 'canonical', writes are treated as authoritative and mandatory. According to the source in agent‑run.ts (lines 122‑124), the AgentRun checks runtimeEventStoreAvailable and throws if the store is unavailable for a terminal write. This ensures that critical terminal events cannot be lost.

Best‑Effort Durability For non‑critical events, the AgentRun may continue even if the store temporarily fails. As implemented in agent‑run.ts (lines 84‑92), the system retries on the next write attempt, lifting the latch if the store becomes reachable again via loadTurnRuntimeEvents. This prevents transient network issues from crashing the entire agent turn while maintaining eventual consistency.

Implementation Example: Emitting Events in Practice

The following TypeScript demonstrates the typical pattern for creating a run, emitting events, and handling handoffs:

// 1️⃣ Create a new AgentRun (simplified)
const run = new AgentRun({
  sessionId,
  header,
  userInput,
  newId: () => crypto.randomUUID(),
  now: () => Date.now(),
  hooks,
  runtimeEventStore,   // ← provided by RuntimeKernel
  runStore,
});

// 2️⃣ Begin the turn – emits the initial runtime event
await run.begin();   // internally calls recordInitialRuntimeEvent → RuntimeKernel

// 3️⃣ Emit a model text fragment (partial stream)
run.acceptMappedEvent(
  { type: 'assistant', text: 'Hello' },           // SessionEvent
  { id: 'ev-123', role: 'model', content: { kind: 'text', text: 'Hello' } }, // RuntimeEvent
);

// 4️⃣ Commit a handoff (co‑operative pause)
const handoff = run.requestHandoff({ remainingSteps: 5, rootRunId: run.runId }, abortSignal);
await handoff.sealed;      // waits for the kernel to acknowledge the pause
handoff.commit();          // kernel records the handoff pause event

Key Source Files

Understanding the implementation details requires examining these specific files in the Apache Maka repository:

  • packages/runtime/src/agent‑run.ts – Defines the AgentRun class, including recordRuntimeEvents, acceptMappedEvent, requestHandoff, and durability checks at lines 122‑124 and 84‑92.

  • packages/runtime/src/runtime‑kernel.ts – Implements the RuntimeKernel, RunHandoffGate, and ledger interaction logic that enforces ordering and quiescence.

  • packages/runtime/src/runtime‑event‑store.ts – Provides the appendRuntimeEvent, readRuntimeEvents, and durability flag interfaces used by the kernel.

  • packages/runtime/src/quiescent‑session‑snapshot.ts – Contains the snapshot logic that throws Runtime Kernel does not expose Session quiescence authority when the kernel is not in a stable state.

Summary

  • AgentRun drives high‑level event emission during a turn, creating both runtime ledger entries and user‑facing session events.
  • RuntimeKernel owns the durable RuntimeEventStore, ensuring authoritative ordering, terminal write guarantees, and quiescence enforcement.
  • Event emission follows a strict lifecycle from begin() through finalize(), with the kernel handling buffering, batching, and durability modes.
  • Canonical durability requires the store to be available for terminal writes, while best‑effort allows retry logic for non‑critical events.
  • Hand‑off coordination relies on the kernel’s RunHandoffGate to record pause events durably before composition changes.

Frequently Asked Questions

What is the difference between runtime events and session events in Apache Maka?

Runtime events are low‑level ledger entries stored in the RuntimeEventStore that record exactly what happened during a turn for debugging and replay. Session events are higher‑level, user‑visible transcripts derived from the runtime events but formatted for UI consumption. AgentRun produces both, delegating the durable storage of runtime events to the RuntimeKernel while managing session projections separately.

How does RuntimeKernel ensure event durability?

The RuntimeKernel enforces durability through the RuntimeEventStore interface, which supports durability: 'canonical' for authoritative writes. It guarantees atomic appends, enforces terminal write commitments before handoffs, and validates quiescence before allowing session snapshots. This ensures that once an event is acknowledged, it survives process restarts and can be read consistently by downstream consumers.

What happens if the RuntimeEventStore is unavailable during a terminal write?

If the store is unavailable during a terminal write and canonical durability is enabled, AgentRun checks runtimeEventStoreAvailable and throws an error (as seen in agent‑run.ts lines 122‑124). This prevents the system from marking a turn as complete when the authoritative ledger cannot record the terminal event, ensuring data integrity over availability in critical paths.

What is quiescence and why does it matter for snapshots?

Quiescence is a state where the RuntimeKernel has completed all pending writes and reached a stable, consistent checkpoint. It matters for snapshots because the kernel must guarantee that no partial events are in flight before capturing session state. If a snapshot is requested before quiescence, the kernel throws Runtime Kernel does not expose Session quiescence authority, preventing corrupted or incomplete snapshots during active event emission.

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 →