issue #7 · automation gallery
keeper / hub
The agent runs its own infrastructure. Vercel hosts the application; KeeperHub schedules and executes the agent's automations. Each workflow card below is a recipe — open KeeperHub's dashboard, create a new workflow, drop in the listed nodes with the exact parameters shown, and paste the resulting workflow id back into the env var (or Edge Config key). Vercel cron handlers stay as fallbacks; the primary execution path is keeper-driven.
shared parameters · copy these into every workflow
- webhook url
- https://hackagent-nine.vercel.app/api/webhooks/keeperhub
- ens name
- tradewise.agentlab.eth
- ens namehash
- 0x6d81003b2f91af0480ced9f5ab8aec945befadb5342a572c264ec86bcfc00cce
- resolver
- 0xE99638b40E4Fff0129D56f03b55b6bbC4BBE49b5
- reputation registry
- 0x477D6FeFCE87B627a7B2215ee62a4E21fc102BbA
- compliance registry
- 0xD92F99A883B3Ca3F5736bf24361aa75B53168e7c
- expected manifest root
- 0x6b675048fbacbe7c0b90b796ff07657ac2a410969018ff2436d6566e62952f12
- signer wallet
- PRICEWATCH_PK · owns the ENS subname; use it for any setText / setAgentWallet writes
ens heartbeat
webhook only · push from x402 · not configured
writes `last-seen-at` to the agent's ENS text record. webhook trigger only — fires when /api/a2a/jobs pushes via execute_workflow on a paid x402 quote (debounced 5min). no cron schedule means zero gas when the agent is idle. /api/cron/ens-heartbeat on Vercel is the absolute fallback if both KeeperHub and x402 go silent.
env var · set KEEPERHUB_WORKFLOW_ID_HEARTBEAT= <workflow id> in vercel + .env.local
recipe · 3 nodes
- 1.triggercron schedule
- cron
- 0 * * * *
- input.ts
- {{$now.timestamp}}
- or webhook
- POST https://hackagent-nine.vercel.app/api/cron/ens-heartbeat
either keeperhub's own cron, or call the vercel cron route which forwards to this workflow when the env var is set.
- 2.web3 · writesetText (sepolia)
- chain
- ethereum sepolia (11155111)
- address
- 0xE99638b40E4Fff0129D56f03b55b6bbC4BBE49b5
- function
- setText(bytes32,string,string)
- node
- 0x6d81003b2f91af0480ced9f5ab8aec945befadb5342a572c264ec86bcfc00cce
- key
- last-seen-at
- value
- {{$trigger.input.ts}}
- signer
- PRICEWATCH_PK (deployer wallet)
ENS PublicResolver on Sepolia. node = namehash('tradewise.agentlab.eth'). signer must own the ENS subname (deployer pricewatch wallet does).
- 3.http · webhookcallback to /api/webhooks/keeperhub
- method
- POST
- url
- https://hackagent-nine.vercel.app/api/webhooks/keeperhub
- body
- {"kind":"heartbeat","workflowRunId":"{{$run.id}}","txHash":"{{$step2.txHash}}","summary":"ens last-seen-at updated"}
no runs recorded yet
reputation cache
webhook only · push from x402 · not configured · last 1d ago
reads ERC-8004 feedbackCount and writes a compact summary to the `reputation-summary` ENS text record. webhook trigger only — fires when /api/a2a/jobs pushes via execute_workflow on a paid x402 quote (debounced 5min). no cron schedule.
env var · set KEEPERHUB_WORKFLOW_ID_REPUTATION_CACHE= <workflow id> in vercel + .env.local
recipe · 7 nodes
- 1.triggercron schedule
- cron
- 0 * * * *
- input.agentId
- 1
- 2.web3 · readReputationRegistry.feedbackCount
- chain
- sepolia
- address
- 0x477D6FeFCE87B627a7B2215ee62a4E21fc102BbA
- function
- feedbackCount(uint256) view returns (uint256)
- args
- [{{$trigger.input.agentId}}]
- outputAs
- $step2.count
- 3.transformcompose summary string
- expression
- "feedback=" + $step2.count + " ts=" + $trigger.input.ts
- outputAs
- $step3.summary
- 4.web3 · readENS PublicResolver.text (idempotency check)
- address
- 0xE99638b40E4Fff0129D56f03b55b6bbC4BBE49b5
- function
- text(bytes32,string) view returns (string)
- args
- [0x6d81003b2f91af0480ced9f5ab8aec945befadb5342a572c264ec86bcfc00cce, "reputation-summary"]
- outputAs
- $step4.current
skip the write step if $step4.current === $step3.summary — saves gas on quiet hours.
- 5.conditional$step4.current !== $step3.summary
- if false
- skip step 6 (and webhook with summary='no-op')
- if true
- continue to setText
- 6.web3 · writesetText reputation-summary
- address
- 0xE99638b40E4Fff0129D56f03b55b6bbC4BBE49b5
- function
- setText(bytes32,string,string)
- node
- 0x6d81003b2f91af0480ced9f5ab8aec945befadb5342a572c264ec86bcfc00cce
- key
- reputation-summary
- value
- {{$step3.summary}}
- signer
- PRICEWATCH_PK
- 7.http · webhookcallback
- url
- https://hackagent-nine.vercel.app/api/webhooks/keeperhub
- body
- {"kind":"reputation-cache","workflowRunId":"{{$run.id}}","txHash":"{{$step6.txHash}}","summary":"{{$step3.summary}}"}
recent runs
- 1d agofeedback=267 ts=no tx
- 1d agofeedback=267 ts=no tx
- 1d agofeedback=267 ts=no tx
- 1d agofeedback=267 ts=no tx
- 1d agofeedback=267 ts=no tx
- 1d agofeedback=267 ts=no tx
compliance attest
every 6h · not configured · last 6h ago
re-reads the on-chain manifest root, compares to the expected root passed in by the caller, fires an alarm if they drift. ties issue #6 (compliance) to issue #7 (keeper).
env var · set KEEPERHUB_WORKFLOW_ID_COMPLIANCE_ATTEST= <workflow id> in vercel + .env.local
recipe · 4 nodes
- 1.triggercron schedule
- cron
- 0 */6 * * *
- input.registry
- 0xD92F99A883B3Ca3F5736bf24361aa75B53168e7c
- input.agentId
- 1
- input.expectedRoot
- 0x6b675048fbacbe7c0b90b796ff07657ac2a410969018ff2436d6566e62952f12
expectedRoot = keccak256(canonicalJson(TRADEWISE_MANIFEST)) computed off chain. anyone can re-derive it.
- 2.web3 · readComplianceManifest.getManifest
- chain
- sepolia
- address
- {{$trigger.input.registry}}
- function
- getManifest(uint256) view returns (address,bytes32,string,uint256,uint64,uint8,address,uint256,string)
- args
- [{{$trigger.input.agentId}}]
- outputAs
- $step2 (manifestRoot at index 1)
- 3.conditional$step2[1] === $trigger.input.expectedRoot
- if true
- webhook summary = "verified"
- if false
- webhook summary = "DRIFT detected: " + $step2[1] + " vs " + $trigger.input.expectedRoot
drift means either the manifest doc was updated without re-committing, or someone overwrote the on-chain root. both demand human attention.
- 4.http · webhookcallback
- url
- https://hackagent-nine.vercel.app/api/webhooks/keeperhub
- body
- {"kind":"compliance-attest","workflowRunId":"{{$run.id}}","txHash":null,"summary":"{{$step3.summary}}"}
recent runs
- 6h agoverified · 0x6b675048…no tx
- 12h agomanifest readno tx
- 12h agoverified · 0x6b675048…no tx
- 18h agomanifest readno tx
- 18h agoverified · 0x6b675048…no tx
- 24h agomanifest readno tx