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
70 changes: 66 additions & 4 deletions apps/sim/blocks/blocks/microsoft_teams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const MicrosoftTeamsBlock: BlockConfig<MicrosoftTeamsResponse> = {
description: 'Manage messages, reactions, and members in Teams',
authMode: AuthMode.OAuth,
longDescription:
'Integrate Microsoft Teams into the workflow. Read, write, update, and delete chat and channel messages. Reply to messages, add reactions, and list team/channel members. 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>`',
'Integrate Microsoft Teams into the workflow. Read, write, update, and delete chat and channel messages. Reply to messages, add reactions, and list teams, chats, channels, and their members. 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>`',
docsLink: 'https://docs.sim.ai/integrations/microsoft_teams',
category: 'tools',
integrationType: IntegrationType.Communication,
Expand All @@ -39,6 +39,10 @@ export const MicrosoftTeamsBlock: BlockConfig<MicrosoftTeamsResponse> = {
{ label: 'Remove Reaction', id: 'unset_reaction' },
{ label: 'List Team Members', id: 'list_team_members' },
{ label: 'List Channel Members', id: 'list_channel_members' },
{ label: 'List Chat Members', id: 'list_chat_members' },
{ label: 'List Teams', id: 'list_teams' },
{ label: 'List Chats', id: 'list_chats' },
{ label: 'List Channels', id: 'list_channels' },
],
value: () => 'read_chat',
},
Expand Down Expand Up @@ -83,6 +87,7 @@ export const MicrosoftTeamsBlock: BlockConfig<MicrosoftTeamsResponse> = {
'reply_to_message',
'list_team_members',
'list_channel_members',
'list_channels',
],
},
required: true,
Expand All @@ -105,6 +110,7 @@ export const MicrosoftTeamsBlock: BlockConfig<MicrosoftTeamsResponse> = {
'reply_to_message',
'list_team_members',
'list_channel_members',
'list_channels',
],
},
required: true,
Expand All @@ -122,7 +128,13 @@ export const MicrosoftTeamsBlock: BlockConfig<MicrosoftTeamsResponse> = {
mode: 'basic',
condition: {
field: 'operation',
value: ['read_chat', 'write_chat', 'update_chat_message', 'delete_chat_message'],
value: [
'read_chat',
'write_chat',
'update_chat_message',
'delete_chat_message',
'list_chat_members',
],
},
required: true,
},
Expand All @@ -136,7 +148,13 @@ export const MicrosoftTeamsBlock: BlockConfig<MicrosoftTeamsResponse> = {
mode: 'advanced',
condition: {
field: 'operation',
value: ['read_chat', 'write_chat', 'update_chat_message', 'delete_chat_message'],
value: [
'read_chat',
'write_chat',
'update_chat_message',
'delete_chat_message',
'list_chat_members',
],
},
required: true,
},
Expand Down Expand Up @@ -281,6 +299,10 @@ export const MicrosoftTeamsBlock: BlockConfig<MicrosoftTeamsResponse> = {
'microsoft_teams_unset_reaction',
'microsoft_teams_list_team_members',
'microsoft_teams_list_channel_members',
'microsoft_teams_list_chat_members',
'microsoft_teams_list_teams',
'microsoft_teams_list_chats',
'microsoft_teams_list_channels',
],
config: {
tool: (params) => {
Expand Down Expand Up @@ -313,6 +335,14 @@ export const MicrosoftTeamsBlock: BlockConfig<MicrosoftTeamsResponse> = {
return 'microsoft_teams_list_team_members'
case 'list_channel_members':
return 'microsoft_teams_list_channel_members'
case 'list_chat_members':
return 'microsoft_teams_list_chat_members'
case 'list_teams':
return 'microsoft_teams_list_teams'
case 'list_chats':
return 'microsoft_teams_list_chats'
case 'list_channels':
return 'microsoft_teams_list_channels'
default:
return 'microsoft_teams_read_chat'
}
Expand Down Expand Up @@ -393,6 +423,21 @@ export const MicrosoftTeamsBlock: BlockConfig<MicrosoftTeamsResponse> = {
return { ...baseParams, teamId: effectiveTeamId, channelId: effectiveChannelId }
}

// Chat member operations
if (operation === 'list_chat_members') {
return { ...baseParams, chatId: effectiveChatId }
}

// List channels in a team
if (operation === 'list_channels') {
return { ...baseParams, teamId: effectiveTeamId }
}

// List the user's teams / chats — no additional identifiers required
if (operation === 'list_teams' || operation === 'list_chats') {
return baseParams
}

// Operations that work with either chat or channel (get_message, reactions)
// These tools handle the routing internally based on what IDs are provided
if (
Expand Down Expand Up @@ -462,8 +507,18 @@ export const MicrosoftTeamsBlock: BlockConfig<MicrosoftTeamsResponse> = {
},
reactionType: { type: 'string', description: 'Emoji reaction that was added/removed' },
success: { type: 'boolean', description: 'Whether the operation was successful' },
members: { type: 'json', description: 'Array of team/channel member objects' },
members: { type: 'json', description: 'Array of team/channel/chat member objects' },
memberCount: { type: 'number', description: 'Total number of members' },
teams: { type: 'json', description: 'Array of teams the user is a member of' },
teamCount: { type: 'number', description: 'Total number of teams' },
chats: { type: 'json', description: 'Array of chats the user is part of' },
chatCount: { type: 'number', description: 'Total number of chats' },
channels: { type: 'json', description: 'Array of channels in the team' },
channelCount: { type: 'number', description: 'Total number of channels' },
hasMore: {
type: 'boolean',
description: 'Whether Graph indicated additional pages beyond this response',
},
type: { type: 'string', description: 'Type of Teams message' },
id: { type: 'string', description: 'Unique message identifier' },
timestamp: { type: 'string', description: 'Message timestamp' },
Expand Down Expand Up @@ -580,5 +635,12 @@ export const MicrosoftTeamsBlockMeta = {
content:
'# List Team Members\n\nRetrieve who belongs to a Microsoft Teams team or channel.\n\n## Steps\n1. Decide whether you need team-wide membership or a single channel and pick List Team Members or List Channel Members.\n2. Run the operation with the team id (and channel id when needed).\n3. Normalize the result into a clean roster of names and roles.\n\n## Output\nA roster list with display name and role. Note the total count at the top.',
},
{
name: 'discover-teams-chats-channels',
description:
'Enumerate the teams, chats, and channels available to the connected Microsoft account before acting on them.',
content:
'# Discover Teams, Chats, and Channels\n\nResolve human-friendly names to the ids other Microsoft Teams operations need.\n\n## Steps\n1. Run List Teams to see every team the connected account belongs to, or List Chats to see active chats.\n2. If the target is a channel, run List Channels with the resolved team id to find the channel id.\n3. If the target is a chat, run List Chat Members to confirm the right people are present before writing to it.\n4. Feed the resolved team id, channel id, or chat id into the read/write/reply/reaction operations.\n\n## Output\nReturn the matched team, chat, or channel name alongside its id so subsequent steps can reference it.',
},
],
} as const satisfies BlockMeta
8 changes: 8 additions & 0 deletions apps/sim/tools/microsoft_teams/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import { deleteChannelMessageTool } from '@/tools/microsoft_teams/delete_channel
import { deleteChatMessageTool } from '@/tools/microsoft_teams/delete_chat_message'
import { getMessageTool } from '@/tools/microsoft_teams/get_message'
import { listChannelMembersTool } from '@/tools/microsoft_teams/list_channel_members'
import { listChannelsTool } from '@/tools/microsoft_teams/list_channels'
import { listChatMembersTool } from '@/tools/microsoft_teams/list_chat_members'
import { listChatsTool } from '@/tools/microsoft_teams/list_chats'
import { listTeamMembersTool } from '@/tools/microsoft_teams/list_team_members'
import { listTeamsTool } from '@/tools/microsoft_teams/list_teams'
import { readChannelTool } from '@/tools/microsoft_teams/read_channel'
import { readChatTool } from '@/tools/microsoft_teams/read_chat'
import { replyToMessageTool } from '@/tools/microsoft_teams/reply_to_message'
Expand All @@ -27,3 +31,7 @@ export const microsoftTeamsSetReactionTool = setReactionTool
export const microsoftTeamsUnsetReactionTool = unsetReactionTool
export const microsoftTeamsListTeamMembersTool = listTeamMembersTool
export const microsoftTeamsListChannelMembersTool = listChannelMembersTool
export const microsoftTeamsListChatMembersTool = listChatMembersTool
export const microsoftTeamsListTeamsTool = listTeamsTool
export const microsoftTeamsListChatsTool = listChatsTool
export const microsoftTeamsListChannelsTool = listChannelsTool
2 changes: 1 addition & 1 deletion apps/sim/tools/microsoft_teams/list_channel_members.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export const listChannelMembersTool: ToolConfig<
const members = (data.value || []).map((member: any) => ({
id: member.id || '',
displayName: member.displayName || '',
email: member.email || member.userId || '',
email: member.email || '',
userId: member.userId || '',
roles: member.roles || [],
}))
Expand Down
88 changes: 88 additions & 0 deletions apps/sim/tools/microsoft_teams/list_channels.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import type {
MicrosoftTeamsListChannelsResponse,
MicrosoftTeamsToolParams,
} from '@/tools/microsoft_teams/types'
import type { ToolConfig } from '@/tools/types'

export const listChannelsTool: ToolConfig<
MicrosoftTeamsToolParams,
MicrosoftTeamsListChannelsResponse
> = {
id: 'microsoft_teams_list_channels',
name: 'List Microsoft Teams Channels',
description: 'List all channels in a Microsoft Teams team',
version: '1.0',
errorExtractor: 'nested-error-object',
oauth: {
required: true,
provider: 'microsoft-teams',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'The access token for the Microsoft Teams API',
},
teamId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description:
'The ID of the team (e.g., "12345678-abcd-1234-efgh-123456789012" - a GUID from team listings)',
},
},

outputs: {
success: { type: 'boolean', description: 'Whether the listing was successful' },
channels: { type: 'array', description: 'Array of channels in the team' },
channelCount: { type: 'number', description: 'Total number of channels' },
hasMore: {
type: 'boolean',
description: 'Whether Graph indicated additional pages beyond this response',
},
},

request: {
url: (params) => {
const teamId = params.teamId?.trim()
if (!teamId) {
throw new Error('Team ID is required')
}
return `https://graph.microsoft.com/v1.0/teams/${encodeURIComponent(teamId)}/channels`
},
method: 'GET',
headers: (params) => {
if (!params.accessToken) {
throw new Error('Access token is required')
}
return {
Authorization: `Bearer ${params.accessToken}`,
}
},
},

transformResponse: async (response: Response, params?: MicrosoftTeamsToolParams) => {
const data = await response.json()

const channels = (data.value || []).map((channel: any) => ({
id: channel.id || '',
displayName: channel.displayName || '',
description: channel.description ?? '',
membershipType: channel.membershipType || 'standard',
webUrl: channel.webUrl || '',
}))

return {
success: true,
output: {
channels,
channelCount: channels.length,
hasMore: Boolean(data['@odata.nextLink']),
metadata: {
teamId: params?.teamId || '',
},
},
}
Comment thread
waleedlatif1 marked this conversation as resolved.
},
}
87 changes: 87 additions & 0 deletions apps/sim/tools/microsoft_teams/list_chat_members.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import type {
MicrosoftTeamsListMembersResponse,
MicrosoftTeamsToolParams,
} from '@/tools/microsoft_teams/types'
import type { ToolConfig } from '@/tools/types'

export const listChatMembersTool: ToolConfig<
MicrosoftTeamsToolParams,
MicrosoftTeamsListMembersResponse
> = {
id: 'microsoft_teams_list_chat_members',
name: 'List Microsoft Teams Chat Members',
description: 'List all members of a Microsoft Teams chat',
version: '1.0',
errorExtractor: 'nested-error-object',
oauth: {
required: true,
provider: 'microsoft-teams',
},
params: {
accessToken: {
type: 'string',
required: true,
visibility: 'hidden',
description: 'The access token for the Microsoft Teams API',
},
chatId: {
type: 'string',
required: true,
visibility: 'user-or-llm',
description: 'The ID of the chat (e.g., "19:abc123def456@thread.v2" - from chat listings)',
},
},

outputs: {
success: { type: 'boolean', description: 'Whether the listing was successful' },
members: { type: 'array', description: 'Array of chat members' },
memberCount: { type: 'number', description: 'Total number of members' },
hasMore: {
type: 'boolean',
description: 'Whether Graph indicated additional pages beyond this response',
},
},

request: {
url: (params) => {
const chatId = params.chatId?.trim()
if (!chatId) {
throw new Error('Chat ID is required')
}
return `https://graph.microsoft.com/v1.0/chats/${encodeURIComponent(chatId)}/members`
},
method: 'GET',
headers: (params) => {
if (!params.accessToken) {
throw new Error('Access token is required')
}
return {
Authorization: `Bearer ${params.accessToken}`,
}
},
},

transformResponse: async (response: Response, params?: MicrosoftTeamsToolParams) => {
const data = await response.json()

const members = (data.value || []).map((member: any) => ({
id: member.id || '',
displayName: member.displayName || '',
email: member.email || '',
userId: member.userId || '',
roles: member.roles || [],
}))

return {
success: true,
output: {
members,
memberCount: members.length,
hasMore: Boolean(data['@odata.nextLink']),
metadata: {
chatId: params?.chatId || '',
},
},
}
},
}
Loading
Loading