Teams
Complete reference for the agent-teams CLI.
Tip:
agent-teamsis a shortcut foragent-messenger teams.
Quick Start
# 1. Sign in with Microsoft device code (required for channels and search)
agent-teams auth login --account-type work
# 2. Get team snapshot
agent-teams snapshot
# 3. Send a message
agent-teams message send <team-id> <channel-id> "Hello from AI agent!"Authentication
Use auth login for work/school channel, directory, search and Graph-backed file operations; accounts set up with auth extract fall back to the older Teams CSA routes for channel, member and file commands. These use Microsoft bearer tokens from the saved device-code account. auth extract supplies a Skype token for chats, legacy discovery and trusted Teams-hosted inline downloads. Your tenant policies and delegated permissions still apply.
An expired device-code login is refreshed for the same account. If refresh fails, the CLI does not replace it with a different desktop/browser identity. Run auth login explicitly to reconnect.
Seamless Token Extraction
agent-teams automatically extracts your Microsoft Teams credentials from the desktop app or Chromium browser:
agent-teams auth extract
# Use --debug for troubleshooting
agent-teams auth extract --debug
# Scan custom Chromium profile/user-data dirs (repeatable or comma-separated)
agent-teams auth extract --browser-profile ~/browser-data
agent-teams auth extract --browser-profile "$HOME/work-profile,$HOME/personal-profile"This command:
- Auto-detects your platform (macOS/Linux/Windows)
- Extracts Teams access token from the desktop app (with browser fallback)
- Validates token against Teams API
- Discovers ALL joined teams
- Stores credentials securely in
~/.config/agent-messenger/ - Supports
--browser-profile <path>for agent-browser profiles, custom Chrome user data dirs, or portable browser profiles
Refresh and expiry
Extracted Skype tokens commonly expire in 60-90 minutes and only support chat routes. Device-code accounts refresh silently for the selected identity. If this fails, run auth login explicitly for the same account. Do not wrap channel/search operations with auth extract, which can discard the AAD refresh credential.
agent-teams auth status
# Explicit reconnect when silent device-code refresh fails:
agent-teams auth login --account-type workAny stored device-code account prevents automatic extraction, including when another account type is selected. Explicit auth extract remains available for deliberate Skype-only authentication.
Authentication Commands
# Check auth status (shows expiry time!)
agent-teams auth status
# Logout (clear stored credentials)
agent-teams auth logoutSupported Teams Versions
agent-teams supports both New Teams (WebView2-based, com.microsoft.teams2) and Classic Teams:
| Version | macOS | Windows | Linux |
|---|---|---|---|
| New Teams | ✅ | ✅ | N/A |
| Classic Teams | ✅ | ✅ | ✅ |
Manual Token Input (Last Resort)
If automatic extraction fails, you can manually provide a token:
agent-teams auth extract --token <your-skype-token>How to get your token manually:
- Open Microsoft Teams in your browser (teams.microsoft.com)
- Open Developer Tools (F12 or Cmd+Option+I)
- Go to Application > Cookies >
https://teams.microsoft.com - Find the cookie named
skypetoken_asm - Copy the Value (it's a long string starting with
eyJ...) - Run:
agent-teams auth extract --token "eyJ..."
Note: Browser tokens also expire in 60-90 minutes. For long-running workflows, you may need to refresh periodically.
Team Management
Teams uses "teams" as the top-level organizational unit. You must select a team before using most commands.
# List all teams
agent-teams team list
# Switch to a different team
agent-teams team switch <team-id>
# Show current team
agent-teams team current
# Get team info
agent-teams team info <team-id>
# Remove a stored team
agent-teams team remove <team-id>Commands
Whoami Command
# Show current authenticated user
agent-teams whoami
agent-teams whoami --prettyOutput includes the authenticated user's identity information.
Message Commands
# Send a message
agent-teams message send <channel-id> <content>
agent-teams message send abc123-def456 "Hello world"
# List messages
agent-teams message list <channel-id>
agent-teams message list abc123-def456 --limit 50
# Get a specific message
agent-teams message get <channel-id> <message-id>
# Delete a message
agent-teams message delete <channel-id> <message-id> --force
# Reply to a message (thread)
agent-teams message reply <channel-id> <message-id> "Reply content"
# Get a single chat message
agent-teams chat get <chat-id> <message-id>Messages read from chats and channels include content (plain text), with optional html (original HTML for rich-text messages) and files (downloadable URLs: inline images first, in order, then attachments). Both are omitted when a message has none. Pass a files URL to file download; SharePoint/OneDrive URLs require agent-teams auth login (cookie-only auth extract credentials cannot download them).
Channel Commands
# List channels in current team
agent-teams channel list
# Get channel info
agent-teams channel info <channel-id>
# Get channel message history
agent-teams channel history <channel-id>
agent-teams channel history abc123-def456 --limit 100User Commands
# List team members
agent-teams user list
# Get user info
agent-teams user info <user-id>
# Get current authenticated user
agent-teams user meReaction Commands
# Add reaction
agent-teams reaction add <channel-id> <message-id> <emoji>
agent-teams reaction add abc123-def456 msg789 like
# Remove reaction
agent-teams reaction remove <channel-id> <message-id> <emoji>
# List reactions on a message
agent-teams reaction list <channel-id> <message-id>File Commands
# Upload file to channel
agent-teams file upload <channel-id> <path>
agent-teams file upload abc123-def456 ./report.pdf
# List files in channel
agent-teams file list <channel-id>
# Get file info
agent-teams file info <channel-id> <file-id>
# Download file
agent-teams file download <file-id> <output-path>
# Download a URL from a message's `files` (inline image or attachment)
agent-teams file download <url> [output-path]Snapshot Command
Get team overview for AI agents (brief by default):
# 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 10Default returns brief JSON with:
- Team metadata (id, name)
- Channels (id, name)
- Hint for next commands
With --full, returns comprehensive JSON with:
- Team metadata (id, name)
- Channels (id, name, type, description)
- Recent messages (id, content, author, timestamp)
- Members (id, displayName, email)
Global Options
All commands support these options:
--pretty # Pretty-print JSON output (default is compact JSON)
--team <id> # Use specific team (overrides current team)Real-time Events (SDK)
Real-time message streaming is available through the SDK's TeamsListener, which
connects to Teams' internal trouter WebSocket as a user — no bot registration and
no public HTTP endpoint. There is no CLI watch command; use the SDK:
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()Each message is a TeamsRealtimeMessage. Alongside chatId/author and
content (plain text with paragraph breaks), optional html/files (same as
for read commands), it carries conversationType ('chat' or
'channel'), teamId/channelId (set for channel messages, for use with
sendMessage), and mentions (always present, empty when there are no
@mentions; each is { id, mri?, displayName }).
The listener reuses your extracted credentials, so the Teams desktop app must be logged in. It reconnects automatically and re-authenticates on token expiry.
Key Differences: Teams vs Discord vs Slack
| Concept | Slack | Discord | Teams |
|---|---|---|---|
| Server/Workspace | Workspace | Guild | Team |
| Channel ID format | Alphanumeric (C01234567) | Numeric snowflake | UUID (abc123-def456-...) |
| Message ID format | Timestamp (1234567890.123456) | Numeric snowflake | UUID |
| User ID format | Alphanumeric (U01234567) | Numeric snowflake | UUID (Azure AD Object ID) |
| Token lifetime | Long-lived | Long-lived | 60-90 minutes |
| API | Slack Web API | Discord API | Teams Messaging API |
| Threads | Thread timestamps | Thread channels | Reply chains |
| Rate limits | Moderate | Moderate | Strict |
Troubleshooting
Token Expired (401 Unauthorized)
Device-code accounts refresh silently. Reconnect with auth login when refresh fails. For Skype-only extraction accounts, re-extract only the intended chat identity. Authentication repair does not establish whether a prior write succeeded; inspect history before resending.
"No teams found"
For device-code work accounts, verify your joined teams live:
agent-teams --account work team list"Channel not found"
Teams channel IDs are UUIDs. Make sure you're using the full ID:
# Get channel list to find correct IDs
agent-teams channel list --prettyRate Limiting (429 Too Many Requests)
GET requests retry transient 429/5xx responses. Writes and search POST run once. After a write error or lost response, reconcile actual history before another attempt. Pace independent operations:
# Add delays between operations in scripts
sleep 2Desktop App Not Detected
Ensure Teams desktop app is:
- Installed (not just web version)
- Currently running
- Signed in to your account
Alternatively, log in via a Chromium browser (Chrome, Edge, Arc, Brave, etc.) — the CLI will fall back to browser extraction automatically.
# Debug extraction
agent-teams auth extract --debugPermission Errors
Some operations require specific Microsoft 365 permissions. Check with your IT admin if you encounter persistent 403 errors.
AI Agent Integration
See skills/agent-teams/ for:
- Complete skill documentation
- Runnable templates
Example: AI Agent Workflow
Sign in once with auth login before running the automation. CLI reads refresh the same device-code account when needed:
#!/bin/bash
set -euo pipefail
agent-teams --account work snapshot
# Send only after resolving the authorized team and channel.
agent-teams --account work message send "$TEAM_ID" "$CHANNEL_ID" "Standup reminder"Preserve the server receipt. If a write fails or its response is lost, inspect exact history before attempting another send. Applications that resume jobs need their own durable reservation/receipt/uncertain state; the upstream CLI does not provide a persistent send ledger.
Message fidelity and pagination
History and message commands retain the legacy text fields and additionally return raw_content, content_type, mentions and attachments. Chat history includes media records; pass --include-system to also include membership, call and other system records. Search returns an indexed preview; fetch the exact message for the full body.
Channel history and replies follow Graph pagination up to --limit. Chat history follows message pages by default; resumable single-page output is explicit:
agent-teams chat history <chat-id> --page --limit 50
agent-teams chat history <chat-id> --cursor '<next_cursor>' --limit 50Single-page output is { messages, next_cursor }. Ordinary history output remains an array.
Writes are attempted once, without automatic retries on HTTP 429 or 5xx. A timeout or server error can mean a message was delivered. Read the target history before deciding on another send; the CLI does not provide server-side idempotency.
Replies, reactions and permissions
Reply get/delete/reaction calls need the parent root ID:
agent-teams message get <team-id> <channel-id> <reply-id> --thread <root-id>
agent-teams reaction add <team-id> <channel-id> <reply-id> '👍' --thread <root-id>
agent-teams reaction remove <team-id> <channel-id> <reply-id> like --thread <root-id>
agent-teams message delete <team-id> <channel-id> <reply-id> --thread <root-id> --forceReaction input accepts Unicode and like, heart, laugh, surprised, sad, angry aliases. Graph requires Unicode, so names are converted. Channel reactions use ChannelMessage.Send. Deletion resolves the exact Graph message or reply, then calls Chat Service with the existing Skype token. This avoids adding Graph ChannelMessage.ReadWrite consent. Teams ownership and deletion policy still apply. A delete write is attempted once with no fallback write; reread the exact target before deciding what happened.
Device-code work team list uses live Graph display names. Extraction account names and team current are cached; verify ambiguous labels with team info. The send interface does not expose a Graph mentions payload, so raw <at> markup is not a verified notification mention.