Summary
The message tool's read and search actions are defined in the action name enum (CHANNEL_MESSAGE_ACTION_NAMES) and fully implemented for Discord (readMessages, searchMessages in discord-actions-messaging.ts), but the Microsoft Teams channel plugin only declares ["poll"] as its supported action.
This means agents connected via Teams cannot read channel message history or search messages — they can only send and react. The agent is blind to any channel activity not directly routed as an inbound message.
Current State
What exists:
CHANNEL_MESSAGE_ACTION_NAMES includes "read" and "search" (source)
- Discord fully implements both:
readMessages — reads channel history with limit, before, after, around params
searchMessages — searches by content, author, channel with filtering
- (source)
What's missing:
- MSTeams
listActions returns only ["poll"] (source)
- No
readMessages or searchMessages handler in the Teams handleAction
- The Graph API endpoints needed (
/teams/{teamId}/channels/{channelId}/messages and /chats/{chatId}/messages) are well-documented and available
Proposed Implementation
1. Add read and search to Teams listActions:
```typescript
listActions: ({ cfg }) => {
// ...existing enabled check...
return ["poll", "read", "search"] satisfies ChannelMessageActionName[];
},
```
2. Implement readMessages in handleAction:
Using Microsoft Graph API:
- Channel messages:
GET /teams/{teamId}/channels/{channelId}/messages?$top={limit}
- Chat messages:
GET /chats/{chatId}/messages?$top={limit}
- Support
limit, before/after pagination (Graph uses $skipToken or @odata.nextLink)
3. Implement searchMessages in handleAction:
Using Microsoft Graph Search API:
POST /search/query with entityTypes: ["chatMessage"]
- Filter by
channelIdentity, from, date range
4. Normalize response format:
Match the Discord implementation's response shape for consistency:
```typescript
return jsonResult({
ok: true,
messages: messages.map((msg) => ({
id: msg.id,
author: msg.from?.user?.displayName,
authorId: msg.from?.user?.id,
timestamp: msg.createdDateTime,
text: msg.body?.content,
attachments: msg.attachments?.map(a => ({ name: a.name, contentType: a.contentType })),
replyTo: msg.replyToId,
})),
});
```
Graph API Permissions Required
The bot registration likely needs:
ChannelMessage.Read.All (application) — for channel messages
Chat.Read (delegated) or Chat.Read.All (application) — for chat messages
ChatMessage.Read — for search
These may already be consented depending on the bot's existing Graph permissions. Worth documenting which are needed in the setup guide.
Why This Matters
- Parity with Discord — Discord agents can read and search; Teams agents cannot. This is the most-requested enterprise channel.
- Agent workspace integration — Teams is often the primary workspace for enterprise users. An agent that can only write but not read operates half-blind.
- Reduces webhook dependency — On-demand read eliminates the need to wire every channel with real-time event forwarding for the agent to have awareness.
- Heartbeat/monitoring workflows — Agents doing proactive monitoring sweeps need to check channels for activity without requiring every message to be individually routed.
Environment
- OpenClaw version: 2026.3.7
- Channel: msteams
- Existing actions available: send, react, poll
- Missing: read, search
Related
- Discord implementation:
src/agents/tools/discord-actions-messaging.ts (lines 220-260, 473-520)
- Action names enum:
src/channels/plugins/message-action-names.ts
- Teams channel plugin:
extensions/msteams/src/channel.ts
Summary
The
messagetool'sreadandsearchactions are defined in the action name enum (CHANNEL_MESSAGE_ACTION_NAMES) and fully implemented for Discord (readMessages,searchMessagesindiscord-actions-messaging.ts), but the Microsoft Teams channel plugin only declares["poll"]as its supported action.This means agents connected via Teams cannot read channel message history or search messages — they can only send and react. The agent is blind to any channel activity not directly routed as an inbound message.
Current State
What exists:
CHANNEL_MESSAGE_ACTION_NAMESincludes"read"and"search"(source)readMessages— reads channel history withlimit,before,after,aroundparamssearchMessages— searches by content, author, channel with filteringWhat's missing:
listActionsreturns only["poll"](source)readMessagesorsearchMessageshandler in the TeamshandleAction/teams/{teamId}/channels/{channelId}/messagesand/chats/{chatId}/messages) are well-documented and availableProposed Implementation
1. Add
readandsearchto TeamslistActions:```typescript
listActions: ({ cfg }) => {
// ...existing enabled check...
return ["poll", "read", "search"] satisfies ChannelMessageActionName[];
},
```
2. Implement
readMessagesinhandleAction:Using Microsoft Graph API:
GET /teams/{teamId}/channels/{channelId}/messages?$top={limit}GET /chats/{chatId}/messages?$top={limit}limit,before/afterpagination (Graph uses$skipTokenor@odata.nextLink)3. Implement
searchMessagesinhandleAction:Using Microsoft Graph Search API:
POST /search/querywithentityTypes: ["chatMessage"]channelIdentity,from, date range4. Normalize response format:
Match the Discord implementation's response shape for consistency:
```typescript
return jsonResult({
ok: true,
messages: messages.map((msg) => ({
id: msg.id,
author: msg.from?.user?.displayName,
authorId: msg.from?.user?.id,
timestamp: msg.createdDateTime,
text: msg.body?.content,
attachments: msg.attachments?.map(a => ({ name: a.name, contentType: a.contentType })),
replyTo: msg.replyToId,
})),
});
```
Graph API Permissions Required
The bot registration likely needs:
ChannelMessage.Read.All(application) — for channel messagesChat.Read(delegated) orChat.Read.All(application) — for chat messagesChatMessage.Read— for searchThese may already be consented depending on the bot's existing Graph permissions. Worth documenting which are needed in the setup guide.
Why This Matters
Environment
Related
src/agents/tools/discord-actions-messaging.ts(lines 220-260, 473-520)src/channels/plugins/message-action-names.tsextensions/msteams/src/channel.ts