# How DeepSeek-Reasonix Implements Extension Protocol v2 for Runtime Event Interception

> Discover how DeepSeek-Reasonix implements Extension Protocol v2 for runtime event interception using stdio RPC and DTOs to route events efficiently.

- Repository: [YHH/DeepSeek-Reasonix](https://github.com/esengine/DeepSeek-Reasonix)
- Tags: internals
- Published: 2026-08-13

---

**DeepSeek-Reasonix implements Extension Protocol v2 as a stdio-based RPC contract between the host runtime and an out-of-process sidecar, using method constants like `MethodExtensionIntercept` and DTOs such as `InterceptParams` and `InterceptResult` to route events through registered interceptor functions.**

The **esengine/DeepSeek-Reasonix** repository provides a robust mechanism for extending AI reasoning workflows through **Extension Protocol v2**. This protocol enables secure, language-agnostic runtime event interception by spawning sidecar processes that communicate with the host over stdio. By leveraging generated DTOs and a transport-neutral RPC wire format, the system allows extensions to observe, modify, or block critical runtime events without compiling into the core binary.

## Architecture of Extension Protocol v2

### Transport and Connection Management

The protocol relies on [`internal/extension/rpcwire/conn.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/extension/rpcwire/conn.go) to manage transport-neutral connections between the host and sidecar. According to the DeepSeek-Reasonix source code, this layer abstracts the stdio pipe into a framed RPC connection capable of handling request-response cycles asynchronously.

### Sidecar Process Model

Extensions run as separate OS processes spawned by the host via [`sdk/go/sdk.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/sdk/go/sdk.go). The host initializes these sidecars using a versioned handshake defined in the protocol specification, ensuring both sides agree on supported method names and DTO schemas before processing events.

## Handshake and Interceptor Registration

### Protocol Initialization

Before intercepting events, the host performs a handshake using `MethodExtensionInitialize` (defined in [`sdk/go/types_generated.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/sdk/go/types_generated.go)). This method establishes the protocol version and capability negotiation between the Reasonix host and the extension sidecar.

### Configuring the Interceptor Map

The host builds an interceptor registry in [`internal/extension/uihub/hub.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/extension/uihub/hub.go) using an `Options` struct containing an `Interceptors` map. Keys are **event names** (e.g., `tool.before`, `session.start`) or the wildcard `"*"` for catch-all handlers. Each entry maps to an `InterceptorFunc` that receives the event string and raw JSON payload.

## Runtime Event Interception Implementation

### Host-Side Event Triggering

When the Reasonix runtime reaches a hook point, the host constructs an `InterceptParams` DTO containing the `Event` enum and payload. The hub implementation in [`internal/extension/uihub/hub.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/extension/uihub/hub.go) then dispatches a JSON-RPC request using the method constant `MethodExtensionIntercept`.

### Request Structure and Wire Format

The generated code in [`sdk/go/types_generated.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/sdk/go/types_generated.go) defines the wire format precisely. The `InterceptParams` struct includes the event type and payload, while `InterceptResult` contains the `Decision` enum and optional replacement data. These DTOs are generated by [`internal/extension/protocolgen/sdkgo.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/extension/protocolgen/sdkgo.go) to ensure type safety across language boundaries.

### Sidecar Request Processing

Upon receiving the request, the sidecar client in [`internal/extension/sidecar/client.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/extension/sidecar/client.go) unmarshals the parameters and routes them to the appropriate handler. The lookup follows a priority order: exact event name match, wildcard `"*"`, then default behavior. The handler returns an `InterceptResult` serialized back to the host.

### Decision Application

The host evaluates the `Decision` field from the sidecar response. As implemented in [`internal/extension/uihub/hub.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/extension/uihub/hub.go), valid decisions include:

- **continue**: Forward the original payload unchanged.
- **replace**: Substitute the payload with the `Replacement` field from the result.
- **block**: Abort the current operation immediately.
- **allow/deny**: Grant or revoke permission for protected operations.

## Error Handling and Timeouts

The protocol defines specific error constants in [`sdk/go/types_generated.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/sdk/go/types_generated.go), including `ErrUnknownMethod` and `ErrInterceptTimeout`. The host enforces per-intercept deadlines; if the sidecar fails to respond within the timeout window, the host defaults to a conservative fallback decision to prevent pipeline stalls.

## Implementation Example

The following example demonstrates registering interceptors and handling decisions in a Go-based extension:

```go
// Initialize host with interceptors
host, err := NewHost(Options{
    Interceptors: map[string]InterceptorFunc{
        "tool.before": func(ctx context.Context, event string, payload json.RawMessage) (*InterceptResult, error) {
            // Inspect tool invocation
            return &InterceptResult{Decision: DecisionContinue}, nil
        },
        "*": func(ctx context.Context, event string, payload json.RawMessage) (*InterceptResult, error) {
            // Catch-all logging or policy enforcement
            return &InterceptResult{Decision: DecisionAllow}, nil
        },
    },
})

```

```go
// Host-side dispatch (simplified from internal/extension/uihub/hub.go)
params := InterceptParams{
    Event:   InterceptEvent("tool.before"),
    Payload: json.RawMessage(`{"tool":"search","query":"data"}`),
}
// Send via rpcwire
resp, err := host.Request(MethodExtensionIntercept, params)
// Apply decision based on InterceptResult

```

## Summary

- Extension Protocol v2 uses **stdio-based RPC** via [`internal/extension/rpcwire/conn.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/extension/rpcwire/conn.go) to communicate with out-of-process sidecars.
- The host registers interceptors in [`internal/extension/uihub/hub.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/extension/uihub/hub.go) using an `Options` map keyed by event names or the `"*"` wildcard.
- Runtime events trigger `MethodExtensionIntercept` requests with `InterceptParams` DTOs defined in [`sdk/go/types_generated.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/sdk/go/types_generated.go).
- Sidecars process requests in [`internal/extension/sidecar/client.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/extension/sidecar/client.go) and return `InterceptResult` containing decisions: **continue**, **block**, **replace**, **allow**, or **deny**.
- Timeout handling and error constants like `ErrInterceptTimeout` ensure robust production operation.

## Frequently Asked Questions

### What transport mechanism does Extension Protocol v2 use?

Extension Protocol v2 communicates over **stdio pipes** managed by [`internal/extension/rpcwire/conn.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/extension/rpcwire/conn.go). This transport-neutral design allows the same protocol to run over alternative transports if needed, though stdio is the default for sidecar isolation.

### How does the host route events to the correct interceptor?

The host maintains an interceptor map in [`internal/extension/uihub/hub.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/extension/uihub/hub.go). When an event occurs, it looks up handlers by exact event name first, falls back to the wildcard `"*"` handler if no specific match exists, and finally applies default behavior if neither is registered.

### What happens if a sidecar interceptor times out?

If the sidecar does not return an `InterceptResult` within the configured deadline, the host raises `ErrInterceptTimeout` (defined in [`sdk/go/types_generated.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/sdk/go/types_generated.go)) and applies a conservative fallback decision—typically **continue** or **block** depending on the event type—to prevent blocking the Reasonix runtime.

### Can extensions modify event payloads or only block them?

Extensions can modify payloads by returning `DecisionReplace` in the `InterceptResult` struct. The host then substitutes the original payload with the `Replacement` field contents before continuing execution, enabling transformation of tool arguments or session data.