# Headless gRPC Server in OpenClaude: Architecture, Purpose, and Integration Guide

> Discover the purpose of the headless gRPC server in OpenClaude. This guide explains how it makes the agent a network-accessible service with bidirectional streaming.

- Repository: [Gitlawb/openclaude](https://github.com/Gitlawb/openclaude)
- Tags: architecture
- Published: 2026-09-08

---

**The headless gRPC server in OpenClaude transforms the CLI-based agent into a network-accessible service, exposing bidirectional streaming capabilities through the `AgentService.Chat` method.**

This server enables external programs to interact with OpenClaude's agentic capabilities without requiring the full interactive terminal interface. By implementing a gRPC service in [`src/grpc/server.ts`](https://github.com/Gitlawb/openclaude/blob/main/src/grpc/server.ts), the codebase supports programmatic integration from any language that can consume gRPC, making it ideal for CI/CD pipelines, custom dashboards, and automated workflows.

## Core Purpose: Why OpenClaude Uses a Headless gRPC Server

The **headless gRPC server** serves as a bridge between OpenClaude's interactive agent core and external systems. Traditional CLI-based agents lock users into terminal sessions. The gRPC server removes this constraint by:

- Exposing agent functionality as a **language-agnostic network service**
- Supporting **bidirectional streaming** for real-time, multi-turn conversations
- Enabling **tool-call mediation** with explicit client approval workflows
- Maintaining **session persistence** across disconnected interactions

According to the OpenClaude source code, this architecture allows embedding into environments where a full TTY interface is impractical or impossible.

## Service Entry Point and Startup

The server initialization logic resides in `GrpcServer.start` (lines 97-108 of [`src/grpc/server.ts`](https://github.com/Gitlawb/openclaude/blob/main/src/grpc/server.ts)). This method creates a `grpc.Server` instance, binds to `localhost:50051` by default (configurable via host/port parameters), and registers the `AgentService` definition loaded from the Protocol Buffer specification.

```bash

# Launch the headless gRPC service (default port 50051)

npm run dev:grpc

```

The CLI entry point at [`scripts/start-grpc.ts`](https://github.com/Gitlawb/openclaude/blob/main/scripts/start-grpc.ts) instantiates the `GrpcServer` class and invokes `start()`, providing a clean bootstrap mechanism for production deployments.

## Bidirectional Streaming Architecture

The centerpiece of the server is the **`AgentService.Chat`** method (lines 111-220 of [`src/grpc/server.ts`](https://github.com/Gitlawb/openclaude/blob/main/src/grpc/server.ts)). `handleChat` implements a duplex stream that handles:

- Client requests containing `session_id`, `message`, and `model` parameters
- Server responses as incremental **text chunks**
- **Tool-start events** signaling pending tool invocations
- **Action-required prompts** requesting explicit user approval
- Final results completing the interaction cycle

This streaming model mirrors the interactive CLI experience but decouples it from terminal I/O constraints.

## Tool-Call Mediation and Permission Flow

Before executing any tool, the server enforces an explicit approval workflow through the **canUseTool callback** (lines 60-84 of [`src/grpc/server.ts`](https://github.com/Gitlawb/openclaude/blob/main/src/grpc/server.ts)):

1. Server emits a `tool_start` event to the client
2. Server issues an `action_required` prompt requesting approval
3. Client response routes back via the pending-requests map
4. Tool executes only after affirmative client confirmation

This security-critical mechanism prevents unauthorized autonomous actions when OpenClaude operates in server mode.

## Session Persistence Across Streams

The server maintains conversation state through an **in-memory session store** (`this.sessions` map). Referenced around lines 41-69 and 60-70 of [`src/grpc/server.ts`](https://github.com/Gitlawb/openclaude/blob/main/src/grpc/server.ts), this store:

- Associates message history with unique `session_id` values
- Enables multi-turn conversations across multiple stream connections
- Provides continuity for long-running agent interactions

Note that sessions are volatile; server restarts clear all conversation history.

## Graceful Interruption and Cleanup

Production-grade reliability requires robust cancellation support. The server implements:

- **Client-initiated cancellation** via the `cancel` message type (lines 89-95)
- **Automatic cleanup** on stream `end` events (lines 108-119)
- **Propagation to QueryEngine** ensuring underlying operations terminate cleanly

These mechanisms prevent resource leaks and hanging processes during unexpected disconnections.

## Integration Example: Programmatic Node.js Client

Consume the headless gRPC server from any supported language. This Node.js example demonstrates connection establishment and basic interaction:

```ts
import * as grpc from '@grpc/grpc-js';
import * as protoLoader from '@grpc/proto-loader';
import path from 'path';

const PROTO_PATH = path.resolve(import.meta.dirname, '../src/proto/openclaude.proto');
const pkg = grpc.loadPackageDefinition(
  protoLoader.loadSync(PROTO_PATH, { keepCase: true, longs: String, enums: String, defaults: true, oneofs: true })
) as any;
const client = new pkg.openclaude.v1.AgentService('localhost:50051', grpc.credentials.createInsecure());

const call = client.Chat();

call.on('data', (msg) => console.log('Server:', msg));
call.write({ request: { session_id: 'demo', message: 'Hello', model: 'gpt-4' } });

```

For interactive testing, use the bundled CLI client:

```bash

# Open a second terminal and execute the lightweight CLI client

npm run dev:grpc:cli

```

## Key Source Files Reference

| File | Role |
|------|------|
| [`src/grpc/server.ts`](https://github.com/Gitlawb/openclaude/blob/main/src/grpc/server.ts) | Core server implementation, streaming logic, tool-permission handling, session store |
| `src/proto/openclaude.proto` | gRPC service and message definitions |
| [`scripts/start-grpc.ts`](https://github.com/Gitlawb/openclaude/blob/main/scripts/start-grpc.ts) | CLI entry point for server instantiation |
| [`scripts/grpc-cli.ts`](https://github.com/Gitlawb/openclaude/blob/main/scripts/grpc-cli.ts) | Minimal client for manual testing |
| [`docs/grpc-server.md`](https://github.com/Gitlawb/openclaude/blob/main/docs/grpc-server.md) | User-facing documentation for deployment |

## Summary

- The **headless gRPC server** converts OpenClaude from a terminal-bound tool into a network service
- **`AgentService.Chat`** provides bidirectional streaming for real-time agent interactions
- **Tool-call mediation** enforces explicit client approval before any tool execution
- **Session persistence** maintains conversation state across multiple connections
- **Graceful interruption** ensures clean resource cleanup on cancellation or disconnection
- Default binding to `localhost:50051` with configurable host/port parameters

## Frequently Asked Questions

### What port does the OpenClaude gRPC server use by default?

The server binds to **port 50051** on localhost by default. This is hardcoded in the `GrpcServer.start` implementation at lines 97-108 of [`src/grpc/server.ts`](https://github.com/Gitlawb/openclaude/blob/main/src/grpc/server.ts), though both host and port are configurable through constructor parameters.

### How does the gRPC server handle tool approvals differently from the CLI?

The CLI can prompt directly in the terminal. The **gRPC server emits `tool_start` and `action_required` events** through the stream, then waits for the client to respond via the pending-requests map before proceeding, as implemented in the `canUseTool` callback (lines 60-84).

### Can multiple clients connect to the same session simultaneously?

The source code shows session state stored in `this.sessions` keyed by `session_id`, but the implementation does not include explicit concurrency controls for simultaneous access. For production use, assume single-client-per-session semantics unless you implement external coordination.

### Is conversation history persisted to disk?

No. The **session store is in-memory only** (lines 41-69, 60-70 of [`src/grpc/server.ts`](https://github.com/Gitlawb/openclaude/blob/main/src/grpc/server.ts)). Server restarts, crashes, or deployments will lose all active conversation history. For persistence requirements, implement external storage through client-side logging or a custom wrapper service.