Skip to content

How Lucius's permissions work

Every tool Lucius can call — reading your ledger, syncing a connector, sending an email, executing a trade-adjacent write, deleting a category — is governed by one setting: its permission level. One of the three levels below has a consequence you need to understand before you flip it.

The three levels

LevelWhat happens when Lucius wants to call this tool
needs_approvalPauses. You see a confirm card with exactly what would happen; you approve or deny. Nothing runs until you tap.
always_allowFires immediately. No card, no pause, no notification first.
blockedRefused outright. Lucius is told it isn’t permitted and never executes it — not even once.

If you’ve never touched a tool’s setting, it behaves as needs_approval. Absence of a stored decision resolves to asking you first, every time — with one exception: a small, explicitly-reviewed set of tools whose only “writes” are internal bookkeeping (search cursors, cache entries) rather than anything in your ledger or accounts. Those run without asking, the same way a get_ tool would — refusing to let Lucius search your own email or re-check a statement diff without a click first would serve no purpose.

always_allow means allow everywhere — including unattended

This is the one thing to understand before you set anything to always_allow: it fires on a scheduled Automation, a headless run, or any surface with no human present — money movement included. It is not quietly downgraded to needs_approval just because nobody is watching. If you’d only be comfortable with a tool firing while you personally supervise it, leave it at needs_approval (or set it to blocked). always_allow is not “trust it while I’m around” — it is “never ask again, on any run, ever.”

Concretely: set a transaction-writing tool to always_allow, then schedule an Automation that calls it at 3 AM — it runs at 3 AM with no card and no confirmation, exactly as if you’d approved it by hand at your desk. Deliberate, not an oversight: the app is self-hosted and single-operator, so an unconfigurable “always ask when only a scheduler triggered this” floor was judged to protect against nothing an attacker couldn’t already reach some other way, while permanently blocking automations you’ve genuinely decided to trust. The tradeoff is real, and it’s yours to make per tool — not the app’s to make for you.

One narrower exception: an Automation’s own run mode governs its approval-tier calls first, before your global settings are even consulted.

  • A manual Automation pauses for your review on any call that would otherwise ask — even a tool you’ve globally set to always_allow — unless that specific tool is on that Automation’s own allowed list.
  • An auto Automation runs everything through on its own, global level or not, except two tools with no override at all (see Automations).

Your global always_allow is what makes an ordinary chat turn skip the card; inside an Automation, it’s the Automation’s own mode that decides.

Setting a level

WhereWhat it’s for
On a confirm card, in the momentAllow once approves just this call. Always allow approves this call and stores always_allow for that tool, everywhere, from now on. Deny refuses just this call without changing the stored level. See Confirm cards.
Ahead of time, per connectorEach connector’s detail page (Connectors → the connector) lists its tools with a ladder you can set directly — pre-approve a read-only connector before you talk to Lucius about it, or lock one to blocked before you’ve tried it.
Settings → PermissionsA review-and-revoke list, not a place to grant new permissions — every tool with a stored decision, grouped, with one-click Reset back to the unset/default state.

Setting a level for a whole group (every tool a connector owns) stamps that level onto every tool in the group in one action; a group with mixed levels shows as “Custom” — display-only, not a level you can pick.

Note: the Permissions screen doesn’t show a specific “this also applies during unattended automation runs” reminder next to Always-allow. The behavior above is real regardless — read this page once and you know it — but the UI itself won’t re-warn you in the moment.

Who owns a tool

Every tool has an owner: the connector it’s scoped to (plaid, telegram, an external MCP server as mcp:<server-id>, a web-search provider as web_search:tavily, …), or the reserved built-in bucket for a tool tied to no connector. Permissions are set per (owner, tool) pair, which is why a connector’s detail page and the app-wide Permissions list show the same data from two angles.

For an unscoped built-in tool with no stored decision, the fallback isn’t a blanket needs_approval: a plain read runs freely, a write asks first. Once you’ve made an explicit decision, it runs, full stop, either direction — nothing overrides an explicit blocked, nothing downgrades an explicit always_allow.

blocked always wins

Refused before anything else is considered, no override fires it anyway. Use it for a tool you never want Lucius to call, on any surface, under any condition.

What this means the first time you ask Lucius to write something

Because needs_approval is the default, an ordinary write — logging a transaction, editing one, moving budget money — shows a confirm card the first time, and every time after, until you grant it. The app asks by default and lets you decide which tools you’re tired of approving, rather than deciding for you which writes are “safe enough” to skip. Tap Always allow once and the same tool writes immediately from then on, with a plain “here’s what I did” summary in the reply instead of a pause. See Confirm cards for exactly what that first card shows and what each button does.