# How the unified-network-interceptor Handles Pi-Only Requests in craft-agents-oss

> Discover how craft-agents-oss unified-network-interceptor specifically handles Pi-only requests by preloading into the Pi SDK subprocess and normalizing SSE streams.

- Repository: [Craft Ai Agents/craft-agents-oss](https://github.com/craft-ai-agents/craft-agents-oss)
- Tags: internals
- Published: 2026-07-06

---

**The [`unified-network-interceptor.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/unified-network-interceptor.ts) acts as a global fetch interceptor that preloads exclusively into the Pi SDK subprocess via Bun's `--preload` mechanism, rewriting tool metadata and normalizing SSE streams while remaining isolated from the Claude SDK.**

The `unified-network-interceptor` is a specialized network shim within the `craft-ai-agents/craft-agents-oss` repository designed to intercept and modify HTTP requests made specifically by the Pi agent. Because the Pi SDK runs on Bun rather than Node.js, the interceptor leverages Bun's preload mechanism to patch `globalThis.fetch` before any application code executes. This architecture ensures that every outgoing request—whether to Anthropic or OpenAI APIs—passes through metadata injection, SSE normalization, and proxy handling logic that is intentionally excluded from the Claude SDK's native binary runtime.

## Preload Mechanism and Bun Configuration

The interceptor activates through a **pre-load mechanism** declared in the repository's [`bunfig.toml`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/bunfig.toml). This configuration ensures the interceptor executes before the Pi SDK imports `fetch`, guaranteeing complete request interception.

In [`bunfig.toml`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/bunfig.toml), the interceptor is declared as a preload script:

```toml

# https://github.com/craft-ai-agents/craft-agents-oss/blob/main/bunfig.toml

preload = ["./packages/shared/src/unified-network-interceptor.ts"]

```

When the Pi process starts with `bun run`, Bun automatically applies the `--preload` flag to this path. This execution order is critical because it allows the interceptor to replace the native `fetch` implementation before any SDK code loads, ensuring **100% request coverage** for the Pi agent.

## Runtime Resolver and Bundle Path Resolution

Production environments (packed Electron builds) use a different loading strategy. The interceptor is bundled as `dist/interceptor.cjs`, and the runtime resolver locates the correct file via `resolveInterceptorBundlePath` in [`packages/agent/backend/internal/runtime-resolver.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/packages/agent/backend/internal/runtime-resolver.ts).

This resolver implements a fallback chain:
1. **Production**: Load the bundled CJS file from the Electron distribution
2. **Development**: Fall back to the TypeScript source file to enable hot-reloading without rebuilds

Build scripts in [`scripts/build/common.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/scripts/build/common.ts) and [`scripts/electron-build-main.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/scripts/electron-build-main.ts) handle copying the interceptor source or bundled `.cjs` into the Electron distribution during the packaging process.

## Core Interception Logic for Pi-Only Requests

The [`unified-network-interceptor.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/unified-network-interceptor.ts) file in `packages/shared/src/` performs several transformation layers on Pi SDK network traffic.

### Patching globalThis.fetch

The interceptor replaces `globalThis.fetch` with a wrapper function that inspects and rewrites requests before they reach the network layer. This monkey-patching approach captures all HTTP traffic from the Pi subprocess without requiring changes to the SDK itself.

### Tool Metadata Injection

For both Anthropic and OpenAI-style requests, the interceptor performs bidirectional metadata handling:

- **Outgoing requests**: The `injectMetadataIntoToolSchema` function adds `_intent` and `_displayName` fields to tool schemas before they reach the API
- **Incoming responses**: When the Pi SDK receives a `tool_use` or `tool_call` block lacking metadata, the interceptor looks up stored values in `toolMetadataStore` and reinserts them via `injectMetadataIntoHistory`

This ensures conversation history retains human-readable tool names and intents even when the underlying API strips these fields.

### SSE Stream Processing

The interceptor normalizes Server-Sent Events (SSE) streams differently for each provider:

**Anthropic**: `createAnthropicSseStrippingStream` buffers `tool_use` deltas, extracts metadata from the JSON payload, strips these internal fields, and re-emits clean SSE events to the Pi SDK.

**OpenAI**: `createOpenAiSseStrippingStream` consolidates fragmented `tool_calls`—including handling "DeepSeek" quirks—into single SSE events containing `id`, `name`, and cleaned arguments. This prevents the Pi SDK from misinterpreting argument-only deltas as new tool invocations.

### Error Handling and Proxy Support

The interceptor implements robust error handling by throwing `MalformedBodyError` for locally detectable request body problems. It converts these exceptions into synthetic 400 responses so the Pi SDK receives actionable error messages rather than network failures.

For proxy support, the interceptor reads `HTTPS_PROXY`, `HTTP_PROXY`, and `NO_PROXY` environment variables, applying proxying selectively while logging sanitized URLs (with credentials redacted) for security.

## Why the Interceptor Is Pi-Only

The `unified-network-interceptor` is **explicitly restricted** from the Claude SDK. According to [`packages/shared/CLAUDE.md`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/packages/shared/CLAUDE.md):

> "The network interceptor ([`unified-network-interceptor.ts`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/unified-network-interceptor.ts)) is currently **Pi-only**: it preloads into the Pi subprocess via Bun `--preload`. The Claude SDK no longer runs under Bun…"

This limitation exists because the Claude SDK now spawns a native binary rather than a Bun process, making the preload mechanism incompatible. Consequently, all interceptor features—metadata injection, SSE stripping, fast-mode handling, and proxy logic—execute **exclusively** for Pi agent requests.

## Summary

- The `unified-network-interceptor` is a **global fetch interceptor** that preloads via [`bunfig.toml`](https://github.com/craft-ai-agents/craft-agents-oss/blob/main/bunfig.toml) before Pi SDK execution
- It patches `globalThis.fetch` to inject `_intent` and `_displayName` metadata into tool schemas using `injectMetadataIntoToolSchema` and `toolMetadataStore`
- SSE streams are normalized via `createAnthropicSseStrippingStream` and `createOpenAiSseStrippingStream` to handle fragmented tool calls
- The interceptor is **Pi-only** because the Claude SDK uses native binaries rather than Bun, making the preload mechanism incompatible
- Production builds use `resolveInterceptorBundlePath` to load bundled versions while development falls back to source files

## Frequently Asked Questions

### Why is the unified-network-interceptor limited to Pi-only requests?

The interceptor relies on Bun's `--preload` mechanism to patch `globalThis.fetch` before application code loads. The Claude SDK now runs as a native binary rather than a Bun process, making preload injection impossible. This architectural difference restricts the interceptor to the Pi SDK, which executes within a Bun subprocess where the preload hook remains effective.

### How does the interceptor inject metadata into tool schemas?

The interceptor uses `injectMetadataIntoToolSchema` to add `_intent` and `_displayName` fields to outgoing tool definitions. When responses return, `injectMetadataIntoHistory` retrieves stored values from `toolMetadataStore` and reinserts them into conversation history. This ensures the Pi SDK maintains rich tool metadata even when APIs strip these internal fields from their responses.

### What SSE processing does the interceptor perform for OpenAI requests?

For OpenAI streams, the interceptor uses `createOpenAiSseStrippingStream` to consolidate fragmented `tool_calls` into unified SSE events. This processor handles edge cases like "DeepSeek" quirks and ensures that argument-only deltas are not misinterpreted as new tool invocations. The result is a clean SSE stream containing complete `id`, `name`, and sanitized argument payloads.

### How does the interceptor handle proxy configuration?

The interceptor reads `HTTPS_PROXY`, `HTTP_PROXY`, and `NO_PROXY` environment variables at runtime. It applies proxy routing only when necessary and logs sanitized URLs with credentials redacted for security. This proxy logic is integrated directly into the patched `fetch` implementation, ensuring all Pi SDK requests respect network policies without requiring manual proxy configuration in the application code.