Skip to main content
Every tool call Fibonacci makes, and every tool call an external agent asks about, is decided against your organization’s rules before it runs. A call is allowed, denied, or held for a human to approve, and the decision is recorded. What makes the rules useful is that they know where data came from, not just which tool is being called.

An example

One rule: “Anything that sends data out needs approval if it touches both web content and internal data.” If the FAQ page carried a prompt injection telling the model to post the roadmap, no single call looks wrong; the rule fires because of what the message is made of. An admin sees the held call in Approvals with the exact message, the rule and the labels, and approves or rejects it.

Five ideas

1. Side effects

Every tool declares one: read (fetches data), write (changes something in a connected system: a ticket, a card, a page) or egress (delivers content to people or places: a message, an email, an invitation, a comment). Rules and the read_only role constraint key off this, never off a tool’s name. The tool catalog lists each tool’s side effect.

2. Labels

Data carries labels such as internal, confidential, untrusted and pii.
  • Tools label what they return. Docs, Sheets, files, Jira, Trello and GitHub code are internal; web search results are untrusted; GitHub issues are both internal and untrusted, because anyone who can open an issue writes that text.
  • Label rules add labels, e.g. “reading sheet cust-2026 is confidential”.
  • Labels follow the workflow. A step’s inputs carry the labels of every step it depends on or references with {{…}}. Parallel branches don’t share labels.

3. Rules

Action rules match on side effect, tools, labels and parameters, and return a verdict: allow, require_approval or deny. When several match, the most restrictive wins.

4. Approvals

A held step pauses the run where it is. Approving resumes it on the worker from that point. Steps that already finished never run again, and the approval covers that exact call (tool plus parameters) and nothing else.

5. Receipts and audit

Every tool call writes a decision with the rule that made it and the labels involved: GET /api/v1/runs/{id}/authorization. The audit log is append-only and hash-chained, and the database rejects edits to it. GET /api/v1/organizations/{id}/audit-events/verify recomputes the chain and reports the first entry that doesn’t match. Before a run starts, Fibonacci analyses the whole plan. If a rule would definitely deny a step, the run is refused up front (403) and nothing executes. POST /api/v1/workflows/{id}/authorization-preview shows that analysis without running anything.

Rules

Rules belong to an organization. Fibonacci ships templates, and nothing is active until an org saves a rule.
Adopt a template:

Rule fields

Parameter operators: equals, in, not_in, contains, startswith, domain_in, domain_not_in.

Label rules

  • Paste links. Google Docs, Sheets, Slides and Drive links match the bare file ID a workflow uses, and the other way round.
  • No placeholders. A whole value like <YOUR_SHEET_ID> is rejected when you save (422) with a message to replace it.

Approvals

Approvals are opt-in: set approvals_enabled in the org’s governance settings. Risk is assessed and audited either way.

Who hears about it

If your org has connected Slack (Organization → Integrations → Add to Slack), the Fibonacci bot sends DMs:
  • When something waits, to every admin and owner who can decide it (owners only when it needs an owner). The message says what is waiting (the tool and step, the workflow, or the agent), the rule and data labels or the risk reasons, who asked and when it expires, and links straight to it in Approvals.
  • When it’s decided, to the person who asked: who approved or rejected it, their reason, and what happens next.
Slack messages never include the call’s parameters, which can hold customer data; the link opens them behind sign-in. People are found in Slack by their Fibonacci email. If Slack is briefly unavailable or rate limiting, each message is retried once; a message that still can’t be sent is logged, and the request is always in the Approvals inbox. Turn the messages off with slack_approval_notifications: false. The Approvals inbox and the dashboard badge also refresh on their own. Besides rules, whole runs can need approval by risk level. Fibonacci scores a workflow from the tools it uses (sending messages and email is high; creating channels, pages, tickets and cards is medium; reading company data is medium), and runs at or above approval_required_from wait for approval before they start.

Organization settings

Tool policies

Block a tool, or narrow what it may do, for the whole org or for one role (owner, admin, member, viewer). In the dashboard: go to Governance → Tool permissions. Pick who the policy applies to and the tool, then set its access and limits. The editor only shows the settings that can affect that tool: a GitHub tool offers allowed repositories, and Slack offers channels and a message length. You can paste a github.com link for a repository. Each role’s row shows the limits that apply once the org’s policy is combined with it, and warns when the two leave nothing allowed. Owners make changes; admins see the policies. Through the API:
On a role policy, "allowed": null keeps the org’s access and only adds limits. false blocks the tool for that role. GET /api/v1/governance/tool-constraints returns this table for every tool, which is what the dashboard uses. For external agents, a policy names the agent’s tool (Bash, Write, or mcp__<server>__<tool>), and only blocks and read_only apply. Without any policy, a tool works as soon as the person running it has connected it. Policies only ever narrow that, including for someone who saved their own token: a personal token only decides which credential a call uses, never whether a role may make it. Role constraints narrow the org’s: lists intersect, limits take the minimum, and read_only holds if either side sets it. An org block always wins.

Quota

A run over quota is refused when it’s queued (429), with the limit it hit.

Workflow versions and the registry

Every execution runs a frozen version of the workflow, so a run is reproducible even if the workflow is edited later.

Reporting

External agents

The same rules for Claude Code and any MCP client

Security

Production hardening and secrets