Skip to content

Commit fdefb14

Browse files
improvement(ms-teams): resolve mentions accurately (#1762)
* improvement(ms-teams): resolve mentions accurately * fix for bots * add utils file * add logs * fix perms issue * fix scopes * fetch works for bots * Revert "fetch works for bots" This reverts commit 0ac702a. * update docs
1 parent 47913f8 commit fdefb14

File tree

9 files changed

+364
-12
lines changed

9 files changed

+364
-12
lines changed

apps/docs/content/docs/en/tools/microsoft_teams.mdx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,3 +208,13 @@ Write or send a message to a Microsoft Teams channel
208208

209209
- Category: `tools`
210210
- Type: `microsoft_teams`
211+
212+
### Mentioning Users
213+
214+
To mention users in your messages (both in chats and channels), wrap their display name in `<at>` tags:
215+
216+
```
217+
<at>John Doe</at> can you review this?
218+
```
219+
220+
The mention will be automatically resolved to the correct user and they will receive a notification in Microsoft Teams. This works for both chat messages and channel messages. Bots/Apps cannot be tagged.

apps/sim/app/api/tools/microsoft_teams/write_channel/route.ts

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { createLogger } from '@/lib/logs/console/logger'
55
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
66
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
77
import { generateRequestId } from '@/lib/utils'
8+
import { resolveMentionsForChannel, type TeamsMention } from '@/tools/microsoft_teams/utils'
89

910
export const dynamic = 'force-dynamic'
1011

@@ -141,23 +142,55 @@ export async function POST(request: NextRequest) {
141142
}
142143

143144
let messageContent = validatedData.content
145+
let contentType: 'text' | 'html' = 'text'
146+
const mentionEntities: TeamsMention[] = []
147+
148+
try {
149+
const mentionResult = await resolveMentionsForChannel(
150+
validatedData.content,
151+
validatedData.teamId,
152+
validatedData.channelId,
153+
validatedData.accessToken
154+
)
155+
156+
if (mentionResult.hasMentions) {
157+
contentType = 'html'
158+
messageContent = mentionResult.updatedContent
159+
mentionEntities.push(...mentionResult.mentions)
160+
logger.info(`[${requestId}] Resolved ${mentionResult.mentions.length} mention(s)`)
161+
}
162+
} catch (error) {
163+
logger.warn(`[${requestId}] Failed to resolve mentions, continuing without them:`, error)
164+
}
144165

145166
if (attachments.length > 0) {
167+
contentType = 'html'
146168
const attachmentTags = attachments
147169
.map((att) => `<attachment id="${att.id}"></attachment>`)
148170
.join(' ')
149-
messageContent = `${validatedData.content}<br/>${attachmentTags}`
171+
messageContent = `${messageContent}<br/>${attachmentTags}`
150172
}
151173

152-
const messageBody = {
174+
const messageBody: {
153175
body: {
154-
contentType: attachments.length > 0 ? 'html' : 'text',
176+
contentType: 'text' | 'html'
177+
content: string
178+
}
179+
attachments?: any[]
180+
mentions?: TeamsMention[]
181+
} = {
182+
body: {
183+
contentType,
155184
content: messageContent,
156185
},
157186
}
158187

159188
if (attachments.length > 0) {
160-
;(messageBody as any).attachments = attachments
189+
messageBody.attachments = attachments
190+
}
191+
192+
if (mentionEntities.length > 0) {
193+
messageBody.mentions = mentionEntities
161194
}
162195

163196
logger.info(`[${requestId}] Sending message to Teams channel: ${validatedData.channelId}`)

apps/sim/app/api/tools/microsoft_teams/write_chat/route.ts

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { createLogger } from '@/lib/logs/console/logger'
55
import { processFilesToUserFiles } from '@/lib/uploads/utils/file-utils'
66
import { downloadFileFromStorage } from '@/lib/uploads/utils/file-utils.server'
77
import { generateRequestId } from '@/lib/utils'
8+
import { resolveMentionsForChat, type TeamsMention } from '@/tools/microsoft_teams/utils'
89

910
export const dynamic = 'force-dynamic'
1011

@@ -139,23 +140,54 @@ export async function POST(request: NextRequest) {
139140
}
140141

141142
let messageContent = validatedData.content
143+
let contentType: 'text' | 'html' = 'text'
144+
const mentionEntities: TeamsMention[] = []
145+
146+
try {
147+
const mentionResult = await resolveMentionsForChat(
148+
validatedData.content,
149+
validatedData.chatId,
150+
validatedData.accessToken
151+
)
152+
153+
if (mentionResult.hasMentions) {
154+
contentType = 'html'
155+
messageContent = mentionResult.updatedContent
156+
mentionEntities.push(...mentionResult.mentions)
157+
logger.info(`[${requestId}] Resolved ${mentionResult.mentions.length} mention(s)`)
158+
}
159+
} catch (error) {
160+
logger.warn(`[${requestId}] Failed to resolve mentions, continuing without them:`, error)
161+
}
142162

143163
if (attachments.length > 0) {
164+
contentType = 'html'
144165
const attachmentTags = attachments
145166
.map((att) => `<attachment id="${att.id}"></attachment>`)
146167
.join(' ')
147-
messageContent = `${validatedData.content}<br/>${attachmentTags}`
168+
messageContent = `${messageContent}<br/>${attachmentTags}`
148169
}
149170

150-
const messageBody = {
171+
const messageBody: {
151172
body: {
152-
contentType: attachments.length > 0 ? 'html' : 'text',
173+
contentType: 'text' | 'html'
174+
content: string
175+
}
176+
attachments?: any[]
177+
mentions?: TeamsMention[]
178+
} = {
179+
body: {
180+
contentType,
153181
content: messageContent,
154182
},
155183
}
156184

157185
if (attachments.length > 0) {
158-
;(messageBody as any).attachments = attachments
186+
messageBody.attachments = attachments
187+
}
188+
189+
if (mentionEntities.length > 0) {
190+
messageBody.mentions = mentionEntities
159191
}
160192

161193
logger.info(`[${requestId}] Sending message to Teams chat: ${validatedData.chatId}`)

apps/sim/blocks/blocks/microsoft_teams.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export const MicrosoftTeamsBlock: BlockConfig<MicrosoftTeamsResponse> = {
99
description: 'Read, write, and create messages',
1010
authMode: AuthMode.OAuth,
1111
longDescription:
12-
'Integrate Microsoft Teams into the workflow. Can read and write chat messages, and read and write channel messages. Can be used in trigger mode to trigger a workflow when a message is sent to a chat or channel.',
12+
'Integrate Microsoft Teams into the workflow. Can read and write chat messages, and read and write channel messages. Can be used in trigger mode to trigger a workflow when a message is sent to a chat or channel. To mention users in messages, wrap their name in <at> tags: <at>userName</at>',
1313
docsLink: 'https://docs.sim.ai/tools/microsoft_teams',
1414
category: 'tools',
1515
triggerAllowed: true,
@@ -47,6 +47,7 @@ export const MicrosoftTeamsBlock: BlockConfig<MicrosoftTeamsResponse> = {
4747
'Channel.ReadBasic.All',
4848
'ChannelMessage.Send',
4949
'ChannelMessage.Read.All',
50+
'ChannelMember.Read.All',
5051
'Group.Read.All',
5152
'Group.ReadWrite.All',
5253
'Team.ReadBasic.All',
@@ -255,7 +256,10 @@ export const MicrosoftTeamsBlock: BlockConfig<MicrosoftTeamsResponse> = {
255256
manualChannelId: { type: 'string', description: 'Manual channel identifier' },
256257
teamId: { type: 'string', description: 'Team identifier' },
257258
manualTeamId: { type: 'string', description: 'Manual team identifier' },
258-
content: { type: 'string', description: 'Message content' },
259+
content: {
260+
type: 'string',
261+
description: 'Message content. Mention users with <at>userName</at>',
262+
},
259263
attachmentFiles: { type: 'json', description: 'Files to attach (UI upload)' },
260264
files: { type: 'json', description: 'Files to attach (UserFile array)' },
261265
},

apps/sim/lib/auth.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,7 @@ export const auth = betterAuth({
512512
'Channel.ReadBasic.All',
513513
'ChannelMessage.Send',
514514
'ChannelMessage.Read.All',
515+
'ChannelMember.Read.All',
515516
'Group.Read.All',
516517
'Group.ReadWrite.All',
517518
'Team.ReadBasic.All',

apps/sim/lib/oauth/oauth.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ export const OAUTH_PROVIDERS: Record<string, OAuthProviderConfig> = {
239239
'Channel.ReadBasic.All',
240240
'ChannelMessage.Send',
241241
'ChannelMessage.Read.All',
242+
'ChannelMember.Read.All',
242243
'Group.Read.All',
243244
'Group.ReadWrite.All',
244245
'Team.ReadBasic.All',

0 commit comments

Comments
 (0)