# Add Resource Requests and Limits to a Kustomize App from a Linear Issue

Yes. An agent reads the issue, finds every container in your Kustomize app without resources, adds requests and limits, validates the render and opens a PR.

[Run this on Rush](https://cloud.getrush.ai/run/add-resource-limits/kustomize/), in a Project that has your repository.

## What the agent does

The agent starts from the Linear issue and the repository in its own cloud sandbox, and takes an inventory before it edits a manifest. In a GitOps repository shaped like argoproj/argocd-example-apps, `sock-shop/kustomization.yaml` lists 29 files under `base/`: 14 Deployments, 14 Services and one Ingress for `sockshop.apps.argoproj.io`. Eight of the Deployments already carry a `resources` block, and they are not uniform: `carts`, `queue-master` and `shipping` ask for and cap at `300m` CPU and `500Mi` memory, `catalogue` at `100m` and `100Mi`, `front-end` requests `100m` and `300Mi` under limits of `300m` and `1000Mi`, `orders` requests `200m` under a `500m` limit, `payment` requests `99m` under `100m`, and `user` requests `100m` CPU under `300m` with `100Mi` both ways. The other six have none: `carts-db`, `orders-db` and `session-db` (the `mongo` and `redis:alpine` images), `catalogue-db`, `user-db`, and `rabbitmq`, which also runs a `kbudde/rabbitmq-exporter` sidecar with no resources of its own, so there are seven containers to change. The smaller `kustomize-guestbook` app has one Deployment of `gcr.io/google-samples/gb-frontend:v5` with nothing set either.

The agent then decides where the change goes. `sock-shop` has no overlays; its `kustomization.yaml` names the base files directly, so a `patches` block would be a second place to look for a value that belongs in one. It edits each Deployment under `sock-shop/base/` in place and keeps the diff to the `resources` block. Where an app does have overlays, as `kustomize-guestbook` would after a staging overlay is added, it writes a strategic merge patch in the overlay instead, so the base stays environment-neutral. The values come from the issue when it gives them; when it gives none, the agent starts each container at the smallest tier already in the app, `100m` CPU and `100Mi` memory as `catalogue` and `payment` use, with requests equal to limits so the pod lands in the `Guaranteed` QoS class like `carts` and `shipping`, and the pull request says plainly that these are starting points to be tuned from metrics, not measured numbers. For `carts` it also notes the existing `JAVA_OPTS` of `-Xmx128m` against a `500Mi` limit, since the heap cap and the container cap should be read together.

Then it renders and checks. `kustomize build sock-shop` must still produce all 29 resources with the new blocks in place and nothing else changed, and the agent diffs that output against a build of the base branch to show the change is only what it meant. It runs `kubeconform -strict -summary` over the rendered YAML so a misplaced key such as `resources` at the pod level rather than the container level is caught, and where a `kind` cluster is available in the sandbox it applies the output with `kubectl apply --dry-run=server` to let the API server validate the quantities. The repository has no CI of its own, so these three commands are the checks, and their output goes into the pull request.

The pull request also carries a table: one row per container, with the image, the requests and limits before and after, and the QoS class the pod will get. Containers that were already set are listed as unchanged, so a reviewer sees the whole app, not only the diff.

## Start it with one API call

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

```json
{
  "agent": "claude",
  "input": "Add resource requests and limits to the Kustomize app the attached Linear issue names. Read its kustomization.yaml and every Deployment it lists, including sidecar containers, and build a table of which containers already have a resources block and which do not. Add requests and limits to the ones without: use the values the issue gives, and when it gives none, start from the smallest tier already present in the app with requests equal to limits, and say in the pull request that they are starting points. Edit the base files in place when the app has no overlays, otherwise add a strategic merge patch in the overlay. Run kustomize build on the app, diff the output against the base branch to show only resources blocks changed, run kubeconform -strict -summary on the rendered output, and apply it with kubectl --dry-run=server if a cluster is available. Open a pull request linking the issue with the before and after table, the QoS class per pod and the command output. Do not change images, replicas or probes.",
  "resources": [
    {
      "url": "https://github.com/your-org/your-app"
    },
    {
      "url": "https://linear.app/your-org/issue/ENG-123"
    }
  ]
}
```

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 that touches only the Deployment files for containers that had no `resources` block, in `sock-shop/base/` six files covering seven containers. The description links the Linear issue, carries the per-container table with the before and after values and QoS class, and quotes the `kustomize build` diff summary, the `kubeconform` summary line and, when a cluster was available, the dry-run output.

The transcript at `GET /o/{org}/sessions/{id}/messages` keeps each `kustomize build`, the diff and the validation runs with their full output, and `GET /o/{org}/p/{project}/sessions/{id}/changes` lists each changed file with its diff. A rendered output that fails validation ends the run `needs_review` instead of a pull request that claims the manifests are valid.

Before merging, a reviewer checks the starting values against what the cluster's metrics show for those pods, confirms no `LimitRange` or `ResourceQuota` in the target namespace rejects them, and reads the `rabbitmq` change twice because that pod has two containers. Argo CD picks the change up on sync; a follow-up on the same session can raise a value once the first sync has run for a day.

## Run it on every Linear issue labelled agent

In the console, add an automation to the Project with this prompt and a `linear` trigger on `linear.issue.labeled`, filtered to the `agent` label and to the platform team. When someone labels an issue such as "sock-shop databases have no resource limits, pods get evicted first under pressure", the trigger puts the issue after the prompt and the run scopes itself to the app the issue names, with the values it gives. Only label changes made by a person in your Rush org fire the trigger, and the automation starts at most `max_runs_per_hour` runs in an hour.

From your own server, the same body goes to `POST /o/{org}/sessions` with the repository in `resources` and the issue's URL beside it, read through your Linear connection, and a `request_id` made from the issue id so a retried call returns the run already started rather than opening a second pull request.

## Why run it on Rush?

Resource blocks are easy to type and easy to put in the wrong place, and a GitOps repository with no CI finds out at sync time. In its own sandbox the agent renders the app with the same `kustomize` Argo CD runs, validates the output with `kubeconform`, and keeps the diff against the base branch, so the pull request shows that the only change is the one the issue asked for.

Several apps can run at once, each in a separate sandbox and a separate pull request, and every command is in the transcript. A reviewer who wants to know why a value was chosen reads the table and the issue, not a commit message.

## Frequently asked questions

### Where do the numbers come from?

From the Linear issue when it gives them. When it does not, the agent uses the smallest tier already present in the same app, which in `sock-shop` is `100m` CPU and `100Mi` memory, sets requests equal to limits, and marks them as starting points in the pull request. It invents no figures from the images, and the reviewer is expected to adjust them from metrics.

### Does it edit the base or add a patch?

It depends on the app's layout. `sock-shop` lists its base files directly in `kustomization.yaml` with no overlays, so the agent edits the Deployment files and the diff stays readable. An app with overlays gets a strategic merge patch in the overlay, so the base stays free of environment-specific numbers.

### What about sidecars?

A Deployment is checked per container, not per pod. In `sock-shop/base/rabbitmq-dep.yaml` the `rabbitmq-exporter` sidecar has no `resources` block even though it sits next to the main container, so it gets its own block and its own row in the table.

### Can it validate without a cluster?

Yes. `kustomize build` and `kubeconform -strict` run with no cluster and catch schema and placement mistakes. The `kubectl apply --dry-run=server` step runs only when a `kind` cluster is available in the sandbox, and the pull request says which of the three checks ran.
