Agent permissions
What an agent may do, who decides it, and what the person who runs it contributes.
An agent acts on your project through the CLI, the API, git, connectors, and
Apps. This page explains how Kortix decides what an agent may do. The project
feature flag agent_principal selects one of two models.
agent_principal |
Who the agent acts as | What the agent may do |
|---|---|---|
| Off (default) | The person who started the session | That person’s project role ∩ the agent’s Kortix permissions |
| On | The agent itself | The agent’s Kortix permissions ∩ the agent’s ceiling role − human-only permissions |
With the flag off, the same agent can do different things for different people. With the flag on, the agent does the same thing whoever runs it.
The agent is the acting principal
With agent_principal on, every agent session has two identities:
| Identity | What it decides |
|---|---|
| Acting principal — the agent | Everything on shared resources: project permissions, shared connector accounts, project secrets, Apps, git. |
| On behalf of — the person | Only that person’s own resources, and only in that person’s own private session. |
Each agent has one identity per project: a service account that Kortix creates for it. You never hold a credential for it.
Kortix permissions — the manifest decides
Each agent declares its Kortix permissions in kortix.yaml, under
agents.<name>.kortix_permissions. The manifest on the default branch is the
source of truth.
agents:
report-writer:
kortix_permissions: [project.file.read, project.connector.read, project.app.read]
connectors: [reports-dashboard-api]
secrets: [REPORTS_API_KEY]
apps: [reports-dashboard]
- The list is deny-by-default. An agent without
kortix_permissionsgets none. allgrants every project permission, still capped by the ceiling.kortix_cliis the deprecated spelling. It still validates, with a warning. Both keys with different values on one agent is a validation error.
Edit the list in Customize → Agents → the agent → Kortix permissions. A
save commits kortix.yaml. See the manifest reference.
The ceiling — an admin decides
The ceiling is a project role that an admin binds to the agent’s service account. The agent’s Kortix permissions never exceed it.
- No role bound: the default agent ceiling applies. It is every project permission except the human-only ones.
- A role bound: built-in
memberormanager, or a custom role. The agent keeps only the Kortix permissions that the role also grants. - A ceiling never adds a permission. A
managerceiling does not give an agent a permission its manifest does not list.
Set the ceiling in the Access hub → Projects → the project → Add. Pick the agent under Agents and choose a role. Only admins who manage roles see agents in the picker. The project’s access list shows each agent ceiling with an Agent badge.
Human-only permissions
Three permissions stay with people. An agent never holds them, whatever its manifest or ceiling says:
| Permission | What it does |
|---|---|
project.members.manage |
Add, change, or remove project members and grants |
project.delete |
Delete the project |
project.credentials.issue |
Mint a project token or a project-scoped PAT |
project.read is the reverse: an agent always holds it inside its own project.
Running an agent lends its authority
With the flag on, the person who runs an agent does not cap it. So the right to run an agent is the delegation. Kortix checks “may this person run this agent” at every entry point:
| Entry point | Required |
|---|---|
| Create, start, or prompt a session; switch its agent | The person may run the agent |
| Fire a trigger by hand | The person who fires it may run the trigger’s agent |
| Start a child session from an agent session | The person behind the parent may run the child’s agent. With no person behind it, only the same agent. |
Grant “may run” on the agent’s People tab, or in the Access hub. Agents are closed by default: a member runs an agent only when an assignment names them or one of their groups.
Personal resources stay personal
An agent session reaches a resource that one person owns only when both are true:
- The session runs on behalf of that person.
- The session is private.
Personal resources are member-owned connector connections, personal project secrets, personal provider keys, and the person’s own computer. A shared session, a trigger or channel session, and an unattended run reach none of them.
When another person prompts a private session — for example an account admin who can open members’ private sessions — the session stops acting on behalf of its creator, for good. The agent keeps its own permissions. The person who prompts never acts through someone else’s accounts.
Apps
An agent opens a restricted or private App only
when its apps: grant names the App’s slug, or is all, and its effective
permissions include project.app.read.
| App access mode | The agent is admitted when |
|---|---|
| Public | Always |
| Project | project.app.read is effective |
| Restricted or private | The slug is in apps: and project.app.read is effective |
| Password | Never |
The App’s Access dialog lists the agents with access, read from
agents.<name>.apps. Change the list with a change request to kortix.yaml.
Widening an agent needs a person
kortix.yaml shapes what agents may do, so whoever lands a change on the
default branch shapes agents. Two guards apply:
- The ceiling is admin-only IAM state. The manifest never exceeds it.
- An agent session cannot merge a change request whose diff touches
kortix.yamlagents.*ortriggers. The merge answers403withcode: "CR_AGENT_GOVERNANCE_CHANGE". A person withproject.gitops.mergemerges it.
Read a denial
Every 403 from an authorization check carries code and action:
code |
Meaning | Fix |
|---|---|---|
agent_scope_insufficient |
action is not in the agent’s Kortix permissions |
Add it to agents.<name>.kortix_permissions |
agent_ceiling_insufficient |
action is outside the agent’s ceiling role |
An admin raises the ceiling |
agent_not_accessible |
The person may not run this agent | Grant them the agent |
project_role_insufficient |
The person’s own role denies action |
Change their project role |
Audit
Every agent action records three fields: actor is the agent,
on_behalf_of is the person or null, and initiator is human,
trigger, or channel. A trigger run records no person.
See it in the dashboard
Open Customize → Agents → the agent → Kortix permissions. The What this agent can do panel shows:
- the Kortix permissions declared in
kortix.yaml, - the ceiling role, or Default agent ceiling,
- the human-only permissions,
- the effective permissions: “People who may run this agent act with these permissions.”
With the flag off, the panel says that the launcher’s role applies.
Turn it on
agent_principal is off by default. Turn it on for one project in
Settings → Feature flags, or from the CLI:
kortix projects features enable agent_principal
Off keeps today’s model exactly. On applies this page to every agent the
project declares under agents:. A project with no agents: map keeps the
launcher model until it declares agents.