Skip to content

Extensions API Reference

The Extensions API provides endpoints for managing and interacting with Ordinaut extensions. This includes extension discovery, health monitoring, and access to extension-specific functionality.

Core Extension Endpoints

Extension Status

Get information about all discovered extensions.

Endpoint: GET /ext/status
Authentication: None required
Scopes: None

Response:

{
  "extensions": {
    "observability": {
      "state": "loaded",
      "info": {
        "id": "observability", 
        "name": "Observability",
        "version": "0.1.0",
        "description": "Prometheus metrics and monitoring"
      },
      "capabilities": ["ROUTES"],
      "loaded_ms": 45,
      "metrics": {
        "requests_total": 150.0,
        "errors_total": 2.0,
        "latency_ms_sum": 1250.5
      }
    }
  },
  "discovery_sources": ["builtin", "env_dir"],
  "total_extensions": 4,
  "loaded_extensions": 3,
  "failed_extensions": 0
}

Example:

curl http://localhost:8080/ext/status

Built-in Extensions

Observability Extension

Provides Prometheus-compatible metrics for system monitoring.

Get Metrics

Endpoint: GET /ext/observability/metrics
Authentication: None required
Content-Type: text/plain; version=0.0.4

Returns Prometheus-format metrics including: - HTTP request/response metrics - Task execution statistics - Extension performance metrics
- System resource usage

Example:

curl http://localhost:8080/ext/observability/metrics

Sample Response:

# HELP http_requests_total Total number of HTTP requests
# TYPE http_requests_total counter
http_requests_total{method="GET",endpoint="/health"} 45.0

# HELP task_executions_total Total number of task executions
# TYPE task_executions_total counter
task_executions_total{status="success"} 123.0
task_executions_total{status="failed"} 5.0

# HELP extension_requests_total Extension request counts
# TYPE extension_requests_total counter
extension_requests_total{extension="webui"} 89.0

Web UI Extension

Provides a web-based interface for task management and system monitoring.

Get Web Interface

Endpoint: GET /ext/webui/
Authentication: None required (configurable)
Content-Type: text/html

Returns the main web interface HTML page.

Example:

curl http://localhost:8080/ext/webui/

API Endpoints

Get Tasks: GET /ext/webui/api/tasks

{
  "tasks": [
    {
      "id": "uuid-1234",
      "title": "Morning Briefing", 
      "status": "active",
      "next_run": "2025-08-26T08:30:00Z"
    }
  ]
}

Create Task: POST /ext/webui/api/tasks

{
  "title": "New Task",
  "schedule_kind": "cron",
  "schedule_expr": "0 9 * * *",
  "payload": {
    "pipeline": []
  }
}

MCP HTTP Extension

Model Context Protocol over HTTP for AI assistant integration.

MCP Metadata

Endpoint: GET /ext/mcp_http/meta
Authentication: None required

{
  "server": "ordinaut-mcp-http",
  "version": "0.2.0", 
  "capabilities": ["handshake", "list_tools", "invoke", "schema", "sse"]
}

MCP Handshake

Endpoint: POST /ext/mcp_http/handshake
Content-Type: application/json

Request:

{
  "client": {
    "name": "ChatGPT",
    "version": "1.0"
  }
}

Response:

{
  "server": {
    "name": "ordinaut-mcp-http",
    "version": "0.2.0"
  },
  "session_id": "sess-uuid-5678"
}

List Available Tools

Endpoint: GET /ext/mcp_http/tools

{
  "tools": [
    {
      "name": "create_task",
      "description": "Create a new scheduled task",
      "parameters": {
        "type": "object", 
        "properties": {
          "title": {"type": "string"},
          "schedule": {"type": "string"}
        }
      }
    }
  ]
}

Invoke Tool

Endpoint: POST /ext/mcp_http/invoke

Request:

{
  "tool": "create_task",
  "parameters": {
    "title": "Daily Report",
    "schedule": "0 18 * * *"
  }
}

Response:

{
  "success": true,
  "result": {
    "task_id": "uuid-9876",
    "message": "Task created successfully"
  }
}

Events Demo Extension

Demonstrates the Redis Streams event system.

Publish Event

Endpoint: POST /ext/events_demo/publish/{stream}
Content-Type: application/json

Example:

curl -X POST http://localhost:8080/ext/events_demo/publish/test \\
  -H "Content-Type: application/json" \\
  -d '{"message": "Hello Events", "timestamp": "2025-08-26T10:00:00Z"}'

Response:

{
  "success": true,
  "stream": "test",
  "event_id": "1692873600000-0",
  "message": "Event published successfully"
}

Subscribe to Events (Server-Sent Events)

Endpoint: GET /ext/events_demo/subscribe/{stream}
Content-Type: text/event-stream

Establishes an SSE connection to receive real-time events.

Example:

curl -N http://localhost:8080/ext/events_demo/subscribe/test

Response Stream:

data: {"stream": "test", "id": "1692873600000-0", "data": {"message": "Hello Events"}}

data: {"stream": "test", "id": "1692873600001-0", "data": {"message": "Another event"}}

Extension Development API

Extension Registration

Extensions are automatically discovered and registered. No manual registration API is required.

Discovery Sources: 1. Built-in: ordinaut/extensions/ directory 2. Environment: ORDINAUT_EXT_PATHS environment variable
3. Entry points: Python ordinaut.plugins entry point group

Extension Capabilities

Extensions can request the following capabilities:

Capability Description API Access
ROUTES HTTP endpoint creation FastAPI router mounting
TOOLS Tool registry access tool_registry.register_tool()
EVENTS_PUB Event publishing events.publish()
EVENTS_SUB Event subscription events.subscribe()
BACKGROUND_TASKS Long-running processes background.start_task()
STATIC Static file serving Automatic static file routing

Context Objects

Extensions receive context objects based on granted capabilities:

Tool Registry Context

# Available when TOOLS capability granted
tool_registry.register_tool(name: str, func: Callable, schema: dict)
tool_registry.list_tools() -> List[ToolInfo]
tool_registry.get_tool(name: str) -> ToolInfo

Events Context

# Available when EVENTS_PUB or EVENTS_SUB granted
await events.publish(stream: str, data: dict) -> str
await events.subscribe(pattern: str, handler: Callable) -> None
await events.unsubscribe(pattern: str) -> None

Background Tasks Context

# Available when BACKGROUND_TASKS capability granted  
await background.start_task(name: str, coro: Coroutine) -> None
await background.stop_task(name: str) -> None
background.list_tasks() -> List[TaskInfo]

Authentication & Authorization

Scope-Based Access Control

Extensions can be protected with scope-based authorization:

Configuration:

export ORDINAUT_REQUIRE_SCOPES=true

Request Headers:

curl -H "X-Scopes: ext:my_extension:routes" \\
     http://localhost:8080/ext/my_extension/protected

Required Scope Pattern: ext:{extension_id}:routes

JWT Token Authentication

When JWT authentication is enabled, extensions inherit the same authentication requirements as the core API.

Request Headers:

curl -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..." \\
     http://localhost:8080/ext/my_extension/secure

Error Responses

All extension endpoints follow consistent error response formats:

400 Bad Request

{
  "error": "bad_request",
  "message": "Invalid request parameters",
  "details": {
    "field": "schedule_expr", 
    "issue": "Invalid cron expression"
  }
}

401 Unauthorized

{
  "error": "unauthorized",
  "message": "Authentication required",
  "details": {
    "required_scopes": ["ext:my_extension:routes"]
  }
}

403 Forbidden

{
  "error": "forbidden",
  "message": "Insufficient permissions",
  "details": {
    "required_capability": "TOOLS",
    "granted_capabilities": ["ROUTES"]
  }
}

404 Not Found

{
  "error": "not_found",
  "message": "Extension not found",
  "details": {
    "extension_id": "nonexistent_extension"
  }
}

500 Internal Server Error

{
  "error": "internal_error",
  "message": "Extension execution failed",
  "details": {
    "extension_id": "my_extension",
    "error_type": "ImportError",
    "traceback": "..."
  }
}

Rate Limiting

Extension endpoints respect the same rate limiting configuration as the core API:

Headers: - X-RateLimit-Limit: Request limit per window - X-RateLimit-Remaining: Remaining requests in current window - X-RateLimit-Reset: Window reset timestamp

429 Too Many Requests:

{
  "error": "rate_limit_exceeded",
  "message": "Rate limit exceeded", 
  "details": {
    "limit": 100,
    "window": "60s",
    "reset_at": "2025-08-26T10:01:00Z"
  }
}

Health Checks

Extensions can implement health check endpoints for monitoring:

Convention: GET /ext/{extension_id}/health

Standard Response:

{
  "status": "healthy",
  "timestamp": "2025-08-26T10:00:00Z", 
  "version": "1.0.0",
  "checks": {
    "database": "healthy",
    "external_api": "healthy", 
    "background_tasks": "healthy"
  }
}

WebSocket Support

Extensions can implement WebSocket endpoints for real-time communication:

Endpoint Pattern: WS /ext/{extension_id}/ws/{path}

Example Implementation:

from fastapi import WebSocket

@router.websocket("/ws/events")
async def websocket_endpoint(websocket: WebSocket):
    await websocket.accept()
    try:
        while True:
            # Handle WebSocket communication
            data = await websocket.receive_json()
            response = await process_websocket_data(data)
            await websocket.send_json(response)
    except WebSocketDisconnect:
        # Handle client disconnect
        pass

Extension Metrics

All extensions automatically get basic metrics collection:

Metrics Available: - extension_requests_total{extension, endpoint, method, status} - extension_request_duration_seconds{extension, endpoint, method} - extension_errors_total{extension, endpoint, error_type} - extension_active_connections{extension, endpoint}

Access via Observability Extension:

curl http://localhost:8080/ext/observability/metrics | grep extension

This API reference provides complete documentation for interacting with Ordinaut's extension system, enabling developers to build powerful extensions and integrate external systems effectively.