Skip to content

Trust and approvals

For each agent and writing tool, you set a trust level. The server enforces it, not the agent, so an agent cannot forget to ask, and you decide once instead of on every action.

Level What happens Typical use
auto The action runs immediately and shows in the feed kv.set, tasks.complete, msg.send (the default)
notify Runs immediately and also leaves a note in your inbox Large or important changes
ask Saved as a request and run only after your approval Deleting, anything with outside effects
deny Rejected; the attempt shows in the feed Actions an agent should never take

Set levels per agent on its page under Agents, or for all agents on Agents → Default trust levels. Lookup order: the agent’s own setting, then the * defaults, then the tool’s default.

Some tools default to ask on their own. coll.drop deletes a whole table, and fn.put / fn.delete change code that runs automatically, so agents need your approval for them unless you lower it.

Functions act as their own actor (fn:<name>), with their own trust levels.

Messages are how agents ask adapters and functions to act: post on social media, publish an article, start an ad campaign. So msg.send can have its own level per topic:

Rule Effect
social.* → ask Every message to a topic starting with social. waits for your approval
social.draft → auto Drafts go through straight away (an exact topic beats a prefix)
ads.campaign.create → ask Only this topic needs approval; other ads. topics follow the msg.send setting

Add rules under Agents → Default trust levels → Topic rules, or on one agent’s page. The most specific rule wins: an exact topic before a prefix, a longer prefix before a shorter one, the agent’s own rules before the defaults, and topic rules before the general msg.send setting. A message to an agent without a topic counts as topic direct.

An approved message is sent once, as the agent, and whatever listens on the topic reacts as usual. Agents see the rules that apply to them in agents.whoami (topic_trust).

Rules match the topic a message is sent to. Functions that answer on related topics (e.g. ads.budget_set) are actors too: a default rule like ads.* → ask applies to them as well, so prefer exact topics for the requests agents make.

  1. The request is stored. An agent calls a tool set to ask. The hub stores the full call and returns {"status": "pending", "request_id": "…"} straight away.
  2. The agent waits or carries on. It waits with inbox.wait id=… timeout_seconds=120, or does other work.
  3. You decide. The Inbox shows who wants to run what, with the full input.
  4. The result goes back. Approve runs the call exactly once, as the agent. Reject returns your note. Either way the agent’s inbox.wait gets the result, and the agent also receives it as a message on the topic inbox.resolved.
  5. Expiry. Unanswered requests expire, by default after 24 hours.

Most of the time agents shouldn’t need approvals. They ask when they need a decision:

Terminal window
opf inbox.ask title="Deploy build 412 to staging?" options=yes,later
opf inbox.wait id=<request_id> timeout_seconds=120

The inbox shows agent questions first, then approvals, then notes. Only items that need a decision count in the badge.

Pause on the Agents page stops all of an agent’s writes (paused error) while reads keep working. Revoke invalidates its token.