Skip to main content
Uses: CLI · Claude Code · Codex
Flo, the agent of the Engini skills workflow plugin, holds a shell and your API key, and can do anything your key can do. This page says what the agent is told never to do on its own, what actually stops it, and where that protection ends. Read it before you rely on the agent, and keep it in mind when you choose the key you give it.

What the agent will never do on its own

Four tools are the only ones the agent asks you about by name - the never-verbs. It never calls one on its own initiative. It calls one only when you explicitly ask for that action on that workflow, and Claude Code then asks you to approve each call:
  • engini_workflows_delete_workflow
  • engini_workflows_run_workflow
  • engini_workflows_enable_or_disable_workflow
  • engini_workflows_rerun_execution
In plain words: the agent does not turn a workflow on or off, run it, rerun an execution or delete a workflow unless you ask for exactly that, and you get a permission prompt each time. It never creates or changes a connection and never handles your API key: when a step needs one, it stops and gives you the command to run in your own terminal.

The layers

Four layers stand between those four verbs and your account. Only the last one is a boundary, and it refuses nothing:
  1. The agent’s instructions say: never on its own initiative; only when you explicitly ask for that exact action, after telling you a permission prompt is coming. This is prose: a model follows it, nothing enforces it.
  2. The plugin’s guard hook - Claude Code only. Installed with the plugin and live at once. See The guard.
  3. Your own settings - the settings below. Copy-paste; a plugin cannot install them for you.
  4. The Engini server refuses nothing here: your key is allowed to do all of it.
Codex has no hook. In Codex, the rules file you paste from Codex rules file is the only layer besides the agent’s instructions. If you skip it, nothing asks you before the four verbs or the key-handling commands. Those commands only ask in Codex, they are not refused: if you approve one, it runs through the agent and the key would pass through it. So decline the prompt and run the command yourself in your own terminal, outside Codex. The agent’s instructions say it never runs them itself and never asks you to paste a key into the chat.

Permission modes

What the Claude Code docs say, not something we ran end to end:
  • Default mode: the guard’s question for a never-verb reaches you. That a hook’s question also beats the Bash(engini:*) allow rule below has not been verified yet; your ask rules cover the same four verbs either way.
  • Auto mode: documented to still send a hook’s question to you (the classifier does not decide it), and to still prompt on ask rules in your settings.
  • --dangerously-skip-permissions (bypass): what a hook’s question does here is undocumented, so assume the guard’s question may not reach you. The docs say ask rules in your settings still prompt in this mode, so paste the safety settings below - those rules are the layer that holds in bypass mode. They match the literal command form only (see Settings to paste yourself).
  • -p (non-interactive): nobody can answer, so the docs say the call is refused rather than asked. dontAsk is expected to do the same (inferred, not documented for a hook).
Do not run the agent with --dangerously-skip-permissions: it holds a shell and your key.

The guard (Claude Code only)

The guard is a hook installed with the plugin. It needs Python 3.8 or later (python3 or python). A question is a prompt, not a block: it works only while your permission mode lets the prompt reach you (see Permission modes). It asks you to confirm these:
  • The four never-verbs. An engini tools call naming any of them is asked about in any argument order and through quoting, case and bash -c wrappers. A tool name the guard cannot read (built from a shell variable or a substitution, such as engini_workflows_$V) is asked about too, because it could be one of the four.
It refuses these:
  • Commands that handle a raw key when the agent runs them: engini connect, engini login, engini connections create|update|delete, engini connections auth-providers create|update, and any --api-key. The refusal tells the agent to hand you the command to run in your own terminal.
  • Reads of your stored login and of key variables: reading the CLI’s stored login (see Where the CLI stores your login), an ENGINI_API_KEY / ENGINI_API_TOKEN / ENGINI_COMPANY_TOKEN variable, or dumping the environment. A presence test such as [ -n "$ENGINI_API_KEY" ] is fine.
  • Edits to the hook itself or to your Claude Code or Codex settings. This includes any command that names your .claude or .codex folder itself, a wildcard name or a ./.. step inside one, or a cd into a folder under one - so even ls ~/.claude is refused. Read, Write, Edit, Grep and Glob paths are judged as given and again after resolving them against the session’s folder and following symlinks.
An engini tools call with a heredoc is judged as code unless it is the agent’s own one-call shape: the <<'EOF' opener ends the command’s first line and the reader is the engini CLI itself (engini, npx @engini/cli or npx @engini/cli@<exact version>).

Scope of the guard

The guard applies to every Claude Code session where the plugin is enabled - not only while the agent is working. It asks you before your own never-verb call (approve it - you meant it) and refuses your own engini connections delete or engini login when the agent runs it: run those in your own terminal, or turn the plugin off for the session with /plugin disable workflow@engini (that removes the guard’s other protections too). Everything else - your builds, git, other tools, other Engini apps’ tools - runs normally.
This applies to every project’s own .claude and .codex folders too. With the plugin enabled, ls .claude, git add .claude, grep -r x .claude and a cd into a folder inside .claude are refused in every project and every session, not only while the agent is working. Run those in your own terminal, or turn the plugin off for the session.

When the guard speaks

The message starts with FLO-HOOK-ASK (a prompt for you) or FLO-HOOK-DENY (a refusal the agent reads) and says which of these it is. A command that trips both is refused. The plugin’s troubleshooting guide covers each case in more detail. Claude Code’s own permission rules (layer 3) match the four verbs inside a compound command such as cd /tmp && engini tools call .... That is tested for deny rules on Claude Code 2.1.316. The permissions docs say deny and ask rules apply when any subcommand of a compound command matches them, so the ask rules below are expected to match the same way, but that was not re-tested. The guard’s extra reach is that it needs no paste, and the quoting and wrapper forms above.

What the guard does not stop

While the agent has a shell and your key, it can do anything your key can do, including acting through your other connections. The guard narrows one literal command form. It is a text matcher, not a sandbox. These are deliberately open, and tested as open:
  • Every other tool. The guard asks about only the four verbs. The agent’s rule against calling other apps’ tools (for example slack_send_message) is an instruction it follows, not something enforced; so is “read execution data only when asked”. Builder tools Engini adds later run normally too.
  • Indirection the guard never sees: eval "$X", bash -c "$X", a shell function, a script file.
  • Anything that skips the CLI: a python -c against the SDK, or a plain HTTPS call with your key.
  • A tool name that is never in the command text at all, for example xargs engini tools call --args - < slugfile.
  • The key file reached through a glob (cd ~/.config && cat engini/conf*), a recursive search from a parent folder in the shell (grep -r ... ~/.config), and a custom XDG_CONFIG_HOME folder named by its own path in a shell command.
  • A settings folder name built from a variable or a wildcard in the folder name itself (~/.cl*).
  • In the shell, a symlink to your settings or key folder that already exists (the command names only the link), and a program that changes folder itself before it writes (os.chdir in a script, git -C, find -execdir). Read, Write, Edit, Grep and Glob follow symlinks, so those tools are covered.

Settings to paste yourself

Each rule below matches the literal command form only. bash -c, a shell variable, eval, reordered arguments or a python -c against the SDK walk past every one of them. They are what holds when the guard does not run, and in Codex they are all there is.
  • Allow only Bash(engini:*) and never run the agent with --dangerously-skip-permissions. The agent holds a shell and your key; this is the widest control by far.
  • The ask rules make Claude Code ask you, outside the conversation, before every create or update, before each of the four never-verbs and before the key-handling commands (engini login, engini connect, engini connections create|update|delete, engini connections auth-providers create|update, engini login --api-key) - the approvals the model cannot give itself. With the plugin’s guard installed, those last commands are refused outright when the agent runs them, so the ask rule is what applies when the guard is not installed. In Codex, which has no guard, the rules file only asks, so an approved command there would carry the key through the agent: decline it and run the command yourself in your own terminal. Only the stored-login Read rules, the one cat rule and the environment dumps are deny.
  • The Read rules cover the stored login on each platform for Claude’s own file tools; they do not bind a shell command, and the one Bash(cat ...) rule covers only that exact command. What keeps other shell reads (grep, head, the other paths) from running unasked is that Bash(engini:*) is the only allow rule, so any other command asks you first.

Claude Code settings

Merge this into your user settings (settings.json in your ~/.claude folder):

Codex rules file

Save this as ~/.codex/rules/flo.rules:
Codex support is not yet verified on a real Codex install. If commands are not asked about in Codex, check that this file exists and that you started a new session after saving it.

Codex sandbox

Codex runs commands without network by default, so every engini call fails. Allow network for commands in your Codex config:
Or approve the commands outside the sandbox. The agent’s optional session log and lessons live in ~/.engini/flo/, outside the workspace: add it as a writable root or the agent skips them. Not yet verified on a real Codex install.

Where the CLI stores your login

The guard refuses reads that name any of these paths, and Grep or Glob searches started from a folder above them, such as your home folder or ~/.config - however that folder is spelled: a relative path, no path while the session runs in it, a symlink, or a second macOS name for your home folder such as the one under /System/Volumes/Data.
  • ~/.config/engini/config.toml (macOS, Linux)
  • $XDG_CONFIG_HOME/engini/config.toml (when XDG_CONFIG_HOME is set)
  • %APPDATA%\engini\config.toml (Windows)
  • %USERPROFILE%\engini\config.toml (Windows, when APPDATA is unset)
For how the CLI stores credentials, see the CLI overview.

Things to know

  • Your key carries its creator’s whole permission set. Use a dedicated, least-privilege, workspace-scoped key you can rotate. See API keys.
  • Log in interactively, in your own terminal. engini login, never --api-key on the command line and never through Claude Code’s ! prefix (no terminal there, so the key cannot be hidden as you type it).
  • What the agent reads enters the model’s context: workflow definitions, and execution data when you ask for it.
  • The stored key is reachable by the agent. It is a file in your own home folder; the agent can reach it through the shell as much as through file reads. The guard refuses the literal reads; what actually protects you is a scoped, rotatable key plus the Bash(engini:*) allow rule - not secrecy from the model.