suprbox
All posts
Architecture

Agent keys, scopes, and session leases

How an AI agent authenticates to Suprbox, what a scope actually limits, and when you need to give it a session.

Hritvik Aggarwal May 7, 2026 7 min read

Every read in Suprbox starts with an agent key. The key tells the server who is asking, which vaults they can reach, and what shape of operation they are allowed to perform. This post covers how keys are minted, what scopes really constrain, and when a session lease is the right enforcement primitive.

What a key is

An agent key is a string that looks like sb_live_XXXXXXXXXX.YYYYYYYYYY.... The first half is an identifier, public and stored in the database. The second half is a secret. Only its hash is stored. The server verifies a presented key by looking up the row by identifier, then comparing the hash of the presented secret against the stored hash. If either half is wrong, the request is rejected with 401 before any rule loads.

Keys belong to a user. They are minted in the dashboard, bound at creation time to a list of vault ids, and given a list of scopes. They can be revoked or set to expire.

What a scope grants

There are three scopes today: read, write, delete.

Read lets the key call the document read endpoints and Suprbox Vault. Without read scope, every read call returns 403 before any rule runs.

Write lets the key replace a document body. The replace endpoint is the only way an agent can change document content, and it requires write scope.

Delete lets the key remove a document from a vault. It does not delete the document itself from storage. The document still exists, and is still in any other vaults it has been added to. The delete is scoped to the membership.

A key with read scope but not write or delete cannot accidentally modify your data. A common safe default is read-only keys for everything except a small subset of agents that need to write.

Vault binding

A key carries a list of vault ids. Any request to a vault not on that list returns 403 with vault_forbidden before the rules engine runs.

Binding is a structural check, not a rule. You cannot override it with a rule. If a key was minted with access to vault 17 and 23, it cannot ever read vault 42, no matter what rules you add. The right way to expand access is to mint a new key or update the binding.

The binding is also the boundary the SDK enforces when an agent calls list_vaults. Only the vaults on the key's binding list appear in the response. An agent never learns about vaults it cannot reach.

Session leases

Some vaults are too sensitive to leave open to an agent for the lifetime of the key. For those, you attach a session-lease rule. The rule has a configured number of seconds, the maximum lease duration.

When a session-lease rule is in force on a vault, every read against that vault requires a session id header. Without one, the response is 401 lease_expired. The agent has to call the session endpoint, get back a session id and an expiration time, and attach the session id to every subsequent read.

The session endpoint takes a vault id and an optional requested duration. The server caps the requested duration against the rule's maximum and returns whichever is smaller. If the rule says ten minutes and the agent requests one hour, the lease is ten minutes.

Once a session expires, the next read returns 401 lease_expired and the agent has to call the session endpoint again to start a new lease. There is no automatic renewal. This is intentional: an expired lease forces a re-decision in the agent code, which is the right place for cooldowns or human checks to fire.

Sessions live in their own database table and are tied to the key that opened them. A session cannot be transferred between keys, and a session opened against one vault does not extend access to another.

How keys, scopes, and rules compose

The order of checks on every read is:

  1. Identify the key. Bad signature, expired, or revoked: 401 invalid_or_missing_agent_key.
  2. Check the key has the right scope for the operation. No read scope on a read call: 403 missing_scope.
  3. Check the key is bound to the vault in the URL. Not bound: 403 vault_forbidden.
  4. Verify a session lease if the vault has a session-lease rule active. No session id: 401 lease_expired.
  5. Run the rules engine on the request. Outcome of allow proceeds, otherwise the appropriate response code is returned.

Steps one through four are structural. Step five is the policy layer. The two layers are deliberately separate. A bug or misconfiguration in a rule can never grant access to a vault the key was not bound to in the first place.

Per-key rate limits

The agent_keys table carries a rate_per_hour cap on every key. This is separate from any throttle rule on a vault. It bounds the total number of requests the key is allowed to make across all vaults in any 60-minute window.

The cap is enforced before the rules engine runs. A key hitting its own cap returns 429 throttled with the key's hourly limit reported in policy headers.

Throttle rules on a vault are independent and stack on top. A key with a 1000-per-hour limit can still be throttled on a vault with a 60-per-hour rule, whichever is hit first.

Expiration and revocation

Keys can be given an expires_at timestamp at creation. After the timestamp passes, the key is rejected at the identify step.

Keys can also be revoked through the dashboard. Revocation is immediate. The next request from a revoked key returns 401 even if the key has not expired yet.

Both are recorded in the audit log when they fire.

Last used and discovery

Every successful request updates the last_used_at timestamp on the key. The dashboard surfaces this to make it easy to see which keys are active, which are stale, and which were minted but never actually used.

A key minted ninety days ago and never used is a candidate for revocation. A key used heavily until yesterday and then quiet for a week is a candidate for investigation.

Why this design

Keys are deliberately simpler than full OAuth. The agents that integrate with Suprbox are server-side processes acting on a single user's behalf. They are not third-party apps trying to fan out across many users' accounts. A simple bearer key with a scoped binding is the right granularity for that use case.

Scopes are deliberately limited to three (read, write, delete) because finer-grained scopes have rarely paid for themselves in practice. The rules engine handles the rest. If you want a key that can read everything except the salary file, mint a read-only key bound to that vault and add a deny rule on the salary file. The result is the same as a hypothetical "read-everything-except" scope, and the deny rule is easier to audit because it appears in the rule list rather than hiding in a key configuration.

Session leases are the answer to "I want this agent to have access during a specific task window." A short-lived session, gated by an explicit endpoint call, is a stronger signal than a long-lived key and easier to reason about than a constantly-rotating key. The lease forces the agent to surface, however briefly, the moment it needs to start a new working window.

A worked example

A finance team wants an agent that can summarize bank statements from one vault but never download the original PDFs. They mint a key bound to that one vault with only the read scope. They add a noDownload rule on the vault.

The agent calls the list-documents endpoint and sees the bank statements. It calls the read-content endpoint, which returns extracted text shaped by the rule (no raw bytes). It calls the download endpoint, which returns 403 because the merged decision has noDownload set.

A second agent wants to write summaries back. They mint a separate key with read and write scopes on the same vault. The agent reads the bank statements, calls a write to a new "summaries" document in the same vault, and is allowed because the key has write scope and no deny rule fires.

Both agents are governed by the same set of rules, but their scopes constrain what shape of operation they can even attempt.

Summary

Authentication, scope, and vault binding are structural checks. The rules engine is the policy layer. Session leases are the right primitive for time-bounded access. The combination gives you enough levers to grant exactly the access a task needs, no more, and to revoke or tighten that access without rewriting any code in the agent itself.

Continue reading

Architecture
How rules work in Suprbox
10 min read
Launch
Introducing Suprbox Vault: chat with your secure documents
6 min read