Skip to content

feat(alerts): MCP recipe for slack/webhook delivery#56706

Merged
vdekrijger merged 27 commits into
masterfrom
posthog-code/mcp-alert-slack-recipe
Apr 30, 2026
Merged

feat(alerts): MCP recipe for slack/webhook delivery#56706
vdekrijger merged 27 commits into
masterfrom
posthog-code/mcp-alert-slack-recipe

Conversation

@vdekrijger
Copy link
Copy Markdown
Contributor

@vdekrijger vdekrijger commented Apr 28, 2026

Problem

When asked to wire up a Slack-routed alert through the MCP, agents could only set subscribed_users (email recipients). The alert-create schema doesn't expose anything about Slack channels or webhooks, so users got back "sorry, only email" responses even though the underlying capability exists.

The frontend's alert page does Slack delivery by calling the existing /api/projects/.../hog_functions/ endpoint with a payload that filters on the alert id — there's no alert-specific Slack API. That hog_functions endpoint is already exposed via MCP as cdp-functions-create. So the gap was discoverability + a missing read-side tool for finding channel ids + an auth path for Slack integrations through API keys.

This was requested over here: https://posthog.slack.com/archives/C09BDQLM8KA/p1777371677710389

Changes

MCP recipe — canonical Slack/webhook recipe on cdp-functions-create
(products/cdp/mcp/cdp_functions.yaml): filter + input shapes, alert-shaped text/blocks (template
defaults are person-event shaped), idempotency via cdp-functions-list (response now includes filters),
and the $insight_alert_firing property catalog. alert-create / alert-update short-pointer to it;
integrations-channels-retrieve enabled (Slack-only); integrations-list mentions Slack.

Backend (posthog/api/integration.py) — three layered gates on the channels action:
scope_object_read_actions += "channels"; API-key queryset broadened from kind="github" to also allow
slack + slack-posthog-code (serializer still omits sensitive_config); 400 kind guard before
SlackIntegration(). Plus typed response, SlackChannelsRetrieveThrottle (30/min/team), structured
cache-miss logs, capture_exception on Slack errors. template_slack.py channel field prefers ids.

Tests (25/25, posthog/api/test/test_integration.py) — parameterized matrix on the channels action:
scope mismatch → 403, github → 400 (kind guard), twilio → 404 (queryset), slack/slack-posthog-code → 200.
Plus slack retrieve via API key with sensitive_config exclusion; list shows {github, slack}.

How did you test this code?

✅ MCP tools render correctly (incl Slack now)

CleanShot 2026-04-29 at 10 01 20@2x CleanShot 2026-04-29 at 10 08 11@2x

✅ Using the MCP in Claude works to create the alert correctly
CleanShot 2026-04-29 at 10 46 31@2x
CleanShot 2026-04-29 at 10 47 19@2x
CleanShot 2026-04-29 at 10 47 26@2x

Publish to changelog?

Yes

🤖 Agent context

PostHog Code agent.

Earlier branch was abandoned at #56679 due to a token issue blocking the push of the final reset; this branch is the clean rewrite.


Created with PostHog Code

The frontend doesn't have an alert-specific Slack API — it just calls
the existing /hog_functions/ endpoint with a payload that filters on
the alert id. That endpoint is already exposed via MCP as
cdp-functions-create, so the only real gap was discoverability and
finding channel ids.

- Spell out the cdp-functions-create recipe for Slack and webhook
  delivery in the alert-create and alert-update MCP tool descriptions,
  including the exact filter shape and the inputs.slack_workspace /
  inputs.channel keys.
- Mirror the same recipe on cdp-functions-create itself so agents who
  land there understand the alert use case.
- Enable integrations-channels-retrieve so agents can list a Slack
  integration's channels and pick a channel id without the user
  having to dig one up by hand.

Generated-By: PostHog Code
Task-Id: eb2510f9-7b2f-4ad8-8976-a57b9f91eb5b
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 28, 2026

Prompt To Fix All With AI
This is a comment left during a code review.
Path: products/integrations/mcp/tools.yaml
Line: 52-55

Comment:
**Ambiguous "pass the result" guidance**

The description says "pass the result into the `cdp-functions-create` `inputs.channel` field", but the result of this endpoint is a *list* of channels. An agent following this literally might pass the whole collection rather than extracting a single channel's `id`. Consider clarifying to something like "use the channel's `id` value as `inputs.channel`".

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "feat(alerts): document MCP recipe for sl..." | Re-trigger Greptile

@github-actions
Copy link
Copy Markdown
Contributor

MCP UI Apps size report

App JS CSS
debug 290.7 KB 25.8 KB
action 275.4 KB 25.8 KB
action-list 281.5 KB 25.8 KB
cohort 274.5 KB 25.8 KB
cohort-list 280.5 KB 25.8 KB
error-details 283.4 KB 25.8 KB
error-issue 275.1 KB 25.8 KB
error-issue-list 281.4 KB 25.8 KB
experiment 278.8 KB 25.8 KB
experiment-list 282.3 KB 25.8 KB
experiment-results 278.4 KB 25.8 KB
feature-flag 279.3 KB 25.8 KB
feature-flag-list 285.9 KB 25.8 KB
insight-actors 277.5 KB 25.8 KB
llm-costs 280.2 KB 25.8 KB
session-recording 276.3 KB 25.8 KB
survey 276.1 KB 25.8 KB
survey-global-stats 277.7 KB 25.8 KB
survey-list 282.2 KB 25.8 KB
survey-stats 277.7 KB 25.8 KB
workflow 274.9 KB 25.8 KB
workflow-list 280.9 KB 25.8 KB
query-results 289.0 KB 25.8 KB

Comment thread products/integrations/mcp/tools.yaml Outdated
Comment thread products/cdp/mcp/cdp_functions.yaml Outdated
tests-posthog Bot and others added 5 commits April 28, 2026 12:37
Address review-swarm findings on the alert→Slack MCP recipe PR:

- HIGH: `integrations-channels-retrieve` would have 403'd every personal
  API key / OAuth caller. The `channels` action was missing from
  `IntegrationViewSet.scope_object_read_actions`, so `_get_required_scopes`
  returned None and `APIScopePermission` denied access. Added `channels`
  to the read-action list and expanded `safely_get_queryset` to expose
  Slack integrations alongside GitHub for API-key callers — both are
  needed for the MCP recipe (find Slack integration → list channels) to
  work end-to-end.

- MEDIUM: filter recipe in alert-create / cdp-functions-create
  descriptions was missing `type:"events"` on each event object, which
  the actual filter schema requires. Switched the inline examples to
  valid JSON syntax with quoted keys.

- MEDIUM: recipe now spells out the idempotency check — list existing
  internal_destination HogFunctions filtered by alert_id before creating,
  so agent retries don't produce duplicate Slack messages.

- LOW: tightened `integrations-channels-retrieve` description (Slack-only,
  documented 1h cache TTL, expanded the returned channel fields to
  include is_private and is_member). alert-update now points at how to
  locate the existing HogFunction by alert_id. Spelled out the
  HogFunction inputs shape ({"slack_workspace": {"value": <int>}, ...}).

Tests cover both scope and queryset paths: 200 with `integration:read`
scope on a Slack integration, 403 without, 404 for any non-github /
non-slack kind, and the list endpoint now returns both kinds.

Generated-By: PostHog Code
Task-Id: eb2510f9-7b2f-4ad8-8976-a57b9f91eb5b
Address review-swarm follow-up: the previous fix expanded
safely_get_queryset to expose Slack integrations to every API-key /
OAuth caller across list, retrieve, and channels — broader than needed
for the MCP recipe. Narrow it so Slack is only visible on the channels
action, preserving the github-only restriction for list / retrieve.

Update the alert-create recipe to reflect the change: agents must ask
the user for the Slack integration id (visible at /settings/integrations)
rather than discovering it via integrations-list, since the latter still
hides Slack for API-key callers. Update the list-test name and
assertion to lock in the github-only behavior.

Generated-By: PostHog Code
Task-Id: eb2510f9-7b2f-4ad8-8976-a57b9f91eb5b
Address every notable finding from the second review-swarm pass:

HIGH — kind handling for channels action
- Narrow safely_get_queryset to kind__in=["slack", "slack-posthog-code"]
  (was ["github", "slack"] — github passing through resulted in a 500 from
  SlackIntegration's bare Exception, and slack-posthog-code was missing).
- Add an explicit kind guard at the top of the channels action that raises
  ValidationError before constructing SlackIntegration, so any future
  queryset drift surfaces as a clean 400.

HIGH — recipe consolidation and idempotency
- Move the canonical Slack/webhook recipe to cdp-functions-create (the
  tool that actually runs it). alert-create / alert-update now emit a
  short pointer instead of duplicating the recipe.
- Expose `filters` on cdp-functions-list responses (it was already in the
  serializer but missing from the MCP include list), so agents can
  actually dedupe before creating. Recipe now tells agents to call with
  limit=1000 to scan past the default page size.

MEDIUM — observability and blast radius
- Add SlackChannelsRetrieveThrottle (30/min/team) parallel to
  GitHubRepositoryRefreshThrottle, so a misbehaving agent loop can't
  drive 100 sequential Slack API calls × N teams.
- Structured-log cache miss start/finish (integration_id, team_id,
  elapsed_ms, channel_count). capture_exception on Slack failures so
  Slack outages are distinguishable from internal bugs.

MEDIUM — schema accuracy
- Add @extend_schema(responses=SlackChannelsResponseSerializer) to the
  channels action. New SlackChannelSerializer + SlackChannelsResponseSerializer
  document the response shape; the MCP handler return type and the
  integrations-channels-retrieve YAML description now match the actual
  contract (404 for non-Slack, not 400; 30/min rate limit noted).
- Recipe specifies channel id (e.g. C0123ABC) is preferred over
  #channel-name, with both accepted. template_slack.py channel field
  description updated to match. Webhook url placeholder is now
  <destination_url> (https:// required).

MEDIUM — test quality
- Drop test_channels_is_mapped_as_read_action (weak attribute check).
- Replace the two channels tests with one parameterized test covering
  the auth + kind matrix: (slack, integration:read) -> 200, (slack-posthog-code,
  integration:read) -> 200, (slack, feature_flag:read) -> 403,
  (github, integration:read) -> 404, (twilio, integration:read) -> 404.
- Mock list_channels return value now includes is_private_without_access
  and the test asserts it round-trips.

LOW
- Comment near scope_object_read_actions pointing at the queryset coupling.

Generated-By: PostHog Code
Task-Id: eb2510f9-7b2f-4ad8-8976-a57b9f91eb5b
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 28, 2026

Size Change: 0 B

Total Size: 134 MB

ℹ️ View Unchanged
Filename Size
frontend/dist/368Hedgehogs 5.41 kB
frontend/dist/abap 14.2 kB
frontend/dist/AccountConnected 2.89 kB
frontend/dist/Action 24 kB
frontend/dist/Actions 1.16 kB
frontend/dist/AdvancedActivityLogsScene 37.1 kB
frontend/dist/AgenticAuthorize 5.6 kB
frontend/dist/apex 3.99 kB
frontend/dist/ApprovalDetail 16.4 kB
frontend/dist/array.full.es5.js 344 kB
frontend/dist/array.full.js 437 kB
frontend/dist/array.js 189 kB
frontend/dist/AsyncMigrations 13.3 kB
frontend/dist/AuthorizationStatus 867 B
frontend/dist/azcli 885 B
frontend/dist/bat 1.88 kB
frontend/dist/BatchExportScene 60.6 kB
frontend/dist/bicep 2.59 kB
frontend/dist/Billing 629 B
frontend/dist/BillingSection 20.9 kB
frontend/dist/BoxPlot 5.18 kB
frontend/dist/browserAll-0QZMN1W2 37.4 kB
frontend/dist/ButtonPrimitives 698 B
frontend/dist/CalendarHeatMap 4.93 kB
frontend/dist/cameligo 2.23 kB
frontend/dist/changeRequestsLogic 680 B
frontend/dist/CLIAuthorize 11.5 kB
frontend/dist/CLILive 4.16 kB
frontend/dist/clojure 9.68 kB
frontend/dist/coffee 3.63 kB
frontend/dist/Cohort 24.9 kB
frontend/dist/CohortCalculationHistory 6.37 kB
frontend/dist/Cohorts 9.54 kB
frontend/dist/ConfirmOrganization 4.66 kB
frontend/dist/conversations.js 67.2 kB
frontend/dist/Coupons 861 B
frontend/dist/cpp 5.33 kB
frontend/dist/Create 796 B
frontend/dist/crisp-chat-integration.js 1.88 kB
frontend/dist/csharp 4.56 kB
frontend/dist/csp 1.45 kB
frontend/dist/css 4.54 kB
frontend/dist/cssMode 4.2 kB
frontend/dist/CustomCssScene 3.7 kB
frontend/dist/CustomerAnalyticsConfigurationScene 2.21 kB
frontend/dist/CustomerAnalyticsScene 26.7 kB
frontend/dist/CustomerJourneyBuilderScene 1.97 kB
frontend/dist/CustomerJourneyTemplatesScene 7.65 kB
frontend/dist/customizations.full.js 17.9 kB
frontend/dist/CyclotronJobInputAssignee 1.47 kB
frontend/dist/CyclotronJobInputBusinessHours 2.85 kB
frontend/dist/CyclotronJobInputTicketTags 852 B
frontend/dist/cypher 3.42 kB
frontend/dist/dart 4.29 kB
frontend/dist/Dashboard 1.31 kB
frontend/dist/Dashboards 22.2 kB
frontend/dist/DashboardTemplateCopyScene 5.85 kB
frontend/dist/DataManagementScene 782 B
frontend/dist/DataPipelinesNewScene 2.45 kB
frontend/dist/DataWarehouseScene 1.47 kB
frontend/dist/Deactivated 1.27 kB
frontend/dist/dead-clicks-autocapture.js 13.1 kB
frontend/dist/DeadLetterQueue 5.53 kB
frontend/dist/DebugScene 20.1 kB
frontend/dist/decompressionWorker 2.85 kB
frontend/dist/decompressionWorker.js 2.85 kB
frontend/dist/DefinitionEdit 8.71 kB
frontend/dist/DefinitionView 24 kB
frontend/dist/DestinationsScene 2.82 kB
frontend/dist/dist 643 B
frontend/dist/dockerfile 1.91 kB
frontend/dist/EarlyAccessFeature 889 B
frontend/dist/EarlyAccessFeatures 2.99 kB
frontend/dist/ecl 5.38 kB
frontend/dist/EditorScene 1.04 kB
frontend/dist/elixir 10.3 kB
frontend/dist/elk.bundled 1.44 MB
frontend/dist/EmailMFAVerify 3.16 kB
frontend/dist/EndpointScene 39.2 kB
frontend/dist/EndpointsScene 21.5 kB
frontend/dist/ErrorTrackingIssueFingerprintsScene 7.13 kB
frontend/dist/ErrorTrackingIssueScene 99.2 kB
frontend/dist/ErrorTrackingScene 22.7 kB
frontend/dist/EvaluationTemplates 711 B
frontend/dist/EventsScene 2.71 kB
frontend/dist/exception-autocapture.js 11.7 kB
frontend/dist/Experiment 195 kB
frontend/dist/Experiments 18.6 kB
frontend/dist/exporter 21.4 MB
frontend/dist/exporter.js 21.4 MB
frontend/dist/ExportsScene 4.13 kB
frontend/dist/FeatureFlag 131 kB
frontend/dist/FeatureFlags 742 B
frontend/dist/FeatureFlagTemplatesScene 7.18 kB
frontend/dist/FlappyHog 5.92 kB
frontend/dist/flow9 1.85 kB
frontend/dist/freemarker2 16.7 kB
frontend/dist/fsharp 3.02 kB
frontend/dist/go 2.69 kB
frontend/dist/graphql 2.3 kB
frontend/dist/Group 14.9 kB
frontend/dist/Groups 4.05 kB
frontend/dist/GroupsNew 7.49 kB
frontend/dist/handlebars 7.38 kB
frontend/dist/hcl 3.63 kB
frontend/dist/HealthCategoryDetailScene 7.38 kB
frontend/dist/HealthScene 10.7 kB
frontend/dist/HeatmapNewScene 4.76 kB
frontend/dist/HeatmapRecordingScene 4.14 kB
frontend/dist/HeatmapScene 6.77 kB
frontend/dist/HeatmapsScene 4.02 kB
frontend/dist/hls 394 kB
frontend/dist/HogFunctionScene 59.4 kB
frontend/dist/HogRepl 7.51 kB
frontend/dist/html 5.62 kB
frontend/dist/htmlMode 4.65 kB
frontend/dist/image-blob-reduce.esm 49.5 kB
frontend/dist/InboxScene 59.9 kB
frontend/dist/index 258 kB
frontend/dist/index.js 258 kB
frontend/dist/ini 1.14 kB
frontend/dist/InsightQuickStart 5.57 kB
frontend/dist/InsightScene 28.9 kB
frontend/dist/IntegrationsRedirect 874 B
frontend/dist/intercom-integration.js 1.93 kB
frontend/dist/InviteSignup 15.1 kB
frontend/dist/java 3.26 kB
frontend/dist/javascript 1.02 kB
frontend/dist/jsonMode 13.9 kB
frontend/dist/julia 7.26 kB
frontend/dist/kotlin 3.44 kB
frontend/dist/lazy 159 kB
frontend/dist/LegacyPluginScene 20.8 kB
frontend/dist/LegalDocumentNewScene 59.5 kB
frontend/dist/LegalDocumentsScene 4.78 kB
frontend/dist/LemonTextAreaMarkdown 638 B
frontend/dist/less 3.93 kB
frontend/dist/lexon 2.47 kB
frontend/dist/lib 2.25 kB
frontend/dist/Link 604 B
frontend/dist/LinkScene 25 kB
frontend/dist/LinksScene 4.34 kB
frontend/dist/liquid 4.57 kB
frontend/dist/LiveDebugger 19.3 kB
frontend/dist/LiveEventsTable 5.37 kB
frontend/dist/LLMAnalyticsClusterScene 19 kB
frontend/dist/LLMAnalyticsClustersScene 51.9 kB
frontend/dist/LLMAnalyticsDatasetScene 19.8 kB
frontend/dist/LLMAnalyticsDatasetsScene 3.42 kB
frontend/dist/LLMAnalyticsEvaluation 58.9 kB
frontend/dist/LLMAnalyticsEvaluationsScene 30 kB
frontend/dist/LLMAnalyticsPlaygroundScene 37.5 kB
frontend/dist/LLMAnalyticsScene 118 kB
frontend/dist/LLMAnalyticsSessionScene 13.5 kB
frontend/dist/LLMAnalyticsTraceScene 129 kB
frontend/dist/LLMAnalyticsUsers 662 B
frontend/dist/LLMASessionFeedbackDisplay 4.98 kB
frontend/dist/LLMPromptScene 17.7 kB
frontend/dist/LLMPromptsScene 4.62 kB
frontend/dist/LLMSkillScene 725 B
frontend/dist/LLMSkillsScene 742 B
frontend/dist/Login 8.76 kB
frontend/dist/Login2FA 4.39 kB
frontend/dist/logs.js 38.5 kB
frontend/dist/LogsAlertDetailScene 15.7 kB
frontend/dist/LogsAlertNewScene 3.87 kB
frontend/dist/LogsScene 11.5 kB
frontend/dist/lua 2.16 kB
frontend/dist/m3 2.85 kB
frontend/dist/main 819 kB
frontend/dist/ManagedMigration 14.3 kB
frontend/dist/markdown 3.83 kB
frontend/dist/MarketingAnalyticsScene 40.1 kB
frontend/dist/MaterializedColumns 10.3 kB
frontend/dist/Max 937 B
frontend/dist/mdx 5.43 kB
frontend/dist/memlens.lib.bundle 27.9 kB
frontend/dist/MessageTemplate 16.4 kB
frontend/dist/MetricsScene 974 B
frontend/dist/mips 2.62 kB
frontend/dist/ModelsScene 13.8 kB
frontend/dist/MonacoDiffEditor 471 B
frontend/dist/monacoEditorWorker 288 kB
frontend/dist/monacoEditorWorker.js 288 kB
frontend/dist/monacoJsonWorker 419 kB
frontend/dist/monacoJsonWorker.js 419 kB
frontend/dist/monacoTsWorker 7.02 MB
frontend/dist/monacoTsWorker.js 7.02 MB
frontend/dist/MoveToPostHogCloud 4.6 kB
frontend/dist/msdax 4.95 kB
frontend/dist/mysql 11.3 kB
frontend/dist/NavTabChat 4.82 kB
frontend/dist/NewSourceScene 919 B
frontend/dist/NewTabScene 783 B
frontend/dist/NodeDetailScene 16.5 kB
frontend/dist/NotebookCanvasScene 3.58 kB
frontend/dist/NotebookPanel 5.55 kB
frontend/dist/NotebookScene 8.59 kB
frontend/dist/NotebooksScene 7.74 kB
frontend/dist/OAuthAuthorize 709 B
frontend/dist/objective-c 2.44 kB
frontend/dist/Onboarding 734 kB
frontend/dist/OnboardingCouponRedemption 1.34 kB
frontend/dist/pascal 3.03 kB
frontend/dist/pascaligo 2.04 kB
frontend/dist/passkeyLogic 620 B
frontend/dist/PasswordReset 4.5 kB
frontend/dist/PasswordResetComplete 3.13 kB
frontend/dist/PendingDeletion 2.35 kB
frontend/dist/perl 8.29 kB
frontend/dist/PersonScene 18.2 kB
frontend/dist/PersonsScene 4.84 kB
frontend/dist/pgsql 13.5 kB
frontend/dist/php 8.06 kB
frontend/dist/PipelineStatusScene 9.24 kB
frontend/dist/pla 1.72 kB
frontend/dist/posthog 145 kB
frontend/dist/postiats 7.9 kB
frontend/dist/powerquery 17 kB
frontend/dist/powershell 3.31 kB
frontend/dist/PreflightCheck 5.71 kB
frontend/dist/product-tours.js 115 kB
frontend/dist/ProductTour 274 kB
frontend/dist/ProductTours 4.82 kB
frontend/dist/ProjectHomepage 41 kB
frontend/dist/protobuf 9.09 kB
frontend/dist/pug 4.86 kB
frontend/dist/python 4.8 kB
frontend/dist/qsharp 3.23 kB
frontend/dist/QueryPerformance 7.13 kB
frontend/dist/r 3.16 kB
frontend/dist/razor 9.38 kB
frontend/dist/react-json-view 121 kB
frontend/dist/recorder-v2.js 111 kB
frontend/dist/recorder.js 111 kB
frontend/dist/redis 3.59 kB
frontend/dist/redshift 11.8 kB
frontend/dist/RegionMap 29.6 kB
frontend/dist/render-query 21.1 MB
frontend/dist/render-query.js 21.1 MB
frontend/dist/ResourceTransfer 9.32 kB
frontend/dist/restructuredtext 3.94 kB
frontend/dist/RevenueAnalyticsScene 25.8 kB
frontend/dist/ruby 8.54 kB
frontend/dist/rust 4.2 kB
frontend/dist/SavedInsights 800 B
frontend/dist/sb 1.86 kB
frontend/dist/scala 7.36 kB
frontend/dist/schema 696 kB
frontend/dist/SchemaScene 21.1 kB
frontend/dist/scheme 1.8 kB
frontend/dist/scss 6.45 kB
frontend/dist/SdkDoctorScene 9.56 kB
frontend/dist/SessionAttributionExplorerScene 6.77 kB
frontend/dist/SessionGroupSummariesTable 4.77 kB
frontend/dist/SessionGroupSummaryScene 17.1 kB
frontend/dist/SessionProfileScene 15.2 kB
frontend/dist/SessionRecordingDetail 1.9 kB
frontend/dist/SessionRecordingFilePlaybackScene 4.61 kB
frontend/dist/SessionRecordings 878 B
frontend/dist/SessionRecordingsKiosk 8.98 kB
frontend/dist/SessionRecordingsPlaylistScene 4.29 kB
frontend/dist/SessionRecordingsSettingsScene 2.04 kB
frontend/dist/SessionsScene 4.12 kB
frontend/dist/SettingsScene 3.12 kB
frontend/dist/sharedChunkAnchors 235 kB
frontend/dist/sharedChunkAnchors.js 235 kB
frontend/dist/SharedMetric 5.08 kB
frontend/dist/SharedMetrics 685 B
frontend/dist/shell 3.11 kB
frontend/dist/SignupContainer 26 kB
frontend/dist/Site 1.33 kB
frontend/dist/solidity 18.6 kB
frontend/dist/sophia 2.8 kB
frontend/dist/SourceScene 860 B
frontend/dist/SourcesScene 6.1 kB
frontend/dist/sparql 2.59 kB
frontend/dist/sql 10.3 kB
frontend/dist/SqlVariableEditScene 7.39 kB
frontend/dist/st 7.44 kB
frontend/dist/StartupProgram 21.3 kB
frontend/dist/StripeConfirmInstall 3.67 kB
frontend/dist/SubscriptionScene 13.4 kB
frontend/dist/SubscriptionsScene 5.04 kB
frontend/dist/SupportSettingsScene 1.57 kB
frontend/dist/SupportTicketScene 25.9 kB
frontend/dist/SupportTicketsScene 869 B
frontend/dist/Survey 984 B
frontend/dist/SurveyFormBuilder 1.68 kB
frontend/dist/Surveys 18.4 kB
frontend/dist/surveys.js 94.3 kB
frontend/dist/SurveyWizard 72.3 kB
frontend/dist/swift 5.3 kB
frontend/dist/SystemStatus 17 kB
frontend/dist/systemverilog 7.65 kB
frontend/dist/TaskDetailScene 22.5 kB
frontend/dist/TaskTracker 14.3 kB
frontend/dist/tcl 3.61 kB
frontend/dist/TextCardMarkdownEditor 11.1 kB
frontend/dist/toolbar 11 MB
frontend/dist/toolbar.js 11 MB
frontend/dist/ToolbarLaunch 2.66 kB
frontend/dist/tracing-headers.js 1.74 kB
frontend/dist/TracingScene 31.5 kB
frontend/dist/TransformationsScene 2.06 kB
frontend/dist/TrendsLineChart 39 kB
frontend/dist/tsMode 24 kB
frontend/dist/twig 6.01 kB
frontend/dist/TwoFactorReset 4.16 kB
frontend/dist/typescript 274 B
frontend/dist/typespec 2.86 kB
frontend/dist/Unsubscribe 1.8 kB
frontend/dist/UserInterview 4.68 kB
frontend/dist/UserInterviews 2.16 kB
frontend/dist/vb 5.83 kB
frontend/dist/VercelConnect 5.13 kB
frontend/dist/VercelLinkError 2.4 kB
frontend/dist/VerifyEmail 4.92 kB
frontend/dist/vimMode 211 kB
frontend/dist/VisualReviewIndexScene 2.35 kB
frontend/dist/VisualReviewRunScene 42.3 kB
frontend/dist/VisualReviewRunsScene 7.11 kB
frontend/dist/VisualReviewSettingsScene 10.9 kB
frontend/dist/VisualReviewSnapshotHistoryScene 8.23 kB
frontend/dist/VisualReviewSnapshotOverviewScene 17.4 kB
frontend/dist/web-vitals.js 6.39 kB
frontend/dist/WebAnalyticsScene 5.91 kB
frontend/dist/WebGLRenderer-DYjOwNoG 60.4 kB
frontend/dist/WebGPURenderer-B_wkl_Ja 36.3 kB
frontend/dist/WebScriptsScene 2.68 kB
frontend/dist/webworkerAll-puPV1rBA 397 B
frontend/dist/wgsl 7.38 kB
frontend/dist/Wizard 4.59 kB
frontend/dist/WorkflowScene 102 kB
frontend/dist/WorkflowsScene 58.4 kB
frontend/dist/WorldMap 4.91 kB
frontend/dist/xml 3.02 kB
frontend/dist/yaml 4.64 kB

compressed-size-action

vdekrijger and others added 2 commits April 28, 2026 15:52
The previous fix scoped the slack visibility carve-out to only the
channels action, which meant agents had to ask the user for the slack
integration id (integrations-list still hid slack). With the channels
action now carrying its own kind guard, the queryset can safely expose
slack alongside github for list and retrieve too — same security
posture as github (config + display metadata only; access tokens stay
in sensitive_config).

- Collapse the per-action carve-out in safely_get_queryset into a
  single allowlist (github + slack + slack-posthog-code). Removes the
  scope_object_read_actions <-> queryset coupling comment along with
  the conditional.
- integrations-list MCP description: "only GitHub and Slack
  integrations are returned" (was github-only).
- cdp-functions-create recipe: drop the "ask the user" detour, instruct
  agents to call integrations-list (filter by kind=slack) directly.
- integrations-channels-retrieve description: clarify the non-Slack
  failure modes (400 if otherwise visible, 404 if hidden), point at
  integrations-list as the lookup path.
- Tests:
  - Rename test_list_integrations_only_shows_github_for_api_keys_and_hides_slack
    -> test_list_integrations_shows_github_and_slack_for_api_keys.
    Assert {github, slack} kinds visible, twilio still hidden, no
    sensitive_config field round-trips.
  - Add test_retrieve_slack_integration_with_scope_succeeds covering
    /integrations/<slack_id>/ via API key.
  - Update the channels matrix test: github now passes the queryset
    so /channels/ on a github id returns 400 from the kind guard
    (was 404). Twilio remains 404 (still queryset-filtered).

Generated-By: PostHog Code
Task-Id: eb2510f9-7b2f-4ad8-8976-a57b9f91eb5b
@tests-posthog
Copy link
Copy Markdown
Contributor

tests-posthog Bot commented Apr 29, 2026

⏭️ Skipped snapshot commit because branch advanced to 046455c while workflow was testing 8f35a6b.

The new commit will trigger its own snapshot update workflow.

If you expected this workflow to succeed: This can happen due to concurrent commits. To get a fresh workflow run, either:

  • Merge master into your branch, or
  • Push an empty commit: git commit --allow-empty -m 'trigger CI' && git push

vdekrijger and others added 2 commits April 29, 2026 11:55
Backend reliability hardening on the channels action:
- Tenant-isolate cache key (instance.id, not Slack workspace id)
- Allowlist SessionAuthentication for force_refresh (was a denylist;
  future auth classes inherit the safer "ignore force_refresh" default)
- Single-flight lock around the Slack fan-out, with TOCTOU re-check
  after lock acquisition; lock TTL covers worst-case wall time
- Structured log on lock contention so operators can see served-stale
  vs served-empty
- Scope WebClient timeout=10 to list_channels' paginated path only
  (subscriptions, threads, unfurls keep their original behavior)

Recipe corrections in cdp-functions-create:
- Fix state value catalog: actual AlertState is "Firing" (not the
  documented "firing"); event is only emitted on firing transitions
- Recipe step 1 covers the slack-posthog-code variant
- Dedupe wording is precise ("value equal to") instead of ambiguous
- Property catalog adds detector metadata fields with annotations

Tests: new test_channels_action_with_missing_authed_user_returns_400
exercises the authed_user 400 guard that the matrix test mocks past.
@tests-posthog
Copy link
Copy Markdown
Contributor

tests-posthog Bot commented Apr 29, 2026

Query snapshots: Backend query snapshots updated

Changes: 1 snapshots (1 modified, 0 added, 0 deleted)

What this means:

  • Query snapshots have been automatically updated to match current output
  • These changes reflect modifications to database queries or schema

Next steps:

  • Review the query changes to ensure they're intentional
  • If unexpected, investigate what caused the query to change

Review snapshot changes →

…ipe with UI

Strip defense-in-depth layers that were speculative against problems other
layers already cover. Net: simpler code, fewer surprises, codebase consistency
with other Slack callers.

Channels endpoint:
- Drop SlackChannelsRetrieveThrottle. The 1h cache + force_refresh gating to
  cookie-session callers already bound agent-driven cold-cache traffic.
- Drop the locally-scoped WebClient timeout in list_channels. gunicorn's
  request timeout is the real outer bound; per-call slack_sdk default (30s)
  is fine and matches every other PostHog Slack caller.
- Drop the single-flight cache.add lock + TOCTOU re-check + structured cache-
  miss / lock-contended logging. The pre-PR shape (cache.get → call Slack →
  cache.set) ran for years without these; adding observability before there's
  a debugging need is noise.
- Drop the capture_exception wrap on list_channels — DRF's middleware already
  reports unhandled exceptions to Sentry.
- Revert cache key to instance.integration_id. Slack workspace channel data
  is workspace-level, so two PostHog teams sharing one workspace correctly
  share the cache.
- Reword force_refresh comment to call out the MCP/agent context explicitly.

Recipe in cdp-functions-create:
- Align text/blocks with the alert-wizard's HOG_FUNCTION_SUB_TEMPLATES entry
  for insight-alert-firing × template-slack so agent-created alerts produce
  the same Slack message shape as UI-created alerts (header + breach +
  project context + divider + View Insight / View Alert buttons).
- Drop slack-posthog-code mention from recipe step 1 — it's an internal
  variant not customer-facing; backend SLACK_INTEGRATION_KINDS still allows
  both.

Tests:
- Use SLACK_INTEGRATION_KINDS constant in the matrix test instead of the
  literal tuple. Adds the constant to the existing import.

MCP descriptions:
- Drop the rate-limit mention from integrations-channels-retrieve description
  (no longer applicable).
Comment thread posthog/api/integration.py
Snapshot framework correctly flags this as orphaned: the regen tool drops
experiment-unarchive from generated-tool-definitions.json because the
operationId experiments_unarchive_create doesn't exist in the OpenAPI spec
(pre-existing Django/yaml drift, unrelated to this PR). Removing the
orphaned snapshot makes the unit test pass.
…nants

Two PostHog teams that install the same Slack workspace share an integration_id
(the Slack workspace id, e.g. T0123ABC) but have distinct Integration row PKs.
Keying the cache by integration_id meant Team A's cached channels — including
the creator's private channels (gated by should_include_private_channels +
authed_user.users_conversations) — could be served to Team B's request when
both share the workspace. Keying by instance.id closes that cross-tenant gap.
…this PR)

The regen tool drops experiment-unarchive because the operationId
experiments_unarchive_create doesn't exist in the OpenAPI spec — pre-existing
drift between products/experiments/mcp/tools.yaml (enabled, references the
operationId) and the Django side (no matching endpoint). Master's JSON has
the entry from an older regen and we don't want to surface that drift in
this PR's diff.

Surgical restore of the entry in both schema JSONs + the unit-test snapshot.
A separate cleanup ticket should resolve the drift (implement the missing
endpoint, or set enabled: false in the YAML).
@vdekrijger vdekrijger requested a review from pauldambra April 29, 2026 11:07
@vdekrijger vdekrijger changed the title feat(alerts): document MCP recipe for slack/webhook delivery feat(alerts): MCP recipe for slack/webhook delivery Apr 29, 2026
@tests-posthog
Copy link
Copy Markdown
Contributor

tests-posthog Bot commented Apr 29, 2026

Query snapshots: Backend query snapshots updated

Changes: 1 snapshots (1 modified, 0 added, 0 deleted)

What this means:

  • Query snapshots have been automatically updated to match current output
  • These changes reflect modifications to database queries or schema

Next steps:

  • Review the query changes to ensure they're intentional
  • If unexpected, investigate what caused the query to change

Review snapshot changes →

@vdekrijger vdekrijger added stamphog Request AI review from stamphog and removed stamphog Request AI review from stamphog labels Apr 30, 2026
vdekrijger and others added 2 commits April 30, 2026 13:58
…ert-slack-recipe

# Conflicts:
#	posthog/hogql_queries/web_analytics/test/__snapshots__/test_web_stats_table.ambr
@tests-posthog
Copy link
Copy Markdown
Contributor

tests-posthog Bot commented Apr 30, 2026

⏭️ Skipped snapshot commit because branch advanced to c97f76f while workflow was testing c4f2822.

The new commit will trigger its own snapshot update workflow.

If you expected this workflow to succeed: This can happen due to concurrent commits. To get a fresh workflow run, either:

  • Merge master into your branch, or
  • Push an empty commit: git commit --allow-empty -m 'trigger CI' && git push

@posthog
Copy link
Copy Markdown
Contributor

posthog Bot commented Apr 30, 2026

👋 Visual changes detected for this PR.

Review and approve in PostHog Visual Review

If these changes are unexpected, they may be caused by a flaky test or a broken snapshot on master. Don't approve — rerun the job or wait for a fix.

@vdekrijger vdekrijger added the stamphog Request AI review from stamphog label Apr 30, 2026
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security fix for cross-tenant Slack cache key leak is correctly applied (switching from shared integration_id to team-scoped instance.id). All three inline review comments were addressed and resolved. New MCP endpoint is properly scoped with integration:read, Slack-kind guard, and session-only force_refresh. Tests are comprehensive. The team-workflows file changes are documentation-only additions to tool descriptions.

@vdekrijger vdekrijger merged commit 1925aa5 into master Apr 30, 2026
238 checks passed
@vdekrijger vdekrijger deleted the posthog-code/mcp-alert-slack-recipe branch April 30, 2026 13:58
@deployment-status-posthog
Copy link
Copy Markdown

deployment-status-posthog Bot commented Apr 30, 2026

Deploy status

Environment Status Deployed At Workflow
dev ✅ Deployed 2026-04-30 14:27 UTC Run
prod-us ✅ Deployed 2026-04-30 15:18 UTC Run
prod-eu ✅ Deployed 2026-04-30 15:24 UTC Run

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

stamphog Request AI review from stamphog

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant