What the agent does
The agent works inside the sample module the prompt names. In ktorio/ktor-samples that is kweet/: build.gradle.kts applies Kotlin 2.4.20, the Ktor plugin 3.6.0, JVM toolchain 17, H2, Exposed, FreeMarker, and test deps ktor-server-test-host-jvm, kotlin-test and mockk. Application code lives under src/main/kotlin/io/ktor/samples/kweet/ with Register.kt, Login.kt, PostNew.kt, Delete.kt, ViewKweet.kt and KweetApplication.kt wiring mainWithDependencies(dao).
It reads the existing src/test/kotlin/KweetApplicationTest.kt. That file already uses testApplication { application { mainWithDependencies(dao) } }, mocks DAOFacade with mockk, and covers empty home, home with kweets, login failure (302) and login success with cookies. Registration (post<Register> in Register.kt), posting (post<PostNew> in PostNew.kt with date/code/text CSRF-style fields) and deletion (Delete.kt) have little or no coverage, and error redirects that set error query fields are untested.
New tests stay on testApplication and the mocked DAO: successful register creating a user and redirecting to the user page; register conflicts when dao.user or dao.userByEmail already exists; post-new rejecting missing fields and accepting a valid post when the session user matches; delete removing a kweet the user owns and refusing when ownership fails. Assertions check status codes, Location headers and substrings in FreeMarker HTML the same way the login tests do.
It runs ./gradlew :kweet:test from the samples root (or ./gradlew test inside kweet/ using the module's gradlew), fixes compile or assertion failures, and opens a pull request that only adds test sources unless a tiny test helper in KweetApplicationTest must be shared.
Start it with one API call
POST https://api.prix.dev/o/{org}/sessions with this body:
{
"agent": "claude",
"input": "In the kweet sample, write tests with Ktor's testApplication for registration, login, posting and deleting a kweet, and the error responses. Run ./gradlew test and open a pull request.",
"resources": [
{
"url": "https://github.com/your-org/your-ktor-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 that extends kweet/src/test/kotlin/ (usually KweetApplicationTest.kt or a new file beside it) with testApplication cases for register, post-new and delete flows. Production route files stay unchanged; the DAO remains mocked so tests do not require a listening port or a real H2 file.
The pull request description lists the Gradle command that passed and which routes each test posts to. The session trajectory keeps Gradle output, mockk verification failures and any retries, so reviewers can see why a redirect assertion was adjusted.
Before merging, a reviewer checks that new tests still call mainWithDependencies(dao), that form bodies use formUrlEncode like the login tests, and that error cases assert the redirect targets Register.kt and PostNew.kt already use. CI should run the same ./gradlew test path the agent used.
Run it on every kweet route handler changed
When a pull request touches kweet/src/main/kotlin/io/ktor/samples/kweet/*.kt, your server can POST this session body with the repository in resources so missing register/post/delete coverage is filled in an isolated sandbox with JDK 17 and Gradle caches.
Configure the API key webhook for run.completed / run.failed to receive the session URL and post the resulting pull request into the Ktor maintainers' channel. Cap concurrency with the key's max_concurrent limit so many sample modules are not tested at once on one key.
The use case this job follows, with its automation and trigger: Write the missing tests.
Why run it on Rush?
Ktor's testApplication is fast, but wiring FreeMarker, sessions and mockk still means a full Gradle JVM test run. Rush runs that in a sandbox with the module's toolchain, so you are not stuck waiting on ./gradlew test locally or polluting your machine with H2 files from accidental non-mocked runs. FreeMarker templates under src/main/resources/templates/ stay fixtures for HTML assertions rather than being rewritten for tests.
You get a pull request whose proof is green Gradle output in the trajectory, not a claim that routes were tested. Parallel runs can cover other samples (jwt-auth-tests, postgres) with the same request shape while this one finishes kweet.
Frequently asked questions
Does it start a real Netty server on a port?
No. It uses io.ktor.server.testing.testApplication and ktor-server-test-host, the same engine as the existing kweet tests. No public port is bound.
Why mock the DAO instead of using H2?
The sample's tests already inject a mockk DAOFacade through mainWithDependencies. Staying on that pattern keeps tests focused on HTTP behaviour and matches KweetApplicationTest.kt today. If you ask for Exposed integration tests, say so in the prompt.
Which Gradle command runs?
Inside the kweet module, ./gradlew test, or from the repo root the project path that builds kweet. The agent uses the wrapper committed next to the sample so the Kotlin and Ktor plugin versions stay pinned.
Will it duplicate the existing login tests?
It keeps testLoginFail and testLoginSuccess and adds the missing register, post and delete paths. If login coverage is already enough, it only references those tests in the pull request description.