Org reach
Decide which of your app's organizations your agents, assistant, scheduled jobs and API keys may act in. The default is none.
You see every organization in your app from the console, because you click every action yourself. The things that act for you without you clicking (your agents, your assistant, your scheduled jobs, and API keys) should not inherit that view by default. Each one has an org reach: the organizations of your app it may act in.
invoices, vendors, payments). Your app has only the tables you create, so put your own table and column names in their place. About the example appOrg reach decides which organizations. Roles and policies still decide what may be done
there. An agent with reach into every organization but no grant on invoices still cannot read an
invoice, and an agent with the grant but no reach sees only your own records.
The three settings
| Setting | Reaches |
|---|---|
| None (the default) | No organization's data. Your own records (those that belong to no organization), shared tables, outside APIs and email still work. |
| All organizations | Every organization in the app, including ones that sign up later. A deliberate opt-in. |
| Only these | The organizations you tick. A deleted organization drops out; a new one is never added on its own. An empty list is the same as None. |
Every setting keeps your own records in reach: these actors work for you, so what is yours is theirs to use.
What has an org reach
| Actor | Where to set it in the console |
|---|---|
| An agent you created | The agent's page, in your app's Agents |
| Your assistant (the Arbiter) in this app | Your app's Agents section, "your assistant" |
| A scheduled job you created | The job's page, in your app's Scheduled jobs |
| An API key on one of your agents | The key, in your app's API keys |
Agents, jobs and keys created inside the app, by one of its users, belong to that user's
organization and act only there. Org reach does not apply to them
(409 ORG_REACH_NOT_APPLICABLE).
Only you, in the console
A reach is a ceiling on what your automation can touch, so nothing below you may move it: not an
app user, not an agent or the assistant (each would be widening itself), and not an API key. Only
the app owner's own console session can set one (403 ORG_REACH_OWNER_ONLY). Every change is
recorded in the app's audit trail, and it applies from the next thing the actor does.
How each actor uses it
- An API key acts as its agent, so it reaches the overlap of the key's reach and the agent's.
- An agent that hands off or delegates to another agent: the other agent acts as itself, within its own reach, exactly as its own roles apply.
- A scheduled job with exactly one organization runs as that organization. Its handler
behaves like a request from one of that organization's users:
ctx.user.orgUidis set, rows carry no organization column, and new rows land in that organization automatically. - Anything with None, All, or more than one organization acts across organizations, so it is
told each row's organization:
- rows it reads carry
org_uid(nullfor your own records), and filters and groupings accept it; - a row it creates in an org-scoped table must name one with
org_uid. Without it the write is refused withROW_ORG_REQUIRED; naming an organization outside the reach isROW_ORG_NOT_FOUND; - an update never changes a row's organization.
- rows it reads carry
A handler can check its own reach instead of inferring it from what it can read:
ctx.audience is { mode, orgUids }, where mode is org, all, orgs or none. See the
handler SDK reference.
export default async function (data, ctx) {
const { sdk, audience } = ctx;
if (audience?.mode === "none") {
return { skipped: "This job reaches no organization yet." };
}
const result = await sdk.readList("invoices", {
filters: { status: "overdue" },
limit: 100,
});
const rows = Array.isArray(result) ? result : result.items;
// Acting across organizations, each row says which one it belongs to.
return rows.map((row) => ({ invoice: row.uid, org: row.org_uid ?? "yours" }));
}Files
Storage follows the same reach. An actor sees your own files and folders, and the files of the
organizations it reaches. Asking for more answers 403 STORAGE_OUT_OF_REACH. Which of your own
folders and files an organization can see is a separate setting, sharing, covered in
Storage.
Errors to branch on
| Code | Status | Meaning |
|---|---|---|
ORG_REACH_OWNER_ONLY | 403 | Only the app's owner, in the console, can change a reach. |
ORG_REACH_NOT_APPLICABLE | 409 | This agent, job or key belongs to one of the app's organizations; reach is for yours. |
ROW_ORG_REQUIRED | 400 | A cross-organization actor created a row in an org-scoped table without org_uid. |
ROW_ORG_NOT_FOUND | 400 | The org_uid names no organization this actor reaches. |
STORAGE_OUT_OF_REACH | 403 | The request reaches organizations outside the actor's reach. |