RAGSpine
Guides

Service

FastAPI composition, async ingestion, workflow catalog and compatibility APIs, authentication boundaries, and default-off execution.

ragspine.service is an optional composition root over the engine. Install [service] to get FastAPI, uvicorn, RQ, and Redis support. The service opens request/job-owned stores, injects providers and matchers through typed seams, and returns opaque errors without tracebacks.

App factory

from ragspine.service.api.app import create_app

app = create_app(
    config=None,
    provider=None,
    queue=None,
    faq_cache=None,
    workflow_matcher=None,
)

Omitted dependencies are assembled from ServiceConfig.from_env(). Instances are held on app.state, which also makes them straightforward to replace in tests. When studio_dir points to an existing directory, its static build is mounted at /studio; an empty or missing directory does not add that route.

Endpoint groups

GroupPathsExecutes work?Authentication
engine/healthz, /readyz, /v1/ask*, ingestion/jobsask and queue operationsnone built in
catalog/v1/workflow-templates*, /v1/workflow-scaffoldnonone built in
compiler/converter/v1/dify/analyze, /compile, /v1/n8n/convert, /v1/topologynonone built in
internal execution/v1/dify/run*, /v1/n8n/runyes, when enabledexecution flag; deploy behind your own auth
Dify-compatible public API/v1/workflows/run*, /v1/info, /v1/parametersrun route when enabledBearer app key
n8n-compatible public API/api/v1/*CRUD; webhook can run when enabledX-N8N-API-KEY
n8n webhook/webhook/{path}active matching workflow, when enabledintentionally none

The general engine and internal /v1/dify/* routes do not provide user authentication. Bind to localhost/private networks or add an authenticated reverse proxy before public exposure.

Engine and ingestion

POST /v1/ask and /v1/ask/stream run the FAQ gate, intent/security decisions, retrieval, anti-fabrication rewrite, and provenance assembly. The SSE endpoint finishes all guards before it opens the stream. AskRequest.history is optional generation context only and cannot become retrieval evidence.

Structured ingestion accepts .xlsx, .xlsm, .pptx, and .pdf; narrative jobs accept .pptx and .pdf. RAGSPINE_ALLOWED_UPLOAD_ROOT constrains resolved paths. The API enqueues a dotted job reference; the worker revalidates paths and owns its own SQLite connections.

FakeQueue is synchronous/in-memory for tests. RQQueue is the Redis-backed production adapter. Queue statuses are queued, started, finished, and failed; reports contain counts/statuses, not raw fact values or chunk text.

Workflow catalog and compiler

Catalog list pages contain metadata only. Detail and scaffold responses add the canonical workflow, Dify YAML, and preview v1. Scaffolding may match semantically, fall back to lexical matching, or generate a fixed graph; it never executes the output.

Dify analyze/compile bodies contain exactly one of a canonical workflow object or legacy yaml string; unknown fields are rejected. Analyze is static only. Compile returns a Python code string and never runs it. n8n conversion is also pure and returns explicit compatibility warnings.

Selected workflow POST request bodies are bounded to 2 MiB before FastAPI buffers them: /v1/workflow-scaffold and /v1/dify/{analyze,compile,run,run/jobs}. The decoded workflow document has the tighter 1 MiB parser limit. Validation-error responses remove Pydantic's echoed input and ctx fields so a rejected secret is not reflected.

Default-off execution

RAGSPINE_DIFY_RUN_ENABLED defaults to false. Until explicitly enabled, /v1/dify/run, /v1/dify/run/jobs, /v1/n8n/run, Dify-compatible workflow execution, and n8n webhook execution fail closed. The provider, model, base URL, and Dify app workflow files come from server configuration; clients cannot inject a provider expression or key.

Execution is compiled and checked by the L0 static gate. The default inprocess isolation applies restricted builtins/imports and a timeout, but is not an OS sandbox. subprocess adds Linux resource limits; on macOS and Windows it falls back to the in-process restrictions. Treat untrusted workflow execution as a separate hardened service boundary.

Dify-compatible public API

RAGSPINE_DIFY_PUBLIC_APPS is a semicolon-separated registry such as app-key=/srv/workflows/support.yml;other-key=/srv/workflows/report.yml. Requests use Authorization: Bearer app-key. If the registry is absent, invalid, or the key is unknown, these routes return 401.

The API supports POST /v1/workflows/run, GET /v1/workflows/run/{id}, GET /v1/info, and GET /v1/parameters. Run requests supply inputs, user, and response_mode; they do not supply the workflow. Streaming uses SSE after execution and replays trace events. Run-detail data is a process-local LRU of the latest 100 runs and is isolated per app key; it is not durable history.

n8n-compatible public API and webhooks

Set RAGSPINE_N8N_API_KEY; clients send X-N8N-API-KEY. If no key is configured, every /api/v1/* request returns 401. Workflow CRUD and activation, plus execution list/get/delete, are backed by the filesystem root RAGSPINE_N8N_STORE_PATH (default data/n8n_store). List limits default to 100, clamp to 1–250, and use cursors.

GET|POST /webhook/{path} deliberately has no API-key check, matching webhook behavior. It matches only an active workflow's webhook node and still requires execution to be enabled. Query parameters and a JSON-object body form inputs, with body keys winning. Put ingress controls, TLS, rate limiting, and request-size policy in front of this route.

Run the service

From the repository root:

RAGSPINE_DB_PATH=data/fact_metric.db \
RAGSPINE_CHUNK_DB_PATH=data/chunks.db \
  .venv/bin/python scripts/run_server.py --host 127.0.0.1 --port 8000

# separate process; Redis required
RAGSPINE_REDIS_URL=redis://localhost:6379/0 \
  .venv/bin/python scripts/run_worker.py

See HTTP API for exact routes and Configuration for the environment surface.

On this page