What Happened When I Let AI Agents Design My REST APIs
One thing I’ve noticed across most enterprise backend systems is this:
What Happened When I Let AI Agents Design My REST APIs

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:
- CrewAI
- OpenAPI Specification
- PostgreSQL
- LangChain
- vector search
- RAG pipelines
- schema introspection
- OpenAPI validation tooling
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_schemapg_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-validatorprance
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