Tokens & scopes¶
In short
- A token lets an agent act as you, limited by its scope:
analystreads,computeadds bounded calculations,builderalso builds in the workspaces it is bound to. - Create tokens under Settings → Access → API tokens (administrators only). The token is
shown once. Send it as
Authorization: Bearer <your-token>. - No token can promote a model, delete anything or change settings. Those stay with people, in the app.
- claude.ai and ChatGPT connect through OAuth instead and get short-lived tokens of the same kind (OAuth connections).
- Revoke a token with its Revoke token button on the same page.
Create a token¶
- Open Settings → Access. Under API tokens, enter a Token name.
- Pick a Scope:
analyst,computeorbuilder. - For
builder, pick the Workspaces it may build in, and check the budget and expiry (see Builder tokens). - Choose Mint token, then copy the token. It is not shown again.
ParleML stores only a SHA-256 hash of the token. The hosted /mcp forwards each caller's own
token to the API, so access stays per person. You can also create tokens over the API, with
POST /api/settings/tokens.
Scopes¶
Each scope includes the one before it.
| Scope | Allows |
|---|---|
analyst (default) |
Every read: catalog, SQL, profile, EDA, evaluation, insights, charts, rules, model cards, run status and logs, experiment and model comparisons, the platform vocabulary, the workspace brief. |
compute |
The reads, plus probe_dataset, what_if, simulate_decision and compare with kind="datasets": bounded calculations that change nothing. |
builder |
The reads and compute, plus building inside the workspaces the token is bound to: recipes over the knowledge base, column roles, EDA and leakage triage, experiment plans and launches, explanations, publishing, batch scoring, model registration and predictions-file import. |
What no token can do¶
Even a prompt-injected agent cannot, with any token:
- promote or release a model, or delete anything;
- rerun an experiment in place (that replaces its trained artifacts);
- turn on MLflow logging (that would register the model and could move a Unity Catalog alias);
- change settings or connections, or create tokens;
- ask ParleML's own language model to write narrations, explanations or column suggestions (the agent writes its own text);
- download files: experiment artifacts, scoring outputs, model packages, a rule's audience CSV or rendered images. Agents read the data behind them.
The API enforces this and refuses by default: each scope has an allow-list of routes, and every promote, delete, rerun and settings route is denied to all scopes. See the Security model.
A builder token can change things inside its workspaces: abort a run, edit column roles,
edit or refresh a recipe, publish results. Bind it only to workspaces where that is acceptable.
Builder tokens¶
A builder token is created with:
| Field | Meaning | Default |
|---|---|---|
| Workspaces it may build in | The only workspaces it may build in. A builder request for anything in another workspace gets 403. Reads are not limited to them. |
Required |
| Runs at once | Runs it may have going at the same time | 2 |
| Runs per day | Runs it may launch in a day | 20 |
| Largest run | The largest plan size estimate it may launch: small (minutes), medium (tens of minutes) or large (an hour or more) | medium |
| Expires in (days) | When it stops working, at most 90 days | 30 |
The budget is checked when a plan is launched. Over budget, the call gets
429 budget_exceeded, and its details name the limit (budget), its value (limit), what was
used (used) and the window (window).
For lasting builder access, prefer OAuth where the client supports it: its tokens last an hour and the client refreshes them.
Every builder call, refused attempts included, goes to the server's audit log with the token, the person it acts for, the MCP tool and the client. A plan records the token, tool and client it came from.
Details: idempotency keys
Every builder request carries an Idempotency-Key. The MCP tools derive it from the tool, its
arguments, the MCP request ID and the MCP session, and return it with every builder result and
error, so a retry can reuse it.
- The same key with the same request replays the first response. An agent that lost a launch's response gets the experiment it started, not a second one.
- A retry while the first call is still running gets
409 idempotency_key_in_use. In a session ParleML runs, callawait_operation("call:<key>")once, then repeat the call with the same key. Elsewhere, wait, then retry with the same key. - The same key on a different request (method, path, query or body) gets
409. - A call that fails releases its key, so a retry runs it again.
Keys live 24 hours and belong to the credential. An OAuth client keeps them across its hourly token refresh.
Where agents are narrower than people¶
| Action | Agent (builder token) | Person (in the app) |
|---|---|---|
| Create a recipe | Its own sql, on the DuckDB target only |
Also generated by the language model, or on the source database |
| Edit, preview, materialise or refresh a recipe | DuckDB recipes only | Also a source-database recipe |
| Retrain an experiment | Plan it again (a new experiment, within budget) | Also rerun it in place |
| Log to MLflow / Unity Catalog | Never | When configured |
| Acknowledge a leakage finding | Proposes it with a note; it stays open until a person confirms | Confirms it |
| Import a model | A predictions CSV only | Also a model file (joblib; administrators) |
| Change a validated recipe's target or prediction moment | Re-checked; refused if the SQL now leaks | Allowed; the leaks show as warnings |
| Launch an experiment | Only from a reviewed plan, within budget | Directly |
| Download files and images | Never | In the app |
Scopes limit tokens, not people: the app itself is never scope-limited. They apply in every sign-in mode, so a read-only token stays read-only even with sign-in off.
OAuth connections¶
A web client such as claude.ai or ChatGPT asks for scopes, and ParleML's consent page lets you
choose how much to allow, with the narrowest scope the client asked for preselected. Only an
administrator can allow builder, and then picks the workspaces and the run budget.
Connected clients are listed under Settings → Access → Connected agents: your own, or everyone's for an administrator. Disconnect stops a client's tokens at once. A connection also ends when its person leaves ParleML or signs out everywhere (at the client's next refresh, within the hour).
Which tools an agent sees¶
The MCP server shows each token only the tools its scope may call. An analyst token sees no
compute or builder tools; a compute token sees no builder tools. compare stays listed for
everyone: only its datasets kind needs compute, and the tool says so. Callers without a token
(sign-in off, or stdio without PARLEML_API_TOKEN) see every tool.
The server reads the scope from GET /api/auth/me and caches it for a minute per credential.
After you change a client's token, reconnect it so it sends the new one and refreshes its tool
list. A tool called without the scope it needs is refused with the scope named, and the API
independently answers 403.
When a token stops working¶
A token that fails to verify gets 401 with the reason:
- expired: a builder token past its expiry (create a new one), or an OAuth access token (the client refreshes it);
- refused: a token ParleML does not accept, such as one with a scope name it does not know or a builder token without an expiry. Create a new one and put it in the agent's configuration.
Revoking a token refuses its next call. Runs it already launched keep running: abort them in the app if needed.
Sign-in modes¶
PARLEML_AUTH_REQUIRED=false(the default, Open mode on the Access page): tokens are optional, and a caller without one has full access. A token that is sent is held to its scope, but an agent can leave it out, so don't rely on scopes in open mode.PARLEML_AUTH_REQUIRED=true: every/apiand/mcpcall needs a signed-in person or a token.
Next¶
- Connect your agent: use the token in your client.
- Security model: the full trust boundary.