Permissions
Golem decides what each agent may do with permission cards. A card lists operations the agent is allowed to perform, such as connecting to a host, reading a directory, revealing a secret, or calling a tool. Golem checks the agent’s cards before every such operation, so an agent can do exactly what its cards allow, regardless of what its code, its prompt, or a model’s output asks for.
This matters for AI agents because they act on text from users, documents, and web pages, and that text can steer a model. An instruction in a prompt such as “never delete files outside the workspace” is not a security boundary. A card that does not grant delete permission outside the workspace is.
How a permission check works
Cards are capabilities: unforgeable values that only the Golem runtime can create. The set of cards an agent holds is its wallet. When agent code makes an HTTP request, opens a file, reads a secret, or calls another agent or a tool, the Golem host checks the request against the wallet first.
Open full-size image in a new tab.
Open full-size image in a new tab.If no card allows the operation, Golem denies it before it happens and records the denial in the agent’s oplog. Each method invocation records which cards it used, so when Golem recovers an agent after a failure, it makes the same permission decisions as the original run. An agent with no cards can compute and return results, but cannot touch files, the network, secrets, other agents, or tools.
Tools act with the calling agent’s cards, so a card that limits file deletion also limits a bash script that the agent runs through the bash tool.
Grants
Each card contains grants. A grant names an operation and the resources it applies to:
filesystem(?agent) @ ?agent : read : /data/**
network() @ ?agent : connect : api.openai.com:443A grant has four parts: resource-type(owner) @ recipient : operation : target.
| Part | In the first grant | Meaning |
|---|---|---|
| Resource type and owner | filesystem(?agent) | The filesystem that belongs to the agent |
| Recipient | @ ?agent | Who may use the grant: the agent holding the card |
| Operation | read | What may be done |
| Target | /data/** | Where: anything under /data (* matches one path segment, ** any depth) |
The second grant lets the agent open connections to api.openai.com on port 443. ?agent stands for whichever agent holds the card, so the same grant works for every agent of a type. Similar placeholders exist for the agent’s component (?component) and environment (?env).
A card has two sets of grants. Its lower bound lists what the card allows; an operation is allowed if any card in the wallet allows it. Its upper bound is a limit on the whole wallet, including cards the agent receives later. Each set can contain negative grants that exclude operations. An upper bound that excludes billing secrets, for example, keeps those secrets out of reach even if another card would allow them.
Default and explicit permissions
If an agent type does not declare its permissions, Golem gives it a broad default card so that a first deployment works without configuration. The default card allows the agent’s own files, any network destination, the environment’s secrets and storage, and calls to any agent and tool in the environment.
The default card is meant for getting started. Before you run agents that act on untrusted input, declare explicit permissions.
To declare explicit permissions, give the agent type an initialCard in golem.yaml. It replaces the default card, so list everything the agent needs:
# golem.yaml (excerpt)
agents:
ReportAgent:
initialCard:
lowerBound:
positive:
- "tool(?component/bash) @ ?agent : invoke : *"
- "filesystem(?agent) @ ?agent : read : /workspace/**"
- "filesystem(?agent) @ ?agent : delete : /workspace/*"
- "network() @ ?agent : connect : api.openai.com:443"
upperBound:
negative:
- "secret(?env) @ ?agent : reveal : billing.*"This agent may run bash, read anything under /workspace, delete files directly inside /workspace, and connect to one host. It can never reveal secrets whose names start with billing..
Database permissions
For relational databases, ordinary query and mutate grants name tables as
database.schema.table, with * allowed in each component. Golem analyzes SQL first and checks
the directly referenced relations that it can identify. A missing table grant denies the statement.
Explicit executable expressions must also belong to the supported analysis subset; an unknown
function, custom operator, or unsupported cast requires explicit unanalyzed authority.
Bare built-in PostgreSQL DEFAULT CURRENT_TIMESTAMP and supported now() work with ordinary
grants; this does not authorize every timestamp routine or form. Unquoted relation-modifier ONLY
in PostgreSQL SELECT, UPDATE, or DELETE requires explicit unanalyzed authority;
supported LOCK TABLE ONLY still uses ordinary grants.
Analyzed PostgreSQL statements resolve unqualified physical relations to public, not the
session’s search_path, for both permission checks and execution. This includes reads, writes,
created tables, index target tables, and foreign-key references. Explicit schemas stay explicit;
a RENAME destination stays in the source schema. CTE references, aliases, columns, and comments
remain unchanged. Approved literal or built-in text parameter regclass casts also resolve
one-part relation names to public, preserving quoted case and explicit schemas. String literals
stay constant to preserve PostgreSQL early OID binding; only text placeholders use runtime
normalization. Both forms identify schema boundaries by dots outside double quotes, preserving
PostgreSQL’s leading-quote rule: a double quote starts quoting only at the beginning of a name part.
Both preserve
native regclass spelling such as unquoted migration-log rather than enforcing SQL identifier
grammar. Explicit multi-part input remains unchanged. Golem leaves
bound parameters and durable SQL unchanged and does not issue session SET commands.
Literal and built-in text parameter normalization recognize only the PostgreSQL scanner’s six
ASCII whitespace characters: space, tab, LF, CR, vertical tab, and form feed. Unicode whitespace
remains part of an unquoted name.
SQL that Golem cannot analyze requires a separate explicit grant, for example
rdbms(?env) @ ?agent : unanalyzed : database(mydb). The default agent card, wildcard table
grants, and wildcard verbs do not include this capability. It cannot override a missing table
grant when analysis succeeds. Use it only for trusted code that needs unsupported statements;
normal table migrations should use ordinary grants. PostgreSQL temporary CREATE TABLE is
unsupported analysis. The fallback executes original SQL without deterministic namespace rewriting.
This grant selects the connection database. It does not guarantee that arbitrary SQL affects only
that database, and the database role still needs appropriate privileges. Ordinary table grants do
not enumerate the indirect effects of authorized database objects, such as view definitions,
triggers, or cascades. Database administrators must control those objects and use least-privilege
roles. They must also control the session namespace, including search_path, and prevent
untrusted objects from shadowing built-in types or routines. Driver metadata queries do not
pass through the SQL analyzer; permission cards do not protect against a hostile namespace. See
SQL permissions and analysis for supported SQL,
transaction requirements, and migration guidance.
Delegating, expiring, and revoking
Every card comes from an earlier one. An account starts with a root card. An account owner can give another account part of its authority with a permission share, and each environment has default cards for managing it. When you deploy, Golem creates an initial card for each agent type, which can never exceed the authority of the person deploying.
At runtime, an agent can derive a narrower card from one it holds and pass it to another agent or a tool, for example read access to one folder for 30 days (written P30D). A derived card can only narrow its parent; it can never add permissions. Cards can expire, and revoking a card also revokes every card derived from it. See the cards reference for the guest API that every SDK provides.
Open full-size image in a new tab.
Open full-size image in a new tab.Secrets
Secrets are passed to agents as opaque handles. An agent can pass a handle to a tool or a Golem integration without seeing the value. To use a secret’s value directly, for example to put an API key in an HTTP header, the agent must reveal it, which requires a reveal permission and is recorded; the revealed value is then ordinary data and appears in the recorded request. A tool binding can prevent a tool from revealing any secret, which keeps API keys away from code generated by a model.
What permissions do not cover
Permissions decide what an agent may do, not which users may call it. Checking that the signed-in user may access a particular agent is application logic, described in Artifacts.
Permissions limit how much damage an agent can do; they do not judge whether an agent’s intentions are good. An agent can still misuse permissions it legitimately holds. For irreversible operations, such as payments or deletions, add an approval step in tool middleware, which the agent cannot bypass.
Next
Agent communication: how agents call each other and wait for people and external events.
Related guides: