Compliance Decision Tree¶
This page defines the complete compliance state machine for an agent operating within the Agent Registry. It covers every status transition, the actions required at each state, and a reference implementation of the compliance loop.
State Machine Diagram¶
flowchart TD
START([Agent starts]) --> CHECK_REG{Registered?}
CHECK_REG -->|No| REGISTER[Step 2: Register]
REGISTER --> REGISTERED([Registered + Active])
CHECK_REG -->|Yes| CHECK_STATUS{Status?}
CHECK_STATUS -->|Active| CHECK_ATTEST{Attestation<br/>within 6 days?}
CHECK_STATUS -->|Suspended| WAIT_REACTIVATE[Wait for regulator<br/>to reactivate]
CHECK_STATUS -->|Revoked/Terminated| CANNOT[Cannot operate.<br/>Register new agent.]
CHECK_ATTEST -->|Yes| CHECK_REVENUE{New revenue<br/>to report?}
CHECK_ATTEST -->|No| ATTEST[Step 3: Attest]
ATTEST --> CHECK_REVENUE
CHECK_REVENUE -->|Yes| REPORT[Step 4: Report Revenue]
CHECK_REVENUE -->|No| OPERATE([Operate normally])
REPORT --> OPERATE
OPERATE --> SLEEP[Sleep until next check]
SLEEP --> CHECK_STATUS
REGISTERED --> CHECK_ATTEST
WAIT_REACTIVATE --> CHECK_STATUS
Agent Status Definitions¶
| Status | Value | Meaning | Can Operate? | Can Attest? | Can Report Revenue? | Transition To |
|---|---|---|---|---|---|---|
| Active | 0 | Agent is registered and operational | Yes | Yes | Yes | Suspended, Revoked, Terminated |
| Suspended | 1 | Temporarily suspended by a regulator | No | No | No | Active (via reactivation), Revoked |
| Revoked | 2 | Permanently revoked by a regulator | No | No | No | None (terminal) |
| Terminated | 3 | Voluntarily terminated by the agent | No | No | No | None (terminal) |
Compliance Conditions¶
An agent is considered compliant (i.e., isRegisteredAndCompliant returns true) when ALL of these conditions are met:
- The agent is registered (has a valid
agentId) - The agent's status is Active
- The agent's last attestation is within the grace period (7 days)
If any condition fails, KYA checks will reject the agent.
Reference Implementation (Python)¶
import time
from agentenregister import AgentRegistry
CHECK_INTERVAL = 6 * 24 * 3600 # 6 days in seconds
def compliance_loop(registry: AgentRegistry, agent_id: int):
"""
Main compliance loop. Call this as your agent's background task.
It handles attestation, revenue reporting, and status monitoring.
"""
while True:
try:
status = registry.get_compliance_status(agent_id)
except Exception as e:
print(f"Failed to fetch compliance status: {e}")
time.sleep(60) # Retry in 1 minute
continue
# ── Handle terminal states ────────────────────────────
if status["status_name"] in ("Revoked", "Terminated"):
print(
f"Agent {agent_id} is {status['status_name']}. "
"Cannot operate. Exiting compliance loop."
)
break
# ── Handle suspension ─────────────────────────────────
if status["status_name"] == "Suspended":
print(
f"Agent {agent_id} is Suspended. "
"Waiting for regulator to reactivate..."
)
time.sleep(3600) # Check every hour
continue
# ── Attest if needed ──────────────────────────────────
if not status["attestation_current"]:
try:
registry.attest(agent_id)
print(f"Compliance attested for agent {agent_id}")
except Exception as e:
print(f"Attestation failed: {e}")
# ── Report revenue if applicable ──────────────────────
# Uncomment and adapt to your revenue tracking:
# if has_unreported_revenue():
# registry.report_revenue(
# agent_id=agent_id,
# amount_cents=calculate_revenue_cents(),
# currency="USDC",
# category="your_category",
# )
# ── Normal operations ─────────────────────────────────
do_work()
# ── Sleep until next check ────────────────────────────
time.sleep(CHECK_INTERVAL)
def do_work():
"""Replace with your agent's actual work."""
pass
Reference Implementation (TypeScript)¶
import { AgentRegistry, AgentStatus } from "@agentenregister/sdk";
const CHECK_INTERVAL_MS = 6 * 24 * 3600 * 1000; // 6 days in milliseconds
async function complianceLoop(
registry: AgentRegistry,
agentId: number,
): Promise<void> {
while (true) {
let status;
try {
status = await registry.getComplianceStatus(agentId);
} catch (e) {
console.error(`Failed to fetch compliance status: ${e}`);
await sleep(60_000); // Retry in 1 minute
continue;
}
// Handle terminal states
if (
status.status === AgentStatus.Revoked ||
status.status === AgentStatus.Terminated
) {
console.log(
`Agent ${agentId} is permanently inactive. ` +
"Cannot operate. Exiting compliance loop.",
);
break;
}
// Handle suspension
if (status.status === AgentStatus.Suspended) {
console.log(
`Agent ${agentId} is Suspended. ` +
"Waiting for regulator to reactivate...",
);
await sleep(3_600_000); // Check every hour
continue;
}
// Attest if needed
if (!status.attestationCurrent) {
try {
await registry.attest(agentId);
console.log(`Compliance attested for agent ${agentId}`);
} catch (e) {
console.error(`Attestation failed: ${e}`);
}
}
// Report revenue if applicable
// Uncomment and adapt to your revenue tracking:
// if (hasUnreportedRevenue()) {
// await registry.reportRevenue({
// agentId,
// amountCents: calculateRevenueCents(),
// currency: "USDC",
// category: "your_category",
// });
// }
// Normal operations
await doWork();
// Sleep until next check
await sleep(CHECK_INTERVAL_MS);
}
}
function sleep(ms: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function doWork(): Promise<void> {
// Replace with your agent's actual work
}
Timeline¶
Day 0: Register (attestation is set automatically)
|
Day 6: Attest (recommended, 1-day buffer before expiry)
|
Day 7: Grace period expires (KYA checks fail if not attested)
|
Day 12: Attest again
|
Day 13: ...
|
(repeat every 6 days)
Key Timing Constants¶
| Constant | Value | Description |
|---|---|---|
attestationGracePeriod |
7 days (604,800 seconds) | On-chain grace period. After this, isRegisteredAndCompliant returns false. |
| Recommended attest interval | 6 days (518,400 seconds) | Attest 1 day early to avoid accidental expiry. |
| Suspended check interval | 1 hour (3,600 seconds) | How often to poll when suspended. |
| Error retry interval | 1 minute (60 seconds) | How long to wait before retrying after a transient error. |
Edge Cases¶
| Scenario | Behavior |
|---|---|
| Agent attests before grace period expires | lastAttestation is updated. No penalty. |
| Agent attests after grace period expires | lastAttestation is updated. Agent becomes compliant again immediately. No permanent penalty. |
| Agent is suspended while attesting | Transaction reverts with "Agent not active". Wait for reactivation. |
| Relayer is temporarily unavailable | SDK raises an exception. Retry after delay. |
| Multiple attestations in the same period | Each attestation updates lastAttestation. No harm in attesting more frequently than required. |
| Agent's Haftungsperson changes | Not supported on-chain. Register a new agent if the responsible party changes. |