Agent Daddy

WebSocket API for agent debugging

Agent Daddy is a real-time debugging mirror. Your agent connects via WebSocket, fires events (fire-and-forget), and they show up instantly in the dashboard chat UI.

Server

https://daddy.codeaxolot.com

WebSocket (wss://) is handled automatically by Socket.IO when connecting over https.


1. Connect

Connect via WebSocket with your agent_id and role=agent. All communication happens over WebSocket (wss://) — no HTTP API, no polling.

Python (pip install python-socketio[client] websocket-client)

import socketio

sio = socketio.Client()
sio.connect(
    "https://daddy.codeaxolot.com",
    transports=["websocket"],
    socketio_path="socket.io",
    headers={"User-Agent": "my-agent"},
    auth={
        "role": "agent",
        "agent_id": "my-agent"
    }
)

# Note: python-socketio passes auth differently from query params.
# You can also use query string style:
sio.connect(
    "https://daddy.codeaxolot.com?role=agent&agent_id=my-agent",
    transports=["websocket"]
)

JavaScript / Node.js (npm install socket.io-client)

import { io } from "socket.io-client";

const socket = io("https://daddy.codeaxolot.com", {
  query: { role: "agent", agent_id: "my-agent" },
  transports: ["websocket"]
});

2. Send Events

Emit an "event" over the WebSocket. Fire-and-forget — no response, no acknowledgement needed.

Field Type Required Description
chat_id string yes Identifies which conversation/chat this belongs to. Each chat gets its own color pill in the dashboard and can be filtered.
direction string yes "sent" = agent/subprocess action (shown RIGHT), "received" = user/external input (shown LEFT)
content any yes Message content — string or JSON object
kind string no Visual shape: "message" (default bubble), "notification", "error", "context"
user object no Sender info: { name?, username?, avatar? }. Shows avatar + name on the bubble.
metadata object no Extra context — type, model, tokens, etc.

kind — visual shapes

message (default)

Chat bubble — left or right based on direction. Use for conversation messages, tool calls, tool results.

notification

Centered banner — for status updates, background process starts, info the agent wants to surface.

error

Red alert banner — for errors, failures, exceptions. Stands out immediately.

context

Compact summary bubble with "Explore" button. Opens a Context Explorer panel on the left to browse messages and attachments. Server computes stats (message count, total size).

Layout: direction: "sent" = agent & subprocess messages appear on the right. direction: "received" = user & external messages appear on the left. Each chat_id gets a unique color pill so you can visually distinguish conversations.

Note: agent_id is set once at connection time via query params, not per event.

Recommended metadata.type values

user_message assistant_message tool_call tool_result error

Python — log a conversation turn

# User sends a message to the agent (left side)
sio.emit("event", {
    "chat_id": "chat-abc-123",
    "direction": "received",
    "content": "What is the weather in Tokyo?",
    "metadata": { "type": "user_message" }
})

# Agent responds (right side)
sio.emit("event", {
    "chat_id": "chat-abc-123",
    "direction": "sent",
    "content": "The weather in Tokyo is 15°C and cloudy.",
    "metadata": { "type": "assistant_message", "model": "claude-sonnet-4-6", "tokens": 42 }
})

Python — log a tool call + result

# Agent/subprocess calls a tool (right side)
sio.emit("event", {
    "chat_id": "chat-abc-123",
    "direction": "sent",
    "content": {
        "tool": "web_search",
        "input": { "query": "Tokyo weather" }
    },
    "metadata": { "type": "tool_call" }
})

# Tool result comes back (right side — still agent's subprocess)
sio.emit("event", {
    "chat_id": "chat-abc-123",
    "direction": "sent",
    "content": {
        "tool": "web_search",
        "result": { "temp": "15°C", "condition": "cloudy" }
    },
    "metadata": { "type": "tool_result", "duration_ms": 1200 }
})

JavaScript — same thing

// User message (left side)
socket.emit("event", {
  chat_id: "chat-abc-123",
  direction: "received",
  content: "What is the weather in Tokyo?",
  metadata: { type: "user_message" }
});

// Agent response (right side)
socket.emit("event", {
  chat_id: "chat-abc-123",
  direction: "sent",
  content: "15°C and cloudy.",
  metadata: { type: "assistant_message" }
});

Python — notifications, errors, context

# Notification — centered banner, not a bubble
sio.emit("event", {
    "chat_id": "chat-abc-123",
    "direction": "sent",
    "kind": "notification",
    "content": "Starting background research on Tokyo weather patterns..."
})

# Error — red alert banner
sio.emit("event", {
    "chat_id": "chat-abc-123",
    "direction": "sent",
    "kind": "error",
    "content": "API rate limit exceeded. Retrying in 30s.",
    "metadata": { "status": 429, "retry_after": 30 }
})

# Agent context — full conversation with model info
sio.emit("event", {
    "chat_id": "chat-abc-123",
    "direction": "sent",
    "kind": "context",
    "content": {
        "context_type": "agent",
        "model": "claude-sonnet-4-6",
        "messages": [
            { "role": "system", "content": "You are a helpful weather assistant..." },
            { "role": "user", "content": "What is the weather in Tokyo?" },
            { "role": "assistant", "content": "Let me check..." }
        ]
    }
})

# Tool call context — sub-model invocation
sio.emit("event", {
    "chat_id": "chat-abc-123",
    "direction": "sent",
    "kind": "context",
    "content": {
        "context_type": "tool_call",
        "model": "claude-haiku-4-5-20251001",
        "messages": [
            { "role": "user", "content": "Summarize this", "attachments": [
                { "name": "doc.pdf", "type": "application/pdf", "size": 245000 }
            ]},
            { "role": "assistant", "content": "Here is the summary..." }
        ]
    }
})

3. User Data (optional)

Attach a user object to any event to show name, username, and avatar on the bubble.

user field Type Description
name string Display name shown on the bubble header
username string Handle shown as @username next to name
avatar string URL to avatar image — shown as a circle next to the bubble
# User message with user info
sio.emit("event", {
    "chat_id": "chat-abc-123",
    "direction": "received",
    "content": "Can you check the weather?",
    "user": {
        "name": "John Doe",
        "username": "johnd",
        "avatar": "https://i.pravatar.cc/150?u=john"
    }
})

# Agent reply with its own identity
sio.emit("event", {
    "chat_id": "chat-abc-123",
    "direction": "sent",
    "content": "Sure! Checking now...",
    "user": {
        "name": "Weather Bot",
        "avatar": "https://i.pravatar.cc/150?u=bot"
    }
})

If no user is provided, the bubble shows the agent_id with initials as the avatar. All three fields are optional — send any combination.

4. Context Events & Explorer

Send full conversation contexts using kind: "context". The content should have a messages array. The server computes stats automatically. In the dashboard, context appears as a compact summary bubble with an "Explore" button that opens the Context Explorer panel on the left.

Context content structure

Field Type Description
content.context_type string Type badge: "agent", "tool_call", "system", "memory"
content.model string Model name shown as pill on bubble (e.g. "claude-sonnet-4-6")
content.messages array Array of message objects (see below)

Message object fields

Field Type Description
role string "user", "assistant", "system", "tool"
content string | object Message text or structured content
name string Optional — tool name for role "tool"
attachments array Optional — array of { name, type, size } (metadata only, don't send file data)

Server-computed stats (context_stats)

  • message_count — number of messages in the context
  • text_bytes — total bytes of message content
  • attachment_bytes — total bytes of all attachments (from size fields)
  • attachment_count — number of attachments
  • total_bytes — text_bytes + attachment_bytes

context_type — visual badges

agent

Agent's own conversation context — the full chat history the agent is working with.

tool_call

Context for a tool call or sub-agent invocation — what was sent to a sub-model.

system

System prompt / configuration context.

memory

Memory or retrieval context — RAG results, recalled info.

Context Explorer: When you click "Explore" on a context bubble, the left panel opens showing all messages row-by-row with role badges, content previews, and attachment metadata. The source bubble gets highlighted in the chat. Only one context can be explored at a time. Context type and model are shown in both the bubble and the explorer header.

5. Send Batch

Emit "batch" with an array of events. Same fields, just wrapped in an array.

sio.emit("batch", [
    { "chat_id": "chat-abc-123", "direction": "received", "content": "Hello" },
    { "chat_id": "chat-abc-123", "direction": "sent", "content": "Hi there!" }
])

6. Register Tools

Emit "register_tools" with an array of tool definitions. They appear in the tools panel on the right side of the dashboard.

Field Type Required Description
name string yes Tool name
description string no What the tool does
parameters object no Map of param name to { type, description, required }
returns string no Return type description
sio.emit("register_tools", [
    {
        "name": "web_search",
        "description": "Search the web for information",
        "parameters": {
            "query": {
                "type": "string",
                "description": "Search query",
                "required": True
            },
            "limit": {
                "type": "number",
                "description": "Max results to return",
                "required": False
            }
        },
        "returns": "array of { title, url, snippet }"
    },
    {
        "name": "read_file",
        "description": "Read contents of a file",
        "parameters": {
            "path": {
                "type": "string",
                "description": "File path to read",
                "required": True
            }
        },
        "returns": "string"
    }
])

7. Full Example

Python (pip install python-socketio[client] websocket-client)

import socketio

sio = socketio.Client()
sio.connect(
    "https://daddy.codeaxolot.com?role=agent&agent_id=my-agent",
    transports=["websocket"]
)

# Register your tools on connect
sio.emit("register_tools", [
    {
        "name": "web_search",
        "description": "Search the web",
        "parameters": {
            "query": { "type": "string", "required": True }
        },
        "returns": "array of results"
    }
])

# In your agent loop — user message (left) then agent reply (right):
sio.emit("event", {
    "chat_id": "session-001",
    "direction": "received",
    "content": "What is the weather?",
    "metadata": { "type": "user_message" }
})

sio.emit("event", {
    "chat_id": "session-001",
    "direction": "sent",
    "content": "It's 15°C in Tokyo.",
    "metadata": { "type": "assistant_message", "tokens": 12 }
})

# When done
sio.disconnect()

JavaScript / Node.js (npm install socket.io-client)

import { io } from "socket.io-client";

const socket = io("https://daddy.codeaxolot.com", {
  query: { role: "agent", agent_id: "my-agent" },
  transports: ["websocket"]
});

socket.on("connect", () => {
  // Register tools
  socket.emit("register_tools", [
    {
      name: "web_search",
      description: "Search the web",
      parameters: {
        query: { type: "string", required: true }
      },
      returns: "array of results"
    }
  ]);

  // Log events — user input on left, agent output on right
  socket.emit("event", {
    chat_id: "session-001",
    direction: "received",
    content: "What is the weather?",
    metadata: { type: "user_message" }
  });

  socket.emit("event", {
    chat_id: "session-001",
    direction: "sent",
    content: "It's 15°C in Tokyo.",
    metadata: { type: "assistant_message" }
  });
});

Summary

WebSocket Event Direction Payload
"event" agent → server { chat_id, direction, content, kind?, user?, metadata? }
"batch" agent → server [ { chat_id, direction, content, kind?, user?, metadata? }, ... ]
"register_tools" agent → server [ { name, description?, parameters?, returns? }, ... ]

Protocol

  • Transport: WebSocket only (wss:// over TLS)
  • Library: Socket.IO v4 (python-socketio or socket.io-client)
  • Pattern: fire-and-forget — emit and move on, no response expected
  • Connection: set role=agent and agent_id=your-name as query params
  • Layout: direction: "sent" = agent & subprocesses (RIGHT), direction: "received" = user & external (LEFT)
  • Each chat_id gets a unique color pill — use it to separate conversations
  • No HTTP endpoints — everything goes through the WebSocket connection