Claude
Skills
Sign in
Back

broadcast-event

Included with Lifetime
$97 forever

Design WebSocket event broadcasting for ADW observability. Use when streaming workflow events to external dashboards or monitoring systems.

Design

What this skill does


# Broadcast Event

Design WebSocket event broadcasting for AI Developer Workflow observability.

## Arguments

- `$ARGUMENTS`: `<event-type> [payload-description]`
  - `event-type`: Type of event to broadcast (e.g., `ToolUseBlock`, `StepComplete`)
  - `payload-description`: Optional payload structure description

## Event Types

| Event Type | Source | Payload |
| --- | --- | --- |
| `TextBlock` | Agent output | Text content |
| `ToolUseBlock` | Tool invocation | Tool name, input |
| `ThinkingBlock` | Extended thinking | Thinking content |
| `StepStart` | Workflow step | Step name, timestamp |
| `StepEnd` | Workflow step | Step name, status |
| `ADWComplete` | Workflow finish | Final status, metrics |

## Instructions

### Step 1: Define Message Format

Standard ADW event structure:

```json
{
  "type": "adw_event",
  "adw_id": "a1b2c3d4",
  "step": "build",
  "event_type": "ToolUseBlock",
  "timestamp": "2026-01-01T14:30:00Z",
  "summary": "Writing authentication middleware to src/auth.py",
  "payload": {
    "tool_name": "Write",
    "file_path": "src/auth.py",
    "content_preview": "class AuthMiddleware:..."
  }
}
```text

### Step 2: Design Summarization Strategy

Use Haiku for fast, cheap summaries:

**Prompt Template:**

```text
Summarize this {event_type} in 15 words or less for a developer dashboard:

Tool: {tool_name}
Input: {tool_input_preview}

Summary:
```text

**Events to Summarize:**

- `ToolUseBlock`: Summarize tool action
- `TextBlock`: Summarize content (if long)
- `ThinkingBlock`: Summarize reasoning

**Events to Pass Through:**

- `StepStart`: Use fixed format
- `StepEnd`: Use fixed format
- `ADWComplete`: Use fixed format

### Step 3: Design WebSocket Server

Server specification:

```python
# adws/websocket_server.py
from fastapi import FastAPI, WebSocket
from typing import Dict, Set
import asyncio

app = FastAPI()

class ConnectionManager:
    def __init__(self):
        self.active_connections: Dict[str, Set[WebSocket]] = {}

    async def connect(self, websocket: WebSocket, adw_id: str):
        await websocket.accept()
        if adw_id not in self.active_connections:
            self.active_connections[adw_id] = set()
        self.active_connections[adw_id].add(websocket)

    async def broadcast(self, adw_id: str, message: dict):
        if adw_id in self.active_connections:
            for connection in self.active_connections[adw_id]:
                await connection.send_json(message)

manager = ConnectionManager()

@app.websocket("/ws/{adw_id}")
async def websocket_endpoint(websocket: WebSocket, adw_id: str):
    await manager.connect(websocket, adw_id)
    try:
        while True:
            await websocket.receive_text()  # Keep alive
    except:
        manager.active_connections[adw_id].discard(websocket)
```text

### Step 4: Design Client Subscription

Client subscription message:

```json
{
  "action": "subscribe",
  "filters": {
    "adw_id": "a1b2c3d4",
    "steps": ["build", "review"],
    "event_types": ["ToolUseBlock", "StepEnd"]
  }
}
```text

### Step 5: Design Resilience Patterns

**Reconnection Strategy:**

```javascript
class ResilientWebSocket {
  constructor(url) {
    this.url = url;
    this.maxReconnectDelay = 30000;
    this.reconnectAttempts = 0;
  }

  connect() {
    this.ws = new WebSocket(this.url);

    this.ws.onclose = () => {
      const delay = Math.min(
        1000 * Math.pow(2, this.reconnectAttempts),
        this.maxReconnectDelay
      );
      setTimeout(() => this.connect(), delay);
      this.reconnectAttempts++;
    };

    this.ws.onopen = () => {
      this.reconnectAttempts = 0;
    };
  }
}
```text

**Heartbeat Mechanism:**

- Interval: 30 seconds
- Timeout: 90 seconds
- Message: `{"type": "ping"}`

## Output

```markdown
## Event Broadcasting Specification

**Event Type:** {event_type}
**ADW Context:** {adw_id}

### Message Format

```json
{message_structure}
```text

### Summarization

**Strategy:** {haiku/passthrough}
**Prompt:** {if haiku}

### Server Endpoint

**URL:** `ws://localhost:8000/ws/{adw_id}`
**Protocol:** WebSocket

### Client Subscription

```json
{subscription_message}
```text

### Resilience

| Pattern | Value |
| --- | --- |
| Reconnect Strategy | Exponential backoff |
| Max Delay | 30 seconds |
| Max Attempts | 10 |
| Heartbeat Interval | 30 seconds |

### Integration

Hook scripts broadcast via HTTP POST to server:

```python
import httpx

async def broadcast(event: dict):
    async with httpx.AsyncClient() as client:
        await client.post(
            f"http://localhost:8000/broadcast/{event['adw_id']}",
            json=event
        )
```text

### Next Steps

1. Implement WebSocket server (`adws/websocket_server.py`)
2. Integrate with hooks (`/configure-hooks`)
3. Build swimlane UI (`swimlane-visualization` skill)
4. Add event persistence (optional database logging)

```text

## SDK Note

> **Implementation Note:** Full WebSocket integration requires production backend. This command provides the specification; implementation requires FastAPI/asyncio setup.

## Cross-References

- @websocket-architecture.md - WebSocket patterns
- @hook-event-patterns.md - Event types
- `event-broadcaster` agent - Broadcasting design
- `swimlane-visualization` skill - UI consumption

Related in Design