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.

Release

# 1. Bump version
uv version --bump minor   # or --bump patch / --bump major

# 2. Clean old artifacts and build
rm -rf dist/*
uv build

# 3. Publish to PyPI
uv publish dist/* --token "$PYPI_TOKEN"

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.4.0.tar.gz (9.5 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.4.0-py3-none-any.whl (7.5 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: flask_fenrir-0.4.0.tar.gz
  • Upload date:
  • Size: 9.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.6 {"installer":{"name":"uv","version":"0.10.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for flask_fenrir-0.4.0.tar.gz
Algorithm Hash digest
SHA256 8dc9ce1eeaae06da511a73a1437de7ea9b37db49425e0108bc0b5e8074c81352
MD5 906a2b4d2f4321d0c1f4801ed26653be
BLAKE2b-256 2c9f3f49f09d7e19c67f814bcc41f7ec50d1b9d67ba4d1e0c3c8f851e5a06327

See more details on using hashes here.

File details

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

File metadata

  • Download URL: flask_fenrir-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 7.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.6 {"installer":{"name":"uv","version":"0.10.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for flask_fenrir-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d076bd9248191f8181e663f11c2f1c24c43c2cfcdaf41a0c478253894a2a8d52
MD5 94a645bea769c79d3035977f1d339cff
BLAKE2b-256 280fb58bb0108515a8440158c415849175fcedc1d5a409635f0d4d5c8bc05fc3

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