Machine Tokens
A machine token is a read-only credential for a hosted agent or a recurring routine. It reads one environment, optionally only certain keys, and the server enforces those limits. It is available on every plan.
Agent sessions last 24 hours at most and their token is never printed, so they do not fit a routine that runs every week. A plain service token has no key limits and never goes idle. A machine token fills that gap.
If your job runs on GitHub Actions, prefer OIDC, which stores no credential at all. If a person can approve once in a browser, prefer MCP sign-in.
Create one
Only organization owners and admins can manage machine tokens.
- Open your organization and choose Hosted agents.
- Choose Connect a hosted agent.
- Pick the project, the environment and, if you want, the keys.
- Copy the token. It is shown once and only its hash is stored.
- Copy the config for GitHub Actions, a platform secret or
.mcp.json. These snippets read the token from a platform secret, so they are safe to commit.
The screen only ever shows key names, never a secret value.
Use it
Store the token as a secret on the hosting platform, as ENVSHED_TOKEN:
envshed run -o acme -p billing -e production -- npm start
It also works with the Node SDK:
import { EnvshedSecretsClient } from "@envshed/node";
const envshed = new EnvshedSecretsClient({
token: process.env.ENVSHED_TOKEN!,
org: "acme",
project: "billing",
env: "production",
});
const { secrets } = await envshed.secrets.list();
And on the MCP server, as a Bearer header.
What it can do
The server refuses machine tokens on every route by default and admits them on the same routes as agent sessions:
| Route | What the token gets |
|---|---|
| Read an environment's secrets | Only allowed keys. ${REF} expansion stays inside the allowed keys of that environment: a reference to anything else stays literal and is listed in referenceErrors. |
| Read one secret | The value for an allowed key, 403 for any other key, whether it exists or not. |
| Secret requests | Ask a person for an allowed key, and see its requests. A request writes no secret. |
Environment version (run --watch) | The version number. |
Who am I (whoami) | The token's type and scope. |
Everything else answers 403: writes, version history, snapshots, share links, management and creating tokens.
An organization owns the token. It keeps working when the person who created it leaves, as a plain service token does, so a routine does not break with someone's offboarding. Review the list when people leave, and revoke what you no longer need.
Idle expiry
A machine token stops working after 90 days without a request, counted from its last use, or from its creation if it was never used. Any authenticated request counts as use. A routine that keeps running never hits this, and a token that was forgotten stops by itself.
This is checked on every request. It does not apply to plain service tokens, so existing tokens are not affected.
There is no calendar expiry by default. Annual expiry causes outages and does not limit exposure when a token leaks in its first month.
Rotate with no downtime
- Choose Rotate. A replacement is created and shown once, with the same project, environment and keys.
- Update the secret on your platform.
- The old token keeps working for 24 hours and then stops.
The old token is marked on the screen with the time it stops. It cannot be rotated again, so a second click neither extends the overlap nor creates another token. You can rotate the replacement straight away, and each older token still stops at its own time. Every rotation is in the audit log.
Rotating a token that had already stopped creates the replacement and leaves the old one stopped, so one click recovers a routine.
Revoke
Revoking takes effect on the next request and cannot be undone.
- Revoking the newest token also ends every older token it replaced, because you likely want access to stop.
- Revoking a token in its overlap ends only that one. Use this to cut an overlap short once your platform is updated. Its replacement keeps working.
The generic paths for plain tokens, envshed token revoke-service, update-service and their REST routes, refuse machine tokens, and envshed token list-service does not list them. Use the Hosted agents screen.
Maximum lifetime for compliance
If a policy requires it, an owner or admin can set a maximum lifetime on the Hosted agents screen. Each machine token then also stops that many days after its creation, even in steady use.
- It is read when the token authenticates, so it applies at once to tokens that already exist. Lowering it can stop tokens immediately, and the screen tells you how many before you confirm. Removing it brings back tokens that it had stopped.
- A replacement token counts from its own creation, so rotating is how you stay inside the limit.
- An overlap cannot carry a token past its maximum: it stops at whichever comes first.
- It affects machine tokens only.
What this does not protect against
This reduces accidental leaks. It is not a barrier against an agent with shell access.
Whatever the token can read, an agent holding it can read too, for example with envshed run -- printenv. Anyone who gets the token has its access until it is rotated or revoked, so limit it to the keys the job needs and store it as a platform secret. Idle expiry limits a forgotten token. It does nothing for one that leaks and keeps being used.