FastAPI · requirements checked during agent edits
Build a FastAPI endpoint that keeps discount limits intact
Pydantic validates the request before the handler runs. A 20% discount on 100 returns 80.00. A 21% discount returns HTTP 422. Removing only the upper bound keeps valid requests working while allowing the business requirement to regress.
Implement the requirement
Save this as main.py:
from decimal import Decimal
from fastapi import FastAPI
from pydantic import BaseModel, Field
app = FastAPI()
class Checkout(BaseModel):
subtotal: Decimal = Field(gt=0)
discount_percent: Decimal = Field(default=0, ge=0, le=20)
@app.post("/checkout")
def checkout(body: Checkout):
total = body.subtotal * (1 - body.discount_percent / 100)
return {"total": str(total.quantize(Decimal("0.01")))}
The requirement is adapted from Perch’s public order-service example at commit 4af67af. The FastAPI implementation below is an illustrative adaptation, not a claim about that source project’s framework.
Create the FastAPI project
mkdir checked-fastapi
cd checked-fastapi
python3 -m venv .venv
. .venv/bin/activate
python -m pip install 'fastapi[standard]' httpx pytest
git init -b tutorial
Save the implementation above in the new project.
Start the development server with fastapi dev main.py. Follow the FastAPI setup documentation for platform prerequisites. The framework API used here is documented in the official reference.
Test the broken and corrected behavior
Save this as test_main.py:
from fastapi.testclient import TestClient
from main import app
client = TestClient(app)
def test_discount_boundary():
response = client.post("/checkout", json={"subtotal": "100", "discount_percent": "20"})
assert response.status_code == 200
assert response.json()["total"] == "80.00"
assert client.post("/checkout", json={"subtotal": "100", "discount_percent": "21"}).status_code == 422
assert client.post("/checkout", json={"subtotal": "100", "discount_percent": "-1"}).status_code == 422
Run python -m pytest -q. Then make this deliberate regression: replace Field(default=0, ge=0, le=20) with Field(default=0, ge=0). The boundary test should fail. Restore the original before continuing.
Save the requirement as a Perch rule
Perch is an open-source semantic linter powered by SystemOne decision models. Save the following rule in .perch/rules/perch-guide-fastapi-intro.yaml at the repository root, keeping your existing perch.yaml:
- name: discount-limit
where: "main.py"
ensure: >-
The discount percentage accepted by the checkout endpoint must be constrained to the inclusive range 0 to 20 before a total is calculated.
Install the CLI and sign in, then check the working file:
npm install -g @lakeday/perch
perch login
perch check main.py --rules discount-limit --json
Use Node 22 or newer. perch login opens the authentication workflow. perch check reads the file currently on disk, so the agent can check an uncommitted edit. A rule finding exits 3; exits 1 and 2 mean the check did not complete. Read the JSON and the code before deciding what to change.
Captured Perch check
On October 14, 2026, we ran the rule above through Perch using jev-latest on the deliberately broken and corrected files.
| Control | Command exit | Outcome |
|---|---|---|
| Broken implementation | 3 | Rule finding reported |
| Corrected implementation | 0 | No rule finding reported |
The rule distinguished these two controls in this captured run. Fresh judgments can vary. Captured command output and the broken and corrected source are available for inspection.
Install the rule pack and configure your agent
Download this rule pack ZIP · Download the YAML rules · Agent task. The pack contains the rule, its example paths and the repair/recheck instructions. Review the where selector before using it in an existing project. Keep your root perch.yaml; install this rule as a separate file under .perch/rules/.
- Install Perch using Node 22 or newer and sign in once:
npm install -g @lakeday/perch
perch login
- Download the pack, inspect it, and extract it from your repository root. The extraction preserves any existing files:
curl -fL 'https://frameworkrecipes.dev/fastapi/intro/rule-pack.zip' -o 'perch-guide-fastapi-intro.zip'
unzip -n 'perch-guide-fastapi-intro.zip'
The installed rule is .perch/rules/perch-guide-fastapi-intro.yaml. Its selector matches main.py in this example; adapt the selector to your application file before checking an existing project.
- Configure the coding agent you use. Run one of these commands:
Claude Code:
perch setup claude-code
Codex:
perch setup codex
Cursor:
perch setup cursor
Pi:
perch setup pi
- Ask the agent to edit the implementation and check the saved requirement:
Use the installed Perch skill while editing main.py. Preserve discount-limit. Run perch check main.py --rules discount-limit --json after the edit. Read each finding and the affected code, fix the implementation, and run the identical check again after the fix. Keep the rule and regression tests intact. Run the application's relevant regression tests and report the commands and actual results. Exit 3 means a rule finding; exit 1 or 2 means the check did not complete. Report an unavailable or incomplete check as blocked. Do not claim the application tests ran if only the Perch check ran.
- After repairing a finding, run the same check again and inspect the result:
perch check main.py --rules discount-limit --json
Commit the downloaded rule and the installed agent configuration with your application. The rule file adds no guarantee of correctness; keep the regression tests from this guide.
Keep the checks within their scope
This example calculates a quote. A real checkout must use trusted server prices, currency-specific rounding, durable order state, and payment-provider idempotency. Request validation is one requirement, not a complete checkout implementation.
Fresh model judgments can vary. Unchanged requests can reuse cached answers. A passing rule check does not prove the application correct; keep the executable test as a separate check. Relevant source code is sent to the configured analysis service.
Published by Perch / Verglas LLC. Framework names identify the software used; this guide is not an official framework publication.