What the Runtime Event Log Actually Records

Apache Maka’s Runtime Event Log answers a specific question: how can a multi-step agent execution remain understandable after model calls, tool use, user intervention, and failure have been mixed together? This chapter follows the identities and control flow that make the answer useful. The goal is to distinguish what happened from how a screen displays it, then to see why that distinction lets Maka reconstruct meaning without promising to reproduce every provider request byte for byte.

A useful starting point is a small change request. A user asks Maka to find a failing test and fix it. The model searches for the test, reads a configuration file, proposes an edit, waits for permission, changes the file, runs the test again, and reports the result. That sounds like one conversation. Operationally, it is a chain of facts with different owners and different consequences.

The model’s search is not the same kind of event as the user’s instruction. The tool’s returned output is not the same as the model’s interpretation of that output. A permission decision is not ordinary chat text, and a stop request is not cancelled simply because a late provider message says “done.” If those distinctions disappear into a single transcript, the runtime must infer them later from prose and timing. Maka instead treats them as typed RuntimeEvents that can be ordered, correlated, and projected for different purposes.

A transcript has the wrong shape

A transcript is organized around what a person may want to read: user messages, assistant replies, perhaps a tool card in between. That is a valid product view, but it is too thin to be the execution record. An agent’s next decision depends on more than the words visible in the conversation. It may depend on the exact tool call, the result returned by the tool, whether an operation passed a permission gate, which Run produced the event, and whether the Run had already reached a terminal state.

Consider the test-fixing request again. Suppose the model calls a search tool and receives three candidate files. It then reads one file and asks for permission to edit it. A transcript may show “I found the likely cause” and later “the test now passes.” The runtime needs to retain more precise facts: the search occurred, the read returned a particular observation, a permission request was made, the user approved or rejected it, the edit was dispatched, and the test command produced a result. If the application crashes between the edit and its recorded result, the absence of a visible response cannot prove that the edit never happened.

This is why Maka calls RuntimeEvents semantic facts rather than ordinary log messages. An ordinary diagnostic log often describes what code reported after a decision was made. A RuntimeEvent participates in the decision model itself. Its content may be user or model text, thinking, a function call, a function response, or an error. Its actions may carry a permission request, a decision, usage, an artifact reference, a tool-dispatch fact, a recovery fact, or an instruction to end the invocation. Its identity and correlation fields explain where the fact belongs.

That richer shape also protects the difference between an event that is still streaming and one that has become a durable fact. The interface can show partial text as it arrives, but a partial fragment should not be mistaken for a final model message or a terminal outcome. A durable event is something later projections can rely on. A terminal event is stronger still: it closes the Run and makes the outcome explicit.

Five identities, five questions

Maka’s terminology becomes easier when each identity is treated as an answer to a different question rather than as a technical label to memorize.

Session answers: which long-lived interaction owns this work? A Session can contain many exchanges and their associated execution history. It is the durable conversational and product context in which work is observed.

Turn answers: which user-visible round is this? A Turn groups the request and the response the user understands as one exchange. A Turn can involve several model steps and tool calls.

Run answers: which concrete execution attempt produced these facts? An AgentRun is the durable envelope around one execution. It has its own lifecycle and terminal state. A later continuation may be a new Run associated with the same broader work, rather than a resurrection of the old process.

Invocation answers: which correlated model/tool flow does an event belong to? In the current production path, it is tied closely to the Run and remains important for event correlation and ordered storage. It lets the runtime group a sequence of facts and bind them to a high-water boundary when needed.

Tool operation answers: which concrete side-effect attempt is being discussed? A tool call can be paired with its result, dispatch record, and later recovery evidence. That operation-level identity becomes essential when the runtime must decide whether an absent result means “not dispatched,” “completed but not recorded,” or “unknown.”

The point is not that Maka has more identifiers than a simple chat application. The point is that one visible request crosses several causal levels. “The user asked for a fix” describes a Turn. “This process began executing it” describes a Run. “The model called the search tool” describes an invocation step. “This edit may have changed the file” describes a tool operation. If those claims are represented by one mutable status field, a later reader cannot tell which one changed.

The log carries those identities alongside ordering information. In the SQLite-backed Runtime Event store, events have an ordered sequence within their correlated execution stream, with a uniqueness constraint preventing the same invocation from receiving the same sequence position twice. That is a modest storage rule with a large architectural consequence: replay is based on committed order, not on the order in which callbacks happened to reach a user interface.

From request to durable event

The normal path begins at a stable product entry point. A caller sends a message to SessionManager, which asks RuntimeKernel to start a Turn. The Kernel creates or obtains an AgentRun and establishes the execution envelope before the model loop begins. The Run records its opening facts, associates the user message with the Turn, binds the runtime configuration needed for the attempt, and builds the prior history from RuntimeEvents.

The backend then prepares a provider request. It may select model-visible text and thinking, pair function calls with their responses, apply context policy, and adapt the result to the selected provider. This is already a projection: the provider does not receive the database rows in their storage shape. The runtime materializes a legal model history from the semantic facts.

The provider emits model text, thinking, or a tool call. When there is a tool call, ToolRuntime performs the relevant availability, argument, permission, boundary, and execution checks. The backend waits for the tool result and then sends the next model step. The loop may repeat many times. The model can change course because a command failed, ask the user a question, wait for a sandbox decision, or finish without using another tool.

At the boundary between the backend and the durable runtime, accepted backend events are mapped into canonical RuntimeEvents. Model text and thinking become model content. Tool starts and results become function calls and responses. Permission decisions and usage become typed actions. Errors, aborts, and completion become explicit facts rather than inferences from a missing callback. The mapper translates vocabulary; it does not own the Run, decide when to stop, or decide whether a fact is durable.

RuntimeKernel owns those lifecycle decisions. It routes stop requests to the active backend, associates responses with the correct Run, persists accepted RuntimeEvents, and ensures that finalization happens when the backend stream ends. The AgentRun receives the accepted facts, updates the projections that need them, and commits the terminal boundary. The product-facing event stream can therefore be live without being the authority for what finally happened.

sequenceDiagram participant U as User participant K as RuntimeKernel participant R as AgentRun participant B as Backend participant M as Model provider participant T as ToolRuntime participant L as Runtime Event Log U->>K: Send Turn request K->>R: Begin durable Run R->>L: Commit opening and user facts K->>B: Start model/tool loop B->>M: Send projected history M-->>B: Text, thinking, or tool call B->>T: Execute tool after preflight T-->>B: Tool result or interaction wait B->>M: Continue with committed result M-->>B: Final response or another step B->>K: Accepted backend event K->>R: Map and accept RuntimeEvent R->>L: Commit terminal fact

The sequence is intentionally not a component inventory. Its important edge is the one into the log. The provider stream can be incremental and the interface can be responsive, but a fact becomes part of the durable semantic history only through the Runtime’s acceptance and commit path. That gives later readers a stable basis for reconstruction even if the original connection, callback, or process disappears.

The terminal fact closes the loop

The hardest lifecycle question is often not “what did the model say?” but “did this execution end, and how?” Maka uses one terminal RuntimeEvent as the authority for that decision. A Run ends exactly once when its terminal fact is durable.

This rule handles several races cleanly. If the user stops a Run, the runtime records the aborted or cancelled outcome and does not allow a late provider completion to rewrite it as successful. If the provider reports an error, the runtime records the error and a failed terminal fact rather than waiting for a later message that might make the failure disappear. If the backend stream exhausts without a terminal fact, the Kernel creates a structured missing-terminal failure instead of leaving the Run indefinitely active or guessing from the final text.

The rule also makes startup recovery more disciplined. A process may have vanished after showing partial output but before closing its Run. On restart, the runtime reads durable events, identifies the non-terminal execution, and commits a repair outcome. It does not need to ask the user interface what it last displayed, and it does not treat a notification as proof that the Run completed. The repair may produce a clear failure or interruption without automatically continuing the work. Continuation is a separate decision that requires a safe boundary.

The terminal fact is therefore a small example of the larger principle. The screen can show a status. A callback can suggest that something happened. A mutable read model can be stale. The semantic log must still contain the fact that establishes the outcome. Views are allowed to lag or be rebuilt; they are not allowed to invent a different ending.

Replaying meaning, not bytes

Once events are durable, “replay” needs a precise meaning. Maka supports a hierarchy of replay goals, and confusing them would create false confidence.

Semantic replay means reconstructing the interaction and Runtime state from the event history. The runtime can recover user and model content, thinking, tool calls and results, permission actions, usage, errors, and terminal facts. It can answer questions such as which tool the model called before a given boundary, what response was committed, and whether the Run ended.

Provider-native replay means turning those facts into a history that a particular model provider accepts. Providers differ. Some require special reasoning signatures; tool calls and results must be paired in a provider-specific shape; some native structures may be unavailable to another model. Maka therefore builds a replay plan that checks partial events, pairing, step identity, and provider capabilities. It may preserve a provider-native representation, use a text-oriented representation, or report a deliberate degradation when the exact form cannot be carried across.

Bit-exact wire replay would mean regenerating every byte of the original request. The Runtime Event Log does not imply that promise. The final provider request also depends on the system prompt, tool schemas, provider options, model implementation, connection settings, and context-selection or compaction policy. Maka records useful identities and hashes for some of those inputs, but the event log is not a complete byte-level snapshot of every network request.

This hierarchy is not a weakness in the log-first design. It separates what the evidence can support. The event history preserves the semantic facts that matter to the Runtime. A provider adapter decides how those facts can be represented for a particular call. A future exact-replay system would need to freeze more of the surrounding configuration, not merely store more conversation text.

The distinction is also useful when reading the interface. A compact tool card may omit arguments that remain available in the underlying event. A provider request may replace old events with a validated summary when context is limited. A diagnostic view may expose correlations that a normal conversation does not. These are different representations of the same execution history. Their legitimacy depends on being derived from the canonical facts and on stating when detail has been reduced.

Maka’s Runtime Event Log therefore does more than preserve a transcript with extra fields. It gives the system a durable semantic center. SessionManager provides the stable entry point, RuntimeKernel controls active execution and terminal handling, AgentRun supplies the execution envelope, the backend advances the model/tool loop, and the mapper translates events into canonical facts. The log then supports the next model context, the interface, recovery, and later projections without asking any one of those consumers to become a second authority.

That architecture leaves a new question open. If several product entry points can observe the same durable history, who is allowed to admit new work, coordinate concurrent Sessions, and shut the system down without creating a competing Runtime? The answer begins with the Runtime Host.

References