What the agent does
An Astro site throws in three places, and the agent reads the Sentry event to tell which. A build-time error comes from a page's frontmatter or a getStaticPaths call and names a file under src/pages; a server endpoint error comes from a .ts route such as og.png.ts or rss.xml.ts; a browser error comes from a script block in a page or from a file under src/scripts. Through the Sentry connection it reads the issue, its latest event, the in-app frames with their paths and lines, the release and the URL, and then opens those files in its clone of the repository before it changes anything.
In a site like satnaing/astro-paper it reads package.json first: astro ^7.0.3, @astrojs/rss, satori and sharp for Open Graph images, pagefind for search, pnpm from the lockfile and Node 22.12 or newer. There is no test runner and no test script; CI runs only lint, format:check and build. The code the frames most often land in is small and importable: src/utils/getPostPaths.ts, which turns a post id and filePath into a slug and drops path segments that start with an underscore; src/utils/slugify.ts, which switches between slugify and lodash.kebabcase on non-Latin input; src/utils/postFilter.ts, which hides drafts and scheduled posts using the 15 minute scheduledPostMargin from astro-paper.config.ts; src/utils/getSortedPosts.ts, which sorts on modDatetime or pubDatetime; and src/pages/og.png.ts and src/pages/posts/[...slug]/index.png.ts, which throw Cannot find the font path when getFontPathByWeight finds no regular or bold font. On the browser side src/scripts/theme.ts reads localStorage and toggles the dark class, and search.astro mounts the Pagefind UI from a bundle path in a data attribute.
Because the repository has no runner, the agent adds vitest as a dev dependency and a test script, with a config that resolves the @ alias from tsconfig.json to src. The test imports the function the frames point at and calls it with the input the event implies: a post whose filePath is undefined, a tag with non-Latin characters, a pubDatetime stored as a string rather than a date, or a font list that lacks a weight. For a frame inside an .astro page it tests the utility the page calls, since that is where the logic lives, and notes in the pull request which line of the page the fix reaches. It runs pnpm exec vitest run and keeps the failing output, which shows the same error message as the Sentry event.
Then it fixes the cause, reruns the test until it passes, and runs pnpm build so astro check, astro build and the Pagefind step all still succeed, followed by pnpm lint and pnpm format:check. The fix is narrow: it does not wrap a page in a try block that swallows the error, and it does not change the content schema in src/content.config.ts unless the event shows a frontmatter field that the schema should have refused. If the error will not reproduce from the frames, the agent stops and reports what it tried instead of guessing.
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 this Astro site; its payload follows this prompt. Use the Sentry connection to read the issue, its latest event, the URL and the in-app stack frames. Decide whether the error happened at build time in a page under src/pages, in a server endpoint such as og.png.ts or rss.xml.ts, or in the browser in a script block or src/scripts, and open those files first. The project has no test runner: add vitest as a dev dependency with a test script and the @ alias from tsconfig.json, write a test that imports the function the frames point at and reproduces the error with the input the event implies, then fix the cause until pnpm exec vitest run passes. Install with pnpm, then run pnpm build, pnpm lint and pnpm format:check. Open a pull request that links the Sentry issue, quotes the frames and the failing test output, and explains the cause. If the error does not reproduce, stop and report what you tried. Change nothing unrelated to this error.\n\nAlert payload:\n{payload}",
"resources": [
{
"url": "https://github.com/your-org/your-app"
}
],
"connections": [
"sentry"
]
}- 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.
- 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.
- 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
The result is a pull request with a small diff: the utility, endpoint or script where the error started, a new test file beside it, vitest and a test script in package.json, a vitest config, and the updated pnpm-lock.yaml. The description links the Sentry issue, names the file and line, shows the test failing before and passing after, and explains the cause in plain words, such as a post in a folder whose name slugifies to an empty segment or a font weight missing from the font config.
The session holds the Sentry queries, the install, the vitest runs, the build and the lint output, plus every file the agent read. Its final message, also sent as result in the run.completed webhook, is the short account; the transcript is where a reviewer checks it.
Before merging, the reviewer confirms the test exercises the same code path the frames name, that a build-time fix still produces the same set of pages, and that a browser-side fix still works when localStorage or the Pagefind bundle is absent. A different approach is a follow-up message to the same session, and the agent amends the branch.
Run it on every new Sentry issue
Add an alert rule in Sentry for the site's project that fires on a new issue, with a webhook action aimed at a handler on your server. The handler sends this request with the alert's JSON after the prompt and the issue id as the Idempotency-Key, so Sentry's retries map to one run and each new issue gets its own sandbox, test and pull request.
Give the API key a webhook URL and Rush POSTs run.completed when the turn ends, with session_url to read the pull request from. The handler can also call a webhook trigger on an automation in the Project, forwarding the alert body with the trigger's secret as the bearer token, since Sentry signs its own requests and cannot send that header itself.
The use case this job follows, with its automation and trigger: Fix a bug from an alert.
Why run it on Rush?
Errors in a static site are awkward to reproduce by hand: the build runs once per deploy, Open Graph endpoints only fail for particular posts, and a browser script fails on a visitor's stored state you do not have. In a Rush sandbox the agent builds the site as many times as it needs, installs a test runner on its own disk and feeds the exact input the Sentry event shows, while your checkout stays untouched.
Each new issue runs on its own, in parallel up to the key's concurrency limit, so a release that broke several posts gets several reviewed fixes rather than one person working through them in order. The pull request carries the failing and passing test output and the full command record, so it can be checked rather than trusted.
Frequently asked questions
The site has no tests. What does the agent write one with?
Vitest, added as a dev dependency with a test script, because the repository ships only lint, format and build checks. The utilities under src/utils and the endpoint modules are plain TypeScript and import cleanly; the test targets those, so it runs in seconds without a browser or a full build.
What if the frames point into dist or a hashed asset?
A browser error reports the built file, so the agent matches the function names and the surrounding code to the script block or src/scripts file that produced it and says in the pull request which frames it placed and which it inferred. Uploading source maps to Sentry with each release makes the next event name the source file directly.
Can it fix a build failure that only happens with my real content?
Yes, when the content is in the repository. Posts live under src/content/posts, so the sandbox builds with the same files that failed. Content that lives outside the repository must be attached or described in the prompt.
Will it touch the content schema?
Only when the event shows a frontmatter value that src/content.config.ts should have refused at build time, and then the pull request says so. The default fix lives in the function that threw and leaves the schema alone.