Tool permissions and approvals
A hosted agent can call tools with real consequences: refunds, emails, changes to records, code that runs in a container. The tool_policy on an agent definition decides which tools run on their own, which wait for a person to approve them, and which are never allowed. This page explains the policy, the approval flow in a session, and how to choose settings.
The policy
{
"tool_policy": {
"default": "allow",
"require_approval": ["issue_refund", "send_email"],
"deny": ["delete_customer"]
}
}| Field | Meaning |
|---|---|
default | allow: tools run without asking unless listed below. ask: every tool waits for an approval decision. |
require_approval | Tools that always wait for a decision, whatever the default. |
deny | Tools the agent may never run. A call is refused and the agent is told so. |
Names are the tool names as the agent sees them: your function tools, built-in tools such as syntic_web_search, and tools offered by the agent’s MCP servers.
The approval flow
The agent calls a guarded tool
The session emits an approval.required event with the call’s tool_call_id, name and arguments, and its status becomes requires_action.
Your code or a person decides
Show the call to whoever approves it, with enough context to decide: the arguments, the recent conversation, the customer.
Send the decision
Post a user.approval event. approve runs the tool; reject tells the agent it was refused, with your optional reason.
The agent continues
The session returns to running. After a rejection the agent adapts, for example by explaining to the customer that a person will follow up.
curl -sS https://app.syntic.ai/v1/sessions/sesn_01JC7M2K4P6R8T0V2X4Z/events \
-H "Authorization: Bearer $SYNTIC_API_KEY" \
-H "Content-Type: application/json" \
-H "syntic-beta: agents-2026-11-01" \
-d '{"events": [{"type": "user.approval", "tool_call_id": "call_9",
"decision": "reject", "reason": "Refunds over 100 EUR need a manager."}]}'A pending approval waits up to 24 hours; after that the turn ends with outcome error. Subscribe to the session.requires_action webhook so approvals do not depend on someone watching a stream.
Who may change the policy
Editing an agent needs a key whose creator holds the Developer role or higher. Turning on tools that the Console marks as approval-required follows the Console’s rule: only keys created by Administrators and Owners may do it. Every change creates a new agent version, so the history shows when a guard was loosened and by whom.
Choosing settings
| Tool kind | Suggested policy |
|---|---|
| Reads your own data (lookups, search) | allow |
| Writes that are easy to undo (notes, tags, drafts) | allow, with logging |
| Money, messages to customers, deletions | require_approval |
| Operations the agent should never do | deny, or leave the tool off the agent entirely |
| Code execution in an environment with network access | require_approval until you trust the agent’s behaviour on your test scenarios |
Approval in code (rules like the 100 EUR limit above) and approval by a person can be combined: decide the clear cases automatically, send the rest to a queue. With default: "ask", the same pattern lets code approve routine read-only calls while a person sees the rest.
A policy limits which tools run; it does not check what a tool does with its arguments. Your tool implementations should still validate every argument and enforce your business rules.
Related
- Agent definitions API
- Send session events
- Build an agent: approval as a tool result in a self-hosted loop.