Skip to main content

Drop-in Flask API for LLM agent access to SQLModel web apps

Project description

flask-fenrir

Drop-in Flask API for LLM agent access to SQLModel web apps. One install, two lines of code, one env var.

Install

uv add flask-fenrir

Usage

from flask_fenrir import create_fenrir_bp

app.register_blueprint(create_fenrir_bp(engine))
from flask_fenrir import secure_app

secure_app(app)  # optional — adds basic auth to the whole app
dokku config:set myapp FENRIR_API_KEY=$(openssl rand -hex 32)

That's it. One env var for everything — bearer token for LLM agents, basic auth password for browser access.

What it does

Registers a /fenrir/ blueprint with four endpoints, all behind bearer token auth:

Endpoint Method Description
/fenrir/ GET App info, FENRIR.md contents, table list with row counts
/fenrir/schema GET Full schema introspection (columns, types, PKs, FKs, indexes)
/fenrir/query POST Read-only SQL (SELECT / WITH ... SELECT), returns rows as JSON

Authentication

FENRIR_API_KEY is the single secret for your app.

Fenrir endpoints (/fenrir/*) require Authorization: Bearer <key>.

secure_app(app) (optional) adds basic auth to all other routes — any username, password must match FENRIR_API_KEY. This replaces Dokku's http-auth so everything is managed in one place.

Both are skipped when FLASK_DEBUG is on. If the env var isn't set, everything returns 401/503 (fail closed).

# Options:
secure_app(app)                                        # basic auth on all routes
secure_app(app, skip_paths=["/health", "/webhook"])     # skip specific paths
secure_app(app, api_key_auth={                          # also accept a separate API key
    "header": "X-API-Key",
    "secret": os.getenv("API_KEY"),
})

FENRIR.md

Write a FENRIR.md at your project root with domain context for the LLM:

# My App

A brief description of what this app does.

## Domain concepts

- **Widget** — the core thing users create. Has a `status` field: draft, active, archived.
- **Team** — groups of users. The `owner_id` is always a user, not another team.

## Useful queries

- Active widgets by team: `SELECT t.name, COUNT(*) FROM widget w JOIN team t ON ...`

The /fenrir/ endpoint serves this content so the LLM can understand your app before querying it.

Generating FENRIR.md with an LLM

If the app is running locally with flask-fenrir enabled, you can have an LLM generate the file. Run this prompt from the app's project root:

This app uses flask-fenrir — a small Flask blueprint that exposes the
database to LLM agents via REST (schema introspection, read/write SQL).
It serves a FENRIR.md file at GET /fenrir/ to give the LLM domain
context it can't infer from the schema alone. That's the file you're
writing now.

The API is at /fenrir/.

Read the codebase to understand the app's models, business logic, and
domain. Then hit GET /fenrir/schema and POST /fenrir/query to see what
the database actually looks like from Fenrir POV.

Compare what you learned from the code with what the schema and data
show. Write a FENRIR.md that bridges the gap — focus on things an LLM
querying the database blind would NOT be able to figure out from the
schema alone:
- What the app actually does (one-liner)
- What each table/field means in business terms
- Non-obvious values: enums, flags, status codes, soft deletes, fields
  whose names are misleading
- How tables relate to each other (especially implicit relationships
  not captured by foreign keys)
- Common useful queries for an operator
- Gotchas and edge cases

Don't repeat what's already obvious from column names and types.
An LLM can read a schema — FENRIR.md should add the context it can't
infer.

Ask me questions if anything in the code or data is unclear. Don't
guess at business logic — it's better to ask than to document something
wrong.

This file will need to be maintained alongside the codebase. Keep it concise
and structured so it's easy to update when models change. If a section
would go stale quickly, leave it out or note what to watch for.

Row limit

By default, /fenrir/query caps results at 1000 rows. Override it:

app.register_blueprint(create_fenrir_bp(engine, row_limit=500))

Dependencies

Just Flask (≥3.0) and SQLAlchemy (≥2.0). Works with any Flask + SQLAlchemy app — SQLModel not required at runtime.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

flask_fenrir-0.1.0.tar.gz (9.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

flask_fenrir-0.1.0-py3-none-any.whl (7.0 kB view details)

Uploaded Python 3

File details

Details for the file flask_fenrir-0.1.0.tar.gz.

File metadata

  • Download URL: flask_fenrir-0.1.0.tar.gz
  • Upload date:
  • Size: 9.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.7.21

File hashes

Hashes for flask_fenrir-0.1.0.tar.gz
Algorithm Hash digest
SHA256 45fa6bfecefa0650495d43affbfa4ee3f870fcd832a1db434a00ea4f61498e06
MD5 ff1d2379681962eba8855c1726680412
BLAKE2b-256 5bb490c507a00b0f4d63fc00d708ccf97f92a704c646d651eb7c6c7b3b2d7d4d

See more details on using hashes here.

File details

Details for the file flask_fenrir-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for flask_fenrir-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f69e4dad3681727f9fd9ee843fc5197da5e9dd0c652a228e78e5218df798d586
MD5 9f599beceaff4e0eabcd1d504982c4ce
BLAKE2b-256 125455d666c576db70c76caa332a8522167460dfa50822b64cf9b8268a4e844e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page