Skip to content

AGENTS.md

124 lines · 4.1 KB · Markdown
Raw

@kody/sentry — agent notes

Human setup and intent live in 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

LaneCredentialNotes
Preferreduser secret sentryAuthTokenBearer for all REST calls; host-approve sentry.io (and region hosts)
OptionalOAuth integration sentryBYO 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

ExportImport
package overviewkody:@kody/sentry
list-organizationskody:@kody/sentry/list-organizations
list-projectskody:@kody/sentry/list-projects
resolve-projectkody:@kody/sentry/resolve-project
search-issueskody:@kody/sentry/search-issues
get-issuekody:@kody/sentry/get-issue
get-latest-issue-eventkody:@kody/sentry/get-latest-issue-event
get-issue-eventskody:@kody/sentry/get-issue-events
summarize-issue-eventkody:@kody/sentry/summarize-issue-event
triage-issuekody:@kody/sentry/triage-issue
requestkody:@kody/sentry/request
smoke-testkody:@kody/sentry/smoke-test

Prefer static kody:@kody/sentry/... imports from execute. Do not lead with packages.invoke.

Smoke tests (read-only)

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):

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):

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:

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.

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:<name>}} 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.