Skip to content

Add JSON-RPC chat adapter (message/send + message/stream)#281

Merged
lezama merged 2 commits into
mainfrom
add/agents-chat-jsonrpc-streaming
Jun 3, 2026
Merged

Add JSON-RPC chat adapter (message/send + message/stream)#281
lezama merged 2 commits into
mainfrom
add/agents-chat-jsonrpc-streaming

Conversation

@lezama

@lezama lezama commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

What

A canonical JSON-RPC chat adapter that makes the existing agents/chat ability drivable by protocol chat clients (e.g. JSON-RPC/SSE chat UIs) — the third integration shape alongside Direct Channels and Remote Bridges.

POST agents-api/v1/agent/{agent_id}, JSON-RPC 2.0:

Method Transport Request Response
message/send JSON {jsonrpc, id, method, params} {jsonrpc, id, result: Task}
message/stream SSE same, Accept: text/event-stream data: {…} frames

How

It's a thin envelope over agents/chat: it reuses the existing handler, conversation store, run-control, and permission stack. The canonical output maps almost 1:1 onto a JSON-RPC Task:

agents/chat output   JSON-RPC Task
------------------   -------------
run_id            -> id
session_id        -> sessionId
reply             -> status.message.parts[0].text
completed===false -> status.state: "input-required" (else "completed")

Token streaming adds one new seam: the wp_agent_chat_stream_handler filter (and a register_chat_stream_handler() helper) — the token-by-token sibling of the synchronous wp_agent_chat_handler. It receives ($input, $emit) and emits canonical deltas (content / tool_call / tool_argument), which the route translates into message/delta SSE frames followed by a terminal result: Task frame.

Graceful degradation: when no streaming runtime is registered, message/stream runs the synchronous handler and emits a single terminal frame — so the endpoint works with any existing handler, just without token-level granularity.

The provider/turn-runner stays out of canonical (consumer territory, the same boundary as agents/chat). End-to-end, the endpoint composes with the opt-in default conversation store (#242) for durable WordPress-native sessions; the store is the persistence example, the endpoint is the transport, and the runtime is supplied by a consumer plugin.

Files

  • src/Channels/register-agents-chat-jsonrpc-route.php — the adapter
  • tests/agents-chat-jsonrpc-route-smoke.php — 36 assertions (request/response mappers, all three delta wire shapes, frame builders, streaming-handler contract via a mock handler + $emit)
  • docs/external-clients.md — new JSON-RPC Protocol Endpoint section
  • agents-api.php, composer.json — bootstrap require + smoke registration

Verification

  • New smoke: 36/36
  • Full smoke suite: green
  • PHPStan max: [OK] No errors
  • PHPCS via CI (Homeboy lint)

🤖 Generated with Claude Code

lezama and others added 2 commits June 3, 2026 14:30
Expose the canonical agents/chat ability over a JSON-RPC 2.0 wire keyed by
agent id, so protocol chat clients can drive a registered runtime via
`message/send` (request/response) and `message/stream` (Server-Sent Events).

The adapter is a thin envelope over agents/chat: it reuses the existing
handler, conversation store, run-control, and permission stack. agents/chat
output maps almost 1:1 onto a JSON-RPC Task (run_id->id, session_id->sessionId,
reply->status.message text, completed===false->input-required).

Token streaming adds one seam: the `wp_agent_chat_stream_handler` filter (and a
`register_chat_stream_handler()` helper), the token-by-token sibling of the
synchronous `wp_agent_chat_handler`. It receives ($input, $emit) and emits
canonical deltas (content / tool_call / tool_argument) which the route
translates into `message/delta` SSE frames. When no streaming runtime is
registered, `message/stream` degrades to the sync handler + a single terminal
Task frame, so it works with any existing handler.

The provider/turn-runner stays out of canonical (consumer territory, same
boundary as agents/chat). End-to-end the endpoint composes with the opt-in
default conversation store for durable WordPress-native sessions.

- src/Channels/register-agents-chat-jsonrpc-route.php: the adapter
- tests/agents-chat-jsonrpc-route-smoke.php: 36 assertions (mappers, delta
  wire shapes, frame builders, streaming-handler contract)
- docs/external-clients.md: JSON-RPC Protocol Endpoint section
- PHPStan max clean; full smoke suite green

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@lezama lezama merged commit c4f10a5 into main Jun 3, 2026
2 checks passed
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.

1 participant