Connect Microsoft Teams to Genesis on SPCS
Microsoft Bot Framework must POST activities to a publicly reachable HTTPS endpoint. Snowflake SPCS ingress is protected by Snowflake authentication, so Bot Framework cannot call an SPCS-hosted Genesis service directly. The Genesis Teams relay provides the public endpoint and forwards each activity through authenticated SPCS ingress.Choose the deployment path
Complete the Azure Bot, Teams channel, Genesis bot credentials, and Teams app
manifest steps in the
direct Bot Framework runbook.
On SPCS, replace only its direct messaging-endpoint step with the relay
endpoint configured below.
Before you begin
You need:- An Azure subscription and permission to deploy a public HTTPS container
- A Microsoft 365 tenant and an Azure Bot configured for Microsoft Teams
- Access to administer the Genesis deployment’s Config pages
- Snowflake permission to create a dedicated service user and role
- The public SPCS service URL for the Genesis deployment
Register the Azure resource provider
Azure Container Apps requires theMicrosoft.App resource provider. On a
subscription that has never hosted a Container App it is unregistered, and
container-app creation fails until registration completes:
Microsoft.Web.
Deploy the relay
Choose an immutable relay release and pull it from the public Docker Hub repository. Relay versions are independent of Genesis versions.vX.Y.Z tag for production. sha-<commit> identifies a
source revision, while latest moves whenever a relay release is published.
Deploy the image to a public Azure container host such as Azure Container Apps
or Azure App Service, expose container port 8080 over HTTPS, and configure:
Store the RSA private key in the Azure host’s secret facility, mount it
read-only, and set
RELAY_SNOWFLAKE_PRIVATE_KEY_PATH to the mount path.
For Azure Container Apps, set minimum replicas to at least 1. Its default
scale-to-zero behavior is unsafe here: the relay pre-warms its Snowflake token
at startup, and a cold token exchange can take tens of seconds while Bot
Framework allows about 15 seconds for delivery. A cold-starting relay can
therefore drop the first message.
Configure the readiness probe to use /ready and the liveness probe to
use /health: readiness gates traffic, while liveness restarts the container.
Replica replacement for platform maintenance, node drain, and image updates
happens regardless of scaling configuration, so the readiness probe matters
even when replicas are pinned to 1. Without it, a replacement relay can receive
activities before its Snowflake token is warm, and Bot Framework may exhaust
its retries before the relay can serve, dropping the message.
The relay’s activity-deduplication cache is per-instance and in memory. With
N relay replicas, the same activity can be admitted up to N times.
Genesis-side deduplication remains authoritative.
After deployment, verify:
token_state is valid.
Configure Snowflake and Genesis
1
Create a dedicated Snowflake identity
Create a service user and a role used only by the relay. The recommended
name for both is Then grant that role exactly two privileges — the Genesis application role,
which is what authorises the relay to reach the Genesis service endpoint,
and usage on the warehouse the deployment runs against:Do not reuse a human,
GENESIS_TEAMS_RELAY. Configure RSA key-pair
authentication on the user.GENESIS_DATA_AGENTS is the Genesis application name; substitute the name
your deployment used at install time. APP_PUBLIC is the application’s only
application role.Confirm both grants landed:ACCOUNTADMIN, or application-owner credential for
the relay. Record the key owner in the deployment runbook.2
Rotate the relay key
Rotation is a two-part operation: publish the new public key in Snowflake,
then point the relay at the matching new private key.Strip the Update the mounted private key in the Azure secret store as part of the same
change, and rotate immediately after any suspected exposure.
-----BEGIN PUBLIC KEY----- and -----END PUBLIC KEY----- lines —
Snowflake stores the base64 body only.Verify what Snowflake now holds:RSA_PUBLIC_KEY_FP is the fingerprint of the stored key and
RSA_PUBLIC_KEY_LAST_SET_TIME records when it was last changed — together
they confirm the rotation took effect rather than silently leaving the old
key in place.For zero-downtime rotation, Snowflake accepts a second key in
RSA_PUBLIC_KEY_2. Publish the new key there first, restart the relay onto
the new private key, confirm /health still reports token_state valid,
then clear the old key:3
Confine the relay identity in Genesis
In the Genesis dashboard, open Config → Advanced Settings and set
teams.relay_service_user to the exact Snowflake service-user name, for
example GENESIS_TEAMS_RELAY.Genesis then confines requests authenticated as that identity to the Teams
message, Teams health, and enabled Teams ingress-canary routes. The
forwarded Bot Framework authorization header is accepted only after this
identity gate passes.4
Optional: enable ingress diagnostics
When header loss or relay routing issues are suspected, set
teams.ingress_canary_enabled to true in Config → Advanced Settings.
The confined relay identity (and unauthenticated callers when the flag is
on) can then reach GET or POST /api/teams/ingress-canary, which returns
a value-redacted summary of headers (presence, length, and a short SHA-256
prefix — never plaintext tokens). Disable the flag after troubleshooting.5
Approve Bot Framework egress
In the Genesis dashboard, open Config → Microsoft Teams, click
Approve External Access (this opens Snowsight to approve the
“Teams Bot Framework” external-access reference), then Assign to
Genesis. Genesis needs this external access both to fetch Microsoft’s
signing metadata (to validate inbound Bot Framework tokens) and to send
replies. Assigning briefly restarts the Genesis service to apply the change.
If the relay starts returning 403s
Configure Azure
- Before restricting Azure Container Apps ingress, verify in a live deployment whether IP restrictions accept the Azure Bot Service service tag or require CIDR ranges. Do not configure a service-tag restriction until that behavior is confirmed.
- In the Azure Bot resource, open Settings → Configuration.
-
Set Messaging endpoint to:
<bot_id>is the case-sensitive Genesis bot id, usuallyEve. - Leave Enable Streaming Endpoint unchecked and click Apply.
Verify the connection
- Confirm
GET https://<relay-host>/healthreports"token_state":"valid". - Confirm the Genesis Teams health endpoint is reachable through the SPCS deployment and reports at least one registered bot.
- Install the Teams app and send the bot a direct message.
- Check relay logs for the request id, bot id, upstream status, and latency. The relay intentionally does not log request bodies, authorization headers, private keys, or tokens.
- Confirm Genesis logs show the activity was enqueued and the reply was sent.
Security boundary
Reduce this residual risk by keeping the relay small and patched, applying a host-specific inbound policy only after it has been verified, confining its Snowflake identity in Genesis, protecting the private key in the Azure secret store, and rotating the key immediately after suspected exposure.Related
- Activate Eve in Teams (Bot Framework) — Azure Bot, Teams app, and direct-public-host setup
- Microsoft Bot Framework documentation

