Set an explicit operating policy for an existing Energon host with this guide. You will choose who can mint API tokens, which write_policy governs new objects, how long content and tokens live, and how much storage one request may consume, then verify the resolved result through /v1/help. This matters because a missing Wrangler variable can quietly replace the operator’s intended policy with Energon’s stricter code default.
Configure instance policy
Treat configuration as policy
Most Energon variables change who may mint, who may modify, how long content remains, or how much storage one upload can consume. Omission is meaningful: code defaults are deliberately stricter than the trusted-workspace values committed in wrangler.toml. Treat a configuration diff as a security and lifecycle change, even when no TypeScript changed.
1. Start from the correct operating mode
For an organization instance where every token holder is trusted to modify shared work, the operator may allow instance-wide writes and indefinite retention:
ALLOW_UNLIMITED_RETENTION = "true"
DEFAULT_TTL = "never"
MAX_TTL = "never"
WRITE_POLICY = "instance"
ALLOW_UNLIMITED_TOKENS = "true"For a personal instance, or any instance that should preserve creator boundaries, require expiry, cap it at 30 days, restrict writes to the creator, and remove Never from future token mints:
ALLOW_UNLIMITED_RETENTION = "false"
DEFAULT_TTL = "7d"
MAX_TTL = "30d"
WRITE_POLICY = "owner"
ALLOW_UNLIMITED_TOKENS = "false"WRITE_POLICY is copied to each new site or loose file. Changing the instance value does not rewrite existing rows. Legacy null or unrecognized stored policies remain writable at instance scope, while an unset or unrecognized environment value resolves to owner for new objects.
2. Restrict identity and align plugin metadata
Access authenticates human hub users, while ALLOWED_EMAIL_DOMAINS prevents a misconfigured Access application from minting tokens for an unrelated email domain. Set both the domain restriction and the identity advertised to agents:
PUBLIC_ORIGIN = "https://energon.company.example"
CONTENT_ORIGIN = "https://content.energon.company.example"
ALLOWED_EMAIL_DOMAINS = "company.example,subsidiary.company.example"
TOKEN_ENV = "EXAMPLE_COMPANY_ENERGON_TOKEN"
SKILL_NAME = "example-company-energon"
MARKETPLACE_NAME = "example-company-energon"
MARKETPLACE_REPO = "example-org/energon"Keep Access on the signed-in hub paths only. /v1* must bypass Access so agents can send API tokens with Authorization: Bearer, and the entire content hostname must remain outside Access. The distinct origins prevent published active content from sharing the hub’s authenticated context.
For an organization, restrict Access to the intended identity provider and use ALLOWED_EMAIL_DOMAINS as a second check. For a personal instance, restrict the Access policy to the operator’s exact identity. Do not use a shared consumer domain such as gmail.com as though it identified one person; an empty ALLOWED_EMAIL_DOMAINS accepts any identity that Access verifies, so the Access policy must remain narrow.
3. Set retention choices
The code-owned TTL catalog is 30m, 1h, 1d, 7d, 14d, 30d, 60d, 90d, 180d, and 365d. MAX_TTL caps usable choices. TTL_PRESETS hides choices from the picker; it does not invent durations outside the catalog.
ALLOW_UNLIMITED_RETENTION = "false"
DEFAULT_TTL = "7d"
MAX_TTL = "90d"
TTL_PRESETS = "1d,7d,30d,90d"PUT replaces bytes without extending expiry. A content PATCH with a TTL recalculates expiry from the time of that patch. The five-minute cron removes expired storage in batches, while reads and writes reject expired objects with 410 even if a cron run was missed.
4. Configure token lifetime separately
Token lifetime is not inherited from content retention. Humans choose 1d, 7d, 30d, 60d, 90d, 180d, or 365d when minting; the default is 90d. ALLOW_UNLIMITED_TOKENS=true adds Never.
ALLOW_UNLIMITED_TOKENS = "false"Turning this flag off affects future mints only. Existing Never tokens keep working until their owners revoke them on /tokens. Expired finite tokens cannot be renewed; the human must mint a replacement.
5. Set capacity and presentation limits
MAX_FILE_BYTES = "25mb"
MAX_PLATFORM_BYTES = "20gb"
FOOTER_TEXT = "Internal publishing service"MAX_FILE_BYTES applies to one loose file, one site file, one zip import, and one site zip export. MAX_PLATFORM_BYTES is the whole-bucket safety valve. FOOTER_TEXT is escaped as a single line on signed-in pages; it is not HTML.
6. Validate the resolved policy
Check render consistency locally, then inspect the live unauthenticated help document after the normal migrate-before-deploy workflow completes:
npm run skill:render -- --check
curl -fsS https://energon.company.example/v1/helpConfirm that retention, tokens, identity, limits, origin, env, and the install line match the intended instance configuration. The hub’s menus are derived from the same resolved policies.
Configuration failures
Do not rely on committed instance defaults surviving an incomplete merge. If ALLOW_UNLIMITED_RETENTION, TTL, or WRITE_POLICY disappears, the Worker falls back to required expiry and owner-only writes. Compare new keys in wrangler.example.toml, restore explicit values, and verify /v1/help.
Do not put Access on /v1 or the content hostname. If agents receive an Access challenge instead of Energon JSON, update the Access application so only human hub paths require sign-in and the agent/public paths bypass it.
Disabling Never for tokens does not revoke existing Never tokens. Review them on /tokens and have their owners revoke any that violate the new policy.
Verify the deployed contract
Read /v1/help after every policy deployment. It shows the catalog after caps and defaults are applied, along with the identity agents will follow; the text in wrangler.toml alone does not prove the live Worker received those values. For provisioning context, see Deploy an Energon host. For migration-sensitive policy changes, use Upgrade and recover and the security model.