Development Choices

Expiry semantics for agent-created resources

Author
Gregory Mostizky Software Engineer
Published
Section
AI Agents
Length
5 min read3 sources cited

A resource an agent creates on a user's behalf expires unless a person claims it. Cloudinary's provisioned product environment deletes itself 24 hours after creation, and claiming requires an email address plus a confirmation from that mailbox, so an unattended run leaves lost work rather than orphaned assets and silent billing.

Resources nobody has agreed to own yet

When an agent provisions something for a user, it creates a resource with no responsible party: the account that would be billed and the person who would answer for it do not yet exist as a single named entity. Expiry semantics are the rules covering that gap — how long the unowned resource lives, what act makes it permanent, and what is destroyed with it when nothing happens.

Twenty-four hours, measured from creation

npx @cloudinary/cloud provisions a Cloudinary product environment with no account, no card and no login, writes CLOUDINARY_URL into ./.env, and prints a claim URL. The environment expires automatically 24 hours after creation unless it is claimed, as set out in Cloudinary’s starting page for agents (checked 2026-08-18).

The clock runs from creation, not from last use. An agent that provisions at the start of a long session is handing over a resource with less than a day left — an eight-hour build has already spent a third of the window before anyone reads the summary. That same property is what bounds the damage: whatever an unattended run gets wrong, the residue is one product environment, and it is gone within a day whether or not anyone notices it exists.

The failure becomes lost work, not litter

The usual shape of the cleanup problem is that created resources persist by default and deletion has to be performed by the process that created them — which, in the case that matters, is the process that crashed, hit its context limit, or was killed halfway. Cleanup is owed by exactly the thing that failed.

Expiry by default inverts that. Nothing has to run for the resource to go away; something has to run for it to stay. The cost of an abandoned run moves from the vendor’s side of the line to the user’s: instead of an environment sitting there accruing storage and delivery against metered vendor billing nobody is watching, you get a directory of work that no longer connects to anything. That is a real cost — the seeded assets and the tuned transformations are gone, and reproducing them costs another run. It is a better cost, because it is visible to the person who can act on it, and it is capped.

Claiming needs a mailbox, not just a click

The claim step is not a confirmation button. It takes an email address and a confirmation sent to that address, and the environment does not become permanent until the confirmation comes back — the mechanics are described in Cloudinary’s claimable-cloud provisioning documentation (checked 2026-08-18).

Two consequences follow. The first is that no permanent resource can exist without a person who can be contacted about it; the mailbox is the identity, and an agent cannot supply one on the user’s behalf. The second is that the human handoff is not optional politeness but a hard step in the mechanism — the run cannot finish itself. The same pattern governs the unauthenticated account-creation endpoint, where the credentials an agent receives only start working once a human has verified the account by email.

The claim URL and the deadline belong in the same message

A claim URL on its own reads as an upsell — a link to an account you can create later if the thing turns out to be useful. Presented with the expiry attached, the same URL reads as what it is: a deadline after which the work is unrecoverable.

This matters because of when the message is read. An agent typically reports at the end of a run, and the user may not open that report for hours; a link whose urgency is implicit has already lost part of its window by then. State the absolute time the environment expires, not a relative one, since “24 hours” is ambiguous once the message has been sitting unread. The credential written to ./.env is worth naming in the same breath — it is a live secret with a shelf life, and where an agent puts credentials it was just issued is the other half of that handoff.

The deadline extends to everything built inside

The expiry is a property of the product environment, and everything created inside it inherits that expiry without saying so. Assets seeded during the run, named transformations defined against them, upload presets, structured metadata fields — all of it is scoped to the environment and all of it goes when the environment goes.

The reason this is easy to miss is that none of the work carries the deadline where the work happens. A named transformation referenced in application code looks like any other configuration string. An upload preset invoked through an MCP server looks like a stable resource. The repository survives in git; the things it points at do not. A project can build cleanly at hour 23 and fail at hour 25 with no change to any file under version control. Anything intended to outlive the session — a transformation naming scheme, a folder structure, a preset another service depends on — is provisional until the claim confirmation lands, and is worth recording as provisional wherever it is defined. The same invisibility applies to delivery, which is locked to the public IP the provisioning command ran from and equally unstated in the code that consumes it.

What to check next

Sources

  1. Cloudinary's starting page for agents cloudinary.com
  2. Cloudinary's claimable-cloud provisioning documentation cloudinary.com
  3. Cloudinary's getting-started material for AI agents cloudinary.com

See also