# @kody/sentry — agent notes Human setup and intent live in [`README.md`](./README.md). This file is for agents: imports, smoke/dryRun execute snippets, and edge cases. Secrets by **name** only — never paste token values. Do not disable live webhooks or jobs in dependent packages. ## Auth | Lane | Credential | Notes | | --- | --- | --- | | Preferred | user secret `sentryAuthToken` | Bearer for all REST calls; host-approve `sentry.io` (and region hosts) | | Optional | OAuth integration `sentry` | BYO Sentry OAuth app; pass `integration: 'sentry'` | Multi-account: `secretName: 'sentryAuthTokenWork'` or `integration: 'sentry-work'`. Pass `host` for `us.sentry.io`, `de.sentry.io`, or self-hosted HTTPS hosts. ## Import paths | Export | Import | | --- | --- | | package overview | `kody:@kody/sentry` | | list-organizations | `kody:@kody/sentry/list-organizations` | | list-projects | `kody:@kody/sentry/list-projects` | | resolve-project | `kody:@kody/sentry/resolve-project` | | search-issues | `kody:@kody/sentry/search-issues` | | get-issue | `kody:@kody/sentry/get-issue` | | get-latest-issue-event | `kody:@kody/sentry/get-latest-issue-event` | | get-issue-events | `kody:@kody/sentry/get-issue-events` | | summarize-issue-event | `kody:@kody/sentry/summarize-issue-event` | | triage-issue | `kody:@kody/sentry/triage-issue` | | request | `kody:@kody/sentry/request` | | smoke-test | `kody:@kody/sentry/smoke-test` | Prefer static `kody:@kody/sentry/...` imports from `execute`. Do not lead with `packages.invoke`. ## Smoke tests (read-only) ```ts import smokeTest from 'kody:@kody/sentry/smoke-test' export default async function main() { return await smokeTest() // without secret => { ok: true, live: false, setup: { nextSteps } } // with secret => { ok: true, live: true, organizations: [...] } } ``` List orgs (proves secret + host approval): ```ts import listOrganizations from 'kody:@kody/sentry/list-organizations' export default async function main() { return await listOrganizations() } ``` Search unresolved (bounded — use the caller's org slug, never a shared one): ```ts import searchIssues from 'kody:@kody/sentry/search-issues' export default async function main() { return await searchIssues({ orgSlug: 'acme', query: 'is:unresolved', statsPeriod: '14d', limit: 5, }) } ``` Triage one issue: ```ts import triageIssue from 'kody:@kody/sentry/triage-issue' export default async function main() { return await triageIssue({ issueId: '1234567890', recentEventLimit: 3 }) } ``` ## dryRun writes (`request`) `GET` / `HEAD` / `OPTIONS` always execute. Other methods default to `{ dryRun: true, wouldCall }` until `dryRun: false`. ```ts import sentryRequest from 'kody:@kody/sentry/request' export default async function main() { const preview = await sentryRequest({ path: '/issues/1234567890/', init: { method: 'PUT', body: JSON.stringify({ status: 'resolved' }) }, }) // => { dryRun: true, wouldCall: { method: 'PUT', path: '/issues/1234567890/', ... } } // Only after explicit user confirmation: const resolved = await sentryRequest({ path: '/issues/1234567890/', init: { method: 'PUT', body: JSON.stringify({ status: 'resolved' }) }, dryRun: false, }) return { preview, resolved } } ``` ## Edge cases / fork notes - `path` on `request` must start with `/`. - `search-issues`: `paginated: true` returns `{ issues, nextCursor, previousCursor }`; `includeLatestSummaries: true` attaches `latestEventSummary` per issue. - `resolve-project` accepts `projectSlug` or `projectId` with `orgSlug`. - `summarize-issue-event` accepts a raw `event`, or `issueId` (optionally with `latest: true`) to fetch then summarize. - Helpers project slim objects for triage. Use `./request` for unwrapped REST. - Never echo a resolvable `{{secret:}}` placeholder into logs or returned strings. - After fork, save **the caller's** token — do not treat live `@kody/sentry` as bound to your org. Faster MCP onboarding: `@kody/sentry-mcp`. - Do not rotate `sentryAuthToken` or revoke host approval without an explicit ask when dependents (for example triage jobs) may rely on it.