What the agent does
The agent reads the service before it writes a test. In serverless/examples' aws-node-rest-api-with-dynamodb it opens serverless.yml and finds frameworkVersion: '4', the nodejs24.x runtime on arm64, five functions (create, list, get, update, delete) behind httpApi routes on /todos and /todos/{id}, and a TodosDynamoDbTable keyed on a string id, with its name passed to every handler as DYNAMODB_TABLE. package.json has "type": "module", the AWS SDK v3 clients @aws-sdk/client-dynamodb and @aws-sdk/lib-dynamodb, and no test script and no dev dependencies at all.
Each handler in todos/ builds its DynamoDBDocumentClient at import time from new DynamoDBClient({}), so the tests cannot hand it a client. The agent points it at DynamoDB Local instead of mocking it: it starts DynamoDB Local in the sandbox, sets AWS_ENDPOINT_URL_DYNAMODB, a region and dummy credentials in a Jest setup file before the handlers load, and creates a table with the same key schema as serverless.yml before each test file. Because the package is ESM, it runs Jest with node --experimental-vm-modules and adds that as the test script, and it imports delete the way todos/delete.js exports it, as del re-exported under the reserved name.
Then it writes one test file per handler, calling each with an API Gateway v2 shaped event (body, pathParameters.id) and reading the item back from the table, not only the response. create must return 201 with a UUID id, checked: false and equal createdAt and updatedAt, and 400 when text is not a string. get returns 404 for an unknown id. update returns 400 unless both text and a boolean checked are sent. list returns every item the table holds.
The bad-input tests are where real behavior shows up, and the agent reports it rather than bending the test to pass. create and update call JSON.parse on the body with no guard, so malformed JSON throws instead of returning 400. update sends an UpdateCommand with no condition, so a PUT to an id that does not exist creates a new item, and delete returns 200 for an id that was never there. The agent writes those cases as tests of the intended behavior, marks them failing with a comment, and lists each one in the pull request.
Start it with one API call
POST https://api.prix.dev/o/{org}/sessions with this body:
{
"agent": "claude",
"input": "In aws-node-rest-api-with-dynamodb, write Jest tests for each Lambda handler in todos/ (create, list, get, update, delete) against DynamoDB Local running in the sandbox, with no AWS account and no mocks of the DynamoDB client. Point the SDK at DynamoDB Local with AWS_ENDPOINT_URL_DYNAMODB in a Jest setup file, create the table from the key schema in serverless.yml before each file, and add a test script that works with the package's ESM setup. Cover the success path of each handler and bad input: missing or wrong-typed fields, malformed JSON bodies, and unknown ids for get, update and delete. If a handler does not behave the way its route implies, keep the test, mark it as failing, and explain it in the pull request. Do not change the handlers. Run the tests and open a pull request.",
"resources": [
{
"url": "https://github.com/your-org/your-serverless-service"
}
]
}- 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 adds a __tests__ directory with one file per handler, a Jest setup file that points the SDK at DynamoDB Local, a helper that creates and deletes the table, and a test script plus Jest in package.json and the lockfile. Nothing under todos/ and nothing in serverless.yml changes, so the deployed service is the same before and after merge.
The description lists each handler with the cases it covers, how to start DynamoDB Local locally to run the suite, and every test marked as failing with the behavior it found: an unguarded JSON.parse, an update that creates missing items, a delete that never reports a missing id. The session's trajectory keeps the DynamoDB Local startup, each npm test run and its full output.
Before merging, a reviewer checks that the table the tests create matches the real TodosDynamoDbTable definition, decides whether each failing case is a bug to fix or intended behavior to document, and adds the DynamoDB Local step to CI if the repository runs one. Fixing the handlers is a follow-up on the same session.
Run it on every new Lambda function
When a pull request adds a function to serverless.yml, a GitHub webhook on your server can send this request with the pull request URL in resources, asking for tests for the new handler only. The agent clones that branch, writes and runs the tests against DynamoDB Local, and pushes them to a branch of its own for review.
Set a webhook URL on the API key and Rush POSTs run.completed or run.failed when the turn finishes, so your server can comment the test branch on the original pull request. A key runs max_concurrent sessions at once, 4 by default, so a service with many functions should queue its requests.
The use case this job follows, with its automation and trigger: Write the missing tests.
Why run it on Rush?
Testing Lambda handlers against a real table locally means installing Java or Docker for DynamoDB Local, juggling dummy credentials so the SDK does not reach your real account, and making Jest load ESM. That setup is why most Serverless services have no tests. In its own sandbox the agent does it from nothing, with no AWS credentials present at all, so a test can never write to a real table by accident.
The result is a suite that ran, not one that looks right: the trajectory shows DynamoDB Local starting and every test run's output, including the cases that fail and why. Because each run is independent, the same request can cover every service in a monorepo of Lambda functions at once, each with its own pull request.
Frequently asked questions
Does it need my AWS credentials?
No. The tests run against DynamoDB Local in the sandbox with dummy credentials and an endpoint override, so nothing reaches AWS. Leave your AWS keys out of the run entirely; the request on this page names none.
Why not mock the DynamoDB client?
A mocked client only proves the handler sent the command the mock expected. Against DynamoDB Local the tests see what the table really does, which is how they find that an UpdateCommand with no condition creates an item for an unknown id. The prompt asks for no mocks for that reason.
Will it fix the bugs the tests find?
Not in this request: it marks those tests as failing and explains each one, so you decide what the right behavior is. Send a follow-up on the same session, such as asking for ConditionExpression on update and a 404 on delete, and it changes the handlers and turns the tests green.
Does it work with Python handlers too?
Yes, with pytest and boto3 instead of Jest and the v3 SDK. boto3 honours the same AWS_ENDPOINT_URL_DYNAMODB override, so the shape of the suite is the same; change the prompt to name pytest.