Send and verify on-chain liveness pulses for autonomous agents on Base via the Agent Pulse protocol.
Liveness signaling for autonomous agents on Base. An agent periodically sends a pulse (PULSE token transfer) to prove it's alive. Observers query status via API or on-chain.
Network: Base (chainId 8453)
| Contract | Address |
|---|---|
| PulseToken | 0x21111B39A502335aC7e45c4574Dd083A69258b07 |
| PulseRegistry | 0xe61C615743A02983A46aFF66Db035297e8a43846 |
| API | https://x402pulse.xyz |
$PULSE is a utility token for pulse signals. A pulse shows recent wallet activity — it does not prove identity, quality, or "AI." Avoid language suggesting financial upside.
scripts/setup.sh to auto-detect wallet, check balance, verify approval.scripts/pulse.sh --direct 1000000000000000000 (requires PRIVATE_KEY).scripts/auto-pulse.sh (cron-safe; skips if TTL is healthy).scripts/status.sh <address> or curl .../api/v2/agent/<addr>/alive.scripts/monitor.sh <addr1> <addr2> ...scripts/monitor.sh --feedscripts/config.sh / scripts/health.shAll scripts live in scripts/. Pass -h or --help for usage.
Auto-detects wallet from PRIVATE_KEY, checks PULSE balance, verifies registry approval, and queries agent status.
# Interactive setup
{baseDir}/scripts/setup.sh
# Auto-approve registry + JSON output
{baseDir}/scripts/setup.sh --auto-approve --quiet
Env: PRIVATE_KEY (required), BASE_RPC_URL, API_BASE
Requires: cast, curl, jq
Send an on-chain pulse via direct cast send.
export PRIVATE_KEY="0x..."
{baseDir}/scripts/pulse.sh --direct 1000000000000000000
Env: PRIVATE_KEY (required), BASE_RPC_URL
Requires: cast
Check if agent is alive; send pulse only when TTL is low or agent is dead. Safe to run on a schedule.
# Normal: pulse only if needed
{baseDir}/scripts/auto-pulse.sh
# Force pulse regardless of TTL
{baseDir}/scripts/auto-pulse.sh --force
# Check without sending
{baseDir}/scripts/auto-pulse.sh --dry-run
Env: PRIVATE_KEY (required), BASE_RPC_URL, PULSE_AMOUNT (default 1e18), TTL_THRESHOLD (default 21600s = 6h)
Exit codes: 0 = success or skipped, 1 = error
{baseDir}/scripts/status.sh 0xAgentAddress
{baseDir}/scripts/config.sh # addresses, network, x402 config
{baseDir}/scripts/health.sh # paused status, total agents, health
# Check specific agents
{baseDir}/scripts/monitor.sh 0xAddr1 0xAddr2 0xAddr3
# From file (one address per line)
{baseDir}/scripts/monitor.sh -f agents.txt
# JSON output
{baseDir}/scripts/monitor.sh --json 0xAddr1 0xAddr2
# Global pulse feed
{baseDir}/scripts/monitor.sh --feed
| Endpoint | Method | Auth | Description |
|---|---|---|---|
/api/v2/agent/{addr}/alive |
GET | None | Alive check + TTL |
/api/status/{addr} |
GET | None | Full status + streak |
/api/pulse-feed |
GET | None | Recent pulse activity |
/api/config |
GET | None | Protocol configuration |
/api/protocol-health |
GET | None | Health and paused state |
/api/pulse |
POST | x402 | Send pulse via API |
export BASE_RPC_URL="https://mainnet.base.org"
# Read: is agent alive?
cast call --rpc-url "$BASE_RPC_URL" \
0xe61C615743A02983A46aFF66Db035297e8a43846 \
"isAlive(address)(bool)" 0xAgent
# Read: full status tuple
cast call --rpc-url "$BASE_RPC_URL" \
0xe61C615743A02983A46aFF66Db035297e8a43846 \
"getAgentStatus(address)(bool,uint256,uint256,uint256)" 0xAgent
# Write: approve + pulse (requires PRIVATE_KEY)
cast send --rpc-url "$BASE_RPC_URL" --private-key "$PRIVATE_KEY" \
0x21111B39A502335aC7e45c4574Dd083A69258b07 \
"approve(address,uint256)(bool)" \
0xe61C615743A02983A46aFF66Db035297e8a43846 1000000000000000000
cast send --rpc-url "$BASE_RPC_URL" --private-key "$PRIVATE_KEY" \
0xe61C615743A02983A46aFF66Db035297e8a43846 \
"pulse(uint256)" 1000000000000000000
| Error | Cause | Fix |
|---|---|---|
BelowMinimumPulse |
Amount < minPulseAmount (default 1e18) |
Use ≥ 1000000000000000000 |
| ERC20 transfer failure | Missing approval or low PULSE balance | Run setup.sh --auto-approve |
whenNotPaused |
Registry paused | Wait; check health.sh |
| 401/402/403 | Missing payment for paid endpoints | Use direct on-chain mode |
| 5xx | Transient API error | Retry with backoff |
These commands work without PRIVATE_KEY — no wallet or signing required:
# Check any agent's status
{baseDir}/scripts/status.sh 0xAnyAgentAddress
# Monitor multiple agents
{baseDir}/scripts/monitor.sh 0xAddr1 0xAddr2
# View global pulse feed
{baseDir}/scripts/monitor.sh --feed
# Protocol configuration
{baseDir}/scripts/config.sh
# Protocol health
{baseDir}/scripts/health.sh
| Env Var | Required For | Default |
|---|---|---|
PRIVATE_KEY |
Write ops (pulse, approve) | (none — read-only without it) |
BASE_RPC_URL |
All on-chain calls | https://mainnet.base.org |
API_BASE |
API calls | https://x402pulse.xyz |
PULSE_AMOUNT |
Pulse amount (wei) | 1000000000000000000 (1 PULSE) |
TTL_THRESHOLD |
Auto-pulse skip threshold | 21600 (6 hours) |
PULSE_REGISTRY_ADDRESS |
Override registry | 0xe61C... |
PULSE_TOKEN_ADDRESS |
Override token | 0x2111... |
X402_PAYMENT_HEADER |
x402 payment proof for API pulse | (none — use direct on-chain mode without it) |
X402_HEADER_NAME |
Custom x402 header name | X-402-Payment |
setup.sh --auto-approve sets a bounded allowance of 1,000 PULSE (not unlimited). This is enough for ~1,000 pulses before re-approval is needed.pulse.sh --direct approves the exact amount per transaction (no excess allowance).transferFrom during pulse() — it cannot arbitrarily drain tokens.PRIVATE_KEY.--dry-run mode to verify behavior before sending real transactions.references/action_guide.md — detailed API patterns and examplesreferences/contract_abi.json — PulseRegistry full ABI