
Agent Friendly Apis
Fix Next.js and REST API bugs that break agent callers—wrong status codes, broken filters, dynamic routes, and summary stats—using symptom-driven recipes.
Install
npx skills add https://github.com/vercel-labs/academy-skills --skill agent-friendly-apisWhat is this skill?
- Symptom-organized fixes for API, documentation, and skill-integration failures
- Wrap `request.json()` in try/catch to return 400 instead of 500 on parse errors
- Query-filter checklist: searchParams, exact param names, `===`, filter before respond
- Dynamic route checklist: bracket paths, await params in Next.js 16, correct data lookup
- Guards against NaN aggregates (e.g. averageRating) on summary endpoints
Adoption & trust: 18 installs on skills.sh; 7 GitHub stars; 2/3 security scanners passed (skills.sh audits).
Recommended Skills
Journey fit
Agent-friendly API design and debugging sit on the backend shelf because route handlers, validation, and JSON contracts are implemented there first. Backend is the canonical home for POST/GET semantics, query filtering, dynamic `[id]` routes, and aggregate endpoints agents rely on.
Common Questions / FAQ
Is Agent Friendly Apis safe to install?
skills.sh reports 2 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.
SKILL.md
READMESKILL.md - Agent Friendly Apis
# Debugging Agent-Friendly APIs Common problems and fixes organized by symptom. Covers API issues, documentation issues, and skill issues. ## API Issues (Section 1) ### POST returns 500 instead of 400 **Symptom:** Sending invalid data to `POST /api/feedback` returns a 500 error instead of a descriptive 400. **Cause:** Validation runs after `request.json()` but the request body isn't valid JSON, or destructuring fails before validation runs. **Fix:** Wrap `request.json()` in a try/catch and return a 400 for parse failures: ```typescript let body; try { body = await request.json(); } catch { return NextResponse.json( { error: "Invalid JSON in request body" }, { status: 400 } ); } ``` ### Query parameters don't filter **Symptom:** `GET /api/feedback?courseSlug=knife-skills` returns all entries instead of filtered results. **Check these in order:** 1. `searchParams` is extracted from the request URL (not the request object directly) 2. Parameter names match exactly (case-sensitive) 3. Filter logic uses `===` not `==` 4. The filter runs before returning the response, not after ### Dynamic route returns 404 **Symptom:** `GET /api/feedback/fb-001` returns 404 even though the entry exists. **Check:** 1. File is at `app/api/feedback/[id]/route.ts` (brackets required) 2. Params are awaited in Next.js 16: `const { id } = await params` 3. The ID lookup function searches the correct data source ### Summary endpoint returns NaN for averageRating **Symptom:** `averageRating` is `NaN` in the summary response. **Cause:** Division by zero when no feedback entries match, or ratings aren't parsed as numbers. **Fix:** Check for empty arrays before dividing: ```typescript const averageRating = entries.length > 0 ? entries.reduce((sum, e) => sum + e.rating, 0) / entries.length : 0; ``` ### Summary missing ratingDistribution levels **Symptom:** `ratingDistribution` only shows levels that have entries (e.g., `{"4": 3, "5": 5}`) instead of all five levels. **Fix:** Initialize all five levels to zero: ```typescript const ratingDistribution: Record<string, number> = { "1": 0, "2": 0, "3": 0, "4": 0, "5": 0 }; ``` ## Documentation Issues (Section 2) ### llms.txt returns HTML instead of text **Symptom:** Hitting `/llms.txt` in the browser shows HTML, or curl returns HTML. **Cause:** The route handler isn't setting the Content-Type header, so Next.js defaults to HTML. **Fix:** Explicitly set the header: ```typescript return new NextResponse(content, { headers: { "Content-Type": "text/plain; charset=utf-8" }, }); ``` ### Docs endpoint returns empty response **Symptom:** `curl /api/docs.md` returns an empty body. **Check:** 1. The template string isn't empty (easy to miss with template literals) 2. The variable holding the content is defined before the export 3. No syntax errors in the template string (unescaped backticks inside code blocks) ### Code blocks in docs have wrong escaping **Symptom:** Generated docs have `\`\`\`` instead of proper code fences, or JSON examples have extra backslashes. **Cause:** Template literals in TypeScript need backticks escaped. When generating docs that contain code blocks, the backticks in the code block conflict with the template literal. **Fix:** Use a raw string or read the content from a separate file instead of embedding it in the route handler. ## Skill Issues (Section 3) ### Skill doesn't trigger **Symptom:** You say "generate docs for my API" but the skill doesn't activate. **Fixes in order:** 1. Check the description field includes trigger phrases matching what you typed 2. Add more variations: "generate docs", "document this API", "create API documentation", "make docs for my endpoints", "write API docs" 3. Make sure the SKILL.md is in the project root or installed via `npx skills add` ### Skill skips endpoints **Symptom:** Generated docs only cover 2 of 4 endpoints. **Cause:** The glob pattern in Step 1 didn't match all route files. **Fix:** Ensure the