What the agent does
The agent clones the service into its own cloud sandbox and starts where Gin starts: the router. In a Gin API like gothinkster/golang-gin-realworld-example-app, go.mod declares go 1.21 with github.com/gin-gonic/gin v1.10.0, gorm.io/gorm v1.25.12 on the SQLite driver, github.com/golang-jwt/jwt/v5 and github.com/go-playground/validator/v10. hello.go builds gin.Default(), turns RedirectTrailingSlash off with a comment explaining that a redirect would drop a POST body, and makes one group, v1 := r.Group("/api"). The registrations that follow are not one list: users.UsersRegister(v1.Group("/users")) comes before v1.Use(users.AuthMiddleware(false)), the anonymous article, tag and profile groups come after it, and v1.Use(users.AuthMiddleware(true)) precedes UserRegister, ProfileRegister and ArticlesRegister. A /api/ping group sits outside v1 entirely.
That ordering is the auth rule, so the agent records it per endpoint rather than per file. users/middlewares.go shows what the two modes mean: extractToken reads an Authorization header that starts with Token or an access_token query parameter, AuthMiddleware(false) sets my_user_id to zero and continues when there is no token, and AuthMiddleware(true) aborts with 401. So POST /api/users and POST /api/users/login take no token, GET /api/articles, GET /api/articles/:slug, GET /api/articles/:slug/comments, GET /api/tags and GET /api/profiles/:username take an optional one, and everything registered after the second Use, from GET /api/user and PUT /api/user to POST /api/profiles/:username/follow, GET /api/articles/feed, PUT /api/articles/:slug, DELETE /api/articles/:slug, the favorite routes and POST and DELETE on comments, requires one.
For each handler the agent reads the function body for what it takes and returns. ArticleList in articles/routers.go reads tag, author, favorited, limit and offset from the query; ArticleFeed reads limit and offset; ArticleRetrieve, ArticleUpdate and ArticleDelete read the slug path parameter; ArticleCreate binds through NewArticleModelValidator and answers 422 with common.NewValidatorError on a bad body or common.NewError("database", err) on a save failure, then 201 with an ArticleSerializer. The same reading of users/routers.go, users/validators.go, articles/validators.go and both serializers.go files fills the validator and response columns. Registrations that exist twice, such as POST "" and POST "/" on /users and PUT /:slug beside PUT /:slug/ on articles, are listed as one endpoint with both spellings, since RedirectTrailingSlash is off and both are reachable.
Then it cross-checks the table against two things that already exist. gin.Default() runs in debug mode and prints every registered route with its handler name at startup, so the agent builds and starts the binary with PORT set, as scripts/run-api-tests.sh does, and diffs that output against its table. And it maps tests to endpoints: articles/unit_test.go has 41 test functions that drive a setupRouter copy of the real groups through httptest, users/unit_test.go has 6 and common/unit_test.go has 16, while api/Conduit.postman_collection.json is the RealWorld collection that run-api-tests.sh runs with newman in the api-test job of .github/workflows/ci.yml. Each row gets a column for unit coverage and one for Postman coverage, with the test or request name.
Start it with one API call
POST https://api.prix.dev/o/{org}/sessions with this body:
{
"agent": "claude",
"input": "Write an inventory of every HTTP endpoint in this Gin service as endpoints.md. Start from hello.go: list each router group, the order in which AuthMiddleware(false) and AuthMiddleware(true) are applied with v1.Use, and which registrations come before and after each. Read users/routers.go, articles/routers.go and users/middlewares.go, then for every route write a table row with method, path, handler function and package, auth rule (none, optional token or required token), path and query parameters read with c.Param and c.Query, the validator that binds the body, the serializer that shapes the response, and the status codes the handler returns. Treat duplicate registrations with and without a trailing slash as one endpoint and note both spellings. Build and start the server with PORT set, as scripts/run-api-tests.sh does, and compare the route list gin prints in debug mode against your table; report any difference. Add a column saying which test in articles/unit_test.go, users/unit_test.go or common/unit_test.go exercises each endpoint and which request in api/Conduit.postman_collection.json does, and finish with the endpoints no test touches. Do not change any file, commit, push or open a pull request.",
"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 one file, endpoints.md, as an artifact on the session, with a download link that works for an hour and is refreshed on every read of the session. Its first part is the middleware map: the /api group, the two Use calls and which group registrations fall before and after each, so the auth rule for every path can be read off in one glance. Its second part is the table, one row per endpoint, in the order Gin registers them, with the handler and package, the auth rule, the parameters, the validator and serializer, the status codes and the two coverage columns.
The report ends with what the cross-checks found: any route the running binary printed that the table lacks or the reverse, and the list of endpoints no unit test and no Postman request reaches. In a service shaped like this one the interesting rows are the duplicate registrations, the access_token query parameter that the header-only Postman collection never uses, and the /api/ping route that lives outside the /api group's middleware.
A reviewer checks the auth column against the middleware order first, because that column is derived from hello.go rather than from annotations and is the one most worth getting right, then uses the untested list to decide what to write next or to hand to a follow-up run on the same session.
Run it on every pull request that touches a routers.go file
The inventory goes stale the day someone adds a route, so run it where routes change. Add an automation to the Project with this prompt and a github trigger on pull_request.opened and pull_request.synchronize; the trigger adds the pull request event after the prompt, so the agent can diff the table it writes against the one on the default branch and post the rows that changed. The run clones the pull request's branch through the Rush GitHub App installation. An automation starts at most max_runs_per_hour runs in an hour, which is the cap to raise when a busy repository opens many pull requests at once.
From your own server, the same request starts a run with resources pointing at https://github.com/your-org/your-app/tree/<branch>, and a request_id derived from the commit SHA so a retried delivery returns the run it already started. Give the key a webhook URL and Rush POSTs run.completed with data.session_url when the turn ends; your handler reads the session, takes the endpoints.md artifact link and attaches it to the pull request as a comment.
The use case this job follows, with its automation and trigger: Produce a report or file, no repo.
Why run it on Rush?
An endpoint table written from memory is wrong the first time someone reorders a Use call. The agent derives it from hello.go and the router files, then starts the real binary in its own sandbox and checks the printed route list against what it wrote. That second step needs a built Go toolchain, a writable ./data/gorm.db path and a free port, which the sandbox has and a shared staging box may not.
The proof travels with the report. The transcript at GET /o/{org}/sessions/{id}/messages keeps the go build, the server start with its debug route listing and every file the agent read, so a reviewer can see where each row came from. Several services, or several branches of one, run at once in separate sandboxes, each producing its own table.
Frequently asked questions
Does it need the server to run to write the table?
No. The table comes from reading hello.go and the routers.go files. Starting the binary is a cross-check: Gin in debug mode prints every registered route with its handler name, and the agent diffs that against its table so a route registered somewhere it did not read still shows up.
How does it decide the auth rule for a route?
From the order of calls in hello.go. A group registered before v1.Use(users.AuthMiddleware(false)) has no auth middleware, one registered between the two Use calls gets an optional token, and one registered after v1.Use(users.AuthMiddleware(true)) requires a token. The agent writes that order down in the report so the rule can be checked rather than trusted.
What does the coverage column mean?
Two things, kept apart. Unit coverage names the Test function in articles/unit_test.go, users/unit_test.go or common/unit_test.go that sends a request to that path through httptest. Postman coverage names the request in api/Conduit.postman_collection.json that the api-test CI job runs with newman against the real server. An endpoint can have one without the other.
Can it also produce an OpenAPI document?
Send a follow-up on the same session asking for openapi.yaml, and it builds one from the same table, with the validator structs as request schemas and the serializer structs as responses. This prompt stops at the Markdown table so the first result is quick to review.