Skip to content

RFC: Channels #117

Description

Currently in the protocol, we have notifications, methods, and states that can be subscribed to. Looking in the future, we are potentially able to multiplex other protocols, and also have subscribable data that is per-client and not stateful. (Currently in the protocol we only subscribe to state.) There are lots of cases for this...

  • Logging (streaming, subscribable, but not state)
  • File watching
  • Port forwarding
  • MCP (soon! kind of, it's complex, but...)
  • Tasks/MCP Tasks
  • LSP
  • TURN/STUN negotation

I want to clean things up a bit by introducing the notion of 'channels'. This largely serves to give us a cohesive way to talk about these multiplexed protocols and pubsub-type mechanics.

Internals

A channel is identified by a URI, like state today. A channel MAY have a state associated with it. Inside the channel are notifications and method calls. The scheme of the channel identifies what type of data is it. For example:

  • ahp-root:// - canonical root state
  • ahp-session://... - session state
  • ahp-log://<level> - logging stream
  • lsp://... - LSP communication

Clients MUST NOT subscribe to any protocols they don't recognize. Methods and notifications in the protocol should be prefixed with a namespace like lsp/message and contain a channel: URI field.

For state subscriptions, this is mostly the same as what we do today.

sequenceDiagram
  participant C as Client
  participant S as Server

  C->>S: subscribe { resource: "ahp-session:/abc" }
  S-->>C: result { state: <snapshot>, fromSeq: 42 }
  S-->>C: session/action { envelope, serverSeq: 43 }
  C->>S: session/dispatch { clientSeq, action }
  S-->>C: session/action { envelope, serverSeq: 44, origin: { clientSeq } }
  C->>S: unsubscribe { resource: "ahp-session:/abc" }
Loading

For consumers who want logs, they can subscribe to the ahp-log://<level> channel of the appropriate type. This channel has no associated state, but just emits log information.

sequenceDiagram
  participant C as Client
  participant S as Server

  C->>S: subscribe { resource: "ahp-log://warn" }
  S-->>C: result { resource: "ahp-log://warn" }
  S-->>C: log/message { resource, message: { level: "warn", msg: "..." } }
  S-->>C: log/message { resource, message: { level: "error", msg: "..." } }
  C->>S: unsubscribe { resource: "ahp-log://warn" }
Loading

For things like LSP communication, we can be more opaque. An LSP can be advertised or created in some way (that's for another proposal) and then the agent host can directly forward traffic over the lsp:// channel back and forth.

sequenceDiagram
  participant App as Client app
  participant C as AHP Client
  participant S as AHP Server
  participant L as LSP server (in host)

  App->>C: open LSP for "typescript"
  C->>S: subscribe { resource: "lsp://typescript" }
  S->>L: spawn / attach
  S-->>C: result { resource: "lsp://typescript" }

  App->>C: LSP initialize
  C->>S: lsp/message { resource, message: <LSP initialize> }
  S->>L: <LSP initialize>
  L-->>S: <LSP initialize result>
  S-->>C: lsp/message { resource, message: <LSP initialize result> }
  C-->>App: deliver

  Note over App,L: bidirectional traffic continues until unsubscribe
  C->>S: unsubscribe { resource: "lsp://typescript" }
  S->>L: shutdown
Loading

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions