---
title: "Design Philosophy"
description: "The engineering principles behind Meerkat's runtime, API boundaries, Rust implementation style, and validation model."
icon: "compass-drafting"
---

Meerkat is built as infrastructure, not as a single assistant application. The
runtime should be easy to embed, strict about semantic ownership, and honest
about which surface owns which behavior.

## Principles

### The Agent Loop Is A Primitive

The agent loop is provider-neutral. It owns messages, tool calls, streaming
assembly, retryable/fatal error classification, and transcript updates. It does
not own CLI policy, REST transport details, OAuth flows, or mob orchestration.

That split lets the same loop run behind a CLI command, an RPC server, a Rust
embedding, a mob member, or a browser runtime.

### Surfaces Are Adapters

CLI, REST, JSON-RPC, MCP, Python, TypeScript, and Web SDKs should expose the
same underlying concepts with surface-appropriate ergonomics. A surface may own
transport details, but it should not create a second semantic model for
sessions, tools, auth, live channels, or mobs.

Runtime-backed surfaces enter through `MeerkatMachine` and consume
`SessionRuntimeBindings`. Standalone embeddings use
`RuntimeBuildMode::StandaloneEphemeral` explicitly.

### One Semantic Fact, One Owner

State that changes what the system *is* needs a clear owner:

| Fact | Owner |
| --- | --- |
| Session runtime admission and completion | `MeerkatMachine` |
| Mob roster, wiring, flow, and task state | `MobMachine` / `meerkat-mob` |
| Auth lease lifecycle | `AuthMachine` via runtime auth handles |
| Schedule and occurrence lifecycle | `meerkat-schedule` machines |
| Transcript content | `SessionService` and session stores |
| Provider request lowering | Provider crates |

Derived projections are allowed, but they must be rebuildable from the owner.

### Typed Boundaries Beat String Folklore

Public APIs should expose domain handles such as `session_id`,
`AgentIdentity`, `blob_id`, `mob_id`, and `job_id`. Internal raw identities and
provider-specific handles should stay behind typed wrappers unless they are part
of an explicit contract.

Provider capabilities come from catalogs and profiles, not from substring
matching. If a model supports realtime, images, web search, or compaction, that
fact should be represented in a typed profile.

### Composition Over Hidden Defaults

Optional subsystems are injected through traits and handles:

- provider clients
- tool dispatchers
- session stores
- memory stores
- hook engines
- skill engines
- comms runtimes
- runtime bindings

When a subsystem is absent, the behavior should degrade explicitly. Hidden
global state and implicit runtime reconstruction make recovery and testing
harder.

## Rust Implementation Style

### Keep Core I/O-Free

`meerkat-core` defines shared types and contracts. Network, filesystem, OAuth,
SQLite, MCP, and provider-specific behavior live in satellite crates.

This keeps core tests fast and lets embedders choose the pieces they need.

### Use Newtypes For Domain Identity

Primitive strings and UUIDs should become semantic types at boundaries:

```rust
pub struct SessionId(uuid::Uuid);
pub struct AgentIdentity(String);
pub struct BlobId(uuid::Uuid);
```

This keeps member identity, runtime binding identity, sessions, blobs, and
provider handles from being mixed accidentally.

### Preserve Raw Provider Payloads Only Where They Are Truly Opaque

Tool arguments use `Box<RawValue>` so the runtime can pass provider-emitted JSON
to the dispatcher without reparsing or reserializing it. Provider metadata that
Meerkat understands should be typed instead of left as arbitrary
`serde_json::Value`.

### Prefer Explicit Runtime Modes

Runtime-backed and standalone execution are different contracts:

| Mode | Use |
| --- | --- |
| `SessionOwned(bindings)` | Runtime-backed surfaces with machine-owned handles and recovery semantics. |
| `StandaloneEphemeral` | Tests, browser runtime, and narrow embeddings without durable runtime services. |

Do not silently fall back from runtime-backed behavior to standalone behavior.

### Make Generated Surfaces Checkable

Schemas, SDK wrappers, machine specs, and generated kernels are checked into the
repo and verified by gates. Generated files should be reproducible, and drift
should fail locally before it reaches CI.

## Operational Bias

Meerkat favors boring, repeatable commands:

```bash
make check
make lint
make test
make agent-gate
```

Cargo remains the default backend. BuildBuddy accelerates the same lanes when
explicitly enabled with `MEERKAT_BUILDBUDDY=1`.

## See Also

- [Architecture](/reference/architecture)
- [Runtime Architecture](/reference/runtime-architecture)
- [Machine Authority](/reference/machine-authority)
- [Build And CI](/reference/build-and-ci)
