Why rules matter
Credentials get an agent through the door. Rules decide what it can do once inside. Without rules, an agent with Gmail credentials can read, send, and delete emails with no limit. That’s useful, but it’s also how you get an agent mass-deleting an inbox before anyone can stop it. Rules let you say things like “this agent can use Gmail, but sending requires approval.”Deterministic enforcement, not prompts
You can tell an agent “never delete emails without my approval” in a system prompt. But a prompt is a suggestion, not a guarantee. Agents are non-deterministic. They can be manipulated through prompt injection, they can misinterpret instructions, or they can be too eager to please and take actions you didn’t intend. Rules are different. They’re enforced outside the agent, at the gateway level, before the request ever reaches the external service. No amount of prompt manipulation, jailbreaking, or overly helpful behavior can bypass a rule. If a rule blocks Gmail deletes, that request is blocked. Every time, deterministically, regardless of what the agent was told or tricked into doing.How the policy engine works
Every request an agent makes passes through the gateway, which evaluates the scope’s rules top-down, first match wins:- Organization rules run first: org-wide guardrails an individual project cannot loosen.
- Project rules run next: refinements for that project’s agents.
- Each level ends in a Default Rule, which decides what happens when nothing matched (Allow or Block).
Draft and publish
Edits never take effect immediately. Changes stage into a draft; the gateway keeps enforcing the last published set until you press Apply Changes (or call the publish API). Publishing snapshots the entire draft (including changes staged by teammates), so review the pending list before applying.
Anatomy of a rule
A rule pairs who (identities) with what (targets), and applies an action with optional modifiers.- Identities: who the rule applies to. Project rules target a specific agent or all agents; organization rules target agent groups, users, or user groups. Empty means everyone.
- Targets: at least one destination:
- an app (
{"kind":"app","provider":"gmail","tools":["send_email"]}), optionally narrowed to specific catalog tools, or the whole app whentoolsis omitted; - a connection (
{"kind":"connection","connectionId":"..."}): one specific connected account; - a secret (
{"kind":"secret","secretId":"..."}): a stored credential and its host; - a network pattern (
{"kind":"network","hostPattern":"api.example.com","pathPattern":"/v1/*","method":"POST"}).
- an app (
- Action:
alloworblock. - Modifiers (allow rules only):
requireApprovalholds matching requests for a human decision;rateLimitplusrateLimitWindowcap usage, with each agent tracking its own counter.

Migrating from the legacy model? The old
rate_limit and manual_approval
actions became modifiers on allow rules, and the flat host/path/method
fields moved into a network target.Creating rules
From the console: Policy → Add Rule. From the CLI:publishSkipped appears in the output) so you never accidentally ship a teammate’s half-finished edits. Review with onecli policy status, then onecli policy publish, or pass --publish-all. Use --no-publish to stage deliberately.
The same rule via the API (an org key needs the X-Project-Id header; a project key scopes itself):
POST /v1/policy/publish, or Apply Changes in the console. Read the enforced set with GET /v1/policy/rules?status=published, and compare draft against published rules by logicalId (published row ids regenerate on every publish).
Examples
Block a destructive operation everywhere (an org rule, applies to everyone):read_all and write_all where the app supports them). Output abridged to a few tools per group; the real catalog lists every tool:
Conditions
Conditions narrow a rule beyond its targets by inspecting the request body. Each condition names atarget (body), an operator (contains), a value, and an optional key to scope the match to one JSON field; multiple conditions are ANDed.
{"repositories": ["org/repo"]} (GitHub) or {"folders": ["/exports"]} (file providers), restricting which resources that connection can touch.
Manual approval
An allow rule withrequireApproval holds matching requests until a human decides. The gateway keeps the agent’s connection open (up to 5 minutes) while it waits; unanswered requests are denied. The reviewer sees the method and URL, sanitized headers, and a body preview, so they can judge exactly what the agent is trying to do.
Decisions flow through the console, or programmatically via the SDK:
App permissions are rules
Per-tool app permissions (“block Gmail sends”, “GitHub pushes need approval”) are ordinary policy rules with anapp target, exactly like the examples above. The per-app App Permissions panel shows the effective result per tool (Allowed, Needs approval, Blocked, or Not managed) and links to the Policy console, which is where you edit.
Read the current per-tool state from the API (available on OneCLI Cloud and Enterprise self-hosted releases):
How rules interact with credentials
Rules evaluate before credential injection. A blocked request is rejected at the gateway: the credential is never attached, and the upstream service never sees the request. Allow rules that name a specific connection or secret also drive which credential is injected.Self-hosted deployments
Self-hosted servers that have not yet cut over to the policy engine keep the legacy/v1/rules model: legacy writes work there, and /v1/policy writes return 403 until the cutover release. On OneCLI Cloud the policy engine is live; legacy rule writes return 410 Gone pointing here.
Coming soon
- Monitor action: log matching requests without blocking, useful for auditing before enforcing
- Time-bound access: grant access only during specific time windows