npm package: @machinemetrics/agent-event-protocol
Description: Agent Event Protocol implementation
Latest version: 0.1.1

# @machinemetrics/agent-event-protocol

A transport-agnostic event protocol for streaming agent responses. Defines the schema and utilities for real-time communication between AI agents and clients.

## Installation

```bash
npm install @machinemetrics/agent-event-protocol
```

## Design Principles

1. **Simple** - Easy to understand and implement
2. **Flexible** - Supports future features without breaking changes
3. **Type-safe** - Strong contracts between client and server
4. **Observable** - Easy to monitor and debug
5. **Transport-agnostic** - Same events work over SSE, NDJSON, WebSocket, NATS, etc.

## Protocol Overview

The protocol defines a streaming event schema for agent responses. All events are self-identifying JSON payloads with common fields:

- `event` - Event type identifier
- `requestId` - Correlates all events to the originating request
- `timestamp` - ISO 8601 timestamp for observability

### Message Flow

```
┌─────────┐                                    ┌─────────┐
│ Client  │                                    │ Server  │
└────┬────┘                                    └────┬────┘
     │                                              │
     │  POST /v1/agents/{agentName}/stream         │
     │  { messages, threadId?, context? }          │
     ├─────────────────────────────────────────────>│
     │                                              │
     │  metadata: {threadId, requestId, agentId}   │
     │<─────────────────────────────────────────────┤
     │                                              │
     │  text: {blockId, stage: "start"}            │
     │<─────────────────────────────────────────────┤
     │                                              │
     │  text: {blockId, stage: "delta", delta}     │
     │<─────────────────────────────────────────────┤
     │                                              │
     │  text: {blockId, stage: "stop"}             │
     │<─────────────────────────────────────────────┤
     │                                              │
     │  done: {content, usage, finishReason}       │
     │<─────────────────────────────────────────────┤
     │                                              │
```

### Client Action Flow

When the agent needs client-side action, the stream pauses and resumes via a new request:

```
┌─────────┐                                    ┌─────────┐
│ Client  │                                    │ Server  │
└────┬────┘                                    └────┬────┘
     │                                              │
     │  POST /stream { messages, threadId? }       │
     ├─────────────────────────────────────────────>│
     │                                              │
     │  continuation: {actionId, kind, payload}    │
     │<─────────────────────────────────────────────┤
     │                                              │
     │  done: {finishReason: "action_required"}    │
     │<─────────────────────────────────────────────┤
     │                                              │
     │  (client handles action based on kind)      │
     │                                              │
     │  POST /stream { messages, threadId,         │
     │    context: { actionResults: [...] }}       │
     ├─────────────────────────────────────────────>│
     │                                              │
     │  (agent continues with result)              │
     │                                              │
```

## Event Types

The protocol defines 9 event types covering the complete lifecycle of an agent response.

| Event | Description |
|-------|-------------|
| `metadata` | Stream initialization with threadId, requestId, agentId |
| `text` | Streaming text output with stage lifecycle |
| `thinking` | Model reasoning/thinking content (extended thinking) |
| `tool_call` | Tool invocation with streaming arguments |
| `tool_result` | Tool execution result (status and summary only) |
| `done` | Stream complete with full content array |
| `error` | Error condition with code and retry guidance |
| `aborted` | Client cancellation acknowledgment |
| `continuation` | Pause for client action (tools, approval, input) |

### Terminal Events

Each request must end with exactly one terminal event: `done`, `error`, or `aborted`.

## Event Lifecycle (Stage Pattern)

Content events (`text`, `thinking`, `tool_call`, `tool_result`) use a consistent stage pattern:

| Stage | Description |
|-------|-------------|
| `start` | Block begins, includes `blockIndex` for ordering |
| `delta` | Content chunk, includes `deltaIndex` for ordering within block |
| `stop` | Block complete, includes final data for that block type |

## Request Schema

```typescript
type AgentRequest = {
  messages: InputMessage[];   // New user input
  threadId?: string;          // Resume existing thread
  context?: {
    actionResults?: ActionResult[];  // Results from continuation events
    [key: string]: unknown;          // Additional passthrough data
  };
};
```

Only `messages` is required. The server loads thread history from storage via `threadId`.

## Content Blocks

**User Content Blocks** (in requests):
- `text` - Plain text input

**Assistant Content Blocks** (in responses):
- `text` - Text output
- `thinking` - Model reasoning
- `tool_use` - Tool invocation with args
- `tool_result` - Tool result status and summary (no full payloads)

## Error Handling

### Error Codes

| Code | Description |
|------|-------------|
| `auth_failed` | Authentication failed |
| `thread_not_found` | Thread does not exist |
| `thread_access_denied` | Thread ownership violation |
| `invalid_message_format` | Invalid request format |
| `message_too_large` | Message exceeds size limit |
| `rate_limit_exceeded` | Rate limit hit |
| `stream_timeout` | Stream timed out |
| `agent_error` | Agent execution error |
| `tool_error` | Tool execution error |
| `internal_error` | Internal server error |
| `invalid_action_id` | Action ID not found or already resolved |

### HTTP Status Mapping

| Status | Error Codes |
|--------|-------------|
| 400 | `invalid_message_format`, `invalid_action_id` |
| 401 | `auth_failed` |
| 403 | `thread_access_denied` |
| 404 | `thread_not_found` |
| 413 | `message_too_large` |
| 429 | `rate_limit_exceeded` |
| 500 | `internal_error` |
| 504 | `stream_timeout` |

### Retry Guidance

- `retryable: true` - Client can retry with backoff
- `retryable: false` - Don't retry, user action required

## SSE Transport

Server-Sent Events is the default transport implementation.

### Wire Format

```
Content-Type: text/event-stream
Connection: keep-alive
Cache-Control: no-cache

event: metadata
data: {"event":"metadata","requestId":"req-1","threadId":"th-1","agentId":"agent","timestamp":"..."}

event: text
data: {"event":"text","requestId":"req-1","messageId":"msg-1","blockId":"b0","stage":"start","blockIndex":0,"timestamp":"..."}

event: text
data: {"event":"text","requestId":"req-1","messageId":"msg-1","blockId":"b0","stage":"delta","delta":"Hello","deltaIndex":0,"timestamp":"..."}

event: done
data: {"event":"done","requestId":"req-1","messageId":"msg-1","threadId":"th-1","content":[...],"finishReason":"stop","timestamp":"..."}
```

### Keepalive

Servers should send SSE comment lines (`: heartbeat\n\n`) every 15 seconds to prevent proxy timeouts.

### Utilities

```typescript
import { encodeSSE, parseSSEChunk } from '@machinemetrics/agent-event-protocol';

// Server: encode events for streaming
const sseData = encodeSSE('text', { event: 'text', ... });

// Client: parse incoming chunks
const { events, remainder } = parseSSEChunk(chunk);
```

## Extensibility

**Adding new events is backward compatible:**
- Clients should ignore unknown event types
- New optional fields can be added to existing events
- No version bump required for additive changes

**Breaking changes require new endpoint version:**
```
/v1/agents/{agentName}/stream  → Current
/v2/agents/{agentName}/stream  → Breaking changes
```

## Exports

```typescript
import {
  // Core types
  InputMessage,
  AgentRequest,
  AgentEvent,
  ActionResult,
  UserContentBlock,
  AssistantContentBlock,
  EventStage,
  MetadataEvent,
  TextEvent,
  ThinkingEvent,
  ToolCallEvent,
  ToolResultEvent,
  DoneEvent,
  ErrorEvent,
  AbortedEvent,
  ContinuationEvent,

  // Schemas (Zod validators)
  AgentRequestSchema,
  AgentEventSchema,
  // ... all event schemas

  // SSE utilities
  encodeSSE,
  parseSSEChunk,
  ParsedEvent,
  ParseResult,

  // Constants
  PROTOCOL_VERSION,
  EVENT_TYPES,
} from '@machinemetrics/agent-event-protocol';
```

## Development

```bash
pnpm install
pnpm build       # Build the package (ESM + CJS)
pnpm test        # Run tests
pnpm typecheck   # Type check
```