What the agent does
Your product takes a customer's feature request, writes it into one prompt, and starts a run on that customer's repository. The agent clones it into its own cloud sandbox and reads the app first. In a Phoenix app like fly-apps/live_beats it finds Phoenix 1.7 and LiveView in mix.exs, Ecto on Postgres, and a test alias that runs ecto.create --quiet and ecto.migrate --quiet before mix test. config/test.exs expects Postgres on localhost with the postgres user and the Ecto.Adapters.SQL.Sandbox pool, so the agent starts Postgres in the sandbox before anything else.
The spec is a play count for each song on the profile page that updates live. The agent follows playback to its source: LiveBeats.MediaLibrary.play_song/1 in lib/live_beats/media_library.ex updates the song's status and played_at inside an Ecto.Multi, then broadcasts %Events.Play{} on the owner's PubSub topic. It reads the cond there closely, because one branch resumes a paused song and keeps its old start time. A resume is not a new play, so the count goes up only when a stopped song starts.
It extends what is there. A migration under priv/repo/migrations/ adds a play_count integer with a default of 0 to songs, the Song schema in lib/live_beats/media_library/song.ex gains the field, and play_song/1 adds the increment to the same Multi that sets status: :playing, the way the import path already keeps songs_count on users. The Events.Play broadcast then carries the updated song, so handle_info for that event in lib/live_beats_web/live/profile_live.ex re-inserts it into the @streams.songs stream and the new column in the songs table shows the count to every viewer of the profile.
Tests go where the project keeps them. test/live_beats/media_library_test.exs gets cases for a first play, a pause then resume that does not add a play, and a second play after a stop; test/live_beats_web/live/profile_live_test.exs, which already logs in a user with user_fixture and opens the profile with live/2, gets a case that plays a song and asserts the rendered count changes. The agent runs mix test and mix format --check-formatted, reads every failure and fixes it before it opens the pull request.
Start it with one API call
POST https://api.prix.dev/o/{org}/sessions with this body:
{
"agent": "claude",
"input": "A customer asked for this feature: show each song's total play count on the profile page, updated live. Count a play only when a stopped song starts, not when a paused song resumes. Follow the project's existing patterns in lib/live_beats/media_library.ex, the Song schema, priv/repo/migrations and the profile LiveView, start Postgres in the sandbox, add tests in test/live_beats and test/live_beats_web/live, run mix test, and open a pull request that explains the change in three bullets.",
"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
What comes back is a pull request on the customer's repository. Its diff has one new migration adding play_count to songs, the field on the Song schema, the increment inside play_song/1's transaction, a column in the profile's songs table, and the new test cases. The description is three bullets: what is counted, when it is counted, and how the profile page learns about it.
This repository ships no CI workflow, so the proof is the run itself: the session keeps the mix test output from the sandbox with Postgres running. A reviewer checks the migration is reversible, that the increment sits in the same Repo.transaction as the status change so a failed play does not count, and that the count appears only where the customer asked for it.
Your product gets the pull request link, the agent's final answer and the run's cost from the session read or the webhook, and can post them back to the customer's request. The transcript has every command and file the agent touched, which answers a customer's question about how the change was made without anyone reconstructing it.
Run it on every customer feature request
Each feature request in your product becomes one POST /o/{org}/sessions with the customer's repository in resources and their words in input. Your backend keeps the mapping from its request id to the returned execution_id, and sends that request id as the Idempotency-Key so a retry returns the same run.
A webhook on the API key closes the loop: when a run finishes, Rush posts run.completed with the result and the session URL to your endpoint, and your product updates the customer's request with the pull request. A follow-up from the customer, such as hiding the count on private profiles, goes to the same session as a message and wakes the parked sandbox where it stopped.
The use case this job follows, with its automation and trigger: Run an agent per customer task.
Why run it on Rush?
Building Phoenix features for many customers on one machine means a Postgres for each one, Elixir and Erlang versions that match each mix.lock, and dependencies like Bumblebee and EXLA in this app that take time to compile. Each Rush run gets its own sandbox: it starts its own Postgres, compiles that customer's dependencies, and leaves nothing behind for the next customer's run to trip over.
The customer gets proof, not a claim. The pull request shows the change, and the session record shows the mix test run that passed against a real database. Runs for different customers start side by side, each on its own branch, so a queue of requests does not wait on one developer's laptop.
Frequently asked questions
Why does resuming a paused song not count as a play?
In this app play_song/1 treats a paused song differently: it keeps the elapsed time and shifts played_at back. That is the same listen continuing, so the prompt asks for the count to rise only when a stopped song starts. A customer who wants every press counted can say so in the spec.
Where does the Postgres for the tests come from?
The sandbox starts one. config/test.exs expects Postgres on localhost with the postgres user, and the test alias in mix.exs creates and migrates the test database before mix test runs, so the agent only has to start the server.
How does the count update for other people viewing the profile?
Through the PubSub broadcast the app already sends. play_song/1 broadcasts Events.Play on the profile owner's topic, and every connected profile LiveView handles it, so carrying the updated song in that event is enough to refresh the row.
The repository has no CI. What checks the pull request?
The run does. The agent runs mix test in the sandbox and the session keeps the output. If the customer's repository has a workflow, its checks run on the pull request as well.