Skip to content

Support OpenAPI/Swagger spec import with LLM-assisted mapping #1351

@harry-rhesis

Description

@harry-rhesis

Summary

Allow users to provide an OpenAPI/Swagger specification (URL or file upload) and automatically generate endpoint mappings using a combination of deterministic schema parsing and LLM-assisted field mapping.

Problem / Opportunity

Many users have OpenAPI/Swagger specs for their endpoints — either auto-generated by their framework (FastAPI, Spring Boot, Express) or published as part of their API documentation. Today, Rhesis has a placeholder Swagger import form (SwaggerEndpointForm.tsx) but no actual import logic. Leveraging these specs would let users skip manual mapping entirely for well-documented APIs.

Unlike the "paste anything" approach (#1350), this is a structured import path: the spec provides a complete, machine-readable schema that can be parsed deterministically. The LLM is only needed for the semantic mapping step — deciding which spec fields correspond to Rhesis variables.

Proposal

User Experience

Extend the existing endpoint creation flow with an "Import from OpenAPI" option:

  1. User provides the spec via:
    • URL (e.g., https://my-api.com/openapi.json, /.well-known/openapi.json)
    • File upload (JSON or YAML)
    • Paste (raw spec content)
  2. System fetches and parses the spec
  3. User selects which operation (path + method) to import (dropdown populated from the spec)
  4. System generates mappings and pre-fills the endpoint form
  5. User reviews and confirms

Implementation Pipeline

Step 1: Spec Parsing (Deterministic)

Parse the OpenAPI 3.x / Swagger 2.0 spec to extract:

  • Available paths and operations (e.g., POST /v1/chat/completions)
  • Request body schema: field names, types, required/optional, descriptions, examples
  • Response schema: field names, types, nested structures
  • Authentication schemes (Bearer, API key header, OAuth2)
  • Server URLs and base paths

Use an existing Python library (e.g., openapi-spec-validator, prance, or openapi-core) for robust parsing and $ref resolution.

Step 2: Operation Selection (Frontend)

Present the parsed operations to the user:

  • List of available POST/PUT endpoints (filtered to likely inference endpoints)
  • Show field names and descriptions from the spec for each operation
  • Auto-suggest the most likely candidate (heuristic: paths containing chat, completions, generate, predict, infer, ask, query)

Step 3: LLM-Assisted Field Mapping

Send the extracted request/response schemas to the LLM with a prompt that:

  • Maps spec request fields to Rhesis variables (input, messages, conversation_id, system_prompt, etc.)
  • Maps spec response fields to Rhesis variables (output, context, metadata, conversation_id, etc.)
  • Identifies static/config fields (e.g., model, temperature) vs. dynamic input fields
  • Determines conversation mode (single-turn, stateless, stateful)

The LLM adds value here because field naming is ambiguous — content could be input or output depending on context, and nested structures (e.g., messages[].content) require semantic understanding.

Step 4: Generate Mappings

Produce:

  • request_mapping: Jinja2 template with Rhesis variables mapped to spec fields, static fields filled with defaults or spec examples
  • response_mapping: JSONPath expressions for each Rhesis output variable
  • request_headers: Authentication headers based on spec's security schemes, using {{ auth_token }}
  • URL and method from the selected operation

Step 5: Pre-fill Form

Populate all endpoint form fields and switch to the manual tabs for review.

Backend Implementation

New service: apps/backend/src/rhesis/backend/app/services/endpoint/openapi_import.py

class OpenApiImportService:
    """Import endpoint configuration from OpenAPI/Swagger specs."""

    async def parse_spec(
        self, spec_content: str | None, spec_url: str | None
    ) -> ParsedSpec:
        """Fetch and parse an OpenAPI spec, resolve $refs."""
        ...

    async def list_operations(
        self, spec: ParsedSpec
    ) -> list[OperationSummary]:
        """List available operations with suggested ranking."""
        ...

    async def generate_mapping(
        self, spec: ParsedSpec, operation_id: str, db: Session, user: User
    ) -> AutoConfigureResult:
        """Use LLM to map spec fields to Rhesis variables."""
        ...

LLM integration: Use get_user_generation_model() with a Pydantic schema for structured output, same pattern as #1350.

Prompt template: apps/backend/src/rhesis/backend/app/templates/openapi_mapping.jinja2

New API endpoints in apps/backend/src/rhesis/backend/app/routers/endpoint.py:

  • POST /endpoints/openapi/parse — parse spec, return operations list
  • POST /endpoints/openapi/generate-mapping — generate mapping for selected operation

Frontend Implementation

Update SwaggerEndpointForm.tsx (or replace it) with:

  1. Spec input: URL field + file upload + paste area
  2. "Parse" button → shows operation selector dropdown
  3. Operation details panel (shows request/response fields from spec)
  4. "Generate Mapping" button → calls LLM-assisted mapping
  5. Results panel with generated mappings and "Apply" button
  6. Integration with EndpointForm.tsx to populate fields

Relationship to #1350

This is a complementary import path alongside the "paste anything" auto-configure (#1350):

Both should produce the same AutoConfigureResult output and feed into the same form population flow. The OpenAPI path will generally produce higher-confidence mappings since it starts from a complete schema.

Acceptance Criteria

  • Accept OpenAPI 3.x and Swagger 2.0 specs via URL, file upload, or paste
  • Parse spec and list available operations with auto-suggested best candidate
  • LLM maps spec fields to Rhesis platform-managed variables
  • Generate valid request_mapping, response_mapping, and request_headers
  • Detect authentication scheme and generate appropriate header config with {{ auth_token }}
  • Detect conversation mode from spec (messages array, session fields)
  • Pre-fill endpoint form fields when user clicks "Apply"
  • Handle common spec issues gracefully (missing examples, incomplete schemas, circular $refs)
  • Show confidence level and field-by-field reasoning

References

  • Existing placeholder: apps/frontend/src/app/(protected)/endpoints/components/SwaggerEndpointForm.tsx
  • Auto-configure feature: AI-powered auto-configuration for endpoint mappings #1350
  • LLM integration: apps/backend/src/rhesis/backend/app/utils/user_model_utils.py
  • Endpoint form: apps/frontend/src/app/(protected)/endpoints/components/EndpointForm.tsx

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions