Operating a live Aether engine

This part of the guide is the runbook for an agent—or a human at the same controls—operating Aether through the MCP harness. It starts after code has been built and answers four practical questions:

  1. Which process owns the thing I am looking at?
  2. Which identifier is safe to reuse?
  3. What evidence can I collect without changing the engine?
  4. What must I clean up when the task ends?

For the transport topology and connection setup, begin with The MCP harness. The pages here assume its tunnel, aether-mcp, and hub are reachable.

The operating model

The harness has four ownership layers. Confusing adjacent layers is the most common source of bad recovery decisions.

LayerOwnsSurvives a hub restart?Operator handle
MCP client sessiontool calls and returned evidencethe tunnel normally does; an aether-mcp restart does notMCP connection
Hubsupervised engine table, engine proxies, artifact storefleet: no; stored artifacts: yeshub-local tools
Substrateone live engine, native caps, live kind and mailbox registriesnoengine_id
Loaded componentone wasm actor behind a substrate mailboxnolineage address

Keep three nouns separate:

  • Stored means bytes and a manifest exist in the hub's content-addressed artifact store. list_binaries and registry list_components report this.
  • Running means a substrate is in the hub's current supervised fleet. list_engines reports this.
  • Loaded means a component actor is registered inside one running substrate. load_component creates it; describe_component inspects it.

A stored component is not loaded. A loaded component on engine A says nothing about engine B. An old engine_id says nothing about a new hub process.

The safe operating loop

Use this loop even for a short probe:

  • Start with list_engines and decide whether to adopt an existing engine or create one.
  • Before using any selector, prove the artifact is stored with list_binaries or registry list_components; otherwise upload it first.
  • Record the exact engine_id returned by spawn_substrate.
  • Record each explicit load's returned lineage address; for boot loads, record the configured name used to derive its lineage.
  • Inspect the live surface before guessing mail: describe_kinds, describe_handlers, or describe_component.
  • Prefer settled send_mail; use send_mail_traced when causal timing or whole-chain proof matters.
  • Collect logs, traces, costs, and frames before destructive recovery.
  • Drop task-owned components and require their successful drop_result, or terminate task-owned engines when done.
  • After termination, call list_engines again and verify the engine cleanup is visible. A component drop is verified by its result, not the fleet list.

The tool's live JSON schema is the parameter reference. This guide names the current tools and their contracts, but does not duplicate every field because that surface evolves.

Choose the next page

If you need to…Read
restart or stop harness processes, or decide who mayHarness lifecycle
adopt, spawn, identify, or terminate substratesEngine fleet
pass a host path, upload code, or persist evidenceHost paths and artifacts
upload, select, load, replace, inspect, or drop wasmComponent registry
learn the live schema or gather diagnostic evidenceInspect and debug
respond to a failure without making it worseRecovery

The subsystem explanations remain useful alongside these runbooks:

Ownership rules

Ownership is operational, not merely descriptive:

ResourceDefault ownerCleanup rule
Engine you spawnedyour task/sessioncall terminate_substrate on its exact engine_id
Engine you merely foundwhoever created itdo not terminate without explicit authority
Component you loaded into a shared engineyour task/sessionsend the component drop mail when safe
Component loaded at boot into your engineyour engineterminating the engine cleans it up
Named artifact in the hub storehub operatornames persist and protect their current target from LRU eviction
Per-engine scratch/handle-store directoryhub operatortermination does not expose directory cleanup through MCP
Evidence file returned by a spill or capturecallerpreserve or remove it deliberately; it is host-side state

There is no current MCP delete tool for stored binaries or components. Reusing an upload name repoints that name to the new hash; it does not erase the old bytes. If no other name points at the old hash, it becomes unnamed history and can later be evicted under the store's disk budget. Do not promise registry cleanup that the tool surface cannot perform.

Component drop closes that one instance: its guest's unwire runs, its name tombstones, and a later load of the same name is refused as retired (ADR-0241 §8). Engine termination ends every instance at once.

Identifier discipline

  • Treat engine_id as a hub-lifetime routing handle. The hub allocates it from process-local state and only guarantees uniqueness in its current fleet. A later hub can mint the same text for a different engine.
  • Treat rpc_port as observation, not identity. Never route a tool call by substituting a port for an engine_id.
  • Hand tagged ids such as knd-… and hdl-… back verbatim. Address an actor by its path; a mailbox id in output is for reading.
  • Address a loaded component by the full lineage name returned by the load, its published name: NS, or NS:key for an instanced type.
  • Prefer a content hash when a rollout or rollback must select exact bytes. A human-readable registry name is a movable pointer.

Mutation posture

Read-only discovery should precede mutation. list_*, describe_*, actor_logs, and actor_cost are the normal first calls. capture_frame is observational to the engine when used without mail bundles; its mails and after_mails fields make it engine-mutating. Independently, save_path creates parent directories and can overwrite a host file even when both bundles are empty. send_mail, component lifecycle calls, spawn, replace, and terminate all change live state. Host paths have an independent authority boundary; follow Host paths and artifacts before uploading native code or persisting a frame.

Fire-and-forget is not a faster form of verification. It proves that the call was written, not that the engine completed the work. Use it only when the recipient intentionally has no useful reply or when a later observation is the actual success criterion.

Source routes

When prose and behavior disagree, inspect these routes in order:

  • MCP tool names and user-facing contracts: crates/aether-mcp/src/tools/mod.rs
  • Live JSON argument and response shapes: crates/aether-mcp/src/args.rs
  • Fleet and component orchestration: crates/aether-mcp/src/tools/engine.rs and components.rs
  • Hub fleet ownership and engine death handling: crates/aether-fleet/src/server/runtime.rs and crates/aether-fleet/src/proxy/runtime.rs
  • Stored artifacts: crates/aether-fleet/src/store/
  • Live kind inventory: crates/aether-inventory/src/
  • Loaded component registry and lifecycle: crates/aether-component/src/component/