Activity & Observability
See what every agent is doing in real time
Overview
The activity feed is a live stream of everything your agents are doing. It shows decisions created and resolved, messages sent, actions performed (file edits, commands, searches), and system events. Users see this in the Activity tab of the Nod app.
Event types
| Type | Description | Example |
|---|---|---|
| decision_created | Agent created a new request | "Deploy Bot requested: Deploy to production?" |
| decision_resolved | A request was approved/rejected/responded to | "Alice approved: Deploy to production" |
| agent_message | Agent sent a chat message | "Deploy Bot sent a message" |
| agent_action | Agent performed an action | "Running: npm install stripe" |
| system | Lifecycle event | "Deploy Bot: started" |
Logging activity from your agent
Use the alert event type to log actions to the activity feed:
POST /api/agent/events
{
"type": "alert",
"title": "Running: npm install stripe",
"text": "npm install stripe --save",
"task_run_id": "run_abc123" // optional — links to a task run
}{
"type": "alert",
"title": "Editing src/index.ts",
"text": "/Users/alice/project/src/index.ts"
}The title is what users see in the feed. The text is shown as a subtitle with additional detail. If you include task_run_id, the activity is linked to that specific task run.
Processing indicators
Show users when your agent is actively working. The Nod app displays a "Thinking..." bubble in the chat with an animated indicator. While this bubble is active, any activity events (alert) your agent logs will update the bubble text in real time — so users see exactly what the agent is doing (e.g. "Running tests...", "Searching the web...").
Processing indicators work via both WebSocket and REST, with different patterns suited to each connection type.
WebSocket agents (automatic)
WebSocket-connected agents use a heartbeat/idle cycle. The Nod app automatically shows the "Thinking..." bubble when the user sends a message or approves a request — your agent just needs to keep it alive and signal when it's done.
// Default — shows "Thinking"
{ "type": "agent_heartbeat", "conversation_id": "conv_abc123" }
// With custom label — updates the bubble text instantly
{ "type": "agent_heartbeat", "conversation_id": "conv_abc123", "status_text": "Searching the web..." }
{ "type": "agent_heartbeat", "conversation_id": "conv_abc123", "status_text": "Reading files..." }
{ "type": "agent_heartbeat", "conversation_id": "conv_abc123", "status_text": "Running tests..." }{ "type": "agent_idle", "conversation_id": "conv_abc123" }The heartbeat system is smart — it only writes to the database on state transitions (idle → processing, text changes), not on every heartbeat. So sending heartbeats every second is efficient.
alert events your agent logs will update the bubble text. For example, logging {"type": "alert", "title": "Editing src/index.ts"} will change the bubble from "Thinking..." to "Editing src/index.ts" automatically.Webhook agents (explicit start/stop)
Webhook-based agents (n8n, Make, custom workflows) don't have a persistent connection, so the app cannot show the indicator automatically. Instead, use explicit start and stop events via REST.
POST /api/agent/events
{
"type": "processing_start",
"conversation_id": "conv_abc123"
}
// With custom label
{
"type": "processing_start",
"conversation_id": "conv_abc123",
"status_text": "Processing your request..."
}POST /api/agent/events
{
"type": "processing_stop",
"conversation_id": "conv_abc123"
}Between start and stop, any alert events you send will update the bubble text — just like WebSocket agents. For example, an n8n workflow might:
POST → { "type": "processing_start", "conversation_id": "conv_abc123" }
POST → { "type": "alert", "title": "Searching the web..." }
POST → { "type": "alert", "title": "Summarizing results..." }
POST → { "type": "message", "text": "Here are the results...", "conversation_id": "conv_abc123" }
POST → { "type": "processing_stop", "conversation_id": "conv_abc123" }processing_stop is never sent, the indicator auto-clears after 30 seconds. This is a built-in safety net — no action required.Online status
When your agent connects via WebSocket, it automatically shows as online in the Nod app. When it disconnects, the status updates accordingly. Users can check the current session state:
{
"is_online": true,
"is_processing": true,
"conversation_id": "conv_abc123",
"status_text": "Searching the web..."
}Task run activities
Activities logged during a task run (with task_run_id set) are associated with that run. Users can view per-run activities in the task detail view:
GET /api/tasks/runs/:run_id/activities