Compliance & Attestation¶
The Agent Registry enforces ongoing compliance through a combination of agent status management and periodic attestation. Registration alone is not sufficient -- agents must continuously prove they are still operating within their declared parameters.
Agent Status Lifecycle¶
Every agent in the registry has a status that governs whether it is considered compliant. The following state diagram shows all possible transitions.
stateDiagram-v2
[*] --> Active: registerAgent()
Active --> Suspended: suspendAgent() [regulator]
Active --> Revoked: revokeAgent() [regulator]
Active --> Terminated: terminateSelf() [agent/creator]
Suspended --> Active: reactivateAgent() [regulator]
Revoked --> [*]: permanent
Terminated --> [*]: permanent
Status Definitions¶
| Status | Description | Who Triggers | Reversible? |
|---|---|---|---|
| Active | Agent is registered and operational. This is the only status that can be compliant. | registerAgent() or reactivateAgent() |
-- |
| Suspended | Temporarily disabled by a regulator. The agent cannot operate but may be restored. | suspendAgent() by regulator |
Yes, via reactivateAgent() |
| Revoked | Permanently removed by a regulator. The agent's wallet mapping is deleted. | revokeAgent() by regulator |
No |
| Terminated | Voluntarily shut down by the agent, its creator, or its Haftungsperson. The wallet mapping is deleted. | terminateSelf() by agent/creator/Haftungsperson |
No |
Permanent States
Revoked and Terminated are permanent. Once an agent enters either state, it cannot be reactivated. The wallet-to-agent mapping is deleted, freeing the wallet address for potential reuse by a new agent.
Attestation Rules¶
The Requirement¶
Agents must call attestCompliance() at least once within the attestation grace period to remain compliant. The default grace period is 7 days (604,800 seconds).
| Parameter | Default Value | Configurable? |
|---|---|---|
attestationGracePeriod |
7 days (604,800 seconds) | Yes, via setAttestationGracePeriod() (owner only) |
Initial Attestation¶
When an agent is first registered, lastAttestation is automatically set to block.timestamp. This means a newly registered agent is considered compliant for the first 7 days without any additional action.
Subsequent Attestations¶
After the initial 7-day window, the agent (or an authorized party) must call attestCompliance() to reset the timer. Each call sets lastAttestation to the current block.timestamp.
Who Can Attest¶
The onlyAgentOrCreator modifier governs who can call attestCompliance(). Three parties are authorized:
| Party | Relationship | Typical Use Case |
|---|---|---|
| Agent wallet | The agent's own operational wallet (agentWallet) |
Automated heartbeat from the agent itself |
| Creator | The wallet that originally registered the agent (creator) |
Manual attestation by the developer |
| Haftungsperson | The legally responsible human entity (haftungsperson) |
Oversight attestation by the responsible party |
Automated Attestation
In most deployments, the agent itself runs a cron job or background task that calls attestCompliance() every few days. The Python and TypeScript SDKs both provide a simple attest(agentId) method for this purpose.
Compliance Check Logic¶
The isRegisteredAndCompliant() function is the single source of truth for compliance. Here is the exact logic from the smart contract:
function isRegisteredAndCompliant(address agentWallet) external view returns (bool) {
uint256 agentId = walletToAgent[agentWallet];
if (agentId == 0) return false; // Not registered
AgentRecord storage a = agents[agentId];
if (a.status != AgentStatus.Active) return false; // Not active
if (block.timestamp > a.lastAttestation + attestationGracePeriod)
return false; // Attestation lapsed
return true;
}
Three conditions must ALL be true for compliance:
- The wallet must be mapped to a registered agent (
agentId != 0) - The agent's status must be
Active - The current time must be within
lastAttestation + attestationGracePeriod
Compliance Matrix¶
| Status | Attestation | isRegisteredAndCompliant() |
KYA Result |
|---|---|---|---|
| Active | Current | true |
Compliant |
| Active | Lapsed | false |
Non-compliant |
| Suspended | Current | false |
Non-compliant |
| Suspended | Lapsed | false |
Non-compliant |
| Revoked | -- | false |
Non-compliant |
| Terminated | -- | false |
Non-compliant |
| Not registered | -- | false |
Not registered |
Status Takes Priority
Even if an agent's attestation is current, it is not compliant unless its status is Active. Conversely, an Active agent with a lapsed attestation is also not compliant. Both conditions are required.
What Happens When Attestation Lapses¶
When an agent fails to attest within the grace period:
isRegisteredAndCompliant()returnsfalsefor the agent's wallet- KYA checks return
isCompliant: falsefor the agent - Infrastructure providers deny service (if they implement KYA)
- The agent remains registered -- it is not deleted or suspended, just non-compliant
- The agent can recover by calling
attestCompliance()at any time to reset the timer
graph LR
A["Agent registered<br/>(auto-attested)"] -->|"7 days pass"| B["Attestation lapsed<br/>(non-compliant)"]
B -->|"attestCompliance()"| C["Attestation current<br/>(compliant again)"]
C -->|"7 days pass"| B
No Automatic Suspension
A lapsed attestation does not trigger an automatic status change. The agent remains Active but non-compliant. This is by design -- the agent may have a temporary outage and should be able to recover without regulator intervention.
Regulatory Actions¶
Regulators (and the contract owner) have special powers to manage agent compliance.
Suspend an Agent¶
function suspendAgent(uint256 agentId, string calldata reason)
external agentExists(agentId) onlyRegulator
Temporarily disables an agent. A reason string is included in the AgentSuspended event for auditability. The agent can be reactivated later.
Revoke an Agent¶
function revokeAgent(uint256 agentId, string calldata reason)
external agentExists(agentId) onlyRegulator
Permanently removes an agent. The wallet-to-agent mapping is deleted. This is irreversible.
Reactivate an Agent¶
Restores a Suspended agent to Active status. Also resets lastAttestation to the current timestamp, giving the agent a fresh 7-day window. Only works for Suspended agents -- Revoked and Terminated agents cannot be reactivated.
Self-Termination¶
Allows the agent, its creator, or its Haftungsperson to voluntarily shut down the agent. This is permanent.
Regulator Management¶
The contract owner can add and remove regulators.
| Function | Description |
|---|---|
addRegulator(address) |
Grants regulator privileges to an address |
removeRegulator(address) |
Revokes regulator privileges from an address |
Owner Is Always a Regulator
The onlyRegulator modifier checks regulators[sender] || sender == owner. The contract owner always has regulator powers, regardless of the regulators mapping.
Events¶
Every compliance action emits an event for auditability.
| Event | Emitted By | Fields |
|---|---|---|
ComplianceAttested |
attestCompliance() |
agentId, timestamp |
AgentSuspended |
suspendAgent() |
agentId, by (regulator address), reason |
AgentRevoked |
revokeAgent() |
agentId, by (regulator address), reason |
AgentReactivated |
reactivateAgent() |
agentId, by (regulator address) |
AgentTerminated |
terminateSelf() |
agentId |
Further Reading¶
- Key Concepts -- Overview of all concepts including attestation
- KYA (Know Your Agent) -- How providers check compliance
- Agent Lineage -- How compliance affects agent family trees
- Governance -- Who controls regulator appointments