#6747·keep

[➕ Feature]: Google Chat provider — choose the space per notification

Author: purisevCreated Sep 2, 2026Updated Sep 2, 2026

Is your feature request related to a problem? Please describe.

GoogleChatProvider._notify (keep/providers/google_chat_provider/google_chat_provider.py:54) takes a message and nothing else, and reads the webhook URL from the provider configuration (line 65). One installed provider serves exactly one space.

Posting to several spaces means installing a provider per space, each holding another webhook URL. And the choice of space can never come from the data: a workflow cannot take it from the alert, a mapping rule cannot supply it, because _notify has no parameter to pass that choice to.

Slack's _notify already accepts channel, blocks and thread_timestamp per notification (keep/providers/slack_provider/slack_provider.py:140). Google Chat accepts plain text to a fixed room.

Describe the solution you'd like

Two ways to route, both per notification:

  • webhook_url — the address for this one message. A caller-supplied address makes the provider a relay for whatever host the caller names, so it needs a guard: exact host chat.googleapis.com, https, redirects not followed.
  • space — a name resolved through a webhook_urls map (space name to webhook URL) held in the provider's authentication config, so workflows and mapping rules can route by name.

webhook_url in the authentication config stays, as the default for callers that pass neither.

Describe alternatives you've considered

  • A provider per space. Multiplies installations and spreads webhook URLs across KEEP_PROVIDERS, and still cannot route on the content of an alert.
  • Keeping the routing table in a mapping rule. Mapping rule rows live in the database and enrich the alert with whatever they matched, so a webhook URL put there ends up in mappingrule.rows, in alert_enrichment, and in every API response that returns the alert. The authentication config goes to the secret manager instead, and the notification carries only a name. A name is not a credential.

Additional context

Two more things the Chat endpoint supports and the provider does not, both one extra key in the payload: cardsV2 and threading (thread.threadKey with messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD).

A PR implementing this follows.