# How Apache Maka Manages sessionId, turnId, runId, and invocationId: A Deep Dive into the Execution Model

> Explore how Apache Maka manages sessionId, turnId, runId, and invocationId for deterministic execution and provenance. Understand Maka's identifier hierarchy for agent conversations and tool invocations.

- Repository: [The Apache Software Foundation/maka](https://github.com/apache/maka)
- Tags: deep-dive
- Published: 2026-08-30

---

**Apache Maka generates and validates a four-tier hierarchy of identifiers—sessionId, turnId, runId, and invocationId—to maintain deterministic execution, strict ordering, and complete provenance across every agent conversation and tool invocation.**

Apache Maka is an open-source AI agent framework that relies on a strict hierarchy of identifiers to maintain deterministic execution and provenance. Understanding how **sessionId**, **turnId**, **runId**, and **invocationId** are generated, scoped, and validated is essential for debugging complex agent workflows. This article examines the actual source implementation across the runtime host and storage packages to explain the complete lifecycle of these critical identifiers.

## The Four-Tier Identifier Hierarchy

### Session ID (sessionId): The Conversation Boundary

The **sessionId** represents the logical "conversation" belonging to a user or client connection. All subsequent turns, runs, and invocations that belong to the same conversation share this identifier. In [`packages/runtime-host/src/server/connection-session.ts`](https://github.com/apache/maka/blob/main/packages/runtime-host/src/server/connection-session.ts), the session is created when a client first connects, while [`packages/runtime-host/src/server/client-capability-coordinator.ts`](https://github.com/apache/maka/blob/main/packages/runtime-host/src/server/client-capability-coordinator.ts) binds the session to specific connection capabilities. The identifier is persisted in [`packages/storage/src/sqlite-session-metadata-store.ts`](https://github.com/apache/maka/blob/main/packages/storage/src/sqlite-session-metadata-store.ts), where it functions as the primary key for session-scoped metadata and capability snapshots. This ID tracks the lifetime of the entire conversation and serves as the root scope for all downstream identifiers.

### Turn ID (turnId): The Prompt-Response Cycle

The **turnId** identifies a single round-trip of a prompt/response cycle inside a session. Each time the model asks the user for input or generates a new output, a distinct turnId is allocated. In [`packages/runtime-host/src/server/interactive-run-composer.ts`](https://github.com/apache/maka/blob/main/packages/runtime-host/src/server/interactive-run-composer.ts), the system computes a composite storage key using `${sessionId}\u0000${turnId}` to ensure uniqueness. This composite key guarantees ordering of prompts within the session and allows the UI to correlate frontend turns with underlying backend events. The turn data is stored in [`packages/storage/src/task-ledger-store.ts`](https://github.com/apache/maka/blob/main/packages/storage/src/task-ledger-store.ts), which maintains the turn’s content and metadata keyed by this composite identifier.

### Run ID (runId): The Execution Chain

The **runId** identifies the execution of a single "agent run"—a chain of turns that belong to one logical operation such as a skill execution, tool call, or user-initiated flow. The `AgentRunStore` class assigns this identifier via methods like `appendRuntimeEvent` and `readImmutableRuntimeEvents`, as demonstrated in [`packages/runtime-host/src/__tests__/execution-model-composition.test.ts`](https://github.com/apache/maka/blob/main/packages/runtime-host/src/__tests__/execution-model-composition.test.ts). Every `RuntimeEvent` record stored in [`packages/storage/src/sqlite-runtime-store.ts`](https://github.com/apache/maka/blob/main/packages/storage/src/sqlite-runtime-store.ts) carries this runId, enabling the system to group turns that belong to the same logical operation and support features like deterministic replay, copy-on-write, and debugging of specific runs.

### Invocation ID (invocationId): The Tool Call Boundary

The **invocationId** provides the finest level of granularity, uniquely identifying a specific tool invocation or internal sub-run within a run. When a tool call frame is created, the system generates `frame.invocationId` using `crypto.randomUUID()`. This ID propagates through [`packages/storage/src/sqlite-runtime-store.ts`](https://github.com/apache/maka/blob/main/packages/storage/src/sqlite-runtime-store.ts), where the authority layer validates it to enforce sandbox-boundary checks and secure provenance tracking. The invocationId ensures that each tool call can be uniquely referenced for conflict detection and deterministic replay.

## How the IDs Interact and Validate

The identifiers form a strict containment hierarchy that enforces data integrity across the storage layer. The **sessionId** serves as the top-level key for all data belonging to a user interaction. Within that session, **turnId** is scoped by the sessionId, with every turn record storing both identifiers. The **runId** is also scoped by sessionId, with each turn belonging to a specific run, allowing a single session to host many concurrent runs. The **invocationId** is scoped by both runId and turnId, ensuring each tool call inside a run receives its own unique trace identifier.

The system enforces strict invariants in [`packages/storage/src/sqlite-runtime-store.ts`](https://github.com/apache/maka/blob/main/packages/storage/src/sqlite-runtime-store.ts). Runtime events must satisfy `RuntimeEvent.sessionId === stored.sessionId` and `RuntimeEvent.runId === stored.runId` (lines 378‑383). Additionally, conflict detection prevents two runtime events from sharing the same invocationId unless they also share the same turnId (lines 3240‑3250), ensuring no duplicate tool invocations corrupt the execution state.

## Implementation Examples

The following TypeScript examples demonstrate the creation and propagation of these identifiers through the Apache Maka runtime:

```typescript
// 1️⃣ Creating a new session (packages/runtime-host/src/server/connection-session.ts)
const sessionId = await connectionSession.createSession();

// 2️⃣ Starting a new turn inside that session 
// (packages/runtime-host/src/server/interactive-run-composer.ts)
const turnId = await turnManager.nextTurnId(sessionId);
const turnKey = `${sessionId}\u0000${turnId}`; // Composite key for task-ledger indexing

// 3️⃣ Starting a new agent run (e.g., a skill execution)
// (packages/runtime-host/src/__tests__/execution-model-composition.test.ts)
const runId = await agentRunStore.startRun(sessionId);

// 4️⃣ Invoking a tool within that run with unique invocationId
// (packages/storage/src/sqlite-runtime-store.ts)
const invocationId = crypto.randomUUID(); // Generated per tool call frame
await runtimeStore.appendRuntimeEvent(sessionId, runId, {
  invocationId,
  turnId,
  // …other event fields
});

```

## Summary

- **sessionId** is created at connection time in [`connection-session.ts`](https://github.com/apache/maka/blob/main/connection-session.ts) and persisted in [`sqlite-session-metadata-store.ts`](https://github.com/apache/maka/blob/main/sqlite-session-metadata-store.ts), serving as the root identifier for all conversation data.
- **turnId** uses a composite key `${sessionId}\u0000${turnId}` in [`interactive-run-composer.ts`](https://github.com/apache/maka/blob/main/interactive-run-composer.ts) to guarantee ordering and is stored in [`task-ledger-store.ts`](https://github.com/apache/maka/blob/main/task-ledger-store.ts).
- **runId** is assigned by `AgentRunStore` and attached to every `RuntimeEvent` in [`sqlite-runtime-store.ts`](https://github.com/apache/maka/blob/main/sqlite-runtime-store.ts), grouping related turns into logical execution chains.
- **invocationId** is generated via `crypto.randomUUID()` for each tool call frame and validated by conflict detection logic in [`sqlite-runtime-store.ts`](https://github.com/apache/maka/blob/main/sqlite-runtime-store.ts) to ensure provenance integrity.
- The hierarchy enforces strict invariants: session > run > turn > invocation, with storage-layer validation preventing cross-contamination of identifiers.

## Frequently Asked Questions

### How does Apache Maka ensure that turn IDs maintain proper ordering within a session?

Apache Maka guarantees turn ordering by generating turnId values sequentially within the session scope and using the composite key `${sessionId}\u0000${turnId}` in [`interactive-run-composer.ts`](https://github.com/apache/maka/blob/main/interactive-run-composer.ts). This composite key is stored in [`task-ledger-store.ts`](https://github.com/apache/maka/blob/main/task-ledger-store.ts), ensuring that turn records are retrieved in the exact sequence they were created. The system treats the turnId as an immutable identifier for that specific prompt-response cycle.

### What prevents duplicate invocation IDs from corrupting the runtime state?

The [`sqlite-runtime-store.ts`](https://github.com/apache/maka/blob/main/sqlite-runtime-store.ts) file implements conflict detection logic (lines 3240‑3250) that rejects any runtime event attempting to reuse an invocationId within the same turn context. Because invocationId is generated using `crypto.randomUUID()` for every tool call frame, and the storage layer validates uniqueness against existing records, the system prevents duplicate tool invocations from overwriting or colliding with existing execution data.

### Can multiple runs exist within a single session simultaneously?

Yes, a single sessionId can host multiple concurrent runId values. The `AgentRunStore` assigns distinct runId identifiers for each logical operation, and [`sqlite-runtime-store.ts`](https://github.com/apache/maka/blob/main/sqlite-runtime-store.ts) maintains separate event streams for each runId under the same sessionId. This architecture allows the system to execute parallel skill flows or handle multiple user requests within one persistent conversation session.

### Where is the session metadata physically stored in the Apache Maka architecture?

Session metadata is persisted in [`packages/storage/src/sqlite-session-metadata-store.ts`](https://github.com/apache/maka/blob/main/packages/storage/src/sqlite-session-metadata-store.ts), which maintains session lifecycle data, capability snapshots from [`client-capability-coordinator.ts`](https://github.com/apache/maka/blob/main/client-capability-coordinator.ts), and provenance validation records. The sessionId serves as the primary key in this SQLite-backed store, enabling fast lookups of session-scoped configuration and state across the distributed runtime.