Apache Maka Model Projection Transition System: Immutability and Safe Context Updates

The Apache Maka model projection transition system enables safe, deterministic updates to model-visible data by creating immutable transition records that replace specific projection parts while preserving an append-only event ledger.

In Apache Maka, a lightweight framework for building reliable AI agents, every LLM interaction is stored as an immutable event. When model-visible data—such as a tool call result—must be changed after it has been recorded, the framework cannot simply edit the original event. Instead, Maka employs a Model‑Projection‑Transition System that expresses modifications as new ledger entries, maintaining both safety and replayability.

Core Concepts of the Model Projection Transition System

The system rests on five interconnected principles that govern how context evolves over time.

Concept Purpose
Append‑only ledger All runtime facts persist as AgentRunEvent records; history is never overwritten
Projection A read‑only view derived from durable events, consumed by UI components and model context builders
Transition record A model_projection_transition_recorded event that identifies a projection part to replace, carries replacement data, and includes the source digest for validation
Deterministic reduction A reducer processes transition records in order, recreating the current projection state
Idempotent creation The transition ID is content‑derived, ensuring duplicate writes produce identical records

These concepts work together to guarantee that context updates are safe, replayable, and concurrent‑writer aware.

How the Transition System Works

Defining the Target with ModelProjectionTransitionTarget

A transition must precisely locate the projection part to replace. The ModelProjectionTransitionTarget interface in packages/core/src/model-projection-transition.ts specifies this address:

// packages/core/src/model-projection-transition.ts
export interface ModelProjectionTransitionTarget {
  runtimeEventId: string;
  part: 'tool_result';
  toolCallId: string;
  toolName: string;
}

This four‑tuple identifies: the originating event, the projection part type (tool_result is the only supported part currently), the specific tool call, and the tool name.

Building a Transition Record

The buildModelProjectionTransition function constructs a complete transition object. It computes SHA‑256 digests of both the source and replacement projections, then derives a deterministic transitionId from the record's content:

export function buildModelProjectionTransition(
  input: BuildModelProjectionTransitionInput,
): ModelProjectionTransition {
  const sourceProjectionDigest = durableToolResultProjectionDigest(
    decodeDurableToolResultProjection(input.sourceProjection),
  );
  // ...
  const transitionId = `mptransition-${nodeCrypto
    .createHash('sha256')
    .update(stableJsonStringify(body))
    .digest('hex')
    .slice(0, 32)}`;
  // ...
}

This design ensures that identical inputs always yield the same transition ID, making the operation naturally idempotent.

Validating Transition Integrity

Before application, decodeModelProjectionTransition enforces schema compliance and validates the digest format:

export function decodeModelProjectionTransition(
  value: unknown,
  sessionId: string,
): ModelProjectionTransition {
  if (!isModelProjectionTransition(value, sessionId)) {
    throw new Error('Invalid model projection transition');
  }
  return value;
}

The validator rejects malformed records early, preventing corrupt transitions from reaching the reducer.

Computing Projection Digests

The durableToolResultProjectionDigest function creates stable identifiers for projection versions:

export function durableToolResultProjectionDigest(
  projection: DurableToolResultProjection,
): `sha256:${string}` {
  return `sha256:${nodeCrypto
    .createHash('sha256')
    .update(stableJsonStringify(projection))
    .digest('hex')}`;
}

Digests enable optimistic concurrency control: a transition is accepted only if its sourceProjectionDigest matches the current projection's digest.

Durable Projection Types

The DurableToolResultProjection type in packages/core/src/durable-tool-result-projection.ts defines valid replacement shapes:

export type DurableToolResultProjection =
  | { version: 1; kind: 'text';  text: string; isError?: true }
  | { version: 1; kind: 'json';  value: DurableProjectionJson; isError?: true }
  | { version: 1; kind: 'content'; parts: DurableToolResultProjectionPart[] }
  | { version: 1; kind: 'execution_denied'; reason?: string }
  | { version: 1; kind: 'failure';
      reason: 'projection_failed';
      message: typeof DURABLE_TOOL_RESULT_PROJECTION_FAILURE_MESSAGE };

These variants cover text results, structured JSON, multi‑part content, explicit denials, and internal failures.

Runtime Enforcement and Error Handling

When the Apache Maka runtime applies a transition, it validates both the target address and the source digest. Mismatched digests cause rejection, protecting against stale writes. The runtime kernel in packages/runtime/src/runtime-kernel.ts throws descriptive errors—such as "No active AgentRun for model projection transition"—when infrastructure preconditions fail.

Practical Examples

Building a Transition Client‑Side

import {
  buildModelProjectionTransition,
  type ModelProjectionTransitionTarget,
  type BuildModelProjectionTransitionInput,
} from '@maka/core/src/model-projection-transition.js';
import { type DurableToolResultProjection } from '@maka/core/src/durable-tool-result-projection.js';

const target: ModelProjectionTransitionTarget = {
  runtimeEventId: 'event-123',
  part: 'tool_result',
  toolCallId: 'call-456',
  toolName: 'search',
};

const source: DurableToolResultProjection = {
  version: 1,
  kind: 'text',
  text: 'Old search result',
};

const replacement: DurableToolResultProjection = {
  version: 1,
  kind: 'text',
  text: 'Corrected search result',
};

const input: BuildModelProjectionTransitionInput = {
  sessionId: 'session-abc',
  target,
  sourceProjection: source,
  replacement,
  now: Date.now(),
};

const transition = buildModelProjectionTransition(input);
console.log('Transition ID:', transition.transitionId);

Validating a Received Transition

import { decodeModelProjectionTransition } from '@maka/core/src/model-projection-transition.js';

try {
  const transition = decodeModelProjectionTransition(raw, 'session-abc');
  console.log('Valid transition for target', transition.target);
} catch (e) {
  console.error('Invalid transition record:', e);
}

Applying a Transition in a Reducer

function applyTransition(
  currentProjection: DurableToolResultProjection,
  transition: ModelProjectionTransition,
): DurableToolResultProjection {
  if (durableToolResultProjectionDigest(currentProjection) !== transition.sourceProjectionDigest) {
    throw new Error('Source projection digest mismatch');
  }
  return transition.replacement;
}

Key Source Files

File Responsibility
packages/core/src/model-projection-transition.ts Transition record types, builder, validator, and digest functions
packages/core/src/durable-tool-result-projection.ts Durable projection schema and type definitions
packages/runtime/src/runtime-kernel.ts Runtime ledger integration and validation
packages/runtime/src/ai-sdk-compaction.ts Reducer implementation for context compaction

Why the Model Projection Transition System Matters for Context Management

  • Safety: The model's view is always derived from validated projections; malformed transitions cannot corrupt historical context
  • Replayability: Any session state can be reconstructed by replaying the event ledger from origin
  • Concurrency safety: Digest‑based guards prevent lost updates when multiple writers compete
  • Precision: Only the targeted tool_result section changes; unrelated session state remains untouched
  • Auditability: Every context modification exists as an explicit, inspectable ledger entry

Summary

The Apache Maka model projection transition system elegantly solves the problem of updating immutable context:

  • All runtime data lives in an append‑only ledger of AgentRunEvent records
  • Projections provide read‑only, derived views for UI and model consumption
  • Transition records express targeted replacements with cryptographic integrity checks
  • Deterministic reduction recreates current state by applying transitions in order
  • Idempotent, content‑derived IDs ensure duplicate operations are harmless

This architecture makes Apache Maka's context management simultaneously safe, transparent, and resilient to concurrency.

Frequently Asked Questions

How does Apache Maka prevent corrupt updates to model context?

Apache Maka prevents corrupt updates through digest‑based validation. Each transition record includes a sourceProjectionDigest computed from the expected current projection. The runtime verifies this digest before applying any replacement. If the current projection has changed—due to another writer or stale data—the digest mismatch causes rejection, preserving data integrity.

Can two processes safely update the same tool result simultaneously?

Yes, with optimistic concurrency control. Both processes read the same source projection digest and construct transitions. The first to commit succeeds; the second finds a digest mismatch and must retry with fresh data. Because transition IDs are content‑derived, accidental duplicate submissions are idempotent and harmless.

What happens when a transition targets a nonexistent event?

The runtime in packages/runtime/src/runtime-kernel.ts validates the target address during transition processing. If the referenced runtimeEventId, toolCallId, or combination does not exist, validation fails with an explicit error. The append‑only ledger structure ensures that targets, once valid, remain addressable for the session lifetime.

How does the system support debugging and audit trails?

Every transition exists as a first‑class ledger entry with a deterministic, content‑derived ID. Developers can inspect the complete sequence of model_projection_transition_recorded events to understand exactly how context evolved. Replaying the ledger through the reducer reproduces the exact model-visible state at any historical point, enabling precise post‑hoc analysis.

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 →