Agent Pulse

Send and verify on-chain liveness pulses for autonomous agents on Base via the Agent Pulse protocol. Use when you need to: (1) prove an agent is alive by sending a pulse, (2) check any agent's liveness status or streak, (3) monitor multiple agents, (4) view the global pulse feed, (5) auto-configure wallet and PULSE balance, (6) run scheduled heartbeat pulses, or (7) read protocol health and config. Supports both API and direct on-chain (cast) modes.

Install
$clawhub install agent-pulse

Agent Pulse 💓

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.

Decision Tree

  1. First time? → Run scripts/setup.sh to auto-detect wallet, check balance, verify approval.

  2. Send a pulse?scripts/pulse.sh --direct 1000000000000000000 (requires PRIVATE_KEY).

  3. Automated heartbeat?scripts/auto-pulse.sh (cron-safe; skips if TTL is healthy).

  4. Check one agent?scripts/status.sh <address> or curl .../api/v2/agent/<addr>/alive.

  5. Check many agents?scripts/monitor.sh <addr1> <addr2> ...

  6. View pulse feed?scripts/monitor.sh --feed

  7. Protocol config/health?scripts/config.sh / scripts/health.sh

Scripts Reference

All scripts live in scripts/. Pass -h or --help for usage.

setup.sh — Self-Configure

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

pulse.sh — Send Pulse

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

auto-pulse.sh — Cron Heartbeat

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

status.sh — Agent Status

{baseDir}/scripts/status.sh 0xAgentAddress

config.sh / health.sh — Protocol Info

{baseDir}/scripts/config.sh     # addresses, network, x402 config
{baseDir}/scripts/health.sh     # paused status, total agents, health

monitor.sh — Multi-Agent Monitor


# 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

API Quick Reference

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

Direct On-Chain (cast)

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 Handling

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

Read-Only Mode (No Private Key)

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

Security

Required Credentials

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

Approval Behavior

  • 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).

  • The PulseRegistry contract can only call transferFrom during pulse() — it cannot arbitrarily drain tokens.

Best Practices

  • Never log, print, or commit PRIVATE_KEY.

  • Use a dedicated wallet with only the PULSE tokens needed — not your main wallet.

  • Start with --dry-run mode to verify behavior before sending real transactions.

  • Verify contract addresses and chainId before signing transactions.

  • Test with small amounts first.

References

  • Action guide: references/action_guide.md — detailed API patterns and examples

  • Contract ABI: references/contract_abi.json — PulseRegistry full ABI