The gate
How your rules decide what an action is allowed to do.
Before your agent does anything, the gate checks the action against the rules you wrote and picks one of four paths: let it through, refuse it, hold it for a person, or let it through with some fields stripped out. Whatever it decides, your code gets back a clear outcome you can branch on.
You write the rules in heso.toml and read the result off outcome.allowed:
# Rules are checked top to bottom. The first one that matches wins.
# A large payment is held for a person.
[[rule]]
id = "payment.large"
order = 10
enabled = true
subject = { kind = "any" }
verb = "payment"
scope = "*.stripe.com"
decision = "require_approval"
conditions = [{ field = "amount", op = "gt", value = 10000 }]
# Everything else a tool call does is fine.
[[rule]]
id = "tool.allow"
order = 100
enabled = true
subject = { kind = "any" }
verb = "tool_call"
scope = "*"
decision = "allow"What the gate returns
Every gated call resolves to one of three outcomes. You read it off outcome.allowed and the outcome value, and act on it:
The four rule paths (allow, block, redact, require_approval) collapse into those three outcomes: a redact rule still lets the action run, so you see allowed with the named fields already gone, and a require_approval rule shows up as suspended until a person clears it.
How a decision is made
Your rules are an ordered list. The gate walks them top to bottom and the first rule that matches the action wins. It checks who is acting, what kind of action it is, where it is going, and any conditions you set (like amount > 10000). Once a rule matches, the gate stops looking and uses that rule’s decision.
No match means a person looks at it
If no rule matches, the gate does not guess and it does not quietly allow. It holds the action for a human (require_approval), so an action you never wrote a rule for becomes suspended rather than slipping through.The floor you cannot weaken
Some actions are risky enough that heso always holds them for a person, no matter what your rules say. A payment with no proof a user authorized it, or a destructive action heso cannot identify, is held by default. A rule you write can make things stricter, but it can never make these looser. heso even refuses to load a policy whose rule would blanket-allow one of them, so you find out when you save the file, not in production.
- An allowed action runs and gets a signed receipt.
- A blocked action never runs, and nothing is signed.
- A suspended action waits for an approver before it can run.
Where to go next
Policy authoring
Write the rules: subjects, conditions, decisions, and the order they fire in.
The gate SDK
Wire the gate into your code and branch on what it returns.
Limits
The gate can only decide on actions it sees. An action that leaves through a path you did not put the gate on is never checked, so coverage is only as complete as where the gate is installed.