Skip to main content
When two modules need to talk, they talk through a typed contract. This page lists the contract types that matter — the ones that, if changed, ripple across the codebase. The authoritative source for these types is the engine repo itself; this page summarizes the shape and links to the canonical locations. If you’re about to add a new public surface that crosses a module boundary, define the type here first, then implement against it. The project’s CLAUDE.md mandates this — types in a central place, modules import from there.

Content blocks

The fundamental unit of LLM communication. A message is a list of content blocks; a model response is a list of content blocks. Source: src/herald/engine_contracts/__init__.py (re-exports from src/herald/types.py).

Messages

A turn or part of a turn.

Tool definitions

How a tool is declared and how a call is invoked. Source: src/utility_directory/, src/herald/engine_contracts/. ToolDef is the schema the model sees in its system prompt. ToolCall is what the model issues. Utility is what the Engine actually invokes.

Events

The vocabulary of the SSE stream and the in-process event bus. Source: src/engine_core/events.py. There are 32+ event types. The major families:
  • LifecycleThreadLifecycle, TaskLifecycle.
  • ContentTextDelta, ThinkingDelta, ContentBlockStart, ContentBlockStop.
  • ToolsToolCall, ToolResult, ToolError.
  • HITLHitlRequest, HitlResolved, PermissionPrompt.
  • MemoryWorkingMemoryUpdate, MemoryRetrieval.
  • CompactionCompactionEvent.
  • DiagnosticsHeartbeat, Usage, Error, CacheHitRatioAlert.
Every event has a timestamp, a task_id, and a type. Concrete fields vary by type.

Errors

Stable error codes used across the Engine. Source: src/errors.py.
The error codes are part of the public API. Don’t rename them. Add new ones; don’t reshuffle existing ones.

Memory primitives

The records persisted in the brain. Source: src/memory/.

Channel state

Execution checkpoint. Source: src/engine_core/channel_state.py.

Asset Directory

MCP connection and registry types. Source: src/asset_directory/states.py, src/asset_directory/__init__.py.

Rules

  • Never inline a contract type. If a type crosses a module boundary, it lives where the producing module exports it (or in a shared engine_contracts module).
  • Never break a public contract silently. Renaming or reshaping ToolUseBlock, ErrorCode, or any event field is a breaking change and needs a migration guide.
  • Document new contract types deliberately. If you’re inventing a new kind of block or a new error code, write down why and where it’s used so the next reader doesn’t have to reverse-engineer the decision.

See also

  • Components — which module owns which types.
  • Data flow — how the types move through the system.