Delegations
Last updated October 5, 2026
On this page
- Following along in the demo
- What a delegation says
- Where you see delegations
- Who you can ask
- Delegating to an agent
- Try it: an ask refused, then allowed
- Limits on a delegation
- Try it: a limit refuses a step
- Chains: passing a delegation on
- Try it: build a chain and watch it narrow
- Revoking
- Try it: revoke and watch the cascade
- Module agents act for a team's members
- Offboarding
- Try it: offboard Tom
- Not possible yet
- For developers
- API
- Events
- CLI
Draft for review
An agent never acts on its own say-so. It acts for someone, and only because that person delegated to it: "the Support Agent may act for me". A delegation is a record in OrchKernel, not a message. It says who acts for whom, within which limits, and it can be revoked at any moment.
This page shows how to delegate to an agent, what happens when you ask an
agent you have not delegated to, how limits and chains work, how revoking
cascades, how module agents act for a team's members, and what offboarding a
person or an agent does. It describes delegations as they work today on the
golive branch. What is not possible yet is listed at the
end.
Following along in the demo#
The examples use the demo company. Start it as described in
Quickstart (ok demo, then ok demo serve) and sign in with
the tokens it prints: ada (admin), alice (sales rep), maya (support
lead), tom (support agent, a person on Maya's team), pat (product
manager) and sam (sales lead).
Some steps use the API. Set these once in a terminal, with the workspace URL
ok demo serve printed (http://127.0.0.1:8080 unless you passed --bind)
and the token of the person the step names:
OK=http://127.0.0.1:8080/api
AUTH="Authorization: Bearer <that person's token>"
The demo runs without a model unless you set a provider key. A stub planner then answers a few known asks with a fixed plan. Every step below works with the stub planner; the ones that need an agent to decide something on its own use an explicit plan (a list of steps you write yourself) instead.
What a delegation says#
| Part | What it means |
|---|---|
| From | The person (or agent) who delegates. They stay accountable for what is done under it. |
| To | The agent that may now act for them. |
| Authority | Act as (the default): the agent acts for them. Advise: meant to let the agent suggest only, but not enforced yet (see Not possible yet). |
| Scope | General (any work), one task, or a named purpose. A module's delegations use the purpose module:<name>. |
| Limits | Optional: a spending limit, the tools and collections it covers, the data classes it may handle, the highest risk it may reach, an end date, and whether the agent may pass it on. |
| Reason | Free text, shown on the card: "Works my follow-ups". |
A module is an installed package of agents, skills and tools for one department, such as Support or CRM (see Modules). A run is one piece of work an agent does after an ask; you see runs under Work.
A delegation takes effect at once. Nobody approves it.
Where you see delegations#
| Place | What it shows |
|---|---|
| Governance › Delegations | Every delegation you gave or hold, newest first, with Delegate to an agent at the top. An admin sees every delegation in the company. |
| Directory, click a name | A side panel with Acts under (delegations this actor holds) and Has delegated (delegations it gave). Only active ones are listed. |
| An agent's page (Directory, click the agent, then Open agent page) | acts for in the overview names everyone it acts for; Acts under repeats its delegations as cards. |
| Events | Set Type to Delegation created ("Support Agent may act for Alice Chen"), Delegation revoked or Delegation refused. See Events and the audit log. |
Each delegation is a card:
- Active or Revoked, then "Agent acts for Person" ("advises" for an advise delegation).
- A badge: Via Support (the module's name) when a module made it, the purpose otherwise, or Task for a task-scoped one.
- The limits in words, for example "up to $50.00 · may read Knowledge articles, Tickets · may use Reply to customer · data: Internal, Customer PII, Public · risk up to Critical". A delegation you make shows "may pass it on" even when you set no other limit.
- The reason, and "passed on from another delegation" when an agent made it under a delegation it holds.
- Revoke, for the person who gave it and for admins.
Who you can ask#
The agents you may ask are listed under Talk to an agent on the Threads page and in a thread's agent selector. An agent is listed when it is on your team (or a team you lead), you delegated to it, its module acts for you or your team, or it reports to you. An admin may ask every agent.
The rule behind it: an agent that acts for other people runs only for the people who delegated to it. Ask one you have not delegated to and the ask is refused before anything runs:
- In the API: 403
denied, "policy denied ask: You have not delegated to Support Agent". - With
ok ask: "Error: policy denied ask: You have not delegated to Support Agent". - On the screen you never get that far. The agent is missing from Talk to an agent, and its page shows Let Support Agent act for me instead of Ask Support Agent. In a thread it is greyed out in the agent selector: "Triage (you can't ask it: it acts for people who delegated to it)". When you can ask none of a thread's agents, the thread says "You can't ask this thread's agents: they act for the people who delegated to them. Post to talk, or ask the owner." See Threads.
Delegating to an agent#
There are two ways on the screen.
From the agent. Open the agent's page and choose Let agent act for me. This makes a general, act-as delegation with no limits. A note confirms "Support Agent now acts for you" and the button turns into Ask Support Agent. The Directory side panel has the same button (see Not possible yet for a catch).
With a spending limit. Open Governance › Delegations and choose Delegate to an agent:
| Field | What it does |
|---|---|
| Agent | Any active agent, by name. Required. |
| Why | The reason shown on the card. |
| Spending limit (dollars) | Leave empty for no limit beyond your own. It caps each single step, not a total; see Limits. |
Choose Delegate. The note says "Knowledge-base writer may now act for you" and, within a few seconds, the new card is at the top of the list.
The other limits (tools, collections, data classes, highest risk, end date,
no passing on) and the Advise authority can only be set through the API or
ok delegate (see For developers).
Try it: an ask refused, then allowed#
Alice is a sales rep. The Support Agent acts for Maya and Tom on the Support team, not for her.
- Sign in as alice, open Directory and click Support Agent, then Open agent page. The header has Let Support Agent act for me, not Ask Support Agent. Its overview says acts for Maya Patel, Tom Becker. Under Threads › Talk to an agent it is not listed either.
- Choose Let Support Agent act for me. The note says "Support Agent now acts for you", the button becomes Ask Support Agent, acts for now includes Alice Chen, and Acts under has a new card: "Support Agent acts for Alice Chen", "may pass it on", reason "delegated from the agent page".
- Open Governance › Delegations. Alice's new card is first, with Revoke. Below it are the module delegations that let the Marketing agents (Via Marketing) and the Sales Assistant (Via CRM) act for her.
- Go back to the agent page and choose Ask Support Agent. New conversation with Support Agent opens. Type "What is open on T-1042?" and choose Ask agent. With the stub planner the agent answers with a table of the four open tickets, T-1042 to T-1045. The run acts for Alice: Work shows "Support Agent acting for Alice Chen".
Step 4 also shows a gap: Alice cannot read tickets herself (the API refuses her: "alice may not read tickets"), yet the agent read them for her, customer emails included. See Not possible yet.
Limits on a delegation#
The gate, the check every agent action passes before it runs, enforces the limits on each action the agent takes for you (see How the gate decides). A step outside them is refused with a reason:
| Limit | Refused with |
|---|---|
| End date | "delegation expired" |
| Tools | "delegation does not cover tool tool" |
| Collections | "delegation does not cover collection collection" |
| Data classes | "delegation does not cover data class class" |
| Highest risk | "delegation caps risk below tier" |
| Spending limit | "cost x exceeds delegated budget y" |
The spending limit caps what a single step may cost, not the total the agent spends for you over time. The agent's own budget (in its overview, "spent $0.00 of $50.00") is the running total.
Try it: a limit refuses a step#
-
As pat (use Pat's token in
AUTH), delegate to the Support Agent with three limits:curl -s -H "$AUTH" -H 'content-type: application/json' $OK/delegations -d '{ "to": "support-agent", "reason": "KB only", "constraints": {"collections": ["kb_articles"], "max_risk": "medium", "expires_at": "2026-12-31T00:00:00Z"}}'The reply is the new delegation as JSON.
-
In Governance › Delegations its card reads "may read KB articles · risk up to Medium · until Dec 31, 2026 · may pass it on", reason "KB only".
-
Ask the Support Agent "What is open on T-1042?" (on its page, or with
curl -s -H "$AUTH" -H 'content-type: application/json' $OK/ask -d '{"agent":"support-agent","text":"What is open on T-1042?","new_thread":true}'). The run fails at its first step. In Work, the run shows Failed and "Op 0: policy denied brain.query(tickets): delegation does not cover collection tickets"; its trace ends with a Refused step.
The risk limit works the same way: when the Support Agent tries to reply to a customer for Pat (a high-risk tool), the step is refused with "delegation caps risk below high".
Chains: passing a delegation on#
An agent may pass part of what it holds to another agent, for example to hand a piece of work over. This is only possible when:
- the agent's skill allows delegating. In the demo the Support Agent, Triage, QA reviewer and Churn-risk watcher skills do, and so do some Product and Engineering ones;
- the delegation it acts under allows passing on. Delegations you make allow it ("may pass it on"); the ones modules make do not, so a module agent acting under its module delegation is refused: "parent delegation does not permit sub-delegation".
A chain only ever narrows. The new delegation inherits every limit it does not set, and any limit wider than its parent is refused: a larger spending limit, a tool, collection or data class the parent does not cover, a higher risk, a later end date, act-as under an advise delegation, or passing on when the parent forbids it. The refusal names the limit, for example "authority widens parent (budget $50.00 exceeds parent $10.00)", and is logged as Delegation refused.
What the agent at the end of a chain may do is the narrowest of every link, and it still acts for the person at the root. That person may then ask it.
Try it: build a chain and watch it narrow#
An agent passes a delegation on as a step of its plan, and the stub planner does not write such steps. So this example sends an explicit plan through the API. A real model may decide to do the same on its own.
You need Alice's delegation to the Support Agent from the first
example, still active. Use Alice's token
in AUTH.
-
Have the Support Agent pass Alice's delegation to Triage with a $10 limit (
budgetis in cents):curl -s -H "$AUTH" -H 'content-type: application/json' $OK/ask -d '{ "agent": "support-agent", "text": "Let Triage work my tickets", "new_thread": true, "plan": {"ops": [ {"op": "delegate", "to": "triage-agent", "scope": {"scope": "general"}, "authority": "act_as", "constraints": {"budget": 1000}, "reason": "work my tickets"}, {"op": "output", "value": "done"}]}}'The reply has
"outcome": "done"and"acting_for": "alice". Before this step an ask of Triage by Alice was refused ("You have not delegated to Triage"); now it runs, for Alice. -
Have Triage pass it on to the Knowledge-base writer with a wider limit: send the same request with
"agent": "triage-agent","to": "kb-writer"and"budget": 5000. The reply has"outcome": "failed"and the reason "op 0: delegation: authority widens parent (budget $50.00 exceeds parent $10.00)". Events logs it as Delegation refused. -
Send it again with
"budget": 500. The outcome isdone. -
As ada, open Directory and click Triage. Acts under has a card "Triage acts for Support Agent", "up to $10.00 · may pass it on", "work my tickets · passed on from another delegation". Has delegated has "Knowledge-base writer acts for Triage", "up to $5.00 · may pass it on".
Leave out scope in a delegate step and the delegation covers only the task
the agent is working on, and that task is handed over to the new agent.
Revoking#
Revoke is on each active card in Governance › Delegations, for the person who gave the delegation and for admins. It asks "Revoke this delegation and everything under it?" and, once you choose Revoke again, the note says "Revoked".
Revoking takes effect at once and cascades: every delegation passed on under it, at any depth, is revoked in the same step. Each one is logged as Delegation revoked. Asks of those agents are refused from then on, and any step they try for you is refused at the gate.
Anyone else who tries to revoke (through the API) is refused: "policy denied delegation.revoke: only the delegator or an admin may revoke".
Try it: revoke and watch the cascade#
- As alice, open Governance › Delegations and choose Revoke on "Support Agent acts for Alice Chen" (reason "delegated from the agent page"). Confirm with Revoke. The card turns Revoked.
- As ada, open Governance › Delegations: "Triage acts for Support Agent" and "Knowledge-base writer acts for Triage" are Revoked too. In Events, set Type to Delegation revoked: there are three entries, one per delegation, all at the same moment.
- As alice, open the Support Agent's page again: it shows Let Support Agent act for me. An ask of the Support Agent or of Triage through the API is refused: "You have not delegated to Support Agent" (or Triage).
Alice herself does not see the delegations passed on under hers; only an admin does (see Not possible yet).
Module agents act for a team's members#
When a module is installed, its agents act for the team it is bound to. The module gives one delegation per member of that team, made by the module and limited to the agent's own tools, collections and data classes, with the module's spending limit and no passing on. The card shows the module's name: Via Support, Via Support operations, Via CRM.
In the demo, the Support Agent and Triage act for Maya and Tom "via Support", and the Sales Assistant acts for Alice and Sam "via CRM".
- Someone who joins a bound team gets the module's delegations at once. A new person added to Support got five: the Support Agent and Triage (Support), and the QA reviewer, Knowledge-base writer and Churn-risk watcher (Support operations).
- Someone who is offboarded loses theirs (see Offboarding).
- These delegations change only through the module. The card still shows Revoke, but choosing it fails with "delegation ... is managed by module marketing; change it on /modules/marketing (the module record)". To stop a module agent acting for someone, change the team the module is bound to, pause the module, or offboard the person. See Modules.
Opting in to personal context capture also makes a delegation, to the Curator. See Context capture.
Offboarding#
Offboarding is how someone leaves: a person who leaves the company or an agent that is retired. Only an admin offboards. When anyone else tries, the request becomes an approval for an admin instead ("approval required"); it shows in Ada's Inbox as "Maya Patel asks to change an actor".
What offboarding does:
| What | Effect |
|---|---|
| Delegations | Every delegation given to or by the actor is revoked, with everything passed on under them (each logged as Delegation revoked). Module delegations go too. |
| Running work | Runs of an offboarded agent are cancelled, parked ones included. Runs that act for an offboarded person are not (see the example). |
| Sign-in | A person's tokens stop working: the API answers 401 "invalid token". |
| Directory | The actor's status is Offboarded; its side panel says active no, "No delegations held." and "None.". It is logged as Actor offboarded. |
| Outside agents | Their pending gateway actions are withdrawn and their work sessions closed (see Outside agents). |
Offboard an agent from the Directory: click its name and choose Offboard (admins only). It asks "Offboard Churn-risk watcher? All delegations are revoked and running work cancelled." Choose Offboard again; the note says "Offboarded".
Offboard a person through the API or the CLI. There is no button for a person:
curl -s -X POST -H "Authorization: Bearer <ada's token>" $OK/actors/tom/offboard
# {"ok":true}
Try it: offboard Tom#
- As tom, ask the Churn-risk watcher "Northwind wants a refund for the double charge". The $250.00 refund is over the agent's cap, so the run parks and waits for an admin.
- As ada, offboard Tom with the command above.
- In Governance › Delegations, Tom's five module delegations (Support Agent, Triage, Churn-risk watcher, QA reviewer, Knowledge-base writer) are Revoked. Tom's token no longer works.
- In Ada's Inbox, "Issue a refund or credit" for Tom Becker is still Pending. It says "A rule now refuses this, so it can no longer go ahead: Churn-watcher holds no delegation from tom", and Approve is off. So nothing is paid, but the item stays open. While it does, a new refund for the same invoice is refused: when Maya asks the Churn-risk watcher the same thing, its run trace has "Invoice inv-2026-09-1042 already has a refund waiting for approval" (the stub planner's answer still reads "Refunded after an admin approved it.").
- To clear it, choose Reject, write a reason (required) and choose Confirm reject. The note says "Issue a refund or credit: rejected · Tom Becker was told", and Tom's run ends as failed. Maya's next refund ask parks for approval as usual.
Steps 4 and 5 show a known gap: offboarding a person does not yet cancel the runs that act for them or withdraw their approvals.
Not possible yet#
- A delegation does not limit the agent to what you can do yourself. A run for you gets the agent's own access plus yours. In the demo Alice cannot read tickets, but the Support Agent read them for her. Only the delegation's explicit limits (and an explicit plan you send) are held to you.
- Advise does not stop side effects. An advise delegation is shown as "advises" and cannot be turned into act-as down a chain, but the gate treats it like act-as: under Sam's advise delegation the Support Agent sent a customer reply on ticket T-1044 with no approval.
- Offboarding a person from the screen, and cancelling the runs and approvals that act for them (see Offboarding).
- Setting tools, collections, data classes, highest risk, an end date, no passing on or Advise on the screen. The form has only the agent, the reason and a spending limit.
- A spending limit for the total an agent spends for you. The limit caps each step.
- Seeing the delegations passed on under yours, unless you are an admin.
- Being offered an agent you reach only through a chain: Alice may ask Triage once the Support Agent passed her delegation on, but Triage is not in her lists.
- Telling whether you already delegated, in the Directory side panel. It shows Let agent act for me next to Ask agent, and choosing it again makes a second, identical delegation.
- Editing a delegation. Revoke it and delegate again.
- Revoking from the CLI. Use the screen or the API.
For developers#
API#
All under /api, with Authorization: Bearer <token>.
| Method and path | Body | Notes |
|---|---|---|
GET /delegations |
Delegations the caller gave or holds; an admin gets all. A JSON array of { delegation, active }, newest first. Paged with limit and cursor; the next cursor is in the x-next-cursor response header. |
|
POST /delegations |
{ to, scope?, authority?, constraints?, reason? } |
Delegates from the caller. scope is {"scope":"general"} (default), {"scope":"task","task":"<id>"} or {"scope":"purpose","purpose":"<name>"}. authority: act_as (default) or advise. constraints: budget (cents), tools, collections, data_classes, max_risk, expires_at, may_subdelegate (default true). Returns the delegation. |
DELETE /delegations/:id |
Revokes it and everything under it. Returns the revoked ids, an empty list if it was already revoked. | |
GET /actors/:id |
{ entry, delegations_held, delegations_given, spent_cents }, active delegations only. |
|
GET /me/agents |
The agents the caller may ask, each with why: team, delegation, acts_for, manages or admin. |
|
POST /actors/:id/offboard |
Admins. Returns { "ok": true }; from anyone else, 202 needs_approval with the approval id. |
Errors:
| Status and code | When |
|---|---|
403 denied |
An ask of an agent that acts for others when the caller did not delegate to it; a revoke by someone other than the delegator or an admin. |
409 managed_by_module |
Revoking a delegation a module made. |
409 now_denied |
Approving an action whose delegation has since been revoked ("the policy now denies this: churn-watcher holds no delegation from tom"). |
A plan delegates with the delegate operation: to, scope, authority
(default advise in a plan), constraints, reason. Without scope it is
scoped to the run's task and hands the task over. See Asking
agents.
Events#
| Event | Fields |
|---|---|
delegation_created |
delegation, from, to |
delegation_refused |
from, to, reason |
delegation_revoked |
delegation (one event per delegation in a cascade) |
actor_offboarded |
actor |
CLI#
ok --as alice delegate --to support-agent --reason "help with my customers' tickets"
ok --as maya delegate --to kb-writer --budget-cents 2000 \
--tools support-ops.helpdesk.tickets --scope purpose:kb --reason "Draft KB articles"
ok --as ada actor offboard tom
--scope is general (default), task:<id> or purpose:<name>;
--authority is act_as (default) or advise. Only --budget-cents and
--tools set limits; tool ids are not checked. delegate prints the
delegation as JSON; actor offboard prints "offboarded tom", or "Error:
approval required: " for anyone but an admin.
The CLI works on the state file directly (in the demo, add --state orchkernel-demo/state.db). Do not run it against the state of a running
server: the server does not see the change, although the event is written to
the log. Use the API while the server runs.