Skip to content
Development
Agent

acp-runtime

The ACP runtime is the domain service that serves the ACP API contract. It owns the host-scoped dependencies needed to run provider ACP sessions, but it should not mix cross-session routing with per-session state projection.

From plugin
emdash
5.7k32 skills32 agents

How it fires

How this agent gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.

Context preview

The summary Claude sees to decide when to auto-load this agent.

The ACP runtime is the domain service that serves the ACP API contract. It owns the host-scoped dependencies needed to run provider ACP sessions, but it should not mix cross-session routing with per-session state projection.

Agent definition

acp-runtime.md

ACP Runtime Architecture

The ACP runtime is the domain service that serves the ACP API contract. It owns the host-scoped dependencies needed to run provider ACP sessions, but it should not mix cross-session routing with per-session state projection.

Ownership

  • `AcpRuntime` is the composition root. It wires the ACP API contract to shared

ports, the resource-cached connection source, and the session manager.

  • `SessionManager` is the conversation directory and cross-conversation coordinator. It owns the

handle map, suspended-intent index, process-close fan-out, lifecycle-chassis wiring, and the composition of the router, materializer, and list projector. Activity tracking, idle sweeping, intent persistence, lifecycle reports, and eviction sequencing remain delegated to the shared session-lifecycle chassis (`packages/core/src/services/session-lifecycle/`). Its explicit `inspect()` seam exposes identifier-only lifecycle snapshots for deterministic ownership and leak assertions without revealing the directory maps.

  • `ConversationHandle` is the aggregate root for one conversation. It owns the wake descriptor,

desired configuration, retained presentation snapshot, conversation-lifetime projection, explicit lifecycle state and epoch, current `SessionRecord`, activation snapshot construction, and its single-key `LifecycleCell`. Descriptor and retained-presentation changes write through one intent-persistence seam, while killed/disposed state and the epoch invalidate stale asynchronous materialization and command work before directory removal.

  • `LifecycleCell` provides coalesced starts, leases, interrupt-before-drain teardown, and bounded

draining for one handle. The multi-key `LifecycleRegistry` remains available to other runtimes.

  • `SessionMaterializer` is stateless. It acquires a connection, loads or creates the provider

session, creates the record's machine-state binding, applies retained configuration and mode, and returns a `SessionRecord` for the handle to adopt. Provisional loading registration and replay setup share one cleanup path so failures cannot leave routing residue.

  • `SessionRouter` owns ACP `sessionId` routing and one scoped provisional load route per process

generation. The materializer serializes `loadSession` handshakes for each generation, so a provider that reports a rebound session ID still resolves unambiguously. Unknown or stale updates outside that scope are dropped rather than retained across activations; generation invalidation drops provisional and registered routes. Its maps stay private; identifier-only queries support lifecycle leak assertions. `SessionsListProjector` composes live handle summaries with lightweight suspended-intent rows.

  • `SessionCell` owns one live activation: the state machine, transcript reducer, permission broker,

prompt queue effects, turn quiescence, and whether the provider's config catalog is pending or ready. It does not own the conversation-lifetime projection or retained rematerialization descriptor.

  • The ACP connection source owns provider processes through `createResourceCache`.

Cache identity includes provider, cwd, and an opaque fingerprint of the requested environment; the process route id stays provider/cwd plus generation and can host multiple ACP sessions with the same environment.

  • Models under `packages/core/src/acp/models/` are the shared vocabulary for

reducer output, live model state, and the public ACP API contract.

  • Runtime implementation code lives under `packages/core/src/runtimes/acp/node/`; the portable

contract and client models stay under `packages/core/src/runtimes/acp/api/`.

  • The Node surface exports `createAcpComponent()`. App-owned worker entries call

`runWireComponentWorker(createAcpComponent(...))`; `@emdash/core` does not export process bootstrap helpers.

flowchart TD
  subgraph api [ACP API]
    commands[Commands]
    liveModels[LiveModels]
    queries[Queries]
  end
  subgraph runtime [Runtime]
    root[AcpRuntime]
    manager[SessionManager Directory]
    router[SessionRouter]
    materializer[SessionMaterializer]
    intentIndex[Suspended Intent Index]
    listProjector[SessionsListProjector]
  end
  subgraph conversation [Conversation Aggregate]
    handle[ConversationHandle]
    lifecycle[LifecycleCell]
    projection[Conversation Projection]
  end
  subgraph session [Live Activation]
    record[SessionRecord]
    machine[SessionMachine]
    reducer[Transcript Reducer]
  end
  subgraph connection [Connection]
    source[ConnectionSource]
    ports[AgentPorts]
  end
  agent[ACP Agent]

  commands --> root --> manager --> handle
  manager --> intentIndex --> listProjector --> liveModels
  handle --> lifecycle --> materializer --> source --> agent
  materializer --> record --> machine
  agent --> ports --> router --> record
  record --> reducer --> handle --> projection --> liveModels
  handle --> listProjector
  reducer --> queries

Command and Read Paths

Commands enter through the API and are routed by `AcpRuntime` to the `SessionManager`. The manager locates or lazily creates a `ConversationHandle`; wake commands ask the handle's lifecycle cell to ensure an activation and acquire the appropriate lease. Session commands then reach the `SessionCell`, where the pure `SessionMachine` decides whether the command is valid and emits effects for the cell to interpret.

Provider updates move in the opposite direction. The connection handler receives ACP callbacks, normalizes raw `SessionUpdate`s through the provider's enrich hook, and asks the `SessionRouter` to resolve the owning conversation. The cell folds the event through the reducer; its handle republishes the resulting activation snapshot through the conversation-keyed projection.

The public API describes user intent instead of exposing lifecycle choreography. Desktop resolves the authoritative conversation configuration and fresh provider environment, th

Read more
Ships withemdash

Emdash is the Open-Source Agentic Development Environment (🧡 YC W26). Run multiple coding agents in parallel. Use any provider.

Get the whole plugin
Stats
5,748
Stars
589
Forks
Active
Maintenance
TypeScript
Language
Apache-2.0
License
16h ago
Last commit
1y ago
Created

Repo: generalaction/emdash

Other agents on emdash.