Scopes and trust
When giving an application or node less authority, read this because a scope list is an allow-list enforced by the daemon and a bearer token can set the maximum authority for every run it creates.
Use scopes to give a node or remote application only the authority it needs. A node carries a scope list; a scoped bearer token carries a ceiling. Omitting a node scope list gives it the inherited runtime vocabulary. Supplying one narrows that authority. A token cannot create a node with scopes outside its own ceiling.
Scope strings are prefixed with crtr:. These are the ones the daemon and CLI check:
| Scope | It gates |
|---|---|
crtr:llm | Daemon-mediated model calls (POST /v1/llm) and starting a run |
crtr:act | Creating, forking, reviving, closing and messaging nodes; bash and files; creating a human request or review (the crtr human commands are hidden from a run without it) |
crtr:schedule | Creating, pausing, resuming, running and deleting crons (the crtr cron commands are hidden without it) |
crtr:memory:read:user[:path], crtr:memory:rw:user[:path], crtr:memory:manage:user | The person's documents: reading, writing (crtr doc), and manage for every privacy level and every document |
crtr:memory:read:app:<id>, crtr:memory:rw:app:<id> | Another app's documents; …:profile:<profile> narrows to one of its profiles |
crtr:files:read|rw:user:<dir>, crtr:files:read|rw:app:<id>:<dir>, crtr:files:share | Host files the run may mount, and sharing files beyond the app's own space |
crtr:conversations:read:app:<id>, crtr:objects:read:app:<id> | Reading another app's conversations or node objects |
<provider>:<group> | One tool group of a provider |
The memory in crtr:memory:* is the scope family's name for access to documents (see Documents); there is no separate memory store. The older short names (ask, act, schedule, memory:read, memory:write, llm) are not accepted by crtr sys connect --scopes. A node's own documents, and an app's documents for its own nodes, need no crtr:memory scope.
This is an allow-list, not a claim that code will behave. The daemon checks the scope at the route that performs the action and rejects an unavailable one. The SDK’s nodes.create scopes field narrows a run: a run's list must stay inside what its creator and grant hold, and crtr:act requires crtr:llm. client.memory is not scope-gated: it lists and reads the person's knowledge and preference documents, and the answer is filtered by privacy — an app sees public documents, and a grant holding crtr:memory:manage:user also sees friends and private ones. Who may read any document is the owner-and-privacy model, not a per-call scope.
Scopes rely on a more basic trust boundary: crtrd is the sole writer of durable canvas state and the sole owner of broker lifecycle. SDK clients, the CLI, and viewers call its API; they do not open the canvas database or launch their own broker. One owner serializes lifecycle changes, makes the same API usable locally and remotely, and keeps a client from silently creating a second state authority.
For a browser or remote process, run crtr sys connect. It enables the daemon’s TCP listener when needed and returns base_url plus a bearer token to give the application. crtr sys connect --app <id> --scopes … mints a new scoped token for that app instead of returning the owner token; --scopes requires --app, and accepts crtr:llm, crtr:act, crtr:schedule, crtr:memory:read:user, crtr:memory:read:app, crtr:memory:rw:app, crtr:files:read:user:. and crtr:files:rw:user:.. Treat either token as a credential: the remote app sends it as Authorization: Bearer <token>, and its scope list is the ceiling for scope-gated calls and newly created nodes.
The remote API is an explicit boundary, not permission to reach around it. Keep application code on the SDK or /v1 contract, and let the daemon own state transitions. Run crtr canvas read internal/nodes-and-canvas for the operational ownership model.
Profiles, kinds, and modes
When designing an agent run, read this because profiles, kinds, modes, and document owners solve different problems and prevent a long prompt from becoming an unstable substitute for an application identity.
Why a daemon
When deciding how an application should host or reconnect to an agent, read this because the daemon keeps the durable canvas and broker lifecycle in one place while terminals and SDK clients come and go.