Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion docs/api-reference.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,21 @@ curl -X POST http://localhost:2138/api/agent/autonomy \
| `DELETE` | `/api/conversations/:id` | Delete a conversation |

<Info>
Conversations are scoped to the web-chat interface. Each conversation maps to an elizaOS room with a deterministic world ID.
Conversations are scoped to the web-chat interface. Each conversation maps to an elizaOS room with a deterministic world ID. Messages from connector channels include additional sender identity fields (`from`, `fromUserName`, `avatarUrl`) when the connector provides them.
</Info>

---

## Inbox (Unified Messages)

| Method | Path | Description |
|--------|------|-------------|
| `GET` | `/api/inbox/messages` | List recent messages across all connector channels in a unified feed |
| `GET` | `/api/inbox/chats` | List connector chat threads (one row per external chat room) |
| `GET` | `/api/inbox/sources` | List distinct connector source tags the agent has messages for |

<Info>
The inbox aggregates messages from every connected platform (iMessage, Telegram, Discord, WhatsApp, WeChat, Slack, Signal, SMS) into a single time-ordered feed. Dashboard web-chat messages are excluded — those are accessible via the [Conversations API](/rest/conversations).
</Info>

---
Expand Down
1 change: 1 addition & 0 deletions docs/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@
"rest/onboarding",
"rest/character",
"rest/conversations",
"rest/inbox",
"rest/knowledge",
"rest/wallet",
"rest/models",
Expand Down
17 changes: 15 additions & 2 deletions docs/rest/conversations.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,16 @@ Retrieve up to 200 messages for a conversation, sorted oldest first. Messages wi
"role": "assistant",
"text": "Hey there! How can I help?",
"timestamp": 1718000001000
},
{
"id": "uuid",
"role": "user",
"text": "What's going on in Discord?",
"timestamp": 1718000002000,
"source": "discord",
"from": "Alice",
"fromUserName": "alice#1234",
"avatarUrl": "https://cdn.discordapp.com/avatars/..."
}
]
}
Expand All @@ -99,7 +109,10 @@ Retrieve up to 200 messages for a conversation, sorted oldest first. Messages wi
| `messages[].role` | string | `user` or `assistant` |
| `messages[].text` | string | Message text content |
| `messages[].timestamp` | number | Unix timestamp (ms) when the message was created |
| `messages[].source` | string\|undefined | Source identifier (omitted for web-chat messages) |
| `messages[].source` | string\|undefined | Connector source identifier (e.g. `discord`, `telegram`). Omitted for web-chat messages |
| `messages[].from` | string\|undefined | Display name of the sender entity, when available |
| `messages[].fromUserName` | string\|undefined | Username or handle of the sender (e.g. Discord username), when the connector provides one |
| `messages[].avatarUrl` | string\|undefined | Sender avatar URL when the connector can provide one |

**Errors**

Expand Down Expand Up @@ -168,7 +181,7 @@ Final event:
data: {"type":"done","fullText":"Here's what I think...","agentName":"Milady"}
```

The conversation title is auto-generated in the background if it is still `"New Chat"`, and a `conversation-updated` WebSocket event is broadcast.
The conversation title is auto-generated in the background if it is still `"New Chat"`, and a `conversation-updated` WebSocket event is broadcast. If AI title generation fails, the title falls back to the first five words of the user's message.

<Info>
Action callbacks (e.g. from music playback, wallet flows) use **replace** semantics: each successive callback replaces the callback portion of the message rather than appending. This matches the progressive-message pattern used on Discord and Telegram. See [Action callbacks and SSE streaming](/runtime/action-callback-streaming) for details.
Expand Down
151 changes: 151 additions & 0 deletions docs/rest/inbox.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
---
title: "Inbox API"
sidebarTitle: "Inbox"
description: "REST API endpoints for the unified cross-channel inbox — aggregated messages, chat threads, and source discovery."
---

The inbox API provides a read-only, time-ordered view of messages from every connector channel the agent participates in — iMessage, Telegram, Discord, WhatsApp, WeChat, Slack, Signal, and SMS — merged into a single feed. Dashboard web-chat messages are excluded since they are already accessible via the [conversations API](/rest/conversations).

## Endpoints

| Method | Path | Description |
|--------|------|-------------|
| GET | `/api/inbox/messages` | List recent messages across all connector channels |
| GET | `/api/inbox/chats` | List connector chat threads (one row per room) |
| GET | `/api/inbox/sources` | List distinct connector source tags |

---

### GET /api/inbox/messages

List the most recent messages across all connector channels in a unified, time-ordered feed (newest first).

**Query parameters**

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `limit` | integer | No | 100 | Maximum messages to return (hard cap 500) |
| `sources` | string | No | All inbox sources | Comma-separated source filter (e.g. `discord,telegram`) |
| `roomId` | string | No | — | Scope to a single room ID for thread-level views |

**Response**

```json
{
"messages": [
{
"id": "uuid",
"role": "user",
"text": "Hey, check this out!",
"timestamp": 1718000000000,
"source": "discord",
"roomId": "room-uuid",
"from": "Alice",
"fromUserName": "alice#1234",
"avatarUrl": "https://cdn.discordapp.com/avatars/..."
}
],
"count": 1
}
```

| Field | Type | Description |
|-------|------|-------------|
| `messages[].id` | string | Memory UUID |
| `messages[].role` | string | `user` or `assistant` |
| `messages[].text` | string | Message text content |
| `messages[].timestamp` | number | Unix timestamp (ms) when the message was created |
| `messages[].source` | string | Connector source tag (e.g. `imessage`, `telegram`, `discord`) |
| `messages[].roomId` | string | External chat room ID for threading |
| `messages[].from` | string\|undefined | Best-effort display name of the sender entity |
| `messages[].fromUserName` | string\|undefined | Username or handle of the sender (e.g. Discord username) |
| `messages[].avatarUrl` | string\|undefined | Sender avatar URL when the connector provides one |

For Discord messages, `from`, `fromUserName`, and `avatarUrl` are enriched from the live Discord user profile when available.

---

### GET /api/inbox/chats

List connector chat threads — one row per external chat room. Used by the sidebar to display a unified chat list alongside dashboard conversations.

**Query parameters**

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `sources` | string | No | All inbox sources | Comma-separated source filter |

**Response**

```json
{
"chats": [
{
"id": "room-uuid",
"source": "discord",
"title": "#general",
"lastMessageText": "Hey, check this out!",
"lastMessageAt": 1718000000000,
"messageCount": 42
}
],
"count": 1
}
```

| Field | Type | Description |
|-------|------|-------------|
| `chats[].id` | string | Room ID (stable across polls, used as selection key) |
| `chats[].source` | string | Connector source tag for badge rendering |
| `chats[].title` | string | Display title — channel name, contact name for DMs, or fallback `"<source> chat"` |
| `chats[].lastMessageText` | string | Preview of the most recent message (truncated to 140 characters) |
| `chats[].lastMessageAt` | number | Epoch ms timestamp of the most recent message |
| `chats[].messageCount` | number | Total messages in this room at scan time |

Chat titles are resolved in the following priority order:

1. Live Discord channel name (fetched from the Discord client for Discord sources)
2. Stored room name (set by the connector plugin when the room was created)
3. Latest sender name (for DM rooms)
4. Fallback: `"<source> chat"`

---

### GET /api/inbox/sources

List the distinct set of connector source tags the agent currently has messages for. Use this to build dynamic source filter chips in the UI without hardcoding connector names.

**Response**

```json
{
"sources": ["imessage", "telegram", "discord", "whatsapp"]
}
```

| Field | Type | Description |
|-------|------|-------------|
| `sources` | string[] | Array of distinct source tags present in agent message history |

## Supported sources

The inbox includes messages from these connector sources by default:

| Source tag | Platform |
|------------|----------|
| `imessage` | iMessage |
| `telegram` | Telegram |
| `discord` | Discord |
| `whatsapp` | WhatsApp |
| `wechat` | WeChat |
| `slack` | Slack |
| `signal` | Signal |
| `sms` | SMS |

Messages from `client_chat` (dashboard web chat) and internal sources (system events, knowledge ingestion) are excluded from the inbox feed.

## Common error codes

| Status | Code | Description |
|--------|------|-------------|
| 500 | `INTERNAL_ERROR` | Failed to load inbox data |
Loading