mcpField
A
agent-teams

agent-teams

github.com/agent-messenger生产力24796 次安装2 天前更新
代码仓库

关于 agent-teams

agent-teams 是供 AI Agent 和用户通过命令行操作 Microsoft Teams 的 TypeScript 工具,支持团队与账户切换,以及消息、聊天、频道和文件操作。它提供设备代码登录和本地令牌提取两种认证方式。

主要功能

  1. 01发送和搜索消息
  2. 02管理聊天与频道
  3. 03切换团队和账户
  4. 04上传和下载文件
  5. 05登录或提取令牌

适用场景

  1. 01由 AI Agent 发送消息
  2. 02查看频道或聊天记录
  3. 03在多个 Teams 团队间操作
  4. 04共享或获取 Teams 文件

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/agent-messenger/agent-messenger --skill agent-teams

安装后在 Claude Code 中输入/agent-teams确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
authentication.md
common-patterns.md
templates/
monitor-channel.sh
post-message.sh
team-summary.sh

详细介绍

Agent Teams

一个 TypeScript 命令行工具,可让 AI Agent 和人类通过简单的命令界面与 Microsoft Teams 交互。支持从 Teams 桌面应用无缝提取令牌(也可回退到浏览器提取),并支持多个团队。

Quick Start

# Get team snapshot (credentials are extracted automatically)
agent-teams snapshot

# Send a message
agent-teams message send <team-id> <channel-id> "Hello from AI agent!"

# List channels
agent-teams channel list <team-id>

Authentication

有两种同等地位的登录方式,可按需选择:

  1. agent-teams auth login(工作/学校或个人 Microsoft 账户)——使用设备代码登录。打开显示的网址,输入代码,然后在浏览器中批准。无需桌面应用或浏览器提取。系统会提示输入 Microsoft 邮箱(也可传入 --email <email>),并自动检测工作账户或个人账户,然后启动对应流程;传入 --account-type work|personal 可强制指定账户类型并跳过检测。只有 auth login 会存储 message search 所需的 AAD 刷新令牌。
  2. agent-teams auth extract——从 Teams 桌面应用中零配置提取,若失败则回退到 Chromium 浏览器。适合已在本地登录 Teams 的情况。此方式只会获取 Skype 令牌,足以发送消息,但不能用于 message search(见下文)。

如果尚未存储凭据,首次使用任何命令时也会自动提取凭据,因此 auth extract 可能会在后台静默执行。

Teams 令牌的有效期较短(提取的令牌为 60-90 分钟,设备代码令牌为几小时)。设备代码账户(auth login)会静默刷新——CLI 会使用已存储的刷新令牌重新生成过期令牌,无需重新登录。只要你仍登录着 Teams 桌面应用或受支持的浏览器,提取账户就会自动重新提取;如果失败,请重新运行 auth extract(或切换到 auth login)。

非交互式 auth login(Agent / CI)

没有 TTY 时,auth login 分为两次调用:

# 1. Start — returns verification_uri, user_code, and device_code as JSON.
#    Pass --email to auto-detect the account type (no prompt without a TTY),
#    or --account-type work|personal to force it.
agent-teams auth login --email <email>

# 2. After the user approves in a browser, finish with the device_code
agent-teams auth login --device-code <device_code>

--client-id <id> 可在任一调用中覆盖 AAD 客户端 ID(或设置 AGENT_TEAMS_CLIENT_ID)。--account-type <work|personal> 用于选择账户(默认值为 work);该设置会在两次调用的流程中保留,因此以非交互方式登录个人账户时,需在两次调用中都传入此参数。

多团队支持
# List all available teams
agent-teams team list

# Switch to a different team
agent-teams team switch <team-id>

# Show current team
agent-teams team current

# Check auth status (includes token expiry info)
agent-teams auth status
多账户支持(工作 / 个人)
# Switch between work and personal accounts
agent-teams auth switch-account work
agent-teams auth switch-account personal

# Use a specific account for one command (without switching)
agent-teams snapshot --account work

Memory

Agent 会维护 ~/.config/agent-messenger/MEMORY.md 文件,作为跨会话的持久记忆。该文件由 Agent 管理——CLI 不会读取或写入此文件。请使用 Read 和 Write 工具管理记忆文件。

读取记忆

在每项任务开始时,使用 Read 工具读取 ~/.config/agent-messenger/MEMORY.md,加载之前发现的团队 ID、频道 ID、用户 ID 和偏好设置。

  • 如果文件尚不存在,也没关系——无需读取即可继续,并在首次获得有用信息时创建该文件。
  • 如果无法读取文件(权限问题、目录不存在),则不使用记忆继续操作——不要报错。
写入记忆

发现有用信息后,使用 Write 工具更新 ~/.config/agent-messenger/MEMORY.md。以下情况应触发写入:

  • 发现团队 ID 和名称后(通过 team list、snapshot 等)
  • 发现有用的频道 ID 和名称后(通过 channel list、snapshot 等)
  • 发现用户 ID 和名称后(通过 user list、user me 等)
  • 用户提供别名或偏好后(“把这个称作站会频道”“我的主要团队是 X”)
  • 发现频道结构后(标准频道或专用频道)

写入时,请包含完整文件内容——Write 工具会覆盖整个文件。

要存储的内容
  • 团队 ID 及其名称
  • 频道 ID、名称及所属团队
  • 用户 ID 及显示名称
  • 用户提供的别名(“站会频道”“主要团队”)
  • 账户偏好(工作或个人)
  • 交互过程中表达的任何用户偏好
不要存储的内容

绝不存储令牌、凭据或任何敏感数据。绝不存储完整消息内容(仅存储 ID 和频道上下文)。绝不存储文件上传内容。

处理过期数据

如果记忆中的 ID 返回错误(找不到频道、找不到团队),请从 MEMORY.md 中删除。不要盲目信任记忆中的数据——发现异常时应进行验证。与其使用可能已过期的记忆 ID,不如重新列出。

格式 / 示例
# Agent Messenger Memory

## Teams

- `team-id-1` — Acme Corp (default, work account)
- `team-id-2` — Side Project (personal account)

## Channels (Acme Corp)

- `channel-id-1` — General
- `channel-id-2` — Engineering
- `channel-id-3` — Standups

## Users (Acme Corp)

- `user-id-1` — Alice (engineering lead)
- `user-id-2` — Bob (backend)

## Aliases

- "standup" → `channel-id-3` (Standups in Acme Corp)
- "main team" → `team-id-1` (Acme Corp)

## Notes

- User prefers work account by default
- Main team is "Acme Corp"

记忆功能可让你跳过重复的 channel list 和 team list 调用。如果你已在之前的会话中知道某个 ID,请直接使用。

命令

身份验证命令
# Sign in via device code (personal Microsoft accounts).
agent-teams auth login
agent-teams auth login --device-code <code>   # finish a non-interactive login

# Extract token from Teams desktop app or browser (usually automatic)
agent-teams auth extract
agent-teams auth extract --debug
agent-teams auth extract --browser-profile ~/browser-data
agent-teams auth extract --browser-profile ~/work-profile --browser-profile ~/personal-profile

# --browser-profile accepts repeatable or comma-separated Chromium profile/user-data dirs

# Check auth status (includes token expiry info)
agent-teams auth status

# Logout from Microsoft Teams
agent-teams auth logout

# Switch between work and personal accounts
agent-teams auth switch-account <account-type>
agent-teams auth switch-account work
agent-teams auth switch-account personal
Whoami 命令
# Show current authenticated user
agent-teams whoami
agent-teams whoami --pretty

输出包含已通过身份验证的用户身份信息。

消息命令
# Send a message
agent-teams message send <team-id> <channel-id> <content>
agent-teams message send <team-id> 19:[email protected] "Hello world"

# Send a rich-text message written in markdown
agent-teams message send <team-id> <channel-id> "## Deploy done
- service A
- service B" --format markdown

# List messages
agent-teams message list <team-id> <channel-id>
agent-teams message list <team-id> 19:[email protected] --limit 50

# Get a single message by ID
agent-teams message get <team-id> <channel-id> <message-id>

# Delete a message
agent-teams message delete <team-id> <channel-id> <message-id> --force

# Search messages across Teams (requires `auth login` — see Authentication)
agent-teams message search <query>
agent-teams message search "deploy" --limit 10 --from 0

message search 需要使用 auth login 登录的账户:它会使用 AAD 令牌查询 Microsoft 的 Substrate 搜索 API,而基于 Cookie 的 auth extract 无法提供该令牌。仅使用 Cookie 的账户会收到清晰的错误提示,告知你运行 auth login。--limit 必须为正整数(默认值为 20);--from 是用于分页的非负偏移量(默认值为 0)。

频道命令
# List channels in a team
agent-teams channel list <team-id>

# Get channel info
agent-teams channel info <team-id> <channel-id>
agent-teams channel info <team-id> 19:[email protected]

# Get channel history (alias for message list)
agent-teams channel history <team-id> <channel-id> --limit 100
聊天命令

适用于没有团队或频道的个人 Microsoft 账户(@outlook.com / @live.com)——这类账户只有 1:1 聊天、群聊和个人聊天线程。工作账户也可以使用这些功能进行 1:1 聊天和群聊。

# List 1:1, group, and self chats
agent-teams chat list

# Get chat message history
agent-teams chat history <chat-id> --limit 100

# Get a single chat message
agent-teams chat get <chat-id> <message-id>

# Send a message to a chat
agent-teams chat send <chat-id> "Hello"
agent-teams chat send <chat-id> "**Important**: see the [board](https://example.com)" --format markdown

# Edit one of your own chat messages
agent-teams chat edit <chat-id> <message-id> "Updated text"
agent-teams chat edit <chat-id> <message-id> "Fixed \`bug\`" --format markdown

聊天 ID 的格式为 19:[email protected](1:1)或 19:[email protected](群聊)。可通过 chat list 获取。48:notes 聊天(type: self)是你的个人“发给自己”的便笺线程。

chat edit 只能编辑你自己的消息,而且仅适用于聊天——无法通过此 API 编辑 Teams 频道消息。

消息内容(文本、HTML、文件)

来自 chat history、chat get、message list/get/replies 和 channel history 的消息包含:

  • content — 纯文本(段落以换行分隔,链接格式为 text (url);数字实体和常见命名实体(例如 &amp;、&nbsp;、&mdash;)会被解码,较少见的命名实体则保持原样)
  • html — 仅适用于富文本消息的原始 HTML;可用于查看图片在文本中的位置
  • files — 消息中所有可下载的 URL:先列出内嵌图片(按顺序),然后是附件

使用 agent-teams file download <url> [output-path] 下载 files 中的任意条目。

消息格式

message send、chat send 和 chat edit 接受 --format <text|markdown|html>(默认为 text)。

在 text 模式下,内容会进行 HTML 转义,因此 <、> 和 & 会按原样发送。

在 markdown 模式下,发送前会将内容转换为 HTML。支持的语法:

语法渲染效果
# Heading 至 #### Heading标题
##### Heading、###### Heading不支持 — 与正文无法区分
**bold**、_italic_、***bold italic***强调
`inline code`行内代码
三反引号围栏围栏代码块,不带语法高亮
- item项目符号列表
1. item编号列表
> quote引用块
[label](https://example.com)链接
---水平分隔线

标题级别 5 和 6 不可用:Teams 客户端会以正文大小渲染 <h5> 和 <h6>,因此它们与周围文本无法区分。标题最多使用到 ####。围栏代码块会渲染为等宽字体块,但不会进行语法高亮——语言标签(```ts)会被接受,但随后忽略。这两种行为均已通过实时账户验证。

链接仅允许使用 http:、https:、mailto:、相对于根路径的 URL(/)和锚点 URL(#);其他内容会渲染为纯文本。

在 html 模式下,内容会经过标签白名单过滤,而不是原样发送。需要使用 Markdown 无法表达的 Teams 专用标记(最常见的是 @提及)时,请使用此模式:

agent-teams message send <team-id> <channel-id> "Hey <at id=\"29:abc\">John</at>, build is ready" --format html

允许的标签:at、a、b、i、u、s、strong、em、code、pre、br、p、ul、ol、li、blockquote、h1–h6、hr。<at> 仅保留其 id 属性;<a> 仅保留 href,且仅当其符合与 Markdown 模式相同的 URL 白名单时才会保留;其他所有标签都不保留任何属性。不在列表中的内容——<script>、<img>、on* 事件属性,以及格式错误或无法识别的标签——会被转义或移除,而不会原样传递。

白名单限制了潜在影响范围,但这并不意味着该模式可以安全处理任意输入:只传入你自行构造的内容。不可信输入应使用 text 模式。

团队命令
# List all teams
agent-teams team list

# Get team info
agent-teams team info <team-id>

# Switch active team
agent-teams team switch <team-id>

# Show current team
agent-teams team current

# Remove a team from config
agent-teams team remove <team-id>
用户命令
# List team members
agent-teams user list <team-id>

# Get user info
agent-teams user info <user-id>

# Get current user
agent-teams user me
表情回应命令
# Add reaction (use emoji name)
agent-teams reaction add <team-id> <channel-id> <message-id> <emoji>
agent-teams reaction add <team-id> 19:[email protected] 1234567890 like

# Remove reaction
agent-teams reaction remove <team-id> <channel-id> <message-id> <emoji>
文件命令
# Upload file
agent-teams file upload <team-id> <channel-id> <path>
agent-teams file upload <team-id> 19:[email protected] ./report.pdf

# List files in channel
agent-teams file list <team-id> <channel-id>

# Get file info
agent-teams file info <team-id> <channel-id> <file-id>

# Download a file (to a path or directory; defaults to the current dir)
agent-teams file download <team-id> <channel-id> <file-id>
agent-teams file download <team-id> <channel-id> <file-id> ./report.pdf
agent-teams file download <team-id> <channel-id> <file-id> ./downloads/ --pretty

# Download a URL from a message's `files` (inline image or attachment)
agent-teams file download <url> ./downloads/

URL 下载输出:{ "name", "size", "content_type", "path" }。当响应中没有文件名时,内嵌图片会回退使用其 Teams 对象 ID(例如 0-skr-d1-....jpg)。

file download 输出:{ "id", "name", "size", "content_type", "path" },其中 path 是文件写入的位置。内嵌图片/附件会使用提取出的 Skype 令牌下载,且适用于任何已登录账户;SharePoint/OneDrive 文档则通过 Microsoft Graph 下载,并要求使用 auth login 账户(仅 Cookie 的 auth extract 账户会收到明确错误,提示你运行 auth login)。

快照命令

获取供 AI Agent 使用的团队概览(默认简要):

# Brief snapshot (default) — fast, minimal API calls
agent-teams snapshot

# Full snapshot — includes messages and members (slow, large output)
agent-teams snapshot --full

# Filtered full snapshots
agent-teams snapshot --full --channels-only
agent-teams snapshot --full --users-only

# Limit messages per channel (only with --full)
agent-teams snapshot --full --limit 10

默认返回简要 JSON,包含:

  • 团队元数据(id、name)
  • 频道(id、name)
  • 后续命令提示

使用 --full 时,返回完整 JSON,包含:

  • 团队元数据(id、name)
  • 频道(id、name、type、description)
  • 最近的消息(id、content、author、timestamp)
  • 成员(id、displayName、email)

输出格式

JSON(默认)

所有命令默认输出 JSON,供 AI 使用:

{
  "id": "19:[email protected]",
  "content": "Hello world",
  "author": "John Doe",
  "timestamp": "2024-01-15T10:30:00.000Z"
}
Pretty(人类可读)

使用 --pretty 标志输出格式化内容:

agent-teams channel list --pretty

与 Discord/Slack 的主要区别

功能TeamsDiscordSlack
服务术语团队Guild工作区
频道标识符UUID 格式(19:[email protected])Snowflake ID频道名称或 ID
令牌存储Cookies SQLiteLevelDBLevelDB
令牌过期60-90 分钟很少过期很少过期
提及<at id="user-id">Name</at>(需要 --format html)<@user_id><@USER_ID>

重要:Teams 使用 UUID 风格的频道 ID(例如 19:[email protected])。不能直接使用频道名称——请先使用 channel list 查找 ID。

常见模式

典型的 AI Agent 工作流请参阅 references/common-patterns.md。

模板

可运行示例请参阅 templates/ 目录:

  • post-message.sh - 发送消息并处理错误
  • monitor-channel.sh - 监控频道中的新消息(含令牌刷新)
  • team-summary.sh - 生成团队摘要

错误处理

所有命令均返回一致的错误格式:

{
  "error": "Not authenticated. Run \"auth extract\" first."
}

常见错误:

  • Not authenticated:没有有效令牌(自动提取失败——请参阅故障排除)
  • Token expired:令牌已过期,且自动刷新失败——请参阅故障排除
  • No current team set:请先运行 team switch <id>。个人账户没有团队——请改用 chat list / chat history / chat send
  • Message not found:消息 ID 无效
  • Channel not found:频道 ID 无效
  • 401 Unauthorized:令牌已过期,且自动刷新失败——请参阅故障排除

配置

凭据存储在 ~/.config/agent-messenger/teams-credentials.json 中(权限为 0600)。格式和安全详情请参阅 references/authentication.md。

SDK:编程式用法

TeamsClient 可作为 TypeScript SDK 使用,用于构建脚本和自动化流程。

设置
import { TeamsClient } from 'agent-messenger/teams'

const client = await new TeamsClient().login()

或手动管理凭据:

import { TeamsClient, TeamsCredentialManager } from 'agent-messenger/teams'

const manager = new TeamsCredentialManager()
const creds = await manager.getTokenWithExpiry()
if (!creds) {
  throw new Error('Teams token not found. Run auth extract first.')
}
const client = await new TeamsClient().login({ token: creds.token, tokenExpiresAt: creds.tokenExpiresAt })
示例
// List teams
const teams = await client.listTeams()

// List channels in a team
const channels = await client.listChannels(teams[0].id)

// Send a message
const msg = await client.sendMessage(teams[0].id, channels[0].id, 'Hello from SDK!')

// React to it
await client.addReaction(teams[0].id, channels[0].id, msg.id, 'like')

// Upload a file
await client.uploadFile(teams[0].id, channels[0].id, './report.pdf')
实时事件

通过内部 trouter WebSocket 实时流式接收 Teams 聊天消息——以用户身份连接,无需机器人或公共端点。需要登录 Teams 桌面应用。

import { TeamsClient, TeamsListener } from 'agent-messenger/teams'

const client = await new TeamsClient().login()
const listener = new TeamsListener(client)

listener.on('message', async (message) => {
  console.log(`New message in ${message.chatId}: ${message.content}`)

  // Channel messages carry team/channel context and parsed @mentions.
  if (message.conversationType === 'channel') {
    for (const mention of message.mentions) {
      console.log(`Mentioned: ${mention.displayName} (${mention.mri})`)
    }
    await client.sendMessage(message.teamId!, message.channelId!, 'On it 👍')
  }
})

await listener.start()

每条 message 都是一个 TeamsRealtimeMessage:

字段类型说明
idstring消息 ID
chatIdstring会话 ID(保持不变)
conversationType'chat' | 'channel'团队频道消息时为 'channel'
teamIdstring?频道消息会设置此字段(与 sendMessage 搭配使用)
channelIdstring?频道消息会设置此字段(与 sendMessage 搭配使用)
contentstring纯文本(保留段落分隔,已解码实体)
htmlstring?原始 HTML,仅限富文本消息
filesstring[]?可下载的 URL:先列出内嵌图片,再列出附件
mentionsTeamsMention[]始终存在;没有 @mentions 时为空。每项格式为 { id, mri?, displayName }
author{ id, displayName }发送者(保持不变)
messageTypestring例如 Text、RichText/Html
timestampstringISO 时间戳
完整 API 参考

完整的方法签名、类型、架构和示例请参阅 Teams SDK 文档。

限制

  • 实时事件仅限 SDK(TeamsListener);CLI 没有 watch 命令
  • 不支持语音/视频频道
  • 不支持团队管理(创建/删除频道、角色)
  • 个人账户:仅支持聊天(不支持团队/频道);请使用 chat 命令
  • 不支持会议
  • 不支持 webhook
  • 仅支持纯文本消息(v1 不支持自适应卡片)
  • 仅支持用户令牌(不支持应用令牌)
  • 令牌有效期较短——设备代码(auth login)账户会使用存储的刷新令牌在后台自动刷新;提取登录信息的账户也会自动刷新,但需要 Teams 桌面应用或浏览器仍处于登录状态

故障排除

agent-teams: command not found

agent-teams 不是 npm 包名称。 npm 包名为 agent-messenger。

如果已全局安装该包,请直接使用 agent-teams:

agent-teams team list

如果未安装该包,默认使用 npx -y。不要询问用户要使用哪种包运行器——直接运行:

npx -y agent-messenger teams team list
bunx agent-messenger teams team list
pnpm dlx agent-messenger teams team list

如果你已知用户偏好的包运行器(例如 bunx、pnpm dlx),则使用该运行器。

切勿运行 npx agent-teams、bunx agent-teams 或 pnpm dlx agent-teams——由于 agent-teams 不是 npm 包名称,这些命令会失败或安装错误的包。

有关其他故障排除信息(身份验证信息提取、令牌过期、权限),请参阅 references/authentication.md。

参考资料

评论

支持 Markdown