Agent SDKControl & GovernancePermissions

Permissions

Permissions are the first line of governance for an agent. They determine which tools Amara may invoke and under what conditions, before any code runs. The Syntic Agent SDK combines coarse-grained permission modes with fine-grained allow/deny rules and a runtime canUseTool callback, so you can be as permissive or as strict as your environment demands.

Permission modes

A permission mode sets the default posture for a session. Pick the one that matches how much you trust the agent in a given context:

  • default — the agent may use read-only tools freely but pauses for approval before actions that modify the workspace or run commands.
  • acceptEdits — file edits are auto-approved, but command execution still requires confirmation.
  • plan — the agent may only read and reason; it cannot make changes, which is useful for producing a plan you review before execution.
  • bypassPermissions — every tool runs without prompting. Reserve this for fully sandboxed, non-interactive environments.
import { query } from "@syntic/agent-sdk";
 
for await (const message of query({
  prompt: "Refactor the auth module.",
  options: { permissionMode: "acceptEdits" },
})) {
  // ...
}

Allow and deny rules

Rules refine a mode by naming specific tools or patterns. Deny rules always win over allow rules, giving you a reliable way to carve out forbidden operations even in permissive modes.

from syntic_agent_sdk import query
 
async for message in query(
    prompt="Clean up the repository.",
    options={
        "permission_mode": "default",
        "allowed_tools": ["Read", "Grep", "Edit"],
        "denied_tools": ["Bash(rm*)", "Bash(git push*)"],
    },
):
    ...

Gating calls with canUseTool

For decisions that depend on runtime arguments — not just the tool name — provide a canUseTool callback. It receives the tool and its input and returns an allow or deny decision, optionally with modified input. This is the right place to enforce policy like “never write outside the project directory.”

options: {
  canUseTool: async (toolName, input) => {
    if (toolName === "Write" && !input.path.startsWith("/workspace")) {
      return { behavior: "deny", message: "Writes are restricted to /workspace." };
    }
    return { behavior: "allow", updatedInput: input };
  },
}