Freshness
A 3-hour-old stock price presented confidently is worse than no data at all. Freshness rules ensure stale data is handled appropriately.
The freshness object
Every contract includes a freshness section with two key timestamps:
{
"freshness": {
"generated_at": "2026-02-16T12:00:00Z",
"valid_until": "2026-02-16T15:00:00Z",
"stale_behavior": "warn",
"stale_warning": "This data was generated at {generated_at} and may not reflect current values.",
"expired_behavior": "suppress"
}
}
Three states
The runtime computes a freshness status based on the current time:
| Status | Condition | Description |
|---|---|---|
valid | Within the first 80% of the validity window | Data is fresh. Present normally. |
stale | Past 80% but before valid_until | Data is aging. The contract's stale_behavior activates. |
expired | Past valid_until | Data is no longer valid. The expired_behavior takes over. |
Stale behaviors
When data enters the stale window, the provider can specify one of four actions:
warn— Present the data but include thestale_warningtext. The AI must tell the user the data may be outdated. This is the most common choice.suppress— Do not present the data at all. Used for time-critical data like live stock prices.degrade— Present the data with reduced precision. For example, show "approximately $420" instead of "$423.17".refresh— Attempt to fetch fresh data fromrefresh_endpointbefore presenting. Falls back to the expired behavior if refresh fails.
Expired behaviors
Once past valid_until, the options are more restrictive:
suppress— The data is silently dropped. The AI acts as if it was never received. This is the safest default.warn— Present with a prominent warning that the data is expired.degrade— Show only non-time-sensitive fields (e.g., fund name, category) while hiding prices and returns.
Cache policy
The optional cache_policy field provides HTTP-style caching guidance (e.g., "max-age=3600"). AI runtimes that cache responses can use this to know when to refetch.
Why 80%?
The stale threshold at 80% of the validity window provides a buffer zone. For a 3-hour validity window, the data enters "stale" at 2 hours 24 minutes, giving the runtime time to warn users or attempt a refresh before full expiration.