All jobs

Turn Sentry Errors Into Fix Pull Requests for a Hono App

Yes. An agent reads the Sentry issue, reproduces the failing Hono route in a Workers Vitest test, fixes the handler and opens a pull request that links the issue.

Run this on RushIn a Project that has your repository.

What the agent does

The agent reads the alert payload after the prompt, then fetches the issue and its latest event through the Sentry connection: the exception type and message, the request method and URL, the tags for release and environment, and the in-app stack frames. For a Worker the frames point at the bundled script, so the agent keeps the message and route and matches them to source rather than to a line number.

In a repository like honojs/examples the blog example is a Cloudflare Worker in blog/, with hono pinned to ^4.2.4 and wrangler, vitest 1.3.0 and @cloudflare/vitest-pool-workers as dev dependencies; blog/vitest.config.ts uses defineWorkersConfig with isolatedStorage: false and the wrangler.toml that wrangler.example.toml becomes, which binds the KV namespace BLOG_EXAMPLE. blog/src/index.ts mounts a basic-auth middleware on every non-GET under /api/posts/* using USERNAME and PASSWORD from the bindings, then mounts the API; blog/src/api.ts defines GET /posts, POST /posts, GET /posts/:id, PUT /posts/:id and DELETE /posts/:id; and blog/src/model.ts stores each post under a v1:post: key as JSON.

A Sentry issue on this app almost always lands in one of a few places the agent reads first. POST /posts and PUT /posts/:id call await c.req.json() with no guard, so a request with a malformed body or the wrong content type throws before model.createPost can answer 422. getPosts in model.ts calls JSON.parse on every value it lists, so one hand-edited KV value breaks the whole list. PUT and DELETE return a bare 204 for a missing post where every other route returns JSON, which a client that always parses the body turns into an exception of its own.

The agent writes the reproduction in blog/src/api.test.ts, which already drives the app with worker.request('/posts', …, env) and the env from cloudflare:test, adds a case that sends the failing request and asserts the status the route should return, and watches it fail with the Sentry message. It then fixes the handler, for example by catching the parse error and answering 400 with { error, ok: false }, runs npm test in blog/, which is vitest --run, and npx tsc --noEmit against blog/tsconfig.json, and opens a pull request that links the Sentry issue and quotes the frames.

Start it with one API call

POST https://api.prix.dev/o/{org}/sessions with this body:

{
  "agent": "claude",
  "input": "A Sentry alert fired for the blog Worker in this repository; the payload follows this prompt. Use the Sentry connection to read the issue, its latest event, the request method and URL, the tags and the in-app frames. Find the handler in blog/src/api.ts, blog/src/index.ts or blog/src/model.ts that the message and route point at. Add a test to blog/src/api.test.ts that sends the same request through worker.request with the env from cloudflare:test and asserts the response the route should give; confirm it fails with the same error. Fix the cause rather than wrapping the route in a try/catch that hides it, keep the JSON response shape the other routes use, run npm test in blog and npx tsc --noEmit, and open a pull request that links the Sentry issue, quotes the frames and the failing test output, and explains the cause. Change nothing outside the blog example.\n\nAlert payload:\n{payload}",
  "connections": [
    "sentry"
  ],
  "resources": [
    {
      "url": "https://github.com/your-org/your-app"
    }
  ]
}
  1. Get an API key. In the console, open Settings, then API keys, and create a key for your org. Send it in the Authorization header as a Bearer token.
  2. Send the request. POST the body in request.json to https://api.prix.dev/o/{org}/sessions, with your repository as the resources URL. The run starts in its own cloud sandbox.
  3. Read what came back. Follow the run on its live stream or wait for the run.completed webhook, then read the result and its trajectory.

What comes back

What comes back is a pull request touching blog/src/api.ts or blog/src/model.ts and blog/src/api.test.ts, usually under thirty changed lines. Its description links the Sentry issue, quotes the exception message and the route from the event, shows the new test failing before the change and passing after, and gives the npm test summary from the Workers pool and the tsc result.

The reviewer checks that the fix returns a status and a body consistent with the rest of api.ts, that a bad request is now 400 or 422 and not a silent 200, that the basic-auth middleware in index.ts still applies to the method in question, and that no KV key format changed. If the cause was data, a corrupt value under v1:post:, the description says so and the fix makes getPosts skip or report that value rather than fail the list.

Run it on every Sentry issue alert

Create an alert rule in the Sentry project for the Worker with a webhook action pointed at a handler on your server. The handler sends this request with the alert's JSON after the prompt and the Sentry issue id as Idempotency-Key, so a retried delivery returns the run already started. Sentry cannot call a Rush webhook trigger directly, because the trigger needs Authorization: Bearer with its secret; the handler adds that header if you prefer an automation in the Project over a direct session.

Give the API key a webhook URL and Rush POSTs run.completed with the session_url and the result when the turn ends; the handler can post the pull request link back on the Sentry issue as a comment. An issue that keeps firing should not keep opening pull requests, so the handler dedups on issue id, or the automation's max_runs_per_hour does.

The use case this job follows, with its automation and trigger: Fix a bug from an alert.

Why run it on Rush?

A Worker bug is cheap to fix and tedious to reproduce: the test pool needs wrangler and a KV binding, and the developer who gets the alert is usually working on something else. The agent does the setup in its own sandbox, runs the one test that matters, and hands back a diff. Several alerts from several example apps in the same repository can be several sessions.

The pull request carries its own evidence. The transcript shows the Sentry event the agent read, the test failing with the same message and passing after the change, and the exact npm test output, so the reviewer judges the fix rather than reconstructing the bug.

Frequently asked questions

Does the Workers test pool run in the sandbox?

Yes. npm install in blog/ brings wrangler and @cloudflare/vitest-pool-workers, and vitest.config.ts points at wrangler.toml for the BLOG_EXAMPLE KV binding. The pool provides a local KV, so the test needs no Cloudflare account.

Stack frames from a Worker point at the bundle. How does the agent find the source line?

From the message and the route. The event names the method and URL, and blog/src/api.ts has one handler per route, so the search is small. If source maps are uploaded to Sentry the frames resolve to src/ lines directly and the agent uses them.

Will it add a global error handler instead of fixing the route?

No. The prompt asks for the cause and forbids a try/catch that hides it. A route that throws on a malformed body should answer 400 with the same { error, ok } shape the other routes use; an app.onError that turns every failure into a 500 JSON would silence Sentry without fixing anything.

Does it work for the other examples in the repository?

The same prompt works for any example with a Vitest setup; the agent reads that example's package.json and config first. The Bun and Deno examples run their tests differently, so name the example and its test command in the prompt.

What if the Sentry issue is from a release that no longer matches main?

The agent compares the release tag on the event with the current source. If the handler already changed, the pull request says the issue is likely fixed, still adds the test to prove the current behavior, and asks the reviewer to resolve the issue in Sentry rather than inventing a second fix.