What is a credential grant?
A credential grant is a named credential that belongs to one user. It has two parts:- Secret: the token, key, or password
- Policy: the destinations that can receive the secret and the code that can use the grant
fetch(grant, input, init) with the grant name. Standard Agents Builder adds the secret to the outgoing request and returns the response. Your code, the model, and the client receive no copy of the secret.
Use a grant for a credential that authenticates one user to an external HTTPS API, such as that user’s GitHub token.
Creating a grant
An administrator creates or replaces a grant with one request:PUT to the same name replaces the secret and the policy.
Request body
A grant name starts with a lowercase letter or a digit. The remaining characters are lowercase letters, digits,
., _, and -. The maximum length is 128 characters.
The request returns HTTP 400 with { "error": "Invalid credential grant" } when a field fails these rules or when the body has a field that this table does not list. It returns HTTP 404 when the user does not exist and HTTP 403 when the caller is not an administrator.
Listing grants
Deleting a grant
- When no instance grant has that name,
fetch()with that grant name returns thegrant_not_founderror after the deletion. - When an instance grant has that name, it applies to the user again after the deletion.
fetch()then uses the secret and the policy of the instance grant.
allow policy.
The secret is write-only
ThePUT request is the one operation that accepts a secret. No route returns it, and UserState has no member that reads it. To change a secret, send a new PUT request with the full grant.
Standard Agents Builder stores each grant in the durable storage of the user it belongs to. The policy is stored next to the secret, and the runtime reads the secret only when it adds the credential to a fetch() request.
The three grant routes accept administrators only. The policy, including metadata, is readable through GET /api/users/:id/grants. Code in agents/ cannot list grants or read their policy.
Kinds and injection
kind sets how the runtime adds the secret to the request. inject adjusts the location for the header and query kinds.
For the
basic kind, store the secret as username:password.
A header grant for an API that expects X-Api-Key: <secret>:
header grant for an API that expects Authorization: token <secret>:
inject:
headeris a valid HTTP header name.formathas at most 1,024 characters and no line break.queryhas 1 to 128 characters from letters, digits,.,_,~, and-.
signing kind. A PUT request with "kind": "signing" returns HTTP 400.
Origin matching
The runtime sends the secret only to a destination that anorigins entry covers. An entry has one of two forms:
- An exact origin uses
https. Write it in lowercase with no path, no trailing slash, and no user name or password. - A wildcard entry does not match the bare domain.
*.example.commatchesapi.example.comand does not matchexample.com. Addhttps://example.comas a second entry to cover it. - Each entry has at most 512 characters.
Redirects
The runtime follows redirects itself and checks each redirect destination againstorigins.
- A redirect to a destination that no
originsentry covers ends the fetch with thegrant_origin_deniederror. The runtime sends no request to that destination. - The runtime adds the credential again to each request that it sends, and it sends the headers from your code with each one.
- The runtime follows at most 5 redirects. A sixth redirect ends the fetch with the
grant_redirect_limiterror. - A 303 response changes the method to
GET, except for aGETorHEADrequest. A 301 or 302 response does the same for aPOSTrequest. The runtime then removes the body and the headers that describe it, such asContent-Type. A 307 or 308 response keeps the method and the body. - The runtime does not forward a
redirectoption from your code.
Allow policy
allow names the code that can use the grant. Each field is a list of up to 128 names. A caller that no list names receives the grant_caller_denied error. A PUT request needs at least one list.
Thread code means tools, hooks, handlers, effects, and thread endpoints. Standard Agents Builder identifies all of them by the agent of the thread, so
allow.agents is the list that admits them.
Two more callers use the userEndpoints list:
- A user lifecycle hook matches its hook type, such as
user_value_changed. - A user room matches the name in its
endpointoption. A room without that option matches its path underagents/users/, such asmy_package/room.
PUT route also accepts allow.tools and allow.endpoints and stores them. No caller in Standard Agents Builder matches those two lists. The route rejects allow.userRooms.
Using a grant
fetch(grant, input, init) takes the grant name, a URL, and request options. It is a member of UserState and of the handle that state.user() returns.
From a user endpoint
github/repos in allow.userEndpoints.
From a tool
allow.agents.
How the runtime handles the request
- The runtime reads the user’s grant with that name. When the user has none, it reads the instance grant with that name.
- It checks the destination against
origins. - It checks the caller against
allow. - It adds the secret to the request as
kindandinjectdescribe. - It sends the request with redirects disabled.
- For a redirect response, it checks the new destination against
origins, adds the secret again, and sends the next request. It repeats this step for at most 5 redirects. - It returns the final response of the external API to your code.
method, headers, and body options. The default method is GET. body is a string or absent, and fetch() throws for any other body type.
Errors
When the runtime does not send the request,fetch() resolves with a JSON response that carries an error code:
The external API can return the same status codes. Read the
error field of the body to tell a grant error from an API response. The error bodies contain neither the secret nor the destination URL.
Instance grants
An instance grant applies to every user of the instance. Set the secretAGENT_BUILDER_CREDENTIAL_GRANTS to a JSON registry:
- Each entry follows the rules of the
PUTrequest body, andnameis required. - The registry holds at most 64 grants and at most 65,536 characters.
- When the registry is malformed, or two entries share a name, the runtime uses no instance grants.
- A user’s own grant takes precedence over an instance grant with the same name. After the user’s grant is deleted, the instance grant applies again.
Grant or variable
state.env(name) and user.env(name) return the value of a variable to your code. Code that holds a value can log it, return it to the model, or send it to any destination.
A grant also limits the credential to listed destinations and listed callers. A variable has no such limits.
Next steps
Users
Run endpoints for one user and push live events to that user
Tools
Read variables with
state.env()API
Create endpoints that operate on one thread
Hooks
Run code at thread lifecycle points