Plugins¶
SecondBrain plugins are declarative capability bundles. A plugin manifest tells operators which connector, kernel tool, MCP server, skill, or resource a bundle adds, which environment variables it needs, and what side effects each capability can have.
Plugins do not bypass the runtime. Tool execution still flows through the existing connector, MCP, skill, kernel policy, approval, tracing, and event-log layers.
Commands¶
sb plugins list
sb plugins show teams
sb plugins tools teams
sb plugins status teams
sb plugins validate teams
sb plugins disable teams
sb plugins enable teams
Use --json on each command for automation.
enable and disable write local plugin state under the configured
SecondBrain state directory. The kernel tool bridge respects that state during
runtime registration, while direct diagnostic commands such as sb teams status
remain available for setup and repair.
The serve daemon exposes the same manifest and connector state at
GET /plugins/status; the web UI renders it on the Settings page.
Microsoft Teams¶
The first built-in plugin is teams. It contributes Microsoft Graph-backed
kernel tools for:
- reading the signed-in profile
- listing joined teams
- listing channels for one team
- listing recent Teams chats
- reading messages from one chat
- fetching one chat message by ID
- reading messages from one channel
- fetching one channel message by ID
- reading replies under one channel message
- resolving users, joined teams, channels, and chats by visible names
- sending text or HTML chat/channel messages, including mentions and attachment payloads
- listing Planner plans, buckets, and tasks
- fetching, creating, updating, and deleting Planner tasks
- fetching and updating Planner task details, descriptions, checklists, and references
- receiving Bot Framework message activities through the conversational adapter
- storing Bot Framework conversation references for later proactive messaging
Read operations are classified as network_read. Sending a chat/channel
message or creating/updating/deleting a Planner task is classified as
external_write and maps to the existing kernel destructive safety class so
the ToolExecutor requires approval before an agent can post externally or
change work in Planner.
Azure CLI can be used for a basic local token check:
Teams chat and message APIs usually require delegated Microsoft Graph scopes that Azure CLI's first-party app cannot request directly. For durable chat, channel, and Planner access, use device-code login with a Microsoft Entra public-client application ID:
export TEAMS_GRAPH_CLIENT_ID=<app-client-id>
sb teams device-login
sb teams auth-doctor
sb teams joined-teams --json
sb teams channels <team_id> --json
sb teams channel-messages <team_id> <channel_id> --json
sb teams channel-message <team_id> <channel_id> <message_id> --json
sb teams channel-replies <team_id> <channel_id> <message_id> --json
sb teams chats --json
sb teams chat-message <chat_id> <message_id> --json
sb teams resolve-users "Ada" --json
sb teams resolve-team "Launch" --json
sb teams resolve-channel <team_id> "General" --json
sb teams resolve-chat "Launch planning" --json
sb teams planner-plans <team_id> --json
sb teams planner-buckets <plan_id> --json
sb teams planner-tasks <plan_id> --all-pages --json
sb teams planner-task <task_id> --json
sb teams planner-task-details <task_id> --json
sb teams login does not copy or store a token. It verifies that the signed-in
Azure CLI account can mint a Microsoft Graph token. If sb teams chats returns
403, do not keep switching Azure subscriptions; use sb teams device-login
with an Entra public-client app that has the required delegated Graph scopes.
The device-code path stores the access token and refresh token in the
SecondBrain keychain. auth_provider=auto can refresh cached device-code
tokens before falling back to Azure CLI. Configure connectors.teams.oauth_*
fields to pin the tenant, client ID source, or scopes.
Conversational Teams Gateway Adapter¶
Graph is still the right path for background reads and writes. Interactive
Teams conversations should use the existing SecondBrain gateway channel
runtime. The Teams adapter normalizes Bot Framework Activity payloads into
MessageEnvelope objects, then hands them to GatewayRuntime.handle_message()
so identity routing, sessions, approval gates, lanes, and outbound delivery
remain shared with HTTP and Telegram channels.
Configure the gateway channel in ~/.secondbrain/gateway.yaml:
channels:
teams:
enabled: true
host: 127.0.0.1
port: 3978
path: /api/messages
auth_mode: token
auth_token: local-dev-token
Point Azure Bot Service or a local tunnel at:
For local tunnel tests, send the gateway token as Authorization: Bearer
local-dev-token or X-Teams-Channel-Token: local-dev-token. In production,
put Bot Connector JWT validation at the edge or use a trusted proxy that
forwards verified requests to the local gateway adapter.
The adapter stores the Bot Framework conversation reference under local state
so gateway outbound delivery can do proactive messaging when
TEAMS_BOT_APP_ID and TEAMS_BOT_APP_PASSWORD are configured. It also splits
text replies and attachments into separate activities, because Teams can split
combined payloads internally and that makes message IDs harder to track.
Manual token setup is still available. The auth command stores a Microsoft
Graph access token in the same SecondBrain keychain path used by sb keys:
The token variable defaults to TEAMS_GRAPH_TOKEN and can be changed with
connectors.teams.token_env in the SecondBrain config. The auth provider
defaults to auto, which tries environment/keychain auth first and falls back
to Azure CLI.
Direct CLI sends require --force:
sb teams send-chat <chat_id> "Status update" --force
sb teams send-chat <chat_id> "<b>Status update</b>" --html --force
sb teams send-chat <chat_id> "Ada please review" --mention <user_id>=Ada --force
sb teams send-channel <team_id> <channel_id> "Status update" --force
sb teams send-channel-reply <team_id> <channel_id> <message_id> "Reply" --force
sb teams create-planner-task <plan_id> <bucket_id> "Follow up" --force
sb teams update-planner-task <task_id> --title "Renamed" --force
sb teams update-planner-task-details <task_id> --description "New details" --checklist-item "Call Ada" --force
sb teams delete-planner-task <task_id> --force
Use --dry-run --json on any write command to preview the Microsoft Graph
request body without posting, creating, updating, or deleting anything. Planner
updates, deletes, and details updates use ETag-safe writes. If --etag is
omitted, the connector fetches the task or details object first and uses the
returned ETag for the write. List commands that can return Graph nextLink
support --all-pages --max-pages N.
Agent-driven sends should use the governed tool path, where approval is handled by the kernel policy layer.
Planner reads require Microsoft Graph Tasks.Read delegated permission. Task
creation, update, delete, and details updates require Tasks.ReadWrite. User
resolution uses basic Microsoft Entra user read permissions such as
User.ReadBasic.All depending on tenant policy.
Live Graph smoke coverage is opt-in and skipped by default: