Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions docs/rfc-reflection-api-v2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# RFC: Reflection API V2 (WebSocket)

## Summary

Introduces a new Reflection API (V2) based on WebSockets and JSON-RPC 2.0. This architecture reverses the connection direction of V1: the Genkit CLI (Runtime Manager) acts as the WebSocket server, and Genkit Runtimes connect to it as clients.

## Motivation

The V1 Reflection API (HTTP Server on Runtime) has limitations that V2 addresses:

1. **Bidirectional Actions**: V1 uses HTTP, which is request/response based. Supporting "Bidi Actions" (streaming input and output) requires a full duplex connection, which WebSockets provide natively.
2. **Environment Constraints**: In many environments (e.g., Web Browsers, Flutter Web, specific cloud sandboxes), it is impossible or impractical for the Runtime to bind to a TCP port and host an HTTP server. V2 allows these runtimes to connect *outbound* to the CLI, enabling support for a wider range of platforms.
3. **Simplified Discovery**: V1 requires a complex discovery mechanism involving writing runtime info files to special directories. V2 simplifies this by using a single environment variable (`GENKIT_REFLECTION_API_URL`) to point the Runtime to the CLI's WebSocket address.

## Design

### Architecture

- **Manager (CLI)**: Hosts the WebSocket server. It listens for connections from Runtimes.
- **Runtime (Application)**: Connects to the Manager's WebSocket URL. It registers itself and waits for commands.

```mermaid
sequenceDiagram
participant Runtime
participant Manager
Note over Manager: Starts WebSocket Server
Runtime->>Manager: Connect (WebSocket)
Runtime->>Manager: register(id, info)
Manager->>Runtime: configure(telemetryUrl)
Note over Manager: Ready to issue commands
```

### Protocol

- **Transport**: WebSocket
- **Format**: JSON-RPC 2.0
- **Streaming**: Extended via Notifications. Since JSON-RPC 2.0 is request/response, we use `Notification` messages to push stream chunks associated with a Request ID.

### API Methods

#### Method Reference

| Method | Direction | Type | Description |
| :--- | :--- | :--- | :--- |
| **`register`** | Runtime → Manager | Notification | Registers the runtime with the manager (ID, info). |
| **`configure`** | Manager → Runtime | Notification | Pushes configuration (e.g., Telemetry URL) to runtime. |
| **`listActions`** | Manager → Runtime | Request | Retrieves the list of available actions/flows. |
| **`runAction`** | Manager → Runtime | Request | Initiates action execution (unary or streaming). |
| **`runActionState`** | Runtime → Manager | Notification | Sends early status/metadata (e.g., `traceId`) during execution. |
| **`streamChunk`** | Runtime → Manager | Notification | Sends a chunk of output data during streaming execution. |
| **`streamInputChunk`** | Manager → Runtime | Notification | Sends a chunk of input data during bidi execution. |
| **`endStreamInput`** | Manager → Runtime | Notification | Signals the end of the input stream for bidi execution. |
| **`cancelAction`** | Manager → Runtime | Request | Requests cancellation of a specific action by `traceId`. |

#### Detailed Flows

**1. Connection & Discovery**
- **Runtime** connects via WebSocket.
- **Runtime** sends `register`.
- **Manager** sends `configure`.
- **Manager** sends `listActions` to populate the UI.

**2. Execution (`runAction`)**
The `runAction` method supports three modes:

- **Unary**: Standard JSON-RPC request/response.
- **Streaming Output**: The Runtime sends `streamChunk` notifications before the final result.
- **Bidirectional**: The Manager sends `streamInputChunk` notifications to the Runtime while receiving `streamChunk` notifications.

**Bidi Flow Sequence:**

```mermaid
sequenceDiagram
participant Manager
participant Runtime
Manager->>Runtime: Request: runAction(id=1, stream=true, streamInput=true)

par Input Stream
Manager->>Runtime: Notification: streamInputChunk(requestId=1, chunk=...)
Manager->>Runtime: Notification: streamInputChunk(requestId=1, chunk=...)
Manager->>Runtime: Notification: endStreamInput(requestId=1)
and Output Stream
Runtime->>Manager: Notification: streamChunk(requestId=1, chunk=...)
Runtime->>Manager: Notification: streamChunk(requestId=1, chunk=...)
end

Runtime->>Manager: Response: { result: ..., telemetry: ... }
```

## Compatibility

V2 is designed to coexist with V1. The Genkit CLI will determine which mode to use (likely via flags or auto-detection). Existing V1 runtimes will continue to work, but will not support Bidi Actions or the new connection model.