What the agent does
The agent starts with the task, not the code. Through the Asana connection it reads the task you name: its title, description, subtasks and comments, and any custom fields your project uses for acceptance criteria. It writes down what done means for this task before opening a file, so a vague ask ("playlists should be sortable") becomes a concrete list it can check against at the end.
Then it reads the repository the way the project expects. In a Laravel app like koel/koel, composer.json requires PHP 8.3 or later and laravel/framework ^13.0, and the repository ships AGENTS.md and CLAUDE.md with Laravel Boost guidelines: follow sibling files, do not add dependencies without approval, prefer feature tests over ad hoc scripts. The agent follows them. It finds the code the task touches by following the route to its controller under app/Http/Controllers/API/, then the service in app/Services/ and the model in app/Models/, and reads the matching tests in tests/Feature/ (koel has 78 of them) to copy their setup.
It does the work with tests in the same shape the suite already uses. phpunit.xml.dist runs three suites (feature, unit, integration) against SQLite :memory: with QUEUE_DRIVER set to sync, so the agent can run them in its sandbox with no database server: composer install, php artisan key:generate, then composer test, which is php artisan test --parallel. Before pushing it also runs the checks CI runs: composer lint (mago lint), composer cs (mago format --check) and composer analyze (PHPStan with phpstan.neon.dist). When the task touches the Vue frontend in resources/assets, it installs with pnpm 10.32.1 from the packageManager field and runs pnpm test and pnpm typecheck as well.
When the work is done and the suite is green, it opens the pull request, then goes back to Asana and adds a comment on the task with the pull request link and a one-line summary of what changed. If the task asked for something it could not do, such as a decision the description leaves open, it says so in that comment and in the pull request instead of guessing.
Start it with one API call
POST https://api.prix.dev/o/{org}/sessions with this body:
{
"agent": "claude",
"input": "Read the Asana task https://app.asana.com/0/<project-id>/<task-id> through the Asana connection, including its subtasks and comments, and list its acceptance criteria. Do the work it describes in this Laravel repository, following AGENTS.md and the conventions of sibling files. Add or update PHPUnit feature tests in tests/Feature for the behaviour it changes. Run composer test, composer lint, composer cs and composer analyze, and pnpm test if you changed anything under resources/assets, and fix what fails. Open a pull request whose description links the task and lists each acceptance criterion with the test that covers it. Then add a comment on the Asana task with the pull request link and a one-line summary. If something in the task is unclear, ask in the comment instead of guessing.",
"resources": [
{
"url": "https://github.com/your-org/your-laravel-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 a new branch, and a comment on the Asana task that links to it. In a repository shaped like koel the diff usually spans a controller or request class under app/Http/, the service that holds the logic under app/Services/, a migration in database/migrations/ when the task changes the schema, and a feature test under tests/Feature/ that drives the endpoint the way a client would. The description links the task and maps each acceptance criterion to the test that covers it.
The repository's own CI is the first check: koel's workflows run the backend suite on SQLite, MariaDB and PostgreSQL, plus the lint and frontend jobs, so a migration that only works on SQLite shows up red on the pull request. The session's trajectory keeps each command the agent ran with its output, including composer test and composer analyze, so the reviewer can see what was run before the push.
Before merging, a reviewer checks the pull request against the task rather than against the agent's summary: that each criterion is really covered, that no dependency was added (the Boost guidelines ask for approval first), and that a new migration is reversible. The Asana comment tells whoever filed the task where to look, without anyone copying links by hand.
Run it on every Asana task moved to Ready
Register an Asana webhook on the project and have your server send this request when a task moves into the section your team uses for agent work, with the task's URL in input and the repository in resources. Each task gets its own run, its own sandbox and its own branch, so three tasks moved on Friday evening are three pull requests on Monday morning, not one tangled branch.
Set a webhook URL on the API key and Rush POSTs run.completed or run.failed to your server when each run's turn finishes, with its session_url. A key runs at most max_concurrent sessions at once (4 by default) and answers 429 past that, so a server that moves a whole backlog at once should queue its requests.
The use case this job follows, with its automation and trigger: Hand off from your terminal.
Why run it on Rush?
Doing an Asana task on a laptop ties it to the laptop: a PHP 8.3 toolchain, composer install, the parallel PHPUnit run, PHPStan at 1 GB of memory, and a working copy that stays on the feature branch until the work is done. On Rush the agent does all of it in its own sandbox with its own clone, so the task keeps moving after you close the lid, and your local branch and database are never touched.
The result carries its own evidence. The pull request runs the repository's CI, the trajectory keeps every command and its output, and the comment on the task links the two, so the person who filed the task can follow it without asking. Because each task is its own run, a team can hand off several at once and review each pull request on its own.
Frequently asked questions
How does the run reach Asana?
Connect Asana once with POST /me/connections; it is in Rush's MCP catalog and signs in with OAuth. Then add its name or id to connections in the request. A key run gets only the connections it names, so without it the agent cannot read the task or post the comment.
Will the tests need MySQL or Redis?
Not for a suite like koel's. phpunit.xml.dist sets DB_CONNECTION to sqlite, DB_DATABASE to :memory:, the queue to sync and the cache to array, so the agent runs composer test in its sandbox without starting a database. Database-specific behaviour is still caught by your own CI running the MariaDB and PostgreSQL jobs on the pull request.
Does it follow my project's AGENTS.md?
Yes. It reads AGENTS.md and CLAUDE.md before changing code, the same way it would on your machine. In koel those are Laravel Boost guidelines, such as reusing existing components and not changing dependencies without approval, and the pull request description says where the work had to make a judgment call.
What if the Asana task is vague?
The request tells the agent to ask instead of guessing. It posts its question as a comment on the task and stops, and you can answer by sending a follow-up to the same session with POST /o/{org}/sessions/{id}/messages, which wakes the parked sandbox where it left off.