← Back to list

What Happened When I Let AI Agents Design My REST APIs

One thing I’ve noticed across most enterprise backend systems is this:

Santosh Sharma · 2026-05-16 19:58 · 0 claps · 6.7 min read paywalled
#crew-ai #agentic-ai #restful-api #llm-applications #multi-agent-systems
Open on Medium ↗
Wiki topics: LLM · Large Language Models AGT · AI Agents 🌐 · Web Development

What Happened When I Let AI Agents Design My REST APIs

Building an AI-Powered OpenAPI Architect with CrewAI, PostgreSQL, and RAG

Building an AI-Powered OpenAPI Architect with CrewAI, PostgreSQL, and RAG

One thing I’ve noticed across most enterprise backend systems is this:

Teams spend enormous effort designing database schemas, but API contracts are still largely handcrafted.

Even in organizations with mature platform engineering teams, OpenAPI specs are often:

  • manually written
  • inconsistent across services
  • poorly versioned
  • disconnected from actual database models
  • missing validation rules
  • lacking pagination standards
  • inconsistent in error handling

And once a system grows beyond a few services, the problem compounds quickly.

A typical enterprise platform may contain:

  • hundreds of REST endpoints
  • dozens of microservices
  • multiple API versions
  • several frontend consumers
  • mobile-specific contracts
  • internal vs external APIs
  • RBAC rules
  • audit requirements
  • async workflows
  • reporting APIs

At that scale, API design becomes an architecture problem, not just documentation work.

This is where AI agents become genuinely useful.

I recently experimented with building a CrewAI-based multi-agent workflow that can generate production-grade OpenAPI specifications directly from:

  • PostgreSQL schemas
  • MongoDB collections
  • relationship metadata
  • use-case documents
  • API governance standards
  • engineering conventions

The interesting part was not generating YAML.

The interesting part was teaching the agents to reason about:

  • resource boundaries
  • workflow semantics
  • pagination
  • filtering
  • validation
  • transactional behavior
  • nested resources
  • RBAC
  • API consistency

The result felt much closer to what an experienced backend architect would design manually.

This article walks through the architecture, the agent workflow, and the implementation details.

The stack includes:

Why “Generate CRUD APIs” Is the Wrong Mental Model

Most code generators think in terms of:

table → CRUD endpoints

That works for toy projects.

Real APIs are far more nuanced.

Consider a simple orders table.

A production API usually requires:

  • filtering
  • sorting
  • pagination
  • optimistic locking
  • RBAC
  • audit metadata
  • partial updates
  • idempotency
  • validation rules
  • search behavior
  • async event triggers
  • reporting endpoints

Even the endpoint structure itself depends on business semantics.

For example:

GET /orders
GET /customers/{id}/orders
POST /orders/{id}/cancel
POST /orders/{id}/refund

These are workflow-oriented APIs, not table-oriented APIs.

That distinction matters a lot.

Why a Multi-Agent Workflow Works Better

I initially tried a single-prompt approach.

Something like:

Generate OpenAPI spec from PostgreSQL schema

The output looked impressive for about 30 seconds.

Then the issues became obvious:

  • inconsistent pagination
  • duplicated schemas
  • weak validation
  • poor endpoint naming
  • missing security definitions
  • generic CRUD behavior
  • unrealistic response structures

The core issue is that API architecture involves several independent reasoning layers.

So I split the workflow into specialized agents.

The architecture eventually evolved into this:

Database Schema
        ↓
Schema Understanding Agent
        ↓
Relationship Analysis Agent
        ↓
Workflow Reasoning Agent
        ↓
REST Resource Modeling Agent
        ↓
Validation & Governance Agent
        ↓
Security & RBAC Agent
        ↓
Pagination & Filtering Agent
        ↓
OpenAPI Spec Generator
        ↓
OpenAPI Validation Agent

This produced dramatically better results.

Example Use Case

For testing, I used a realistic commerce + subscription platform.

The database contained:

  • customers
  • organizations
  • subscriptions
  • invoices
  • orders
  • payments
  • inventory
  • shipment tracking
  • audit logs

The AI system had access to:

  • PostgreSQL DDL
  • foreign key relationships
  • use-case documentation
  • API governance standards
  • naming conventions
  • pagination guidelines

The objective was to generate:

  • OpenAPI 3.1 specs
  • reusable components
  • validation constraints
  • filtering standards
  • security models
  • request/response contracts
  • realistic resource hierarchies

Project Structure

I intentionally kept the project modular because each agent needs different context.

openapi-architect/
│
├── agents/
│   ├── schema_agent.py
│   ├── workflow_agent.py
│   ├── relationship_agent.py
│   ├── governance_agent.py
│   ├── pagination_agent.py
│   ├── security_agent.py
│   ├── openapi_agent.py
│   └── validator_agent.py
│
├── tools/
│   ├── postgres_schema_tool.py
│   ├── mongodb_schema_tool.py
│   ├── openapi_validator_tool.py
│   ├── governance_tool.py
│   └── vector_search_tool.py
│
├── knowledge/
│   ├── openapi_docs/
│   ├── enterprise_api_patterns/
│   └── requirements/
│
├── crews/
│   └── openapi_crew.py
│
└── main.py

Installing Dependencies

pip install crewai
pip install langchain
pip install chromadb
pip install pyyaml
pip install psycopg2-binary
pip install openapi-spec-validator
pip install prance
pip install sentence-transformers

Step 1 — Schema Understanding Agent

The first agent introspects the database schema.

For PostgreSQL, I used direct metadata queries against:

  • information_schema
  • pg_catalog

The agent extracts:

  • tables
  • columns
  • foreign keys
  • indexes
  • unique constraints
  • nullable fields
  • enums

PostgreSQL Schema Extraction

import psycopg2
conn = psycopg2.connect(
    host="localhost",
    database="commerce",
    user="postgres",
    password="postgres"
)
cursor = conn.cursor()
cursor.execute("""
SELECT
    table_name,
    column_name,
    data_type,
    is_nullable
FROM information_schema.columns
WHERE table_schema = 'public'
""")
columns = cursor.fetchall()

This metadata becomes the foundation for downstream reasoning.

Schema Agent

from crewai import Agent
schema_agent = Agent(
    role="Database Schema Architect",
    goal="""
    Analyze relational schemas and identify:
    - entities
    - relationships
    - ownership models
    - transactional boundaries
    - lifecycle semantics
    """,
    backstory="""
    Principal backend architect specializing in
    enterprise API and database design.
    """,
    verbose=True
)

The key here is that the agent is not simply generating CRUD operations.

It is trying to infer business semantics from the schema.

Example Database Schema

Here’s a simplified example schema used during testing.

CREATE TABLE customers (
    customer_id UUID PRIMARY KEY,
    email VARCHAR(255) UNIQUE NOT NULL,
    status VARCHAR(50),
    created_at TIMESTAMP NOT NULL DEFAULT NOW()
);
CREATE TABLE orders (
    order_id UUID PRIMARY KEY,
    customer_id UUID NOT NULL,
    total_amount NUMERIC(12,2),
    status VARCHAR(50),
    created_at TIMESTAMP NOT NULL DEFAULT NOW(),
    CONSTRAINT fk_customer
        FOREIGN KEY(customer_id)
        REFERENCES customers(customer_id)
);
CREATE TABLE order_items (
    order_item_id UUID PRIMARY KEY,
    order_id UUID NOT NULL,
    product_id UUID NOT NULL,
    quantity INTEGER,
    unit_price NUMERIC(12,2),
    CONSTRAINT fk_order
        FOREIGN KEY(order_id)
        REFERENCES orders(order_id)
);

A basic generator would create:

  • /customers
  • /orders
  • /order-items

But a workflow-aware system reasons differently.

It understands:

  • orders belong to customers
  • order items are subordinate resources
  • orders require filtering and pagination
  • order state transitions matter

That changes the API design significantly.

Workflow Reasoning Agent

This agent reasons about actual business workflows.

from crewai import Agent
workflow_agent = Agent(
    role="Business Workflow Architect",
    goal="""
    Infer business workflows from:
    - schemas
    - use cases
    - transactional behavior
    - lifecycle states
    """,
    backstory="""
    Enterprise architect experienced in
    SaaS platforms and transactional systems.
    """,
    verbose=True
)

This agent is what transforms:

  • tables → resources
  • relationships → workflows
  • state columns → lifecycle operations

Relationship Analysis Agent

One thing I noticed quickly: resource hierarchy matters enormously in OpenAPI design.

This agent analyzes:

  • ownership
  • cardinality
  • aggregate boundaries
  • nested relationships
from crewai import Agent
relationship_agent = Agent(
    role="Relationship Modeling Specialist",
    goal="""
    Analyze:
    - parent-child relationships
    - aggregate ownership
    - nested resources
    - cardinality
    """,
    verbose=True
)

Without this step, APIs become flat and unnatural.

REST Resource Modeling Agent

This agent generates actual endpoint structures.

from crewai import Agent
resource_agent = Agent(
    role="REST Resource Architect",
    goal="""
    Generate:
    - endpoint hierarchy
    - REST resources
    - pagination models
    - filtering conventions
    - response structures
    """,
    backstory="""
    Principal API architect specializing in
    enterprise-scale REST systems.
    """,
    verbose=True
)

This is where the generated APIs started feeling much more production-oriented.

RAG Layer for OpenAPI Standards

One major improvement came from grounding the agents using:

  • OpenAPI docs
  • internal engineering standards
  • pagination conventions
  • governance guidelines

Without RAG, the APIs were inconsistent.

With RAG, the output became much more stable.

OpenAPI Vector Search

from langchain.vectorstores import Chroma
from langchain.embeddings import HuggingFaceEmbeddings
embedding = HuggingFaceEmbeddings(
    model_name="sentence-transformers/all-MiniLM-L6-v2"
)
vectordb = Chroma(
    persist_directory="./openapi_docs_db",
    embedding_function=embedding
)
def search_openapi_docs(query):
    results = vectordb.similarity_search(query, k=5)
    return "\n".join([
        doc.page_content for doc in results
    ])

This becomes the governance knowledge layer.

CrewAI Orchestration

from crewai import Task, Crew
schema_task = Task(
    description="""
    Analyze schema metadata and identify:
    - entities
    - relationships
    - constraints
    """,
    agent=schema_agent
)
workflow_task = Task(
    description="""
    Infer business workflows and lifecycle semantics.
    """,
    agent=workflow_agent
)
resource_task = Task(
    description="""
    Generate REST resource hierarchy and OpenAPI endpoints.
    """,
    agent=resource_agent
)
crew = Crew(
    agents=[
        schema_agent,
        workflow_agent,
        relationship_agent,
        governance_agent,
        pagination_agent,
        security_agent,
        openapi_agent,
        validator_agent
    ],
    tasks=[
        schema_task,
        workflow_task,
        resource_task
    ],
    verbose=True
)

Generated OpenAPI Output

The generated OpenAPI spec started looking much closer to something a backend team would actually maintain.

openapi: 3.1.0
paths:
  /customers/{customerId}/orders:
    get:
      summary: List customer orders
      parameters:
        - name: customerId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - name: page
          in: query
          schema:
            type: integer
            minimum: 0
        - name: size
          in: query
          schema:
            type: integer
            maximum: 100
      responses:
        "200":
          description: Paginated orders

This is already significantly more realistic than simple CRUD generation.

Pagination Standardization

One thing I wanted was consistent pagination across all endpoints.

So I created a dedicated pagination agent.

Generated schema:

components:
  schemas:
    PageResponse:
      type: object
      properties:
        content:
          type: array
        page:
          type: integer
        size:
          type: integer
        totalElements:
          type: integer
        totalPages:
          type: integer

This consistency matters a lot in large organizations.

Validation Rules

The governance agent generated reusable validation schemas.

CustomerRequest:
  type: object
  required:
    - email
  properties:
    email:
      type: string
      format: email
      maxLength: 255
    status:
      type: string
      enum:
        - ACTIVE
        - INACTIVE

These details are where the system starts feeling production-aware.

Security & RBAC Agent

Another major improvement came from separating security reasoning into its own agent.

This agent generated:

  • OAuth2 flows
  • JWT security schemes
  • RBAC scopes
  • protected endpoints

Example:

components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
security:
  - bearerAuth: []

This made the generated APIs much closer to real enterprise systems.

OpenAPI Validation Agent

One thing that becomes critical quickly: generated YAML often contains structural inconsistencies.

So I added a validation agent using:

  • openapi-spec-validator
  • prance

OpenAPI Validation

from openapi_spec_validator import validate_spec
import yaml
with open("openapi.yaml") as f:
    spec = yaml.safe_load(f)
validate_spec(spec)

This catches:

  • invalid schemas
  • missing references
  • malformed response objects
  • broken component links

What Worked Surprisingly Well

The agents performed especially well at:

  • relationship-aware endpoints
  • reusable components
  • pagination consistency
  • request validation
  • nested resource modeling
  • RBAC-aware APIs
  • naming consistency

The workflow-aware reasoning was the biggest improvement.

Without it, APIs felt autogenerated.

With it, they felt architected.

What Still Needs Human Oversight

The system is useful, but human review is still necessary for:

  • versioning strategy
  • backward compatibility
  • domain semantics
  • event-driven APIs
  • GraphQL vs REST decisions
  • performance optimization
  • public API governance

AI accelerates API design.

It does not replace architectural ownership.

Final Thoughts

What surprised me most was not that AI could generate YAML.

That part is trivial.

What was genuinely interesting was how effective the agents became once they were given:

  • schema metadata
  • relationship context
  • workflow semantics
  • governance rules
  • OpenAPI documentation

At that point, the system started behaving much more like a real backend architect.

And that feels like the real shift happening right now.

The future probably isn’t:

  • developers manually writing thousands of lines of OpenAPI YAML

It’s more likely:

  • architects defining standards
  • AI agents reasoning over schemas and workflows
  • APIs being generated consistently
  • humans reviewing and refining edge cases

That is where this starts becoming genuinely useful in real engineering organizations.


메타데이터
post_id
6db17e7db6b7
slug
what-happened-when-i-let-ai-agents-design-my-rest-apis-6db17e7db6b7
url
https://medium.com/@santoshkr.sharma/what-happened-when-i-let-ai-agents-design-my-rest-apis-6db17e7db6b7
canonical_url
https://medium.com/@santoshkr.sharma/what-happened-when-i-let-ai-agents-design-my-rest-apis-6db17e7db6b7
author_url
https://medium.com/@santoshkr.sharma
status
ok
fetched_at
2026-06-09 15:37:30