Capsules
A Capsule is Murmur's primary execution abstraction.
A capsule launches from a manifest, installs its declared artifacts, executes inside a constrained environment, writes outputs, and exits. The manifest is the complete configuration.
Agent capsules
An agent capsule runs the LLM inference loop built into the runtime. It is defined
entirely by its murmur.yaml: an inference: block in the manifest is what puts the capsule
in agent mode.
# minimal agent manifest
name: my-agent
version: "0.1.0"
artifacts:
- name: murmur-driver-anthropic
version: "1.0.0"
runtime: driver
capabilities:
shell:
allow:
- bash
inference:
transport: http
endpoint: https://api.anthropic.com
model: claude-sonnet-5
api_key: ${ANTHROPIC_API_KEY}
driver:
artifact: murmur-driver-anthropic
mur build packages this as a manifest-only .mur.zip.
Isolation model
Murmur uses the WASM Component Model as the primary execution boundary:
- WASM components run in a sandboxed runtime
- WASI capabilities explicitly control filesystem and network access
- Manifest capability grants are part of the security policy
Why WASM
WASM enables consistent execution contracts and explicit capability boundaries, while still allowing portable packaging and composable interfaces between runtime components.
Lifecycle
Typical lifecycle:
- Launch capsule
- Read manifest
- Resolve and install artifacts
- Execute workload
- Write outputs/logs
- Exit
Capsules are designed to be fast-starting and horizontally scalable.
Every capsule goes through the same runtime, which turns its manifest into a running process:
- Parses capsule and artifact metadata
- Resolves dependencies from local/remote registry sources
- Configures capability grants (filesystem, network, shell) from the manifest (see Access control)
- Links and invokes runtime interfaces for tools and artifact management
- Captures outputs and logs in a predictable workspace layout
Execution limits
Every component call the runtime makes — a capsule run, a tool or driver run, and each
hook lifecycle call — is bounded by two independent limits:
| Limit | Bounds | What happens at the limit |
|---|---|---|
| Deadline | Wall-clock time for one component call | A call that never returns is stopped with an error instead of hanging the session |
| Resource limiter | Memory growth, table growth, and instance count | A call that tries to grow past its cap is stopped with an error instead of consuming host memory without bound |
Both are set per-manifest under capabilities.limits (see Manifest
Schema). Omitting them applies generous
built-in defaults — a manifest that says nothing gets the defaults, not unlimited resources.
The default deadline for a hook lifecycle call is 30 seconds, against 600 for a capsule, tool
or driver call, so one wedged hook cannot stall a session for the capsule-wide budget on every
event; a declared deadline_seconds replaces both defaults and applies to every component call,
hooks included. Hitting either limit is reported distinctly from an ordinary crash. On the hook
path it is handled like any other hook error: logged, and the runtime moves on to the next hook.
Caveat: the deadline only counts down while the component's own code is running. Time it spends waiting on the runtime (for example, a driver awaiting a streaming provider response) counts against the same budget but cannot be cut short until control returns to the component. The deadline bounds runaway compute, not slow I/O.
Runtime identity
Every running agent capsule gets a capsule name and version (from murmur.yaml), a
runtime-generated session id, and a capsule URL (an OS-assigned local listener port). The same
identity is exposed in MURMUR.md, in the WASI env for the driver
and WASM tools, and in the shell tool subprocess env — so the agent, its tools, and its hooks
all see one consistent identity for the session.