What the agent does
The site data comes from Ahrefs, and the files come from the repo. Ahrefs is a connection: POST /me/connections with type mcp, name ahrefs, url https://api.ahrefs.com/mcp/mcp and auth mode oauth. The catalog says it queries your Ahrefs SEO data, spends monthly API units, and needs a Lite plan or higher. authorize_url is finished by the key's creator while signed in to the Rush console. The session names that connection. A key run receives only the connections it names. The repository is a second input, resources with the GitHub URL, which clones it through the Rush GitHub App. One repository per run. The prompt tells the agent not to change code.
The example tree is leerob/next-mdx-blog. package.json pins next 16.2.11, react 19.1.0 and @next/mdx 16.1.5, with Tailwind 4 and no test script. pnpm-lock.yaml is lockfileVersion 9.0, and there is no packageManager field. The README says Node.js v18.17 or newer; @types/node is ^22. app/layout.tsx exports metadata with metadataBase https://next-mdx-blog.vercel.app, title default John Smith, template '%s | John Smith', description 'My portfolio, blog, and personal website.', and alternates.canonical set to '/'. The html element sets lang to en. There is no openGraph object, no twitter object, and no app/robots.ts. The home page is app/page.mdx, which starts with a markdown heading and does not export metadata of its own, so the layout defaults are what the home response carries.
Posts live at app/n/1/page.mdx, app/n/2/page.mdx and app/n/3/page.mdx. Each exports metadata with a title and a canonical path (/n/1, /n/2, /n/3). app/sitemap.ts hardcodes SITE_URL to the same Vercel host, walks app/n for files named page.mdx, and sets lastModified to new Date() on every call, so the sitemap's dates change even when the MDX did not. next.config.ts loads redirects from a Postgres redirects table when POSTGRES_URL is set, and enables experimental.mdxRs with mdxType gfm. The agent pulls the site-audit issues for that deployed host through the Ahrefs connection, then for each issue type opens the template that emits it: a title or description issue against app/layout.tsx and the note's metadata export, a canonical issue against those alternates, a sitemap issue against app/sitemap.ts, a missing robots issue against the absence of app/robots.ts.
The mapping is by issue type, not by rewriting the page. A thin description on the home URL is the description string in app/layout.tsx, because page.mdx does not override it. A note whose title looks duplicated is the layout template '%s | John Smith' wrapped around the note's own title. A lastmod that looks like the crawl time is the new Date() in sitemap.ts, line that builds lastModified. The agent writes the Ahrefs issue, the pages it listed, and this file and line. It does not need POSTGRES_URL to explain the metadata. The report lists the Ahrefs calls so the units are visible.
Start it with one API call
POST https://api.prix.dev/o/{org}/sessions with this body:
{
"agent": "claude",
"input": "Use the Ahrefs connection to pull site-audit issues for the deployed blog at https://next-mdx-blog.vercel.app. The repository is in the sandbox. Read app/layout.tsx, app/page.mdx, app/sitemap.ts, app/n/1/page.mdx, app/n/2/page.mdx, app/n/3/page.mdx and next.config.ts. For each issue type, name the template or component that produces it. Write seo-audit.md with the issue, the pages affected, the file and line, and the fix. Do not invent issues the connection did not return. Change no code. Do not create an Ahrefs project.",
"resources": [
{
"url": "https://github.com/your-org/your-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
seo-audit.md is a session artifact with a name, a mime type and a url on api.prix.dev. The url downloads the file with no key until url_expires_at, about an hour; read the session again for a new one. GET /o/{org}/sessions/{id}/artifacts/seo-audit.md with the key returns it. The clone is clean. No commit, no pull request, no edit to layout.tsx.
Each section is one issue type from the Ahrefs audit: the issue name, the URLs Ahrefs listed, the file and line in this Next.js tree, and a fix that was not applied. This prompt says not to invent issues, so a missing robots.ts is included when Ahrefs reported it, with the note that the file is absent. lastModified: new Date() in sitemap.ts is cited when the audit complains about lastmod.
A reviewer checks that every URL in the report is on the metadataBase host, that the file exists at the cited line, and that the fix matches the App Router file (a metadata export, not a pages/_document.js head). The transcript has the Ahrefs calls and the files read. API units are Ahrefs's, from the plan the connection is signed into. The Rush session does not apply the fixes.
Run it on every weekly crawl
After Ahrefs finishes a crawl, or on a weekly schedule if you do not have that webhook, your server POSTs this body to https://api.prix.dev/o/{org}/sessions. Use the crawl id as the Idempotency-Key so a repeat notification does not spend the units twice. The repository in resources must be covered by the Rush GitHub App. A fork of the blog is a different URL in resources and a different deployed host in the prompt.
Set webhook_url on the API key from an admin session. Rush POSTs run.completed within about 30 seconds, signed per Standard Webhooks. seo-audit.md is larger than the 16 KiB result field, so download the artifact from the session. A failed delivery retries at 2, 4 and 6 minutes with the same webhook-id. max_concurrent on the key (default 4) caps how many sites you can map at once.
The use case this job follows, with its automation and trigger: Produce a report or file, no repo.
Why run it on Rush?
An Ahrefs issue names a URL. The person who can fix it needs the file. In this blog that is app/layout.tsx for the default title and description, the note's own metadata export for a post, and app/sitemap.ts for lastmod. The agent reads the crawl through the Ahrefs connection and the clone in the same sandbox, and the session keeps both the issue list and the file reads, so the mapping is a line you can open.
Crawls of several sites are several sessions. Each has its own sandbox, its own clone and its own connection calls, up to the key's concurrency limit, after which the API answers 429. The sandbox parks when the turn ends, costs nothing while parked, and is kept for 7 idle days. A follow-up can ask for one issue type to be mapped again after you change the prompt, without a second crawl if the first tool results are still in the transcript.
Frequently asked questions
Will it edit the metadata or open a pull request?
No. The prompt says change no code. seo-audit.md holds the fix as text. layout.tsx, the MDX notes and sitemap.ts stay as they were cloned. A later run can apply one fix; this one is the map from issue to line.
The blog has no robots.ts. Is that always a finding?
Only if Ahrefs reported it, because the prompt says not to invent issues. The agent can still point at the missing file as the place a robots response would be added, next to that issue. It should not add a robots finding the crawl did not contain.
Does it need POSTGRES_URL?
No. next.config.ts returns an empty redirect list when POSTGRES_URL is unset. Metadata, the sitemap and the MDX notes do not read that variable. A redirect issue from Ahrefs is mapped to the redirects() function and the redirects table the README creates, and the report says the table was not connected if the env var was absent.
Whose Ahrefs units does this spend?
The account that completed the OAuth grant, on a Lite plan or higher, as the catalog states. The connection is named on the session. The report should list the calls so you can see the units. A run with no Ahrefs connection cannot see the crawl; the clone alone is not the audit.