Strata PlatformDocs

Agent permissions and safety

Agents run without a human in the loop, so the rules for what they can do are stricter than for chat. This page covers the per-agent tool set, the dry-run sandbox, the safety patterns we recommend, and the org and per-user controls admins can apply on top.

The allowed tool set

Every agent has its own Capabilities map (the Tools section of the agent form). The map lists every tool the AI might call during a run, grouped by category:

  • Database — run_sql.
  • Outlook — search_outlook, read_outlook_email, read_outlook_attachment, send_email.
  • OneDrive — search_onedrive, read_onedrive_file, save_to_onedrive.
  • Jira — search_jira, write_jira.
  • Confluence — search_confluence, write_confluence.
  • Generation — generate_excel, generate_pdf.
  • Code & composition — run_python, invoke_agent, spawn_subagents (shown as Sub-agents).
  • Web — search_web.

A tool only enters the agent's toolset if its switch is on in the agent form and every layer of governance above it allows it (the extensions the owner may use — from their role, any role bound to one of their groups, the organization and their per-user settings — and the per-user agent extension mask). At runtime the AI sees only the tools that survived all layers — others are stripped entirely, not just "denied on call".

Note

The Web, Jira and Confluence groups are hidden when that extension isn't allowed for you, by the same check as step 4 under "Server-side enforcement" below: your role, widened by any role bound to one of your groups, narrowed by your organization's extension list in Ceiling mode, minus any extension an admin turned off for you. An admin's change reaches the form without a reload: Strata re-reads your access whenever you come back to its tab or window, at most once a minute. If it couldn't read your access in full, the form hides none of these groups rather than guess. The per-user agent extension mask (step 3) isn't reflected in the form, so a group can still show whose tools the mask strips before the run. Other categories stay visible even when the underlying extension is off — those are enforced at runtime (see "Server-side enforcement" below), so a switch you flip on may still be stripped before the run if the org, your roles or your per-user settings disallow it.

"Sensitive" tools

These tools have visible side effects outside Strata. The four that send email, write files, or write into Jira or Confluence carry a small Sensitive tag next to the name in the agent form:

  • send_email — sends a message via Outlook with no in-run confirmation prompt. (Tagged Sensitive.)
  • save_to_onedrive — creates or overwrites files in OneDrive. (Tagged Sensitive.)
  • write_jira — files issues, posts comments, changes an issue's status and edits its fields (summary, description, priority, labels, components, due date, assignee) in Jira with no in-run approval prompt. In chat, Strata asks the member before each write; a scheduled run has nobody to ask, so the write proceeds. It also needs Jira writes to be permitted for the agent's owner — see below. Treat it as one-way: a Jira Service Management comment cannot be edited or deleted through Atlassian's API once posted, and a status change can notify the customer who raised a request. (Tagged Sensitive.) See the Atlassian extensions page.
  • write_confluence — creates pages and posts page comments in Confluence with no in-run approval prompt, on the same no-one-to-ask reasoning as write_jira. The agent form labels it Create pages and comment; Strata has no tool that edits an existing page. It resolves against the owner's Confluence write access, separately from Jira's. (Tagged Sensitive.) See the Atlassian extensions page.
  • spawn_subagents — lets the run split its work across up to 5 parallel sub-agents per step (10 per run, no nesting). It isn't tagged Sensitive because a run's sub-agents are always read-only: they use only the tools this agent was granted, can't take any action that changes data, and share the run's token and cost ceilings rather than each getting the full amount. It also requires sub-agents to be allowed for the agent's owner. See Sub-agents in scheduled agents.
  • run_python — executes sandboxed code (no network, no host filesystem, but it can still produce files and consume tokens). It isn't tagged in the agent form, but it's treated as destructive for dry runs (see below).

Every issue and comment an agent creates in Jira (including a note added with a status change) ends with a trailing line naming Strata, the agent, and the member the run belonged to — for example Filed by Strata — scheduled agent "Ticket triage" for dana@example.com. Jira's own author field is whoever the connection authenticates as, so that line is the only signal to a reader that an automation did it. A status change or field edit carries no such line; Jira's history shows it under the connection's account, and Strata's audit log records it as jira.issue_transitioned or jira.issue_updated.

An agent's Atlassian access is its owner's

A scheduled agent reaches Jira and Confluence through the member who deployed it — one Atlassian connection covers both. In the default each person signs in mode it runs on that person's connection and can never see more than they can; if they disconnect, its Jira and Confluence tools go quiet. (In one organization account mode the reads go through the org's service account instead, so what it sees stops depending on the owner.)

Whether it may write is resolved for the owner in both modes, from the organization's writes toggle for that product narrowed by the owner's role and their per-member override. Jira and Confluence writes resolve independently, so an owner can be cleared for one and denied the other. Setting any of those layers to Denied stops every agent that person owns — an owner narrowed out of writes cannot regain the capability by scheduling a run. And when writes do not resolve on, write_jira (or write_confluence) is not registered for the run at all: there is no tool for the AI to call, rather than a tool that refuses. See Who may write.

These tools shouldn't be granted unless the agent's prompt genuinely needs them. The agent form's Tools section says:

Turn on only what this agent needs. Tools that send email or write files act without asking you during a run, so turn them on only when you trust the instructions.

Safety pattern — errors-only notifications

The cleanest pattern for a monitor agent is errors-only notifications + minimal capabilities + tight runtime cap:

  • Capabilities: only what the task absolutely needs.
  • Notifications mode: Only on failures.
  • Response size: Quick (60s, 5,000 tokens) unless the output genuinely needs more.

The built-in SQL anomaly watcher template uses this pattern. It runs hourly during business hours (9 AM–5 PM, Mon–Fri), finds nothing wrong most of the time, and only emails when something looks off. You stay quiet and trust the silence.

Dry runs

A dry run, Test run on the Agents page, is the agent equivalent of a test pull request — it executes the prompt with destructive tools (send_email, save_to_onedrive, run_python, write_jira, write_confluence, invoke_agent) stripped from the toolset for that single execution. The AI sees an extra system-prompt line:

DRY RUN: Tools that send email, save files, run code, write to Jira or Confluence, or run other agents are disabled. For any such step, describe in writing what you would have done — do not pretend it succeeded.

invoke_agent is stripped because the agent it calls would otherwise run for real, with its own tools, from a run started only to see what would happen.

Result lands in run history with trigger_type=manual-dry, shown as Test run. Notifications are skipped (no point notifying about something that didn't actually happen). A test run doesn't change the agent's status or its failure streak: a failing test run can't back the agent off, and a good one can't clear the streak. It does count toward your daily run limit and the agent's monthly spend.

Start one from Test run in the ... menu of an agent's row or of its own page, from Try it now on a new agent's page, or programmatically — POST /api/agents/:id/run?dry=1 (or dry: true in the request body). See /docs/agents/schedules.

Use test runs before enabling Sensitive tools on a new agent. Read the run output to confirm the agent describes the destructive action correctly (which email it would send, which file it would overwrite). Only then enable the capability and let it run for real.

Reviewing run logs and outputs

Every run lands in the agent's Recent runs section, with status, trigger type, elapsed time, a short summary, and (in the run modal) the full output and an Action steps trace of every tool the AI called. Status values:

  • success — the AI emitted STRATA_STATUS: SUCCESS.
  • error — the AI emitted STRATA_STATUS: FAILED - <reason>, or one or more tool calls returned errors and the AI didn't confirm completion.
  • timeout — the run exceeded its max_runtime_sec cap and was aborted.
  • throttled — the AI model was rate-limited or briefly unavailable (an HTTP 429 or 503 from Azure AI Foundry). The run didn't fail; it defers ~15 minutes and retries, and is never counted against the agent. Shown as Skipped in the run list and Skipped — the AI service was busy in the run detail.
  • blocked — the run was never allowed to start: the org is suspended, its subscription is inactive, a usage, model or spend limit was reached — including a group's model limit on the agent's owner — or Strata couldn't read the owner's group roles to check the agent's model (Could not check which models this agent's owner may use., then It will try again in 15 minutes. on a scheduled run, which is deferred, or Try again in a moment. on any other run, including Run now). Shown as Skipped in the run list and Skipped — not started in the run detail. Not counted as a failure, so it never contributes to the back-off below. A scheduled run stopped by a monthly limit (its owner's own spend limit, the AI spend ceiling or the credit allowance) or by the pool tries again at the earlier of that limit's reset and one hour; one stopped by the hourly limit tries again in 15 minutes. Run now answers with the same reason, in words.
  • orphaned — the run was cut off before it finished, for example by a restart. Shown as Interrupted in the run list and Interrupted — cut off before it finished in the run detail.

After 5 consecutive failures (MAX_CONSECUTIVE_FAILURES), the agent is backed off rather than killed. A run refused because its model isn't allowed is recorded as error but, like blocked, isn't counted as a failure, so pressing Run now on such an agent can't start the back-off. The Agents page shows it as Failing; the scheduler defers it about an hour at a time, and once an hour has passed since its last run lets a single probe run through. The first probe that succeeds resets the streak and the agent resumes on its normal schedule automatically; a probe that fails backs it off for another hour. You never have to re-enable it by hand — fixing the underlying cause simply lets the next probe succeed.

Server-side enforcement of "allowed"

The agent permission map is enforced at the scheduler, not at the AI's discretion. selectAvailableTools(agent, …) in agentScheduler.js builds the toolset by intersecting:

  1. The agent form's tool switches.
  2. (If dry run) the destructive-tools blocklist.
  3. (If admin set one) the per-user agent extension mask (see /docs/agents/per-user-governance).
  4. The extensions the owner may use at all — their role's list, widened by any role bound to one of their groups, narrowed by the organization's list when it is locked, minus any extension an admin turned off for them. A role saved with no extensions ticked allows none. File generation, Analysis, agent chaining and sub-agents aren't governed this way, so this step leaves them alone.

A tool that doesn't survive that intersection is simply not registered for the run — even if the AI tries to call it, the call fails immediately because the tool isn't in its toolset. When a per-user mask is active, the system prompt also appends a line:

ADMIN RESTRICTION: Your administrator has limited the tools this agent can use. Only the following tools are actually available at runtime: <list>. Do not try other tools — they are stripped from your toolset and will fail. If the task requires a tool not in this list, fail with STRATA_STATUS: FAILED and explain that the required tool was not available.

This means the AI doesn't just try and fail — it sees the restriction up front and either completes the task within the allowed tools or fails cleanly with a clear reason.

[Admin] Org-level agent limits

Admins can apply broad controls in Organization > Agents (/admin/agents):

  • Agents per member (max_agents_per_user) — per-user cap on how many agents a single user can deploy. Hitting it returns Agent quota reached: your organization allows up to N agent(s) per user. Delete an existing agent to make room.
  • Minimum time between runs (min_agent_interval_seconds, set in minutes) — minimum cadence between runs. Schedules that fire more often return Schedule is too frequent: your organization requires at least Ns between runs...
  • Runs per member, per day (max_agent_runs_per_day) — a per-user daily cap, counted across all of that user's agents since midnight UTC. Once the count is reached, further runs are skipped silently (skipped: true, reason: daily_cap_reached). This applies to every trigger — scheduled, webhook, manual Run now, test runs (dry runs), and invoke_agent linked-agent runs alike — because each is a run against the same ceiling. Run now past the cap is normally answered 409 with You've reached your organization's limit of N agent runs per member per day. Runs start again at midnight UTC. (It used to exempt manual and linked-agent runs, which let a user exhaust the cap by hand and starve their own scheduled runs.)
  • Cost ceilings — Tokens per run (max_agent_tokens_per_run) and Spend per run (max_agent_cost_cents_per_run) cap what a single run may consume (the run is stopped mid-execution once a ceiling is reached), and Monthly spend per agent (max_agent_cost_cents_per_month) caps each agent's total spend per calendar month (once reached, the agent is skipped until the month resets). See Rate limits and quotas for the recommended values.
  • Freeze agent changes (lock_agents) — org-wide kill switch, under Rules for everyone, effective now at the top of the section. Blocks all new agent creation and content edits across the org, admins included. Existing agents continue to run on schedule.

These controls cascade through both POST /api/agents and PATCH /api/agents/:id. Pause / resume and starring an existing agent bypass the lock (see the pause-only exception in /docs/agents/per-user-governance).

[Admin] Per-user lock and tool mask

Independent of org-wide controls, admins can lock a single user out of creating or editing agents, and / or restrict which extension categories that user's agents can touch at runtime. See /docs/agents/per-user-governance for the full mechanics — including the lock-but-allow-pause exception, the intersection of template permissions and user mask, and how existing scheduled runs continue while the next create/edit gets blocked.

[Admin] The model an agent runs on

Each agent is pinned to one AI model, chosen in the footer of the agent form's Instructions box. The picker offers the models you may use: those your organization has enabled in the Model Catalog (Organization → Models → Manage models), narrowed by your role and any limit set for you, so an agent is never saved on a model its runs would be refused. The effective set a model run is allowed to use — the same governed set chat uses — is the intersection of three layers:

  1. The models your organization has enabled in the catalog.
  2. The models the owner's role allows, widened by any role bound to one of their groups. A built-in role doesn't restrict models.
  3. The owner's per-user model override, if an admin set one.

The form's model picker filters on the org layer only. Creating an agent, switching it to another model, or resuming it checks all three layers for the member doing it, so a model they can pick but their role or per-user override excludes is refused there with <Model> isn't available to you: your role doesn't allow it. Pick one of: …. (or your organization doesn't allow it / it isn't in your own model list); a refused resume reads This agent can't resume. <that sentence> Edit it to use another model, then resume it. If the member's access can't be read at that moment, the save goes through and the run decides. A save that keeps the model and doesn't resume the agent isn't checked, so an owner who lost the model can still pause, rename or reschedule the agent. Before a scheduled, webhook, or manual run starts, the scheduler re-resolves the owner's allowed list and:

  • Validates the agent's pinned model. If the owner may no longer use that model (an admin turned the model off for the organization after being shown which agents would pause, or narrowed the owner's role, a role one of their groups gives them, or their per-user models; see the warning below), the run fails with a message that names the level leaving the model out and lists the chat models still allowed, by their catalog names: Agent model "<Model>" is not allowed by your role or group roles. An admin can allow it on your role in Organization › Roles, or you can edit this agent to use one of: …., …is not in your own model list. An admin can allow it on your record in Organization › Users, or you can…, or …is not in your organization's allowed list. An admin can allow it in Organization › Models, or you can… (when no model is left at all, it points to Organization › Models, Organization › Roles and Organization › Users; when models are left but none of them is a chat model, the admin clause widens instead of listing models — …An admin can allow it, or another chat model, on your role in Organization › Roles., and the same for the other two levels). When the refused run was unattended — its schedule, its webhook, or another agent invoking it — Strata then pauses the agent: it shows Paused, the run's error and the owner's Inbox notice (<name> stopped, Stopped · its model is not allowed) end This agent is paused until then; press Resume on it to start it again., and it doesn't run on schedule, from its webhook (which answers 409 Agent is paused) or when another agent invokes it (the calling agent is told The agent "<name>" is paused. Its owner can resume it on the Agents page.) until its owner presses Resume. The agent does not silently fall back to another model. Run now and a dry run are refused the same way but pause nothing, because the owner started them. POST /api/agents/:id/run waits up to 1.5 seconds for that answer, so a refusal comes back as 409 with the reason (the Agents page shows it under Could not start run) instead of queued; a run still going after that wait is answered queued as before. A refused Run now leaves an <name> failed notice beside any report the owner hasn't read, and a dry run leaves none. The same notice isn't posted to the owner again within 24 hours. If the owner's group roles couldn't be read at that moment and, without them, the model isn't allowed, the model isn't refused and nothing is paused: the run is recorded as not started with Could not check which models this agent's owner may use. A scheduled run adds It will try again in 15 minutes. and is deferred by 15 minutes; any other run adds Try again in a moment., and for Run now that sentence comes back as the 409 (Could not start run).
  • Clamps background reviewers (the artifact and document review passes) to the same allowed set, so a scheduled run can never reach a model the owner couldn't use in chat.

To restrict the models a single user — and therefore their agents — can pick, open Organization → Users → (manage user) → Access → AI models and uncheck models. A model their role doesn't allow (roles bound to their groups included) is shown as Not allowed by their role and can't be ticked. Leaving every box checked means the user inherits every model the organization and their role allow; unticking every box does the same rather than blocking them, and the hint then reads Nothing is ticked, so this user gets every model their role allows: N of M.

Warning

Turning a model off for the whole organization asks first while agents run on it. In the Model Catalog, Disable model, and Remove deployment, which turns the model off too, don't go through straight away while an agent that can still run is set to the model: one that isn't paused, owned by a member whose account isn't disabled. A second dialog, Turn off <model>? (or Remove deployment?), says how many agents run on it and whose (<N> agents owned by <M> people run on this model. They pause on their next run until moved to another model, and each owner is told.) and lists them by owner, the people with the most agents first, each with their count and their agents' names. The list scrolls inside the dialog, a Filter by person or agent field appears once there are more than six owners, and in a large organization the list holds the first 200 agents and counts the rest (And <N> more people with <N> agents between them.). Nothing changes until you press Turn off <model> anyway (or Remove deployment anyway); Cancel leaves the model on and the deployment in place. Once it is off, those agents fail their next run: a scheduled, webhook or linked-agent run pauses them and tells their owner, and Run now is refused without pausing. Paused agents and agents whose owner is deactivated aren't counted, since they don't run on their own; a paused agent on a model the organization has turned off can't be resumed, and Run now on it is refused, until it is moved to another model or the model is turned back on. An admin can't edit another member's agent, so only its owner can move it (an admin with Manage users can delete it from the owner's Agents tab in Organization › Users). The onboarding Models step doesn't ask: it keeps a model agents use and says Leave it on here and turn it off from the Model Catalog, which names them and asks first. Through the API, the change answers 409 with code: "agents_will_pause", the agent and owner counts (agentCount, ownerCount) and up to 200 of the agents, and goes through when it is sent again with confirmPause: true (?confirmPause=1 on the deployment removal). Narrowing a role's models (a group-bound one included), changing a member's role, groups or AI models, removing a member from a group, unbinding a role from a group or deleting a group isn't refused this way, and neither is Change role or Remove from group in bulk from the Users list: the save goes through and warns about the agents it newly leaves without their model: <N> agents will pause, <agent> (<owner>), <agent> (<owner>), <agent> (<owner>) and <N> more, owned by <M> people, run on a model this change no longer allows. They pause the next time they run on a schedule, a webhook or another agent, until moved to another model; Run now is refused. Each owner is told. It names three agents at most, however many there are, and counts the rest and their owners; when they are all one person's it reads …, owned by <owner>, run on… and ends Their owner is told., and for one agent <agent>, owned by <owner>, runs on a model this change no longer allows. It pauses the next time it runs… and Its owner is told. An agent an earlier change already left without its model isn't named again, and if Strata can't check which agents were left without their model before the save, or which are after it, the save goes through without that warning. Changes your identity provider makes through SCIM don't show that warning; the owner still gets the Inbox notice when the agent pauses. Those agents fail their next run, a scheduled, webhook or linked-agent run pauses them, and Run now is refused without pausing; a paused agent stays paused, and Resume is refused, until the model is allowed again or its owner moves it to an allowed model. Retirement is different: on a model's retirement date Strata moves pinned agents to its replacement itself, unless Move to the replacement when a model retires is off under Organization → Models.

[Admin] Where to look for agent activity

  • Organization > Users > (click user) > Agents tab — every agent this user has deployed, with status and a delete affordance.
  • Organization > Usage — agent runs and cost roll up here alongside chat usage. Filter to a single user for per-person breakdowns.
  • Organization > Audit log — agent-template create/edit/delete events. Run-level events are not audit-logged today (they're in the agent's own run history).

What can go wrong

  • An agent shows Paused after its owner moved to another organization — when someone signs in and Strata places them in a different organization (their email domain now belongs to another one), their agents move with them and are paused, so nothing runs on the new organization's AI engine or bill until the owner checks each agent and presses Resume. Resume re-checks the agent's model against the new organization's rules.
  • An agent ran but did nothing useful — check Recent runs. Most often the agent had STRATA_STATUS: FAILED because a required extension wasn't connected, or a required tool was masked off. The failure reason is in the run detail.
  • An extension the agent needs isn't connected — a scheduled run has no one to show a connect card to, so it never offers one. It does what it can without the extension, and its result (and its notification, if it sends one) names the extension, says you can connect it in Settings › Apps, and that the agent will use it on its next run. Connect it there and the next run picks it up.
  • Agent quota reached: your organization allows up to N agent(s) per user. Delete an existing agent to make room. — you've hit your org cap. Delete an unused agent.
  • Schedule is too frequent: ... — your schedule violates the org minimum interval. Pick a less frequent cadence.
  • The AI says "the required tool was not available" — the per-user agent extension mask is blocking a tool the agent's prompt needs. Ask your admin to enable the corresponding extension category on your account, or rewrite the agent to use a different tool.
  • An agent shows as Failing after 5 failures — open the agent: the panel under its name gives the last error, with View run and Run again. The agent isn't gone: the scheduler lets one probe run through per hour, and the first success (whether that hourly probe or your own Run now) clears the failure streak and returns it to Scheduled. A test run counts neither way. You don't have to re-enable it manually.
  • An agent shows as "Paused" and nobody paused it — its pinned model is no longer allowed for its owner. The owner's Inbox notice and the run's error name the setting that leaves the model out: the owner's role or group roles (Organization › Roles), their own model list (Organization › Users), or the organization's list (Organization › Models). Allow the model there, or have the owner edit the agent to use an allowed model; then the owner presses Resume, which is refused while the model still isn't allowed.
  • A test run shows the AI "would have" sent an email but a real run sends a wildly different one — the AI is non-deterministic. Repeat the test run a few times to see the spread of behaviors, and tighten the prompt with explicit constraints before enabling Sensitive tools.

Related