Add privacy-safe Sentry AI agent monitoring for OpenAI answer calls - #1544
Conversation
- Wrap the OpenAI client with Sentry's instrumentOpenAiClient in a new
observability/agent-monitoring module — metadata only (model, operation,
latency, token usage); recordInputs/recordOutputs stay false so clinical
queries, source evidence, and generated answers never leave the server.
- Gate the wrap on DSN + positive traces sample rate + an initialized Sentry
client, so it is inert in the ingestion worker, tests, and demo mode.
- Allowlist gen_ai metadata attributes in privacySafeTransactionEvent and
rebuild gen_ai span descriptions as "<operation> <model>"; prompt, message,
tool-payload, and embedding-input attributes are stripped on export.
- Set dataCollection.genAI { inputs: false, outputs: false } in the server and
edge Sentry configs as defense in depth.
- Group each answer request's LLM calls into one Sentry conversation via
Sentry.setConversationId(interactionId) in /api/answer and /api/answer/stream.
- Raise the @sentry/nextjs floor to ^10.67.0 (agent-monitoring APIs; 10.69.0
installed) and sync the lockfile.
- Unit tests for the gen_ai scrubbing boundary and the monitoring gate; docs
updated (docs/error-tracking.md, docs/codebase-index.md).
Sentry.setUser is deliberately not wired: the committed privacy boundary
strips user from every outgoing event, and identity-linking clinical query
telemetry needs its own governance review.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SBBj97cbs3rNGk8BX3g1CVCo-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SBBj97cbs3rNGk8BX3g1CV
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in:50 minutes Your organization has reached its usage spending cap. Adjust your spending cap in the billing tab. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (13)
Comment |
This pull request has been ignored for the connected project Preview Branches by Supabase. |
🔒 Upgrade RequiredPrivate repository analysis requires Pro or Enterprise. Upgrade: https://ecc.tools/pricing?plan=pro ECC Tools keeps the core app open, and puts private repos, team features, and enterprise controls behind paid tiers. |
CI triageCI failed on this PR. Automated classification of the 8 failed job(s):
Compared with main CI run #7634 (cancelled). Classification is evidence routing, not permission to ignore a failure. Exact quarantined Playwright identities remain governed by the flake ledger. |
npm 11.6.2's install/package-lock-only regeneration prunes the @emnapi/core and @emnapi/runtime entries (optional wasm32-wasi deps of @tailwindcss/oxide / @napi-rs/wasm-runtime) that its own npm ci then reports as "Missing ... from lock file", failing every CI job at the setup step. Keep origin/main's lockfile byte-identical except the root "@sentry/nextjs" range, which must mirror package.json's ^10.67.0 for npm ci's sync check. Validated with npm ci --dry-run (exit 0), a full npm ci reinstall, and check:installed-lock-parity. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SBBj97cbs3rNGk8BX3g1CV
🔒 Upgrade RequiredPrivate repository analysis requires Pro or Enterprise. Upgrade: https://ecc.tools/pricing?plan=pro ECC Tools keeps the core app open, and puts private repos, team features, and enterprise controls behind paid tiers. |
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Qodo reviews are paused for this user.Troubleshooting steps vary by plan Learn more → On a Teams plan? Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center? |
🔒 Upgrade RequiredPrivate repository analysis requires Pro or Enterprise. Upgrade: https://ecc.tools/pricing?plan=pro ECC Tools keeps the core app open, and puts private repos, team features, and enterprise controls behind paid tiers. |
🔒 Upgrade RequiredPrivate repository analysis requires Pro or Enterprise. Upgrade: https://ecc.tools/pricing?plan=pro ECC Tools keeps the core app open, and puts private repos, team features, and enterprise controls behind paid tiers. |
Uh oh!
There was an error while loading. Please reload this page.
Summary
instrumentOpenAiClientin a newsrc/lib/observability/agent-monitoring.tsmodule so Sentry's AI agents views show per-call operation, model, latency, and token usage.recordInputs/recordOutputsare false: clinical queries, source evidence, prompts, generated answers, and embedding inputs are never recorded.SENTRY_DSNbeing set, a positive traces sample rate, and an initialized Sentry client, so it is inert in the ingestion worker, in Vitest, and in demo/dev mode without Sentry configuration.privacySafeTransactionEventwith an explicit allowlist of gen_ai metadata attributes (system, operation name, request/response model, response id, finish reasons, token usage, conversation id) and rebuild gen_ai span descriptions as<operation> <model>from allowlisted attributes; message, prompt, tool-payload, and embedding-input attributes are stripped on export even if a future SDK version records them.dataCollection.genAI: { inputs: false, outputs: false }in bothsrc/sentry.server.config.tsandsrc/sentry.edge.config.tsas defense in depth.Sentry.setConversationId(interactionId)in/api/answerand/api/answer/stream— the id is the request's synthetic UUID, never query text.@sentry/nextjsmanifest floor from^10.17.0to^10.67.0(the minimum carrying the agent-monitoring APIs; 10.69.0 is installed and pinned in the lockfile) and syncpackage-lock.json(npm also normalized pre-existing@emnapi/*optional-dep drift).Sentry.setUseris deliberately not wired: the committed privacy boundary (tests/error-tracking.test.ts) assertsuseris stripped from every outgoing event, and identity-linking clinical-query telemetry would need its own governance review first.docs/error-tracking.mdanddocs/codebase-index.mdare updated.SENTRY_DSN(and optionally raiseSENTRY_TRACES_SAMPLE_RATEabove the 0.1 default) in the Railway service environment per the operator-approval section ofdocs/error-tracking.md. No DSN is committed to the repository.RAG impact: no retrieval behaviour change — instrumentation-only telemetry wrapper around the OpenAI client and request-scoped conversation ids; no ranking, selection, ordering, or eval surface is touched, and no ragRanking-protected path is in the diff.
Verification
npm run verify:pr-local— exit 0; plan rancheck:runtime,check:installed-lock-parity,format:changed,lint,typecheck,test,build,eval:rag:offline; decisive lines:Offline RAG fixture and manifest validation passed (36 golden cases, 23 suites).andOffline RAG fixture and production-contract checks passed.npm run verify:cheap— exit 0;Gate-manifest OK: all 32 verify:cheap gates are enforced in CI; unit suiteTest Files 458 passed (458) / Tests 4781 passed | 4 skipped (4785)npx vitest run tests/error-tracking.test.ts tests/agent-monitoring.test.ts—Test Files 2 passed (2) / Tests 9 passed (9)UI verification not run: no UI, routing, styling, or browser-facing change — the diff is server-side observability, API-route scope calls, tests, and docs.
npm run eval:retrieval:quality/eval:rag/check:production-readinessnot run: provider-backed live gates requiring explicit approval; no retrieval, ranking, or answer-content behaviour changed (offline RAG fixture validation passed inverify:pr-local).Risk and rollout
SENTRY_TRACES_SAMPLE_RATE=0(stops all agent spans, keeps error capture) or unsetSENTRY_DSN(stops all Sentry export) and restart the service.SENTRY_DSNin the deployment environment.Clinical Governance Preflight
Clinical KB Database(sjrfecxgysukkwxsowpy)Notes
responses.parse(schema-parsed generation) is not in the Sentry SDK's instrumentation registry and emits no gen_ai span;responses.createandembeddings.createare covered.ConversationIddefault integration stampsgen_ai.conversation.idonto gen_ai spans from the isolation scope, which is why the attribute is in the scrubber allowlist.src/lib/openai.ts; the client gate (Sentry.getClient()) keeps the wrap a no-op there because the worker never runsSentry.init().🤖 Generated with Claude Code
https://claude.ai/code/session_01SBBj97cbs3rNGk8BX3g1CV
Generated by Claude Code