All jobs

Add a Feature to a Flask App from a Customer Spec

Yes. Your product sends the customer's spec in one API call; an agent builds it in their Flask repo with tests and opens a pull request.

Run this on RushIn a Project that has your repository.

What the agent does

The request comes from your product, not from a developer at a terminal: a customer writes a short spec, and your server sends it to POST /o/{org}/sessions with the customer's repository in resources. The agent clones that repository into its own cloud sandbox and reads it before writing anything. In a Flask app like miguelgrinberg/microblog, requirements.txt pins Flask==3.0.0, Flask-SQLAlchemy==3.1.1, SQLAlchemy==2.0.23, Flask-Login==0.6.3 and Flask-WTF==1.2.1, the app is built by create_app in app/__init__.py with blueprints under app/main, app/auth, app/api and app/errors, and the tests live in one file, tests.py, a unittest suite with a TestConfig that uses sqlite://.

The spec here is: let a user export their own posts as a CSV download from their profile page. The agent finds that something close already exists, and that matters more than any new code. app/main/routes.py has an /export_posts route that calls current_user.launch_task('export_posts', ...), and app/tasks.py runs it on an RQ worker backed by Redis (rq==1.15.1, REDIS_URL in config.py), sleeping five seconds per post and emailing a posts.json attachment. app/templates/user.html shows the "Export your posts" link only while no export task is in progress. The pull request has to say how the new download relates to that flow instead of quietly adding a second export.

So it builds the download beside the existing pattern. A new route in app/main/routes.py, @bp.route('/export_posts.csv') with @login_required, selects only current_user's posts with user.posts.select().order_by(Post.timestamp.asc()) (the same query the task uses), writes them with the standard library's csv module to a Response with mimetype='text/csv' and a Content-Disposition: attachment header. Columns are the post's timestamp in ISO format with a Z, as the JSON export writes it, and body. A link next to the existing one in user.html appears only on the signed-in user's own profile, and the label goes through _() like every other string, so Flask-Babel can translate it.

Tests go into tests.py in its style: a new TestCase that creates two users with posts, signs one in through the test client, requests the CSV, and asserts the status, the content type, the header row, that only that user's posts are present and in order, and that a signed-out request redirects to the login page. The agent runs python -m unittest tests for the whole suite and opens the pull request with the three bullets the spec asks for.

Start it with one API call

POST https://api.prix.dev/o/{org}/sessions with this body:

{
  "agent": "claude",
  "input": "Build this feature: let a user export their own posts as a CSV download from their profile page. Read the app first and follow its patterns for routes, blueprints, templates, translations and tests. If the app already has an export of any kind, keep it working and explain in the pull request how the new download relates to it. Only the signed-in user's own posts may be exported; a signed-out request must go to the login page. Add tests in the project's existing test style covering the download's content, ordering, that another user's posts are never included, and the signed-out case. Run the full test suite and open a pull request that explains the change in three bullets.",
  "resources": [
    {
      "url": "https://github.com/your-org/customer-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 on the customer's repository that changes app/main/routes.py, app/templates/user.html and tests.py, and no other file. Its description is the three bullets the spec asked for: what the route does, how it relates to the existing emailed JSON export (left unchanged), and which tests cover it. Your product can show those bullets to the customer as they are.

The session read gives your server everything it needs to report back: the status, the pull request and the final answer in result, with the transcript of every command in the sandbox, including the python -m unittest tests run and its output. Any checks the customer's repository runs on pull requests run on this one too.

Before the customer merges, a reviewer on their side checks the one question that matters for a data export: whether the query can ever return another user's posts. They also decide whether the old emailed export should stay, since two exports with different formats is a product choice, not a code one.

Run it on every customer feature request

Each request from your product starts one run: one customer, one repository in resources, one spec in input. Send an Idempotency-Key built from your own request id, so a retry after a network error returns the run already started instead of building the feature twice.

Set a webhook URL on the API key and Rush posts run.completed or run.failed for each run with its execution_id and session_url. Your handler matches the id to the customer's request, reads the session for the pull request, and updates the customer's ticket. A key runs at most max_concurrent sessions at once, 4 by default, and answers 429 past that, so queue requests during busy hours.

The use case this job follows, with its automation and trigger: Run an agent per customer task.

Why run it on Rush?

When your product hands customer work to an agent, each customer's code has to stay apart from every other customer's. Each Rush run gets its own sandbox with only the one repository its request names, cloned through your GitHub App installation, so one customer's code never sits on a machine with another's.

Your customer gets a pull request with tests they can run and a transcript of what the agent did, which is the proof an agency or a dev-tools product needs before billing for the work. Your server starts as many runs as customers send, up to the key's limit, without a laptop or a person in the loop.

Frequently asked questions

How does the agent get access to my customer's repository?

The customer installs the Rush GitHub App on their repository once, which needs a person on github.com. After that, GET /o/{org}/github lists the repositories the key can reach, and any of them can go in resources.

What if the spec conflicts with code that already exists?

The agent reads the repository before building, and the prompt tells it to keep existing features working and explain the overlap. In microblog that means the emailed JSON export stays as it is and the pull request says how the CSV download differs.

Can I send a follow-up when the customer wants a change?

Yes. POST /o/{org}/sessions/{id}/messages with the change as input wakes the same sandbox where it left off, with the branch and the work already there, and the agent updates the same pull request.

Does the customer see the agent's whole transcript?

Only if you show it. The transcript is available to your server through GET /o/{org}/sessions/{id}/messages, and your product decides what to pass on.