Skip to main content
Meerkat is modular. Every feature is opt-in. This matrix shows what works in each build profile.

Build profiles

ProfileCargo FeaturesUse Case
Minimal--no-default-featuresEphemeral agent, no persistence, no compaction
Persistentsession-storeSessions survive restart with the realm-pinned backend (sqlite by default when compiled)
Compactingsession-compactionAuto-compact long conversations
Fullsession-store,session-compactionPersistent + compacting

Capability behavior

OperationMinimalPersistentCompactingFull
create_sessionWorksWorksWorksWorks
start_turnWorksWorks + snapshot savedWorksWorks + snapshot saved
interruptWorksWorksWorksWorks
read (live session)WorksWorksWorksWorks
read (archived)SESSION_NOT_FOUNDFalls back to storeSESSION_NOT_FOUNDFalls back to store
listLive sessions onlyLive + stored sessionsLive sessions onlyLive + stored sessions
archiveRemoves from memoryRemoves from memory, snapshot keptRemoves from memoryRemoves + snapshot kept
Auto-compactionNo-opNo-opTriggers at thresholdTriggers at threshold

Error codes

Deterministic error codes across all surfaces. The canonical mapping is defined in meerkat-contracts (ErrorCode). Every SessionError variant maps to a stable string code and a transport-specific representation:
SessionErrorCodeJSON-RPCRESTMCPCLI
NotFoundSESSION_NOT_FOUND-32001404tool errorexit 10
BusySESSION_BUSY-32002409tool errorexit 11
NotRunningSESSION_NOT_RUNNING-32003409tool errorexit 12
PersistenceDisabledCAPABILITY_UNAVAILABLE-32020501tool errorexit 40
CompactionDisabledCAPABILITY_UNAVAILABLE-32020501tool errorexit 40
StoreINTERNAL_ERROR-32603500tool errorexit 1
AgentAGENT_ERROR-32013500tool errorexit 30

Transport error mapping summary

  • JSON-RPC: Custom error codes in the -32000..-32099 range. The code field of the JSON-RPC error object carries the string code (e.g. SESSION_NOT_FOUND).
  • REST: HTTP status codes (404, 409, 500, 501). Error body includes { "code": "...", "message": "..." }.
  • MCP Server: Tool calls return is_error: true with the error message and code in the content.
  • CLI: Non-zero exit codes. Each ErrorCode maps to a stable exit code (see CLI exit codes). Error details printed to stderr.

Pick only what you need

# Minimal: just the agent loop
[dependencies]
meerkat = { version = "0.5", default-features = false, features = ["anthropic"] }

# Add persistence
meerkat = { version = "0.5", default-features = false, features = ["anthropic", "session-store"] }

# Add compaction
meerkat = { version = "0.5", default-features = false, features = ["anthropic", "session-store", "session-compaction"] }

# Kitchen sink
meerkat = { version = "0.5", features = ["all-providers", "session-store", "session-compaction", "comms", "mcp"] }

Model capabilities

ModelProfile describes per-model capabilities used for feature gating and tool visibility. Two fields are relevant to multimodal content support:
CapabilityDescriptionAnthropicOpenAIGemini
visionModel can process image content in user messagesYesYesYes
image_tool_resultsModel can process image content in tool resultsYesNoYes
These fields are set in the model catalog (meerkat-models) and exposed via ModelProfile. They control:
  • view_image tool visibility — hidden via ToolScope when either vision or image_tool_results is false.
  • ContentBlock::Image in tool results — providers that do not support image_tool_results will receive image content blocks converted to text descriptions.
  • ContentBlock::Image in user messages — providers that do not support vision will not receive image content blocks in user messages.

MCP server loading

MCP server connections are non-blocking across all surfaces. Servers connect in parallel in the background after apply_staged(). The agent loop polls poll_external_updates() at each CallingLlm boundary and injects a [MCP_PENDING] system notice while servers are still connecting. Tools become visible as each server completes its handshake.
  • Per-server timeout: connect_timeout_secs in MCP config (default: 10s)
  • CLI: --wait-for-mcp blocks before the first turn until all servers finish connecting
  • SDK: McpRouterAdapter::wait_until_ready(timeout) provides the same blocking behavior programmatically

Compaction behavior

When session-compaction is enabled:
  • Trigger: last_input_tokens >= threshold OR estimated_history_tokens >= threshold
  • Guards: Never on first turn. Minimum 3 turns between compactions.
  • Failure: Non-fatal. CompactionFailed event emitted, agent continues with uncompacted history.
  • Budget: Compaction LLM call draws from the same token budget as regular turns.
Events emitted: CompactionStarted, CompactionCompleted, CompactionFailed.

Concurrency

  • At most one turn runs per session at a time.
  • Second start_turn while one is in-flight returns SESSION_BUSY.
  • interrupt() cancels the in-flight turn.
  • read() and list() are non-blocking.
  • No queueing: callers retry on Busy.

Durability

  • Ephemeral: Process death loses all state.
  • Persistent: Snapshot saved after turn completion according to the pinned realm backend.
  • Backends are pinned per realm (realm_manifest.json) and shared across surfaces only when realm_id matches.
  • SQLite-backed realms are the standard same-realm multi-process mode.

See also