Skip to main content
Fibonacci can decide tool calls for agents it doesn’t run. A developer’s Claude Code session, or any MCP client, asks Fibonacci before each tool call, and your organization’s governance rules answer: allow, deny, or hold for approval. Every decision lands in the same Approvals inbox, receipts and hash-chained audit log as workflow runs. Tool outputs never leave the developer’s machine. Adapters send only the tool’s name and arguments. Both are single Python files (3.8+, standard library only), served by the API.

Set up

1

Create a key

In the web app, open Agents → Connect an agent. It creates an API key with only the agents:authorize scope, which can ask for decisions and nothing else, and generates the config to paste.
2

Download the adapter

GET /api/v1/integrations lists the files with their checksums.
3

Wire it in

Merge into ~/.claude/settings.json (per user) or .claude/settings.json (per repo):
For org-wide enforcement, ship the hooks in Claude Code’s managed settings with "allowManagedHooksOnly": true, so developers can’t remove them.

What the agent sees

A crashed hook blocks the call in closed mode (Claude Code would otherwise treat a crash as “allow”).

How agent tools are classified

Labels are session-wide for agents: once a session has read something internal and fetched something untrusted, later calls carry both. So “Approve sends that mix web content with internal data” holds a curl -X POST issued after the agent read the repo and fetched a web page. When unsure, a tool counts as write, never read. MCP annotations only make classification stricter (openWorldHint: true turns a write into egress). Override any tool per org in the governance settings’ external_tools:
Org tool policies apply by tool name too, for example blocking Bash for the member role.
A script’s command line doesn’t show what it sends, so once a session holds anything but web content, python -c …, node -e … and other script runners count as egress, and rules like “Confidential data never leaves” apply to them. Fibonacci reads the command the way the shell runs it, so quotes, line breaks, variables and wrappers don’t hide the program, and a command too long or tangled to read counts as a script. Test and build commands (pytest, npm test, make) are not counted, so agents can keep working. Matching commands is still a heuristic (a program copied under another name isn’t recognised): for a hard boundary on where data can go, also run the agent with a network sandbox, such as Claude Code’s sandbox with an allowlist of hosts.

Sessions and the kill switch

The Agents page in the web app shows every live session and revokes one in a click. A session belongs to the organization it started in (FIBONACCI_ORG_ID; without it, the key owner’s organization, so set it if you belong to several). The caller’s role is checked in that organization on every call. A call that names a different organization is denied, and so is anyone who has left the organization: start a new session to work elsewhere. These come back as deny decisions, never errors, so FIBONACCI_FAIL_MODE=open can’t turn them into an allow.

Calling /authorize from your own agent