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.

The examples on this page use the tables of a sample invoicing app (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 app

Org 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

SettingReaches
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 organizationsEvery organization in the app, including ones that sign up later. A deliberate opt-in.
Only theseThe 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

ActorWhere to set it in the console
An agent you createdThe agent's page, in your app's Agents
Your assistant (the Arbiter) in this appYour app's Agents section, "your assistant"
A scheduled job you createdThe job's page, in your app's Scheduled jobs
An API key on one of your agentsThe 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.orgUid is 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 (null for 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 with ROW_ORG_REQUIRED; naming an organization outside the reach is ROW_ORG_NOT_FOUND;
    • an update never changes a row's organization.

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

CodeStatusMeaning
ORG_REACH_OWNER_ONLY403Only the app's owner, in the console, can change a reach.
ORG_REACH_NOT_APPLICABLE409This agent, job or key belongs to one of the app's organizations; reach is for yours.
ROW_ORG_REQUIRED400A cross-organization actor created a row in an org-scoped table without org_uid.
ROW_ORG_NOT_FOUND400The org_uid names no organization this actor reaches.
STORAGE_OUT_OF_REACH403The request reaches organizations outside the actor's reach.

What's next

On this page