Extension Runtime v2 Architecture in DeepSeek-Reasonix: A Technical Deep Dive
DeepSeek-Reasonix Extension Runtime v2 is a sidecar-based, full-trust execution environment that isolates plugin code through JSON-RPC, giving extensions precise, manifest-driven control over event interception, model providers, and UI contributions.
The Extension Runtime v2 architecture powers how third-party code integrates with DeepSeek-Reasonix. Unlike traditional plugin systems that run inside the host process, this design launches extensions as separate processes communicating over a stable, versioned wire protocol. This separation enables deep customization while maintaining predictable security boundaries and clean failure modes.
Core Components of Extension Runtime v2
Sidecar Process
The sidecar is the fundamental unit of execution. Each extension runs as an independent OS process launched by the Reasonix host and persists until a runtime reload or crash termination.
Key characteristics from the source implementation in docs/EXTENSION_PROTOCOL.md:
- Starts via
extension/initializewith a 30-second initialization budget - Receives session context and host capabilities through
InitializeParams - Must respond with
InitializeResultdeclaring its supported capabilities - Shuts down gracefully via
extension/shutdownor is killed on timeout
The host spawns up to four sidecars in parallel during startup, validating that all declared capabilities remain a subset of the manifest.
Reasonix Extension Protocol v2
The wire contract reasonix.extension.v2 defines how host and sidecar communicate. This JSON-RPC protocol specifies methods, events, limits, and error codes in a frozen, forward-compatible schema.
Generated Go types in sdk/go/types_generated.go include:
- Method name constants (e.g.,
MethodExtensionIntercept,MethodProviderStreamOpen) - Frame size limits: 8 MiB per JSON-RPC frame
- Externalization threshold: 64 KiB for payload offloading
- Content reference chunk size: 256 KiB
Manifest v2 Runtime Block
Extensions declare their capabilities statically in reasonix-plugin.json. The host only starts sidecars for manifests installed through the plugin flow—project files cannot spawn runtimes.
// Example: Declaring a runtime block in reasonix-plugin.json
{
"apiVersion": "reasonix.io/plugin/v2",
"manifest": {
"runtime": {
"command": "myextension --host $HOST --port $PORT",
"intercepts": ["input.receive", "permission.decision"],
"replaces": ["system_prompt"],
"providers": ["myProvider"],
"uiActions": ["status"]
}
}
}
Interception and Replacement System
Extension Runtime v2 provides 17 hook points where sidecars can influence host behavior. Each interceptor receives the full payload and returns a decision:
continue— Pass through unchangedblock— Halt the operationreplace— Substitute modified payload
// Example: Responding to an intercept request in a sidecar (Go SDK)
func handleIntercept(ctx context.Context, params extension.InterceptParams) (extension.InterceptResult, error) {
// Decide to modify the input payload
newInput := strings.ReplaceAll(string(params.Payload), "foo", "bar")
return extension.InterceptResult{
Decision: extension.DecisionReplace,
Payload: []byte(newInput),
}, nil
}
Replacement slots enforce single ownership with manifest priority ordering. This prevents conflicts when multiple extensions target the same hook point.
Streaming Model Providers
Extensions can expose new model providers through namespaced identifiers: plugin/<plugin>/<provider>/<model>. The streaming protocol follows a strict lifecycle:
extension/provider/stream/open— Establish stream- Chunk transmission — Bounded 8 MiB frames
extension/provider/stream/end— Clean termination
This design allows extensions to integrate custom inference backends without modifying the host's core model routing.
Structured UI Contributions
Sidecars publish interface elements via host/ui/publish, supporting status entries, cards, forms, and notifications. UI actions follow namespaced identifiers:
// Example: Publishing a UI status from the sidecar (JSON‑RPC)
await client.send({
jsonrpc: "2.0",
method: "host/ui/publish",
params: {
kind: "status",
surfaceId: "status",
pluginId: "myextension",
generation: 3,
payload: { label: "working", details: "Processing…" }
}
});
Action handlers use the format /<plugin>:<action> and are invoked through extension/ui/action. The host enforces manifest validation before exposing any UI capabilities.
Content Externalization and Performance
Large payloads exceeding 64 KiB are automatically externalized to the host's content store, referenced via ExternalizedField structures. This prevents JSON-RPC frame bloat while maintaining data accessibility.
| Limit | Value | Purpose |
|---|---|---|
| Frame size | 8 MiB | Maximum JSON-RPC message |
| Externalization threshold | 64 KiB | Payload offloading trigger |
| Content chunk size | 256 KiB | Incremental large object reads |
These constraints enable deterministic benchmarking through go test ./internal/extension/... -bench 'Extension|Dispatch'.
Runtime Reload and Failure Handling
Extension Runtime v2 implements atomic generation-based reloading:
- New sidecar generation spawns in parallel
- Session state preservation during transition
- Traffic cutover on successful initialization
- Automatic rollback on build failure
Crashed sidecars trigger cancellation of pending RPCs. The host restarts the sidecar only after an idle-time reload, preventing crash loops from destabilizing the session.
Security Model
The Extension Runtime v2 full-trust design grants sidecars substantial privileges:
- Unfiltered environment variable access
- Complete session visibility
- Permission bypass capability
Authorization occurs only at install/update time, with the host displaying a FULL TRUST warning during --dry-run preview. The manifest serves as the capability contract; runtime enforcement validates declared permissions and redacts credentials before UI exposure.
Implementation Reference
Key files defining the Extension Runtime v2 architecture:
| File | Contents |
|---|---|
docs/EXTENSIONS.md |
Runtime overview, reload semantics, security model |
docs/EXTENSION_PROTOCOL.md |
Complete protocol specification (transport, lifecycle, limits) |
sdk/go/types_generated.go |
Generated DTOs, method constants, frozen limits |
desktop/frontend/src/lib/useController.ts |
UI surface management for extension generations |
workers/crash-report/src/diagnostics_v2.ts |
Runtime version tracking for diagnostics |
Summary
- Extension Runtime v2 isolates plugins through sidecar processes communicating via JSON-RPC
- 17 interception points enable fine-grained control over host behavior with single-owner replacement semantics
- Streaming providers integrate custom models through namespaced identifiers with bounded 8 MiB frames
- Atomic reload preserves session state across generation transitions with automatic failure rollback
- Full-trust security delegates authorization to install time, enforcing manifest-based capability validation throughout operation
Frequently Asked Questions
How does Extension Runtime v2 differ from traditional plugin architectures?
Traditional plugins typically run inside the host process with sandboxed permissions. Extension Runtime v2 launches separate OS processes with full-trust privileges, using JSON-RPC for communication. This separation prevents plugin crashes from destabilizing the host, enables independent resource management, and supports clean hot-reloading without session interruption.
What happens if a sidecar exceeds the 30-second initialization budget?
The host terminates the sidecar process and marks the extension as failed. Other parallel sidecar initializations continue unaffected. The host will attempt restart only after an idle-time runtime reload, not immediately, to prevent resource exhaustion from repeatedly failing extensions.
Can multiple extensions replace the same system prompt?
No. Replacement slots enforce single ownership with manifest priority determining which extension wins when multiple claim the same slot. This design prevents conflicting modifications and ensures deterministic behavior. Extensions should declare replacement intents explicitly in their manifest's replaces array.
How does payload externalization work for large data transfers?
When a payload exceeds 64 KiB, the host automatically stores it in a content-addressed blob store and replaces the field with an ExternalizedField reference containing the content ID. The sidecar retrieves chunks via content reference methods with 256 KiB granularity, keeping JSON-RPC frames under the 8 MiB limit while enabling efficient large object handling.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →