# Add Health Checks to an ASP.NET Core App from a Linear Issue

Yes. An agent picks up the Linear issue, adds liveness and readiness checks to your ASP.NET Core app, tests them and opens a pull request.

[Run this on Rush](https://cloud.getrush.ai/run/add-health-checks/aspnet-core/), in a Project that has your repository.

## What the agent does

The agent clones the repository into its own cloud sandbox and first finds what the app already has, because a .NET solution built on Aspire usually maps health endpoints before anyone asks for them. In a solution like jasontaylordev/CleanArchitecture (SDK `10.0.402` in `global.json`, packages pinned in `Directory.Packages.props`), `src/ServiceDefaults/Extensions.cs` has `AddDefaultHealthChecks`, which registers one check named `self` tagged `live`, and `MapDefaultEndpoints`, which maps `/health` for every check and `/alive` for the `live` ones. Both are mapped only inside `if (app.Environment.IsDevelopment())`, under a comment pointing to the Aspire guidance on exposing them in other environments. So today the endpoints exist, under different paths, return plain text, and are absent in production.

Next it looks for the database check the issue's ready endpoint needs. `src/Web/Web.csproj` already references `Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore` (version `10.0.13` in `Directory.Packages.props`), but nothing in `src/` calls `AddDbContextCheck`, so the package is there and no check uses it. `src/Infrastructure/DependencyInjection.cs` registers `ApplicationDbContext` against SQLite, PostgreSQL or SQL Server depending on template symbols, and the PostgreSQL and SQL Server branches also call Aspire's `EnrichNpgsqlDbContext` or `EnrichSqlServerDbContext`. The agent checks whether that enrichment already adds a check for the context before adding its own, so the ready endpoint does not report the database twice under two names.

Then it makes the change in the file that owns health checks rather than in `Program.cs`: in `Extensions.cs` it adds a `ready`-tagged `AddDbContextCheck<ApplicationDbContext>()` (or tags the existing one), maps `/health/live` to the `live` checks and `/health/ready` to the `ready` ones, and sets `ResponseWriter` on both `HealthCheckOptions` so the body is JSON with the overall status and each check's name, status and duration. Whether the endpoints leave the development-only block is a decision for the issue's author, so the agent keeps them where the issue says, and if the issue does not say, it leaves the block alone and asks on the pull request. `src/Web/Program.cs` already calls `app.MapDefaultEndpoints()`, so it needs no edit.

Last, it writes the tests where the solution's tests already run against a real app. `tests/Application.FunctionalTests` starts `TestAppHost` with `DistributedApplicationTestingBuilder`, waits for the database resource to be healthy and builds a `WebApiFactory`, a `WebApplicationFactory<Program>` that sets `ConnectionStrings:CleanArchitectureDb`. The agent adds tests that call `/health/live` and `/health/ready` through that factory and read the JSON, and one where the database is unreachable and ready reports `Unhealthy` while live stays `Healthy`. It runs `dotnet test` the way `.github/workflows/build.yml` does, after `dotnet restore` and `dotnet build`, and fixes what fails before it pushes.

## Start it with one API call

`POST https://api.prix.dev/o/{org}/sessions`

```json
{
  "agent": "codex",
  "input": "A Linear issue labeled agent says: \"Add Health Checks to an ASP.NET Core App. Add /health/live and /health/ready endpoints with ASP.NET Core health checks, where ready checks the database, and return JSON with each check's status.\" Before changing anything, find where this solution already registers and maps health checks (AddHealthChecks, MapHealthChecks, any Aspire ServiceDefaults project) and whether the endpoints are limited to Development, and list it in the pull request. Extend that code rather than adding a second registration: live runs only the checks tagged live, ready runs a database check through the EF Core DbContext, and both write JSON with the overall status and each check's name, status and duration. Do not change which environments expose the endpoints unless the issue says so; ask in the pull request instead. Add tests in the existing functional or integration test project, including one where the database is unreachable, run dotnet restore, dotnet build and dotnet test until they pass, and open a pull request that links back to the issue.",
  "resources": [
    {
      "url": "https://github.com/your-org/your-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 its own branch, linked to the Linear issue. In a solution shaped like CleanArchitecture, the diff is small: `src/ServiceDefaults/Extensions.cs` gains the database check and the two mapped paths with a JSON response writer, and a new test class sits in `tests/Application.FunctionalTests`. The description lists what was already there (`/health`, `/alive`, the `self` check, the unused EF Core health check package), what changed, and the open question about exposing the endpoints outside Development.

The pull request's own checks run the solution's workflow: `.github/workflows/build.yml` restores, builds in Release and runs `dotnet test` on every pull request to `main`. The session's transcript keeps every command the agent ran in its sandbox with its output, so a reviewer can read the failing test run that came before the fix, not only the passing one.

Before merging, a reviewer checks that the old `/health` and `/alive` paths still answer for anything that probes them (an Aspire dashboard, a container orchestrator's liveness probe) or that the pull request says they moved, that the ready check uses the same connection string the app does, and that the JSON body exposes no connection string or exception detail to whoever can reach the endpoint.

## Run it on every Linear issue labelled agent

Add an automation in the console with a `linear` trigger on `linear.issue.labeled` for the label `agent`, and every issue labelled that way starts one run in the Project's repository with the issue as its context. Changes an app integration makes never fire the trigger, so an agent's own comment on the issue does not start another run.

To start runs from your own service instead, send one `POST /o/{org}/sessions` per issue with the repository in `resources`, and the issue's `https://linear.app/<workspace>/issue/<ID>` URL beside it to have Rush read the issue through your Linear connection. Give the API key a webhook URL and Rush posts `run.completed` or `run.failed` when each turn finishes.

## Why run it on Rush?

Health checks only prove anything when the app starts and the database is really there. A Rush sandbox has its own .NET SDK, restores the solution's packages and starts the Aspire test host and its database on its own disk, so the agent runs the same `dotnet test` the workflow runs, including the case where the database is down, without anyone's local SQL Server or Docker state being touched.

The label is the only step a person takes, and the result arrives with its evidence: the transcript holds each `dotnet` command with its output, the pull request carries the workflow's checks, and the description says what existed before. Several labelled issues across services can run at once, each in its own sandbox and on its own branch.

## Frequently asked questions

### My app uses Aspire ServiceDefaults. Will it add a second set of health checks?

No. The prompt has the agent find `AddDefaultHealthChecks` and `MapDefaultEndpoints` first and extend them, so there is still one place where checks are registered and mapped. The pull request lists what was there before it changed anything.

### Will the endpoints be exposed in production?

Only if the issue says so. The Aspire template maps health endpoints in Development only, on purpose, and the agent keeps that unless told otherwise. When the issue does not say, it asks in the pull request, because exposing them is a security decision and not an implementation detail.

### Which database does the ready check use?

The one your `DbContext` is configured with. `AddDbContextCheck` runs a connection test through the registered context, so it follows whatever provider and connection string the app uses, whether SQLite, PostgreSQL or SQL Server.

### How is the JSON response shaped?

The agent sets a `ResponseWriter` on `HealthCheckOptions` that writes the overall status and, for each check, its name, status and duration. If your team already has a format, such as one an orchestrator or a dashboard reads, name it in the issue and the agent writes that shape instead.
