What the agent does
The agent narrows the search with the two facts the alert gives: Android only, and mostly in the feed screen, starting with the latest release. Android-only rules out most pure JavaScript logic and points at what differs by platform: native modules, the new architecture, image decoding and memory, and code behind Platform.OS checks. In an Expo app like Obytes' React Native template, it reads app.config.ts first: newArchEnabled: true at line 41, the android block with the adaptive icon and package, and the plugins list. Then package.json, which pins expo ~54.0.32, react-native 0.81.5, @shopify/flash-list 2.0.2, react-native-reanimated ~4.1.6, react-native-mmkv ~4.1.1 and expo-image ~3.0.11, so it can compare each against the previous release's lockfile.
Then it reads the feed path end to end. src/app/(app)/index.tsx re-exports FeedScreen from src/features/feed/feed-screen.tsx, which renders a FlashList with a keyExtractor that returns item-${index} at line 29, an index key that makes recycled cells reuse state from a different post when the list changes under them. Each cell is PostCard in components/post-card.tsx, which picks its image URL with Math.random() at line 28, inside render, so every re-render of a recycled cell asks expo-image to fetch and decode a different 800-pixel-wide Unsplash photo. On Android devices with less memory, that churn is a plausible path to an out-of-memory crash that iOS never shows, and the agent ranks it with that reasoning and the check that would confirm it.
It reads the data layer too. src/features/feed/api.ts builds usePosts and usePost with react-query-kit's createQuery, both with queryKey: ['posts'] (lines 18 and 28), and usePosts returns response.data.posts from the axios client in src/lib/api/client.tsx. Whether the two hooks can overwrite each other's cache depends on whether react-query-kit 3 appends variables to the key, so the agent checks the installed version's source and lists the suspect as confirmed or cleared rather than guessing. A post detail object landing where the feed expects an array would crash only after a user opens a post and returns, which matches "most events in the feed screen".
Finally it diffs the release: the last 30 commits with git log -p, the lockfile changes between the two release tags, and any change to app.config.ts, eas.json or babel.config.js. With the Sentry connection named on the run, it reads the crash events' stack traces, device models, OS versions and memory figures, and checks each suspect against them. It writes incident.md and changes no code.
Start it with one API call
POST https://api.prix.dev/o/{org}/sessions with this body:
{
"agent": "claude",
"input": "Incident: Sentry shows crash-free sessions dropping from 99.6% to 97% on Android only after the latest release, most events in the feed screen. Read app.config.ts, package.json and the lockfile, the feed screen and everything it renders, the data hooks it uses, and the last 30 commits with their diffs, including dependency changes since the previous release tag. If the Sentry connection is available, read the crash events' stack traces, devices, OS versions and memory figures. Find the most likely causes, explain why each affects Android and not iOS, and write incident.md with a timeline, each suspect ranked with file and line evidence, and the exact test, device check or Sentry query that would confirm or clear it. Change no code.",
"resources": [
{
"url": "https://github.com/your-org/your-react-native-app"
}
]
}- 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
What comes back is incident.md, attached to the session as an artifact with a download link, and the agent's answer naming the leading suspect. The report starts with a timeline: the release tag, the commits and dependency bumps inside it, and, when Sentry was read, when the crash-free rate started to fall and on which devices first.
Each suspect is ranked and anchored: the random image URL in post-card.tsx line 28 and the index key in feed-screen.tsx line 29 for memory and recycling, the shared ['posts'] key in api.ts lines 18 and 28 for a cache shape mismatch, a native dependency upgrade under the new architecture for a crash below JavaScript. Each says why it fits Android only, and ends with its check: scroll the feed for two minutes on a low-memory Android emulator with adb shell dumpsys meminfo running, open a post and go back with the query cache logged, or filter the Sentry events by their error mechanism to separate native crashes from JavaScript exceptions.
The trajectory keeps every file the agent read and every command it ran, so each claim can be traced. The report tells the on-call engineer which check to run first; it does not change the app or ship a release.
Run it on every crash-free rate alert
Set a Sentry alert on crash-free session rate per release and send its webhook to your server, which starts this request with the release, platform and rate in input and the repository in resources. The investigation then begins while the release is still rolling out, and a staged rollout can be paused on evidence rather than on a hunch.
Give the API key a webhook URL and Rush POSTs run.completed when the turn finishes, with the agent's answer and the session_url. Your server can read the session for the incident.md link and post it to the release channel, next to the rollout controls.
The use case this job follows, with its automation and trigger: Investigate an incident.
Why run it on Rush?
A crash spike after a release is a race against the rollout, and the first hour goes to reading the diff, the lockfile and every screen the stack traces mention. On Rush the agent does that reading in its own sandbox with its own clone, at the same time as the engineer looking at Sentry, without tying up anyone's machine with installs or emulators.
The report is something to verify, not to trust: every suspect has a file and line and a reason it is Android-only, and every check is concrete. The trajectory shows exactly what was read. Two platforms or two apps can be investigated at once, each in a separate run with its own report.
Frequently asked questions
My app does not have Sentry set up in the template. Does that matter?
Obytes' template ships without @sentry/react-native, so in a copy of it the agent works from the code and the numbers you give it. When your app reports to Sentry, connect Sentry once with POST /me/connections and name it in connections, and the agent reads the crash events, devices and stack traces as well.
Will it run the app on an Android emulator?
The request on this page is read-only: it reads code, history and crash data, and writes the checks for a person to run on a device. Reproducing on an emulator is a separate job that needs an Android build; ask for it in a follow-up if the report's top suspect needs one.
Can it tell a JavaScript crash from a native one?
It separates them in the report. A JavaScript exception has a stack in your source and gets a file and line; a native crash in a module like FlashList or Reanimated gets the dependency, the version change and the Sentry filter that shows its native frames.
Does it change any code?
No. The request says to change no code, and the only output is incident.md. Once you know the cause, a second request can ask for the fix as a pull request.