agentsclimarketplace

Fai api endpoint generator

Skill frootai/frootai/skills/fai-api-endpoint-generator

Generate typed REST API endpoints with Zod/Pydantic input validation, RFC 7807 error responses, OpenAPI annotation, and Managed Identity auth — eliminating schema drift and IDOR vulnerabilities.From its SKILL.md

Install
npx -y skills add frootai/frootai --skill fai-api-endpoint-generator

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 7 stars7 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

6.0 KB, as published. Nobody here has run it

FAI API Endpoint Generator

Builds production-ready REST API endpoints that combine strict schema validation, standardised error envelopes, and OpenAPI documentation in a single pass. Prevents the three most common API issues in AI services: missing input bounds (which enable prompt injection), inconsistent error surfaces, and docs that lag behind code.

When to Invoke

SignalExample
Building a new AI service routePOST /completions, GET /documents/{id}
Existing endpoint lacks validationNo Pydantic model or Zod schema present
Error responses are inconsistentMix of plain strings and JSON objects
OpenAPI spec is missing or staleSwagger shows wrong request shape

Workflow

Step 1 — Define the Contract

Before writing any code, capture the request shape, success payload, and failure modes.

// TypeScript — Zod contract first
import { z } from "zod";

export const CompletionRequestSchema = z.object({
  prompt:      z.string().min(1).max(4000),
  model:       z.enum(["gpt-4o", "gpt-4o-mini"]).default("gpt-4o-mini"),
  max_tokens:  z.number().int().min(1).max(2000).default(512),
  temperature: z.number().min(0).max(2).default(0.7),
  stream:      z.boolean().default(false),
});

export type CompletionRequest = z.infer<typeof CompletionRequestSchema>;
# Python — Pydantic contract first
from pydantic import BaseModel, Field
from typing import Literal

class CompletionRequest(BaseModel):
    prompt:      str  = Field(min_length=1, max_length=4000)
    model:       Literal["gpt-4o", "gpt-4o-mini"] = "gpt-4o-mini"
    max_tokens:  int  = Field(default=512, ge=1, le=2000)
    temperature: float = Field(default=0.7, ge=0, le=2)
    stream:      bool  = False

Step 2 — Implement the Route Handler

// Express route with Zod middleware
import express from "express";
import { DefaultAzureCredential } from "@azure/identity";
import { AzureOpenAI } from "openai";

const router = express.Router();
const credential = new DefaultAzureCredential();   // Managed Identity — no API key

router.post("/completions",
  validateBody(CompletionRequestSchema),            // Zod middleware
  async (req, res, next) => {
    try {
      const { prompt, model, max_tokens, temperature } = req.body as CompletionRequest;
      const client = new AzureOpenAI({ azureADTokenProvider: () => credential.getToken("https://cognitiveservices.azure.com/.default").then(t => t.token) });
      const result = await client.chat.completions.create({
        model, messages: [{ role: "user", content: prompt }],
        max_tokens, temperature,
      });
      res.json({ status: "success", data: result.choices[0] });
    } catch (err) {
      next(err);                                   // Centralised error handler
    }
  }
);

Step 3 — Standardise Error Responses (RFC 7807)

// Centralised error handler — all errors become Problem Details
interface ProblemDetails {
  type:      string;
  title:     string;
  status:    number;
  detail?:   string;
  instance?: string;
}

function errorHandler(err: unknown, req: express.Request, res: express.Response) {
  const problem: ProblemDetails = {
    type:     "https://frootai.dev/errors/internal",
    title:    "Internal Server Error",
    status:   500,
    instance: req.path,
  };

  if (err instanceof z.ZodError) {
    problem.type   = "https://frootai.dev/errors/validation";
    problem.title  = "Request Validation Failed";
    problem.status = 400;
    problem.detail = err.errors.map(e => `${e.path.join(".")}: ${e.message}`).join("; ");
  }
  res.status(problem.status).json(problem);
}

Step 4 — Add OpenAPI Annotation

/**
 * @openapi
 * /completions:
 *   post:
 *     summary: Generate an AI completion
 *     tags: [Completions]
 *     security:
 *       - BearerAuth: []
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             $ref: '#/components/schemas/CompletionRequest'
 *     responses:
 *       200:
 *         description: Successful completion
 *       400:
 *         description: Validation error (RFC 7807 Problem Details)
 *       429:
 *         description: Rate limited
 */

Step 5 — Request ID Propagation

// Middleware — inject correlation ID for distributed tracing
app.use((req, res, next) => {
  const requestId = (req.headers["x-request-id"] as string) ?? crypto.randomUUID();
  res.setHeader("x-request-id", requestId);
  (req as any).requestId = requestId;
  next();
});

Output Envelope

{
  "status": "success",
  "data": { "text": "...", "model": "gpt-4o-mini", "usage": { "total_tokens": 213 } },
  "meta": { "request_id": "a1b2c3d4", "duration_ms": 187, "cached": false }
}

WAF Alignment

PillarContribution
SecurityZod/Pydantic bounds prevent over-size prompt injection; Managed Identity eliminates API key exposure
ReliabilityRFC 7807 error envelope enables consistent retry logic on the client side
Performance EfficiencyTyped schemas reduce deserialization overhead; stream=true enables token-level streaming
Operational ExcellenceOpenAPI annotation keeps docs in sync with code; request ID enables distributed trace correlation

Compatible Solution Plays

  • Play 01 — Enterprise RAG (POST /query endpoint)
  • Play 14 — Cost-Optimized AI Gateway (routing endpoints)
  • Play 29 — MCP Server (tool registration endpoints)

Notes

  • Always leave the name field unquoted per agentskills.io spec
  • Zod errors -> 400 with Problem Details; unhandled exceptions -> 500
  • Use DefaultAzureCredential not an API key — avoids key rotation risk and supports local dev via az login

Keep looking

Skills are one crate of 627,801. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.