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.2.0.tar.gz (8.8 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.2.0-py3-none-any.whl (7.0 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for flask_fenrir-0.2.0.tar.gz
Algorithm Hash digest
SHA256 2c17803d86464190f2f6f5ffa695841567fa02bff87fd4500895fd6c7ba192c6
MD5 26a2fb5a5f3dc4f239ca93bd0f602c56
BLAKE2b-256 caddddd5ffe77666d97e22e038f0f493d636ee8d80eac1c4ef933c1a2e556c9c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for flask_fenrir-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 67bdb278bb0184673e206850be6bf87c5af45ee921347123f032b801a5d65c12
MD5 091a2111f78c337c5715075b8c9b81b4
BLAKE2b-256 df8c2a78004909af438f8b090e7273214e5c6a53de387b3bde14ed162731a939

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