# Fix a Django App Bug Reported in Slack

Yes. A Slack message can start an agent that reproduces a Django bug, adds a TestCase, and opens a pull request the team can steer.

[Run this on Rush](https://cloud.getrush.ai/run/fix-slack-bug-reports/django/), in a Project that has your repository.

## What the agent does

The report names two surfaces, and the agent finds both in the tree before it changes anything. healthchecks pins Django to 6.1.2 in requirements.txt. The README runs ./manage.py test and ./manage.py runserver, and the site listens on http://localhost:8000. hc/settings.py uses SQLite at hc.sqlite unless DB=postgres or DB=mysql. PING_BODY_LIMIT defaults to 10000. The ping API is hc/api/views.py: ping is csrf_exempt and looks up Check by UUID, rejects an exit status over 255, reads the client address from X-Forwarded-For, stores request.body up to PING_BODY_LIMIT, and answers OK with a Ping-Body-Limit header. ping_by_slug looks up slug plus project ping_key and returns 400 when the slug is not lowercase. Routes are in hc/api/urls.py under ping/<uuid> and ping/<ping_key>/<slug>, including the fail, start and log suffixes.

The alert side is the integrations registry. hc/urls.py includes one urls module per integration, from apprise through zulip, and hc/settings.py INSTALLED_APPS lists the same packages, including hc.integrations.slack. The front office for a saved channel is hc/front/urls.py: edit, name, test, checks and remove, under the checks and integrations paths. Tests are Django TestCase subclasses, BaseTestCase in the app's own tests, for example hc/front/tests/test_update_channel_name.py and hc/api tests next to the ping views. A bug that appears after saving is a POST to one of those edit or add views that then renders an error on the following GET. The agent starts runserver, signs in, and walks the page the message describes. It does not invent a failure the page does not show.

The fix is the smallest change that makes the save succeed, plus a TestCase that posts the same payload and asserts the response the UI should have given. The new test sits beside the existing one for that view, uses the project's BaseTestCase, and runs under ./manage.py test for that module rather than the whole tree first. When that module is green, the agent runs ./manage.py test. SQLite needs no extra server. The pull request's description is the steps to reproduce: the URL, the field that was saved, and the error page that followed.

The team sees that attempt in the console. A follow-up can say the failure is on the slug form of the ping URL, or on the Slack integration's add view rather than the generic channel edit. The agent repeats the browser steps, adjusts the test and only then opens the pull request. The Slack thread is how the report arrived. A server that starts the same work sends the report text as input and the repository as resources.

## Start it with one API call

`POST https://api.prix.dev/o/{org}/sessions`

```json
{
  "agent": "codex",
  "input": "A teammate reported in Slack that a page in the ping API and the alert integrations shows an error after saving. Reproduce it in the sandbox browser against ./manage.py runserver. Read hc/api/views.py ping and ping_by_slug, and the channel edit routes in hc/front/urls.py, and say which page fails. Fix it with a Django TestCase next to the existing tests, using the project's BaseTestCase. Run ./manage.py test for that module, then ./manage.py test. Open a pull request that describes the steps to reproduce. Apply follow-ups from the team before you open it.",
  "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. The description is the reproduction: which URL, which save, and the error that followed, naming the view in hc/api or hc/front. The diff is the fix and one TestCase. The transcript holds the manage.py test output, including a run that failed before the fix if there was one. The session read includes the pull request URL when the agent has opened it.

A reviewer checks that the new test fails if the fix is reverted, that it uses BaseTestCase and the same client the neighbouring tests use, and that ping's existing rules are intact: exit status over 255 is still a 400, a missing check is still not found, and the body is still cut at PING_BODY_LIMIT. They check the integration list in hc/urls.py was not rewritten.

Steering is a follow-up on the session that is doing the reproduction. The live stream is GET /o/{org}/sessions/{id}/events. POST /o/{org}/sessions/{id}/messages once status has left running. A POST while the turn runs is 409 TURN_ACTIVE, and the console queues a message sent then. The sandbox parks with the checkout and the dev server's database file, and a follow-up wakes it. Parked sandboxes last 7 idle days.

## Run it on every Slack message

A message to Rush in Slack starts a run in that person's default Project, the Project whose is_default is set. The session's source kind is slack. The message text is the task. Teammates in the org can open the run and read the browser steps, and the starter or an org admin can send a follow-up or take the browser on a five-minute lease.

The same work from your own server is the POST on this page: the report in input, the repository in resources. Give the API key a webhook URL and it receives run.completed, run.failed or run.cancelled when the turn finishes, with session_url. If the agent should also read the Slack thread, name your Slack connection on the run. Slack is then available inside the sandbox as the slack CLI signed in as that person. A key's max_concurrent, 4 by default, answers 429 when it is full.

## Why run it on Rush?

A bug that shows up after a save needs a browser and the test suite, and the person who reported it is in Slack, not in the repository. The sandbox runs manage.py runserver and manage.py test against its own SQLite file, so the report becomes a branch without anyone cloning healthchecks to reproduce a screenshot. The thread stays where the report was typed.

The pull request is the part you merge, and it contains the steps and the test. The transcript is the part that shows the page failing and then the module going green. Two reports are two sandboxes. They do not share hc.sqlite.

## Frequently asked questions

### Which page does it open if the message is vague?

It says what it tried. The ping URLs are under hc/api/urls.py, and the channel edit, test and remove URLs are under hc/front/urls.py. A follow-up that names the integration, for example the Slack add view in hc/integrations/slack/urls.py, points the next turn at that form. It does not patch a page it could not make fail.

### Does the test need Postgres?

Not by default. hc/settings.py uses SQLite at hc.sqlite unless the DB environment variable is postgres or mysql. ./manage.py test uses that default. Set DB in the prompt when you want the suite on Postgres. The agent says which engine it ran.

### Will it rewrite every integration?

No. hc/urls.py includes each integration's urls module separately, and the fix belongs to the view the reproduction hit. The pull request should be that view, its form and one TestCase. A diff that touches the whole integrations list is a reason to send a follow-up.

### How does a teammate add a step to the reproduction?

They send a follow-up on the session, after the turn ends, or the console queues it during the turn. The starter or an org admin can send it. The parked sandbox still has the database and the branch. After 7 idle days the sandbox is gone and you start a new session.
