Access
Declare who can run what. role blocks derive roles from verified identity attributes, and policy grants map those roles to agents, workflows, and tools.
What it is. Who may reach in: the roles and grants that decide which people can talk to which agents and start which workflows. The mirror image of connections, which govern what your system reaches out to.
Use it when you want to control who can talk to an agent or start a workflow, or you have an org chart and want the system to respect it.
Works with the Portal's project Access page (assign attributes to members), OIDC federation (your IdP's claims as the facts), agents and workflows (the targets of grants), and the audit log (where access decisions are recorded).
By default, every member of your organization can run everything in a deployment. role and policy blocks change that. Declare roles derived from verified identity attributes, attach grants to them, and the project flips to deny by default: a principal can only reach what a matched role grants.
Access control lives in your .swirls files, so every change to who can run what is reviewed, versioned, and deployed like the rest of the system.
The model: identity asserts facts, the file decides what they mean
The identity source never assigns a Swirls role. It only asserts facts about the principal: a Swirls user carries their organization role and any attributes assigned in the Portal, and a federated user carries the verified claims from their identity provider's JWT. Your role blocks decide which facts to trust and what they mean. The claim keys named in match rules are the only attributes the policy engine ever reads; anything else the identity source sends is inert.
The role block
A top-level block that derives a named role from attribute values:
role finance {
description: "Finance team"
match {
department: "finance"
}
}
role exec {
match {
org_role: [ "owner", "admin" ]
}
}| Field | Type | Required | Notes |
|---|---|---|---|
description | string | No | Human-readable description of the role. |
match | block | Yes | Attribute conditions, one per line. |
Match semantics:
- A scalar value is an equality test:
department: "finance"matches when the principal'sdepartmentisfinance. - A list value is a membership test:
org_role: [ "owner", "admin" ]matches either value. - Multiple conditions in one
matchblock must all hold (AND). Declare separate roles for OR. - A principal whose attribute is itself a list (for example,
groups) matches when any of its values intersects the condition. - An empty
matchblock matches no one;swirls doctorwarns about it.
Role names match ^[a-zA-Z0-9_]+$, and duplicate role names are an error.
The policy block
A top-level block that attaches grants to role names:
policy {
allow finance -> agent accountant {
workflows: [ brex, quickbooks ]
}
deny finance -> agent ceo_pa
allow exec -> agent *
}Each grant is allow or deny, a role name, ->, and a target agent <name> or agent *. The policy block takes no name, and agent * (every agent in the deployment) is the only wildcard.
- An omitted body grants all of the agent's workflows and tools. The body's only keys are
workflows:andtools:, bare-identifier arrays that narrow the grant. denyalways wins overallowfor the same agent, across every role the principal matched. Deny works at the agent granularity; there is no per-workflow or per-tool deny.- A principal matching multiple roles gets the union of their grants.
- Declaring any grant flips the project to deny by default. Principals matching no granting role cannot run the deployment. Remove every grant to return to the open posture; an empty
policy { }enforces nothing.
Roles without grants are inert. Define them first, deploy, and confirm who matches in the Portal before adding grants.
Where attributes come from
Swirls users
Members of your organization carry two kinds of attributes:
org_role: the organization role (owner,admin, ormember), managed on the Members page in the Portal. Use it for org-wide rules like an admin role.- Project attributes: facts like
departmentorgroup, assigned per project in the Portal under your project → Access. The page reads the active deployment, offers only the attribute keys your deployedroleblocks reference, and previews which roles each member matches as you assign values. Assignments in one project never affect another.
Only organization owners and admins can assign project attributes, and a project attribute can never override org_role.
Federated users (OIDC)
Principals authenticating through OIDC Federation carry the verified claims from the JWT they exchanged. Your identity provider is the attribute source: put department, groups, or any other fact in the token, and match rules evaluate it directly. See map identity claims to access roles for provider setup.
Enforcement
Access is evaluated when a run starts, bound to the principal who triggered it. Every entry point takes the same path: chat, forms, webhooks, schedules, and the API all evaluate the policy before a run begins. Runs started by schedules and triggers evaluate as the principal who owns the trigger.
A principal matching no granting role cannot start a run on a deny-by-default deployment. The decision is stamped into the run's short-lived scoped execution credential, and during the run each agent invocation is checked against the granted agent set, so a workflow can never reach an agent its principal was not granted, including agents reached mid-run. Grants and denials are recorded in the audit log.
Enforcement applies at the agent boundary today. workflows: and tools: narrowing is declared in the grant and recorded on the execution credential, with enforcement at those finer boundaries rolling out next. Use agent profiles to restrict an agent's tools in the meantime.
Enforcement fails closed. An unresolvable principal is denied, a deployment that declares a policy refuses to run unenforced, and a policy that cannot be read denies rather than falling open.
Validation
swirls doctor checks role name shape, duplicate role names, and empty match blocks. It does not verify that a grant's role, agent, workflow, or tool names reference declared blocks: a typo'd name in a grant surfaces at run time as a denial, not at author time. Check grant spelling against your declared role and agent blocks before deploying.
Common mistakes
- Writing an
access { }block. There is noaccessblock; it is a parse error. Opt-in is implied by declaring grants. - A typo in a grant. Grant names are not checked against declared blocks at author time; the misspelled grant silently denies at run time.
- Expecting a per-workflow
deny.denytargets agents only; workflows and tools union across matched grants. - Expecting the IdP or Portal to assign roles. Identity sources assert facts; only
roleblocks in the file assign meaning. - Confusing
rolewith agentprofile. See below.
role is not profile
These are different layers. A top-level role controls who may invoke an agent. An agent's profile controls what the agent may do when it runs: its tools, system prompt, and sandbox. Use both: a role grants the accountant agent to the finance team, and a profile keeps the accountant agent scoped to read-only tools for routine work.
Example: map an org chart
The CEO and CFO reach every agent. The accountant reaches the accountant agent's bookkeeping workflows. HR reaches the HR agent.
role exec {
match {
title: [ "ceo", "cfo" ]
}
}
role accounting {
match {
department: "accounting"
}
}
role hr {
match {
department: "hr"
}
}
policy {
allow exec -> agent *
allow accounting -> agent accountant {
workflows: [ brex, quickbooks ]
}
allow hr -> agent hr_assistant
}Deploy with git push or swirls deploy, then assign title and department to members on the project's Access page, or include them as claims in your identity provider's JWTs.
Further reading
- Audit log: the record of who did what, including access grants and denials
- OIDC federation: bring your identity provider's claims as the facts roles match
- Connections: the outbound mirror image of access
Actions and the catalog
Typed provider operations installed with swirls add. Browse the integration catalog, install action blocks, generate them from any API spec, and request new providers.
Audit log
The append-only record of who did what across your organization. Read it on the Audit page in the Portal or query it with the SDK using cursor pagination.