Skip to main content

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.

  1. Open your organization and choose Hosted agents.
  2. Choose Connect a hosted agent.
  3. Pick the project, the environment and, if you want, the keys.
  4. Copy the token. It is shown once and only its hash is stored.
  5. 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:

terminal
envshed run -o acme -p billing -e production -- npm start

It also works with the Node SDK:

typescript
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:

RouteWhat the token gets
Read an environment's secretsOnly 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 secretThe value for an allowed key, 403 for any other key, whether it exists or not.
Secret requestsAsk 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​

  1. Choose Rotate. A replacement is created and shown once, with the same project, environment and keys.
  2. Update the secret on your platform.
  3. 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.