Skip to content

feat: WebSocket transport for goose-acp#6895

Merged
jh-block merged 1 commit intomainfrom
jhugo/acp-websocket
Feb 2, 2026
Merged

feat: WebSocket transport for goose-acp#6895
jh-block merged 1 commit intomainfrom
jhugo/acp-websocket

Conversation

@jh-block
Copy link
Collaborator

@jh-block jh-block commented Feb 2, 2026

Adds WebSocket transport alongside the existing streamable HTTP transport for ACP, providing an alternative simpler implementation for bidirectional communication.

Protocol Details

Connection Model: A WebSocket connection maps one-to-one with an ACP session.

Message Format: JSON-RPC 2.0 (same as the streamable HTTP transport) over WebSocket text frames. All message types (requests, responses, notifications) share the same connection with native bidirectional support.

Lifecycle:

  1. WebSocket upgrade to ws://host:port/acp. Session ID is returned in an Acp-Session-Id header in the same way as for streamable HTTP.
  2. Bidirectional messaging: same protocol as used for streamable HTTP, but all over the single connection
  3. Graceful or abnormal WS connection close with cleanup

Implementation Choices

Shared Components: Extracted ReceiverToAsyncRead and SenderToAsyncWrite adapters into adapters.rs, enabling both HTTP and WebSocket transports to reuse the same serve() protocol handler with consistent framing.

Architecture:

  • TransportSession manages per-connection state for both http and ws transports: bidirectional mpsc channels and agent task handle
  • A tokio::select! loop concurrently routes messages: client→agent and agent→client
  • Uses axum's built-in WebSocket handling with automatic ping/pong support

Server Integration: Both transports are served by the same HTTP server via merged Axum routers, allowing clients to choose their preferred transport at will.

@jh-block jh-block requested a review from alexhancock February 2, 2026 12:50
An alternative to streamable HTTP (#6741) that simplifies bidirectional
communication
@jh-block jh-block force-pushed the jhugo/acp-websocket branch from bfe86e1 to 1206006 Compare February 2, 2026 13:55
Copy link
Collaborator

@alexhancock alexhancock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good to get this in and then experiment with clients that use both transports!

) -> Poll<std::io::Result<usize>> {
self.buffer.extend_from_slice(buf);

while let Some(pos) = self.buffer.iter().position(|&b| b == b'\n') {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there any way this could catch \n in content?

Copy link
Collaborator Author

@jh-block jh-block Feb 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(this isn't new code, just extracted out of the http transport impl)

If the protocol client is well-behaved, the JSON-RPC messages should not contain any actual newline characters, and they're not valid within JSON strings (a newline within a string would be encoded as two characters: backslash followed by n).

If the protocol client somehow manages to fail at that, then we'd end up trying to parse an incomplete JSON documents and error out, which I think is fine

@jh-block jh-block added this pull request to the merge queue Feb 2, 2026
Merged via the queue into main with commit ce95e04 Feb 2, 2026
18 checks passed
@jh-block jh-block deleted the jhugo/acp-websocket branch February 2, 2026 14:14
stebbins pushed a commit to stebbins/goose that referenced this pull request Feb 4, 2026
Signed-off-by: Harrison <hcstebbins@gmail.com>
kuccello pushed a commit to kuccello/goose that referenced this pull request Feb 7, 2026
Tyler-Hardin pushed a commit to Tyler-Hardin/goose that referenced this pull request Feb 11, 2026
Tyler-Hardin pushed a commit to Tyler-Hardin/goose that referenced this pull request Feb 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants