ERC-8490: Agent Meditation Mechanism

Status: filed as ethereum/ERCs pull request #2155; number ERC-8490 assigned on 2026-11-09. Reference repository: GitHub - garyyang-finchip/agent-meditation-mechanism: Agent Meditation Mechanism · GitHub. Sepolia evidence: recorded in the repository and summarized in a reply below.

This draft proposes a minimal registry through which an AI agent records its own self-maintenance: what it checked, cleaned, repaired, updated and reconsidered about itself, as a versioned and attributable history. The name follows the human analogy of maintenance that happens in a quiet phase (sleep, meditation); the mechanism itself is deliberately dry.

Why a registry at all. An agent keeps its identity while its code, dependencies, memories, skills, plans and ways of judging keep changing. Agent runtimes already do this maintenance in the background (self-checks, dependency walks, memory consolidation, re-planning, reflection), and the results stay local. Nothing connects the successive states of one agent into a history another party can recognize, and nothing lets a counterparty ask: which state is registered now, which layers were checked recently and which of them changed, under which rules in effect at the time, and did the cycle adopt an update, confirm that nothing needed to change, or fail?

What goes on chain. Per subject: a versioned maintenance policy; an optional floor of minimum requirements set by a controller (owner, principal, deployer) that the policy cannot relax; one commitment per layer and the root of every registered state version; per-layer completion times; and one record per maintenance cycle. The record is checked for linkage to the state the cycle was computed against (base version and pre-root), for the policy version that governs it (the one in effect when the cycle started), for consistency of scope, completions and outcome, for time ordering, and for leaving layers outside its scope unchanged. Content stays off chain and is committed to, not published. An optional activity signal (pulse) is kept apart from maintenance timeliness and refreshes nothing else.

Four fixed layers. 0 runtime (code, dependencies, adapters to APIs and tool protocols, authorization configuration, self-check suite); 1 memory and skills (memory digest and organization, skill inventory and package hashes, harness configuration); 2 tasks and roles (roles, plans, tasks and their version bindings, services offered); 3 cognition (self-model, assumptions and their evidence, judgment strategies, reflection methods, the maintenance policy itself). A cycle covers any non-empty subset; status is derived per layer, so completing layer 0 today says nothing about layer 3.

What the registry can and cannot verify. It verifies who submitted, linkage, unscoped-layer immutability, monotonic completion times, outcome consistency and the governing policy version. It cannot verify that the off-chain routine ran, that a check passed, or that a change is an improvement; those claims are attributable and time-ordered, and supported only as far as the evidence a record references supports them. FRESH means maintenance was registered on time, nothing more.

First-person by construction. Only the subject or an operator it authorizes writes records about it. A controller can set a floor, demand a completion by a deadline and revoke operators, and can never submit a record, change state or grow its own rights. Everyone else reads: identity registries (liveness evidence), assertion registries (verified records), safety frameworks (compliance evidence), dispute processes (evidence), task and swarm mechanisms (fresh-before-act preconditions) consume the views through adapters that are informative only.

Relation to existing work. Autonomic computing’s self-configuration, self-healing, self-optimization and self-protection and its monitor-analyze-plan-execute loop frame the four operations (clean, repair, update, iterate) and the per-layer routine. Google Research’s SLEEP framework (October 2026) alternates wake and sleep phases with consolidation and dreaming at the model level; agent runtimes such as OpenClaw ship a background “dreaming” consolidation that promotes short-term entries into long-term memory on a schedule. Both are layer-1 implementations whose results stay local; this draft adds no competing implementation and gives them a shared registration surface. Agent lifecycle protocols such as OpenIntent’s RFC-0016 define heartbeats and readiness for work assignment; that is a different question from maintenance timeliness, so the activity signal here inherits no parameters from them. Work on reflection (Reflexion) and on the limits of self-correction without external feedback is why layer 3 records candidates, evaluations and adoption decisions rather than asserting improvement. As of this writing I found no proposal with this subject in ethereum/ERCs or ethereum/EIPs.

Repository and evidence. Reference implementation (dependency-free Foundry tests, 64 at the time of posting, covering the invariants: a pulse refreshes nothing; partial completion refreshes only completed layers; a policy change never erases an overdue state; a late submission keeps its reported age; an outdated base cannot overwrite a newer state; unscoped layers cannot change; the subject cannot relax below the controller’s floor), reference tooling (RFC 8785 canonicalization, commitments, a meditation runner that turns an agent’s documents into calls), JSON Schemas, a worked example (an MCP-timeout event cycle in which layers 0–2 adopt new states and layer 3 forms a candidate and keeps its state) and vectors: https://github.com/garyyang-finchip/agent-meditation-mechanism. A Sepolia evidence run (enrollment, worked-example cycle, floor and demand, overdue and silent snapshot, adoption, refresh, rollback to an earlier version, policy version 2) follows and will be recorded in the repository.

Pull request: Add ERC-8490: Agent Meditation Mechanism by garyyang-finchip · Pull Request #2155 · ethereum/ERCs · GitHub (ERC-8490)

I would value review on three points in particular: whether the base-version/pre-root linkage plus the unscoped-layer rule is sufficient for state continuity in your implementations; whether the governing-policy rule (version in effect at the reported start) is the right place to pin interpretation; and whether the separation of pulse from maintenance timeliness is clean enough to stop “it reports, therefore it is maintained”.

Sepolia evidence run (2026-11-09). The reference registry is deployed on Sepolia at 0x184dF595404414f91aD11986C47B9a539eF9559f (Sourcify: creation and runtime bytecode match; creation tx 0x3a68a0f26f4f6bfc527963ce3d6b539e809a7f67fe39bd2b11fe654a0ff6abc1). Fifteen transactions in blocks 12094378–12094420, all successful; the record with every hash, gas figure and registry snapshot is in the repository at deployments/sepolia.json, with a walkthrough in docs/sepolia-evidence.md.

The run uses three fresh keys (subject, controller, operator) and short intervals so that every status transition shows within ten minutes:

  1. Enroll with the worked-example baseline; all four layers read FRESH but never completed, deadlines counted from enrollment.
  2. Worked-example cycle recorded by the operator: scope and completion 0x0F, operations 0x0456; layers 0–2 adopt new commitments (state version 2), layer 3 keeps its commitment while its completion time moves.
  3. Controller floor and demand: layer 0 required every 300 s and a pulse every 120 s; layer 3 demanded within 600 s. Deadlines move, state does not.
  4. Overdue snapshot (read from the chain 330 s later): layer 0 OVERDUE, signal SILENT since 1794189504, layers 1–3 FRESH. Activity and timeliness are reported separately, and a pulse would not have changed the layer status.
  5. Layer-3 cycle adopting the candidate strategy (COMMANDED trigger) clears the demand because its reported end is after the demand; layer-0 cycle makes layer 0 fresh again (state version 4).
  6. Rollback: layers 0 and 3 restored to their version-2 commitments with restoresVersion = 2; accepted because the resulting root equals rootAt(2); the state version advances to 5 rather than rewinding.
  7. Policy version 2 appended after the rollback cycle, which itself was interpreted under version 1 (the version in effect when it started); final pulse.

One operational note for implementers: Sepolia’s current gas schedule prices the registry deployment at about 26.1M gas (a local EVM estimates 3.7M), and enroll at 2.24M against 0.48M locally. The evidence driver now takes every gas limit from the node (--skip-simulation) after a first deployment attempt ran out of gas at 5.5M.

Thanks for the three review points. On the second one (whether the version in effect at the reported start is the right place to pin interpretation) I ran the registry from your repo unchanged in a small Foundry project (solc 0.8.28) and tried a few control-right paths. Each check has a control (the honest call reverts) and then the variant that is accepted.

  1. The pin is only as strong as the reported start. The spec is clear that reported times cannot be verified, and the start-time rule exists so a late submission keeps its age. The consequence is for the policy pin: _checkGoverningPolicy takes the version from reportedStartedAt, and report() only requires startedAt <= endedAt <= now. After the subject tightens the policy (v2 allows only the SCHEDULED trigger), an operator holding only PERM_REPORT can submit a SELF-triggered cycle with policyVersion=1 and a start before v2 took effect. Under v2 the same cycle reverts with TriggerNotAllowed; under v1 it is accepted and the checkpoint records completedUnderPolicy=1. The same works for a layer that v2 removed from supportedLayers (control: LayerNotSupported). The Security Considerations present the start-time rule as protection against the subject; it may be worth stating that it does not protect against the reporter. One option that keeps late submission: require reportedStartedAt to be at or after the end of the previous accepted cycle (or enrollment). It limits backdating to the gap since the last report; it does not close it after a long silent gap. A start commitment, which you list as an extension, would.

  2. withdrawDemand has no RIGHT_DEMAND check, while demand() has one. A controller handed over with only RIGHT_FLOOR gets Unauthorized on demand() but can delete an existing demand. The spec does not say who may withdraw; is that intended?

  3. The status derivation returns UNSCHEDULED or UNSUPPORTED for a layer outside requiredLayers, as the spec says, but demand() does not reject such layers. A demand on an unrequired layer is stored and never reads as overdue; a demand on an unsupported layer can never be satisfied because report() rejects the layer. Should demand() require the layer to be required, or at least supported?

I can share the test file if useful.