# How to set up Hermes Agent on Microsoft Teams

> Register a Teams bot, connect its HTTPS webhook to Hermes, restrict access by user ID and send a first direct message.

Canonical: https://hermeswatcher.com/learn/hermes-agent-microsoft-teams-setup  
Section: Learn · Messaging & the gateway  
Last reviewed: Oct 29, 2026  
Basis: Explained from the official Hermes Agent docs and repository (Nous Research). Steps follow the linked official sources.

## What you need

Teams sends messages to Hermes through a webhook, a URL that receives event requests. It needs a public HTTPS URL: an internet-reachable address with an encrypted connection. A local-only address is insufficient.

- Hermes Agent installed with a model provider configured.
- A Microsoft 365 account in a tenant that allows custom app upload. A tenant is your organization's Microsoft environment. An administrator may need to enable this permission.
- Node.js and npm to install the Teams CLI. The Microsoft registration quickstart lists Node.js 22.12 or later.
- A public HTTPS endpoint, or a development tunnel forwarding to the local Hermes HTTP port 3978. A tunnel gives a local service a public address.
- A computer that remains on, plus the Teams client where you will install the app.

This guide covers normal bot conversations. The separate [Microsoft Teams Meetings workflow](https://hermes-agent.nousresearch.com/docs/user-guide/messaging/teams-meetings) requires additional setup.

## Ask your Microsoft 365 admin for

- Permission to upload custom apps in your organization.
- Depending on your organization's policies, you may also need approval to register apps and to use Dev Tunnels.

## Install the Teams CLI and sign in

The official Hermes page uses the preview CLI command below. The current [Microsoft registration quickstart](https://learn.microsoft.com/en-us/microsoftteams/platform/teams-sdk/get-started/quickstart-register) instead shows `npm install -g @microsoft/teams.cli`. Microsoft's page installs the standard release. The Hermes docs use the `@preview` release, so use the Hermes command below.

Hermes-documented Teams CLI setup:

```
npm install -g @microsoft/teams.cli@preview
teams login
teams status --verbose
```

Sign in to the intended Microsoft 365 organization. Check that custom app upload is enabled. Record your AAD object ID (your Microsoft Entra ID user ID, formerly Azure Active Directory) from the verbose status output. You will put it in the allowlist. This is your account's directory ID, not its email address.

Hermes supplies the bot runtime. Do not scaffold or run the separate Microsoft echo-bot project as part of this connection.

## Expose the local webhook

For local development, install and sign in to Microsoft Dev Tunnels. Microsoft documents the Windows install command below; its tunnel guide also lists installation for macOS and Linux. Then create and host the named tunnel using the commands from the Hermes page.

Named profile: when one gateway serves several profiles (the default), a secondary profile's Teams endpoint is `https://<your-host>/p/<profile>/api/messages` on the default profile's shared API-server listener, not port 3978. Register the exact URL logged at startup and point the tunnel at that shared listener's port. The unprefixed examples below are for the default profile.

Windows, if Dev Tunnels is not installed:

```
winget install Microsoft.devtunnel
```

Sign in to Dev Tunnels:

```
devtunnel user login
```

Create and host the tunnel:

```
devtunnel create hermes-bot --allow-anonymous
devtunnel port create hermes-bot -p 3978 --protocol http
devtunnel host hermes-bot
```

Leave the hosting terminal open and copy the printed HTTPS address. Anonymous tunnel access lets Teams reach the webhook; it does not authorize people to operate Hermes. Keep bot request authentication and the user allowlist in place.

HTTPS ends at the tunnel. It must forward plain HTTP to the local Hermes listener. If you change `TEAMS_PORT`, use that port in the tunnel too. See [Microsoft tunnel instructions](https://learn.microsoft.com/en-us/microsoftteams/platform/teams-sdk/developer-tools/local-tunnels).

The documented Teams listener binds all interfaces (IPv4 and IPv6) on port 3978, rather than loopback only. Block direct public access to port 3978 with your firewall and let only your reverse proxy or tunnel reach it.

## Create the Teams app

With the tunnel running, register the bot using the official Hermes command. Replace the URL placeholder with your actual tunnel hostname. Keep /api/messages at the end.

Terminal, Bash line continuation:

```
teams app create \
  --name "Hermes" \
  --endpoint "https://<your-tunnel-url>/api/messages"
```

Save the reported `CLIENT_ID`, `CLIENT_SECRET`, `TENANT_ID`, Teams App ID and installation link. The Hermes docs say the client secret is not shown again. Keep the secret private.

The Microsoft quickstart also documents writing registration credentials into an environment file. Hermes uses the TEAMS_ names in the next step, so do not assume the unprefixed CLI names configure Hermes automatically.

In PowerShell, put the command on one line or use a backtick for line continuation.

## Choose who can talk to it and connect Hermes

Run `hermes gateway setup` and select Microsoft Teams for the guided route. For manual setup, add the following values to your active profile .env.

The platform docs use `~/.hermes/.env` for the default profile on Linux, macOS and WSL. Native Windows normally uses `%LOCALAPPDATA%\hermes\.env`. If you use a custom Hermes home or another profile, edit that profile's file instead. Replace every example value before starting.

Set `TEAMS_ALLOWED_USERS` to your own AAD object ID first. Separate additional authorized IDs with commas. An allowlist is the list of people permitted to use the agent. Authorize only people you trust with its enabled tools and files. Keep `GATEWAY_ALLOW_ALL_USERS` unset or false and `TEAMS_ALLOW_ALL_USERS` unset or false and review existing global allowlists and pairing approvals, which can also grant access. Do not expect an unknown sender to receive a pairing code when an allowlist is set.

Setup wizard:

```
hermes gateway setup
```

Profile .env, manual alternative:

```
TEAMS_CLIENT_ID=<your-client-id>
TEAMS_CLIENT_SECRET=<your-client-secret>
TEAMS_TENANT_ID=<your-tenant-id>
TEAMS_ALLOWED_USERS=<your-aad-object-id>
# Optional; official default false. Set true once the app manifest grants message-read RSC permissions.
TEAMS_REQUIRE_MENTION=true
```

Keep `TEAMS_CLIENT_SECRET` out of repositories, shared chats and logs. The Hermes docs recommend private .env permissions and secret rotation.

With `TEAMS_REQUIRE_MENTION=true`, the bot answers in channels and group chats only when someone @mentions it or replies to it. This matters only once the app's manifest grants resource-specific consent (RSC) to read messages (`ChannelMessage.Read.Group` or `ChatMessage.Read.Chat`), which makes Teams deliver every message in the conversation. The mention setting is a trigger rule, not a replacement for sender authorization. Personal DMs are mention-exempt.

## Start the gateway and install the app in Teams

Start the gateway in the foreground. In another terminal, use the health check if you need to inspect the listener.

Foreground gateway:

```
hermes gateway
```

Local listener check:

```
curl http://localhost:3978/health
```

Recover the installation link if needed:

```
teams app get <teamsAppId> --install-link
```

The official docs show ok as the health response and a log entry for a listener on port 3978 at /api/messages. A health response alone does not show that Teams can reach it.

Open the installation link while signed into the intended Teams account, then add the app. Replace <teamsAppId> with the Teams App ID from registration if you need to retrieve the link.

Send Hello in a personal DM from your allowed account. Then try an @mention in a group or channel where the app is installed. Inspect both the Teams response and gateway logs before treating the connection as ready.

## Only if the Teams SDK is missing

Skip this unless the gateway log says the Teams SDK is missing. The docs say the gateway can request it on first start.

For a source or local installation missing the Teams SDK, the official page gives this dependency command. Use a PM-prepared source checkout, as described in the [package-management workflow](https://hermes-agent.nousresearch.com/docs/reference/package-management#developer-workflow). PM is the Hermes package manager. Do not run the command in an unrelated system Python.

Activated Hermes source checkout:

```
python -c "import pm; pm.sync_venv(['teams'], explicit=True)"
```

After it completes, reactivate the same checkout and restart Hermes so it uses the prepared environment. The docs say the gateway can request the optional extra on first startup when policy permits. This command is a recovery path for a missing dependency, not a separate bot runtime.

## What it can do

- The official comparison table lists images, threads and a typing indicator for Teams. It does not list voice, general file attachments, emoji reactions or streaming updates for this adapter. Do not assume every attachment type is supported.
- Personal chats do not need mentions. Group and channel conversations use mentions unless message-read consent and configured trigger rules broaden intake.
- Potentially dangerous commands can produce an Adaptive Card with Allow Once, Allow Session, Always Allow and Deny. Choose the narrowest approval that fits the task; Always Allow persists the pattern.
- Meeting transcript summaries are a separate workflow. Configuring this conversational bot does not subscribe it to Microsoft Graph meeting events.

## Keep it running

The bot is silent while its computer sleeps or is switched off. Keep the Hermes host awake and online whenever you need replies. A background service does not prevent sleep.

After your first message succeeds, stop the foreground gateway with Ctrl+C. For a normal host installation, the official gateway docs give these service commands:

Install, start and inspect the host service:

```
hermes gateway install
hermes gateway start
hermes gateway status
```

Linux uses systemd, macOS uses launchd, and Windows uses a Scheduled Task at logon. On a headless Linux host using a user service, the docs give `sudo loginctl enable-linger $USER` to keep it available after logout. Windows Task Scheduler does not restart a gateway that crashes after its launcher exits.

In a container, use the documented container startup and restart policy instead of installing a host user service. For hosting choices, see [How to run Hermes Agent 24/7 on a VPS or home server](https://hermeswatcher.com/learn/run-hermes-agent-24-7.md).

### Keep the public endpoint available

A running gateway service does not keep a development tunnel alive. If the tunnel stops, Teams cannot deliver messages even while the local health check answers. If its URL changes, update the app endpoint.

For a permanent host, the Hermes docs describe a reverse proxy with a valid public TLS certificate, forwarding to plain HTTP at 127.0.0.1:3978. A reverse proxy accepts public requests and forwards them to the local listener. Block direct public access to port 3978 with your firewall; let only the proxy or tunnel reach it.

If you move to a permanent domain, update the registered endpoint (replace both placeholders):

```
teams app update --id <teamsAppId> --endpoint "https://your-domain.com/api/messages"
```

Use an endpoint you control. The official docs say Teams rejects self-signed certificates. See [How to run Hermes Agent 24/7 on a VPS or home server](https://hermeswatcher.com/learn/run-hermes-agent-24-7.md) for host choices.

## If it doesn't answer

- Cannot install the app: check the signed-in tenant and whether custom app upload is enabled.
- Local health check works but Teams is silent: check the tunnel process and the registered HTTPS URL, including /api/messages.
- Logs show UNKNOWN / HTTP/1.0 with a 400 response: the tunnel may be forwarding HTTPS to the plain HTTP listener. Forward HTTP on the local port.
- Authentication errors: check all three TEAMS_ credentials and that the tenant matches your login. Missing model configuration is a separate error.
- Messages arrive but are ignored: compare your AAD object ID with `TEAMS_ALLOWED_USERS` and check mention rules.
- Missing Teams SDK or adapter: use the PM dependency step, reactivate the environment and restart the gateway. Read detailed service logs with `hermes gateway status -l`.
- For the broader checklist, see [Hermes Agent bot not responding in your chat app](https://hermeswatcher.com/troubleshoot/gateway-bot-not-responding.md).

## Official docs

Reviewed Oct 29, 2026 against the official Hermes docs.

[Official Hermes Microsoft Teams docs](https://hermes-agent.nousresearch.com/docs/user-guide/messaging/teams)

## Related guides

- [All messaging platforms](https://hermeswatcher.com/messaging.md)
- [Hermes Agent messaging gateway explained](https://hermeswatcher.com/learn/messaging-gateway-explained.md)
- [How to set up Hermes Agent on Slack](https://hermeswatcher.com/learn/hermes-agent-slack-setup.md)
- [How to set up Hermes Agent on Google Chat](https://hermeswatcher.com/learn/hermes-agent-google-chat-setup.md)
- [Hermes Agent bot not responding in your chat app](https://hermeswatcher.com/troubleshoot/gateway-bot-not-responding.md)

## Related tools

- [CLI: run bounded tasks and inspect the working environment](https://hermeswatcher.com/tools/cli.md)
- [Deployment: separate the agent host from its execution sandbox](https://hermeswatcher.com/tools/deployment.md)
- [Command approvals: decide what the agent may run unattended](https://hermeswatcher.com/tools/approvals-security.md)

## Sources

- [Hermes Agent: Microsoft Teams](https://hermes-agent.nousresearch.com/docs/user-guide/messaging/teams)
- [Microsoft: register your app](https://learn.microsoft.com/en-us/microsoftteams/platform/teams-sdk/get-started/quickstart-register)
- [Microsoft: local tunnels](https://learn.microsoft.com/en-us/microsoftteams/platform/teams-sdk/developer-tools/local-tunnels)
- [Package management: source checkout workflow](https://hermes-agent.nousresearch.com/docs/reference/package-management#developer-workflow)
- [Messaging gateway](https://hermes-agent.nousresearch.com/docs/user-guide/messaging)
- [Gateway authorization source](https://github.com/NousResearch/hermes-agent/blob/088f657ecf77674c7b8e2ededf4e3576d82e042c/gateway/authz_mixin.py#L660-L772)
- [Native Windows settings paths](https://hermes-agent.nousresearch.com/docs/user-guide/windows-native)
- [website/docs/user-guide/multi-profile-gateways.md](https://raw.githubusercontent.com/NousResearch/hermes-agent/main/website/docs/user-guide/multi-profile-gateways.md)

---

HermesWatcher is an independent guide. It is not affiliated with or endorsed by Nous Research. The [official Hermes Agent documentation](https://hermes-agent.nousresearch.com/docs) and [repository](https://github.com/NousResearch/hermes-agent) from Nous Research are the authority; each page here lists the official sources it was written from. If this site and the official docs disagree, trust the official docs. Index for agents: https://hermeswatcher.com/llms.txt
