# How AgentRun and RuntimeKernel Handle Event Emission in Apache Maka

> Discover how Apache Maka's AgentRun orchestrates event emission and RuntimeKernel ensures durable, ordered storage with RuntimeEventStore for audit trails.

- Repository: [The Apache Software Foundation/maka](https://github.com/apache/maka)
- Tags: internals
- Published: 2026-09-12

---

**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:

```typescript
// 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.