Sentry Integration Expertise
Directive knowledge for integrating Sentry error tracking into GainInsight projects, including SDK setup, webhook-driven auto-fix agent pipelines, and per-project configuration.
When to Use This Skill
Load this skill when:
- Setting up Sentry SDK in a new project (Next.js, Node, React, Python)
- Configuring webhook integration for auto-fix agents (Holly pipeline)
- Managing Sentry internal integrations via API
- Configuring per-project error thresholds and auto-fix settings
- Troubleshooting webhook delivery, signature verification, or agent spawning
- Querying Sentry errors or issues via API
Organisation
- Org:
gain-insight
- Region: EU (Germany) —
de.sentry.io
- Team:
gain-insight
- Dashboard:
https://gain-insight.sentry.io
Rules (FOLLOW THESE)
API Rules
- MUST use
de.sentry.io for all API calls — the org is EU-region hosted
- MUST use PAT from Doppler (
doppler secrets get SENTRY_AUTH_TOKEN --project gi --config prd --plain) — never the MCP token
- MUST NOT expose DSNs in logs — they contain ingest keys
- MUST use
sentry.io (US endpoint) for internal integration CRUD — this is a Sentry API quirk
Webhook Rules
- MUST verify HMAC-SHA256 signature using
sentry-hook-signature header and crypto.timingSafeEqual()
- MUST fail closed — reject webhooks when secret is unset in production (
NODE_ENV=production)
- MUST deduplicate by
sentry_issue_id — use a unique partial index excluding archived agents
- MUST handle race conditions — catch unique constraint violations (PostgreSQL 23505) gracefully
- SHOULD use
async fetch() for all HTTP calls in webhook handlers — never execFileSync('curl')
Configuration Rules
- MUST add
sentry config to project's config_json when enabling for a new project
- MUST set
enabled: true explicitly — missing config means disabled
- SHOULD set
min_count: 1 for new projects to catch errors early
- SHOULD default
min_level to error — only error and fatal spawn agents
- MUST set
auto_fix: false for alert-only mode (Linear issue created but no agent spawned)
SDK Rules
- MUST install platform-specific SDK (e.g.,
@sentry/nextjs, @sentry/node, @sentry/react)
- SHOULD enable Session Replay on client-side (10% normal, 100% on error)
- SHOULD follow the Andon pattern for Next.js SDK integration (see Workflows)
Quick Reference
Webhook Pipeline
Sentry Issue → Webhook (HMAC-SHA256) → Coordinator → Filter → Linear Issue → Agent Spawn
Severity Levels
| Level |
Value |
Default Action |
debug |
0 |
Ignored |
info |
1 |
Ignored |
warning |
2 |
Ignored |
error |
3 |
Spawn agent (if enabled) |
fatal |
4 |
Spawn agent (Urgent priority) |
Unknown levels default to 0 (never trigger unless threshold is debug).
Per-Project Config Schema
{
"sentry": {
"enabled": true,
"project_slug": "my-project",
"min_level": "error",
"min_count": 1,
"auto_fix": true
}
}
Store in projects.config_json column.
Linear Priority Mapping
| Sentry Level |
Linear Priority |
fatal |
1 (Urgent) |
error |
2 (High) |
| Other |
2 (High) |
Default Assignee
Sentry-created Linear issues are auto-assigned to Andy Davidson (4ea0cf3c-49f4-42a6-ab7d-01f2c95af853) by default. This is set via SENTRY_DEFAULT_ASSIGNEE_ID in the coordinator's watcher.ts. The createSentryLinearIssue function accepts an optional assigneeId parameter to override per-call.
Workflows
Workflow: SDK Setup (Next.js)
When: Adding Sentry to a new Next.js project
Steps:
- Install SDK:
npm install @sentry/nextjs
- Create files:
next.config.ts — Wrap with withSentryConfig
instrumentation.ts — Server/edge init with DSN
instrumentation-client.ts — Client init with replay (10% normal, 100% error)
src/app/global-error.tsx — Error boundary component
- Get DSN via API:
curl -s -H "Authorization: Bearer ${SENTRY_TOKEN}" \
"https://de.sentry.io/api/0/projects/gain-insight/{slug}/keys/"
- Hardcode DSN in instrumentation files (not env var — it's public and baked at build time)
- Set webpack config:
org: "gain-insight", project: "{slug}"
- Test: throw a test error, verify it appears in Sentry dashboard
Success criteria:
- Errors appear in Sentry dashboard within 30 seconds
- Source maps upload correctly
- Session replay captures user interactions
Workflow: Enable Webhook Auto-Fix for a Project
When: Connecting an existing Sentry project to the Holly auto-fix pipeline
Steps:
- Ensure Sentry internal integration exists with correct webhook URL
- Update project config in database:
UPDATE projects SET config_json = jsonb_set(
COALESCE(config_json, '{}'),
'{sentry}',
'{"enabled": true, "project_slug": "my-slug", "min_level": "error", "min_count": 1, "auto_fix": true}'
) WHERE project_key = 'my-project';
- Verify via dashboard status endpoint:
GET /api/sentry/status
- Test with dry-run:
POST /api/sentry/test-webhook with project slug
- Verify test creates Linear issue and spawns agent (or dry-run passes all checks)
Success criteria:
- Status endpoint shows project with
enabled: true
- Test webhook creates Linear issue with correct priority
- Agent spawns with
workflow_type: 'sentry-fix'
Workflow: Create Internal Integration (API)
When: Setting up the webhook receiver for the first time or rotating secrets
Steps:
- Create integration via US endpoint (Sentry API quirk):
SENTRY_TOKEN=$(doppler secrets get SENTRY_AUTH_TOKEN --project gi --config prd --plain)
curl -s -X POST \
-H "Authorization: Bearer ${SENTRY_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"name": "Holly Agent Integration",
"scopes": ["event:read"],
"events": ["issue"],
"webhookUrl": "https://{coordinator-host}/webhooks/sentry",
"isInternal": true,
"verifyInstall": false
}' \
"https://sentry.io/api/0/sentry-apps/"
- Save
clientSecret from response as SENTRY_WEBHOOK_SECRET
- Store secret in Doppler and AWS Secrets Manager
- Force-redeploy coordinator to pick up new secret
- Verify: send test webhook, expect 200 (not 401)
Success criteria:
- Integration appears in Sentry Settings > Developer Settings
- Webhook receives valid HMAC signatures
- Coordinator verifies signatures and processes events
Workflow: Troubleshoot Webhook Delivery
When: Webhooks are not being processed or returning errors
Steps:
- Check integration exists:
GET https://de.sentry.io/api/0/sentry-apps/
- Check webhook URL is correct in integration settings
- Verify ALB/proxy routing: webhook path (
/webhooks/sentry) must route to coordinator port (not API server)
- Verify secret matches: compare Doppler/Secrets Manager value with integration's
clientSecret
- Check coordinator logs for signature verification errors
- Send manual test with valid HMAC:
SECRET="..."; BODY='{"action":"created","data":{...}}'
SIG=$(echo -n "$BODY" | openssl dgst -sha256 -hmac "$SECRET" | awk '{print $2}')
curl -X POST -H "Content-Type: application/json" \
-H "sentry-hook-signature: $SIG" \
-d "$BODY" "https://{coordinator-host}/webhooks/sentry"
- Check response: 200 = processed, 401 = bad signature, 500 = handler error
Success criteria:
- Webhook returns 200 with
{"handled": true} or {"handled": false, "reason": "..."}
- Reason messages explain filtering decisions clearly
Database Schema
Required Columns (tasks table)
ALTER TABLE tasks ADD COLUMN sentry_issue_id TEXT;
ALTER TABLE tasks ADD COLUMN sentry_event_id TEXT;
Dedup Index
CREATE UNIQUE INDEX idx_tasks_sentry_dedup
ON tasks (sentry_issue_id)
WHERE sentry_issue_id IS NOT NULL
AND agent_status NOT IN ('archived');
Prevents duplicate active agents for the same Sentry issue. Archived agents don't count.
Environment Variables
| Variable |
Location |
Purpose |
SENTRY_AUTH_TOKEN |
Doppler gi/prd |
Full-access PAT for API operations |
SENTRY_DSN |
Per-project Doppler |
Error tracking ingest endpoint |
SENTRY_WEBHOOK_SECRET |
Doppler + AWS SM |
HMAC signature verification |
Essential Reading
Remember:
- EU region =
de.sentry.io for API, but sentry.io for integration CRUD
- Webhook secret comes from integration's
clientSecret, not a separate API key
- Always verify HMAC with
timingSafeEqual — never string comparison
- Fatal = Urgent priority, everything else = High
- Unknown severity levels default to 0 (safest default)
- Dedup by
sentry_issue_id with partial unique index excluding archived agents
1---2name: af-sentry-expertise3description: Use when integrating Sentry error tracking into a project — SDK setup, webhook-driven auto-fix agents, per-project configuration, and internal integration management.4---5
6# Sentry Integration Expertise
7
8Directive knowledge for integrating Sentry error tracking into GainInsight projects, including SDK setup, webhook-driven auto-fix agent pipelines, and per-project configuration.
9
10## When to Use This Skill
11
12Load this skill when:
13- Setting up Sentry SDK in a new project (Next.js, Node, React, Python)
14- Configuring webhook integration for auto-fix agents (Holly pipeline)
15- Managing Sentry internal integrations via API
16- Configuring per-project error thresholds and auto-fix settings
17- Troubleshooting webhook delivery, signature verification, or agent spawning
18- Querying Sentry errors or issues via API
19
20## Organisation
21
22- **Org**: `gain-insight`
23- **Region**: EU (Germany) — `de.sentry.io`
24- **Team**: `gain-insight`
25- **Dashboard**: `https://gain-insight.sentry.io`
26
27## Rules (FOLLOW THESE)
28
29### API Rules
301. **MUST use `de.sentry.io`** for all API calls — the org is EU-region hosted
312. **MUST use PAT from Doppler** (`doppler secrets get SENTRY_AUTH_TOKEN --project gi --config prd --plain`) — never the MCP token
323. **MUST NOT expose DSNs in logs** — they contain ingest keys
334. **MUST use `sentry.io`** (US endpoint) for internal integration CRUD — this is a Sentry API quirk
34
35### Webhook Rules
365. **MUST verify HMAC-SHA256 signature** using `sentry-hook-signature` header and `crypto.timingSafeEqual()`
376. **MUST fail closed** — reject webhooks when secret is unset in production (`NODE_ENV=production`)
387. **MUST deduplicate** by `sentry_issue_id` — use a unique partial index excluding archived agents
398. **MUST handle race conditions** — catch unique constraint violations (PostgreSQL 23505) gracefully
409. **SHOULD use `async fetch()`** for all HTTP calls in webhook handlers — never `execFileSync('curl')`
41
42### Configuration Rules
4310. **MUST add `sentry` config to project's `config_json`** when enabling for a new project
4411. **MUST set `enabled: true`** explicitly — missing config means disabled
4512. **SHOULD set `min_count: 1`** for new projects to catch errors early
4613. **SHOULD default `min_level` to `error`** — only `error` and `fatal` spawn agents
4714. **MUST set `auto_fix: false`** for alert-only mode (Linear issue created but no agent spawned)
48
49### SDK Rules
5015. **MUST install platform-specific SDK** (e.g., `@sentry/nextjs`, `@sentry/node`, `@sentry/react`)
5116. **SHOULD enable Session Replay** on client-side (10% normal, 100% on error)
5217. **SHOULD follow the Andon pattern** for Next.js SDK integration (see Workflows)
53
54---
55
56## Quick Reference
57
58### Webhook Pipeline
59
60```
61Sentry Issue → Webhook (HMAC-SHA256) → Coordinator → Filter → Linear Issue → Agent Spawn
62```
63
64### Severity Levels
65
66| Level | Value | Default Action |
67|-------|-------|----------------|
68| `debug` | 0 | Ignored |
69| `info` | 1 | Ignored |
70| `warning` | 2 | Ignored |
71| `error` | 3 | Spawn agent (if enabled) |
72| `fatal` | 4 | Spawn agent (Urgent priority) |
73
74Unknown levels default to 0 (never trigger unless threshold is `debug`).
75
76### Per-Project Config Schema
77
78```json
79{
80 "sentry": {
81 "enabled": true,
82 "project_slug": "my-project",
83 "min_level": "error",
84 "min_count": 1,
85 "auto_fix": true
86 }
87}
88```
89
90Store in `projects.config_json` column.
91
92### Linear Priority Mapping
93
94| Sentry Level | Linear Priority |
95|-------------|-----------------|
96| `fatal` | 1 (Urgent) |
97| `error` | 2 (High) |
98| Other | 2 (High) |
99
100### Default Assignee
101
102Sentry-created Linear issues are auto-assigned to **Andy Davidson** (`4ea0cf3c-49f4-42a6-ab7d-01f2c95af853`) by default. This is set via `SENTRY_DEFAULT_ASSIGNEE_ID` in the coordinator's `watcher.ts`. The `createSentryLinearIssue` function accepts an optional `assigneeId` parameter to override per-call.
103
104---
105
106## Workflows
107
108### Workflow: SDK Setup (Next.js)
109
110**When:** Adding Sentry to a new Next.js project
111
112**Steps:**
1131. Install SDK: `npm install @sentry/nextjs`
1142. Create files:
115 - `next.config.ts` — Wrap with `withSentryConfig`
116 - `instrumentation.ts` — Server/edge init with DSN
117 - `instrumentation-client.ts` — Client init with replay (10% normal, 100% error)
118 - `src/app/global-error.tsx` — Error boundary component
1193. Get DSN via API:
120 ```bash
121 curl -s -H "Authorization: Bearer ${SENTRY_TOKEN}" \
122 "https://de.sentry.io/api/0/projects/gain-insight/{slug}/keys/"
123 ```
1244. Hardcode DSN in instrumentation files (not env var — it's public and baked at build time)
1255. Set webpack config: `org: "gain-insight"`, `project: "{slug}"`
1266. Test: throw a test error, verify it appears in Sentry dashboard
127
128**Success criteria:**
129- Errors appear in Sentry dashboard within 30 seconds
130- Source maps upload correctly
131- Session replay captures user interactions
132
133---
134
135### Workflow: Enable Webhook Auto-Fix for a Project
136
137**When:** Connecting an existing Sentry project to the Holly auto-fix pipeline
138
139**Steps:**
1401. Ensure Sentry internal integration exists with correct webhook URL
1412. Update project config in database:
142 ```sql
143 UPDATE projects SET config_json = jsonb_set(
144 COALESCE(config_json, '{}'),
145 '{sentry}',
146 '{"enabled": true, "project_slug": "my-slug", "min_level": "error", "min_count": 1, "auto_fix": true}'
147 ) WHERE project_key = 'my-project';
148 ```
1493. Verify via dashboard status endpoint: `GET /api/sentry/status`
1504. Test with dry-run: `POST /api/sentry/test-webhook` with project slug
1515. Verify test creates Linear issue and spawns agent (or dry-run passes all checks)
152
153**Success criteria:**
154- Status endpoint shows project with `enabled: true`
155- Test webhook creates Linear issue with correct priority
156- Agent spawns with `workflow_type: 'sentry-fix'`
157
158---
159
160### Workflow: Create Internal Integration (API)
161
162**When:** Setting up the webhook receiver for the first time or rotating secrets
163
164**Steps:**
1651. Create integration via US endpoint (Sentry API quirk):
166 ```bash
167 SENTRY_TOKEN=$(doppler secrets get SENTRY_AUTH_TOKEN --project gi --config prd --plain)
168 curl -s -X POST \
169 -H "Authorization: Bearer ${SENTRY_TOKEN}" \
170 -H "Content-Type: application/json" \
171 -d '{
172 "name": "Holly Agent Integration",
173 "scopes": ["event:read"],
174 "events": ["issue"],
175 "webhookUrl": "https://{coordinator-host}/webhooks/sentry",
176 "isInternal": true,
177 "verifyInstall": false
178 }' \
179 "https://sentry.io/api/0/sentry-apps/"
180 ```
1812. Save `clientSecret` from response as `SENTRY_WEBHOOK_SECRET`
1823. Store secret in Doppler and AWS Secrets Manager
1834. Force-redeploy coordinator to pick up new secret
1845. Verify: send test webhook, expect 200 (not 401)
185
186**Success criteria:**
187- Integration appears in Sentry Settings > Developer Settings
188- Webhook receives valid HMAC signatures
189- Coordinator verifies signatures and processes events
190
191---
192
193### Workflow: Troubleshoot Webhook Delivery
194
195**When:** Webhooks are not being processed or returning errors
196
197**Steps:**
1981. Check integration exists: `GET https://de.sentry.io/api/0/sentry-apps/`
1992. Check webhook URL is correct in integration settings
2003. Verify ALB/proxy routing: webhook path (`/webhooks/sentry`) must route to coordinator port (not API server)
2014. Verify secret matches: compare Doppler/Secrets Manager value with integration's `clientSecret`
2025. Check coordinator logs for signature verification errors
2036. Send manual test with valid HMAC:
204 ```bash
205 SECRET="..."; BODY='{"action":"created","data":{...}}'
206 SIG=$(echo -n "$BODY" | openssl dgst -sha256 -hmac "$SECRET" | awk '{print $2}')
207 curl -X POST -H "Content-Type: application/json" \
208 -H "sentry-hook-signature: $SIG" \
209 -d "$BODY" "https://{coordinator-host}/webhooks/sentry"
210 ```
2117. Check response: 200 = processed, 401 = bad signature, 500 = handler error
212
213**Success criteria:**
214- Webhook returns 200 with `{"handled": true}` or `{"handled": false, "reason": "..."}`
215- Reason messages explain filtering decisions clearly
216
217---
218
219## Database Schema
220
221### Required Columns (tasks table)
222
223```sql
224ALTER TABLE tasks ADD COLUMN sentry_issue_id TEXT;
225ALTER TABLE tasks ADD COLUMN sentry_event_id TEXT;
226```
227
228### Dedup Index
229
230```sql
231CREATE UNIQUE INDEX idx_tasks_sentry_dedup
232 ON tasks (sentry_issue_id)
233 WHERE sentry_issue_id IS NOT NULL
234 AND agent_status NOT IN ('archived');
235```
236
237Prevents duplicate active agents for the same Sentry issue. Archived agents don't count.
238
239---
240
241## Environment Variables
242
243| Variable | Location | Purpose |
244|----------|----------|---------|
245| `SENTRY_AUTH_TOKEN` | Doppler `gi/prd` | Full-access PAT for API operations |
246| `SENTRY_DSN` | Per-project Doppler | Error tracking ingest endpoint |
247| `SENTRY_WEBHOOK_SECRET` | Doppler + AWS SM | HMAC signature verification |
248
249---
250
251## Essential Reading
252
253- [Sentry Developer Docs: Internal Integrations](https://docs.sentry.io/organization/integrations/integration-platform/internal-integration/)
254- [Sentry Webhook Events](https://docs.sentry.io/organization/integrations/integration-platform/webhooks/)
255- [af-security-expertise](../af-security-expertise/SKILL.md) — Related security patterns
256
257---
258
259**Remember:**
2601. EU region = `de.sentry.io` for API, but `sentry.io` for integration CRUD
2612. Webhook secret comes from integration's `clientSecret`, not a separate API key
2623. Always verify HMAC with `timingSafeEqual` — never string comparison
2634. Fatal = Urgent priority, everything else = High
2645. Unknown severity levels default to 0 (safest default)
2656. Dedup by `sentry_issue_id` with partial unique index excluding archived agents