> ## Documentation Index
> Fetch the complete documentation index at: https://docs.os.meetluno.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Governance

> Project roles, per-agent and per-workflow access lists, approvers, and project-scoped API keys.

Governance decides who can do what inside a project: who ships code, who only uses agents and workflows, who may approve sensitive tool calls, and which scripts can reach which resources. Everything on this page is set in the Space's **People** tab in Governance (`/settings/projects/<slug>?tab=people`, owners and admins) (or through the API and CLI) and every change is recorded in the [audit log](https://docs.os.meetluno.ai/learn/settings/enterprise.md#audit-logs).

## Project roles

Every project member has one of four roles, assigned per project: invite ten people to the organization and give each a different role in each project. Organization owners and admins act as project admins in every project without being members, and only they manage a project's members.

| Role | Meant for | Can |
| - | - | - |
| **Admin** | Project owners | Everything in the project but its members: settings, credentials, channel bindings, approvers, access lists, deploys, runs, deleting it |
| **Editor** | Developers | Deploy code and triggers, manage project credentials, update project settings, run agents and workflows, read everything |
| **Operator** | Business users | Use only: chat with agents and run workflows (subject to access lists) and read what they are allowed to see. No deploys, credentials, channels, approvers or access changes |
| **Viewer** | Stakeholders, auditors | Read only: see the project, its agents, workflows, runs and history. Cannot run or change anything |

Behind the roles are project actions. [Permission groups](https://docs.os.meetluno.ai/learn/settings/enterprise.md#permission-groups) can grant any of them across every project.

| Action | What it allows | Admin | Editor | Operator | Viewer |
| - | - | :-: | :-: | :-: | :-: |
| `project:read` | See the project, its agents, workflows, runs and sessions | ✓ | ✓ | ✓ | ✓ |
| `project:run` | Prompt agents, run workflows, decide approvals, send signals, restart runs (in your own sessions and runs; see [sessions and approvals](#sessions-and-approvals)), execute MCP tools with shared credentials ([who can execute](https://docs.os.meetluno.ai/learn/credentials/custom-integrations.md#who-can-execute-a-tool)) | ✓ | ✓ | ✓ | |
| `project:deploy` | Deploys, drafts, triggers, project credentials, evals, table writes, webhook URLs | ✓ | ✓ | | |
| `project:manage` | Channel bindings, tool approvers, agent and workflow access lists, acting in anyone's session or run | ✓ | | | |
| `project:update` | Project settings, workflow forms, forgetting agent memory | ✓ | ✓ | | |
| `project:delete` | Delete the project | ✓ | | | |
| `project:manage-members` | Add, remove and change the roles of members and groups; set the default role and who may invite | | | | |
| `project:invite` | Invite members | | | | |

### Who manages members

Managing a project's members is organization member management: org **owners and admins** do it, whatever their project role, and a project role (even **Admin**), a custom project role or a permission group never grants it. When your organization [edits its roles](https://docs.os.meetluno.ai/learn/settings/enterprise.md), the `users:manage` permission ("Manage members and roles") decides instead: a custom org role that holds it manages project members too, and an Admin role edited without it does not. API keys need the `admin` scope.

An owner or admin can set a project's invite permission to everyone: its admins and editors may then also invite viewers, operators or editors, up to their own role and never as admins. Changing roles and removing members stays with org owners and admins, and a project always keeps at least one admin: the last admin cannot be demoted or removed. Manage members from the Space's Governance **People** tab, or with the CLI:

```bash theme={null}
luno --project support-automations project members invite --email ada@acme.com --role operator
luno --project support-automations project members role <user-id> --role editor
```

> [!NOTE]
>
> Existing members keep their access: project admins stay **Admin**, former builders are now **Editor** (they also gain `project:update`: project settings, workflow forms and forgetting agent memory) and operators stay **Operator**. **Viewer** is new: assign it to someone who should only look.

## Access lists

By default everyone with `project:run` in the project can use every agent and workflow. An access list narrows that for one agent or workflow.

* **Who can use** (agents and workflows): the members and permission groups listed. Without a list, the project default applies (everyone who can run). Project admins and organization owners and admins can always use a resource, since they can edit its list.
* **Who can approve** (agents): the members and permission groups who may decide the agent's tool approvals. Without a list, whoever can use the agent can approve. An approve list is **strict**: admins are not exempt, so it works as a separation-of-duties control. Approvers do not need to be on the use list.
* **Per-tool approvers** (`needsApproval: { approvers }` in code, or the agent's approvals panel) narrow further when a decision is made. See [human approval](https://docs.os.meetluno.ai/learn/agents/build-agents.md#who-can-approve).

The Access page shows each agent and workflow with its lists, or "Everyone with run access" when it inherits the project default. Picking "Only specific people" with nobody selected leaves the resource to admins only.

### Sessions and approvals

A conversation belongs to whoever started it. Continuing it (web app, API, MCP `sessionId`, A2A `contextId`), sending it signals or cancelling it needs **both** the agent's use list and being the session's owner or a project admin (`project:manage`: the **Admin** role, org owners and admins). Sessions nobody owns — Slack and Teams channel conversations, trigger runs — are a project admin's only. Editors and operators therefore act only in their own sessions. Restarting a workflow run follows the same owner-or-admin rule, and private per-user agent memory is shown only to its owner and project admins.

One rule decides a paused tool call, wherever it is decided (web app, CLI, API, Slack, Teams): the agent's approve list (else its use list); then the tool's approvers, when it has any, must name you; otherwise you must own the session or be a project admin. In a Slack or Teams thread the thread is the conversation, so any member there who may approve for the agent decides calls without approvers; chat users who map to no organization member never decide, and WhatsApp never shows approval buttons. The web app hides the composer and the approve buttons when this rule would refuse you.

Access lists do not hide agents or workflows from project lists. They gate using them, their sessions and run history, and approvals.

### Where access is enforced

| Entry point | Behavior for someone not on the list |
| - | - |
| HTTP prompt and run (`POST /agents/{agent}`, `POST /workflows/{workflow}`) | `403` with code `resource_access_denied` |
| Sessions, signals, run history, restarts, subscriptions | `403` |
| Approval decisions | `403` unless on the approve list (or the use list when there is none) |
| Project MCP server (`/mcp`) | The agent or workflow is left out of the tool list |
| A2A agent card and endpoint | `404` |
| SDK and CLI | Same API, same errors |
| Project apps (`defineApp`) | Runs and prompts are refused for that agent or workflow |
| Web app | Chat and run controls are hidden or disabled with a reason |

### Check what someone can do

The **Effective permissions** view on the Access page answers "what can this person do here": their organization role, project role, permission groups, project actions, and for each agent and workflow whether they can use or approve it. Anyone can check themselves; checking someone else needs `project:manage`.

```bash theme={null}
curl -H "Authorization: Bearer $LUNO_API_KEY" \
  "https://<your-project>/api/projects/<project-id>/access/effective?userId=<user-id>"
```

## API key restrictions

[API keys](https://docs.os.meetluno.ai/learn/settings/api-keys.md) act as their creator with a read, write or admin scope. You can also pin a key to **one project**, and optionally to specific agents and workflows in it. A restricted key:

* sees every other project as missing (`404`);
* can only use the agents and workflows it names (naming only agents means it cannot run any workflow; naming neither means every resource in the project);
* must use the read or write scope, since organization administration is organization-wide;
* narrows even an owner's key. It never grants more than its creator has.

Create one in **Governance → API keys** by choosing a project (and optionally agents and workflows), or with the CLI:

```bash theme={null}
luno api-key create --name "Support widget" --project support-automations --agent support-bot
luno api-key create --name "Nightly sync" --scope write --project data-ops --workflow sync-accounts --workflow sync-invoices
```

## Channels

Agents bound to Slack, Teams or WhatsApp are governed by the **channel's settings**: whoever can post in the bound channel or number can talk to the agent. Member access lists do not apply to channel conversations, so choose channel bindings (a `project:manage` action) with that in mind.

When a channel can map the speaker to an organization member (for example a direct message from a Slack user whose email matches a member), the integration respects the agent's access list for that member. Tool approvals in chat still check the per-tool approvers.

## Audit log

Every governance change is recorded:

| Event | When |
| - | - |
| `project.member_added`, `project.member_updated`, `project.member_removed` | Members and roles change |
| `agent.access_updated` | An agent's use or approve list changes |
| `workflow.access_updated` | A workflow's use list changes |
| `agent.approvers_updated` | Per-tool approvers change |
| `api_key.created` (with its restriction), `api_key.revoked` | API keys change |

## Next steps

> **[Manage projects](https://docs.os.meetluno.ai/learn/projects/manage-projects.md)**
>
> Invite members and update project settings.

> **[API keys](https://docs.os.meetluno.ai/learn/settings/api-keys.md)**
>
> Scopes, service accounts and restrictions.

> **[Human approval](https://docs.os.meetluno.ai/learn/agents/build-agents.md#who-can-approve)**
>
> Pause agents until someone approves a tool call.

> **[External channels](https://docs.os.meetluno.ai/learn/agents/external-channels.md)**
>
> Connect agents to Slack, Teams and WhatsApp.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.