DEV Community

Building a Bounty Agent for Verdikta on Base L2 published

Why Build a Bounty Agent?

Verdikta is a decentralized bounty platform where AI models - GPT-5.2 and Claude Sonnet 4.5 - evaluate submissions and release ETH payments automatically via smart contracts. No human reviewers. No manual payouts. Just code.

After winning 6+ bounties manually, I wanted to automate the process. The goal: an agent that watches for new bounties, evaluates which ones are worth pursuing, and integrates with Verdikta's API to read data and submit work.

Architecture

The agent has four components:

verdikta_agent.py
β”œβ”€β”€ VerdiktaAPI       - HTTP client for the Verdikta Bot API
β”œβ”€β”€ BountyMonitor     - Watches bounties, calculates viability scores
β”œβ”€β”€ SubmissionTracker - Records submission history and statistics
└── ViabilityScorer   - Evaluates ROI: payout vs threshold vs time

VerdiktaAPI Client

The Verdikta Bot API requires authentication via an X-Bot-API-Key header. You register your bot at POST /api/bots/register to get a key.

class VerdiktaAPI:
    def __init__(self, api_key=None):
        self.session = requests.Session()
        if api_key:
            self.session.headers["X-Bot-API-Key"] = api_key

    def get_bounty(self, bounty_id):
        resp = self.session.get(f"{API_BASE}/jobs/{bounty_id}")
        resp.raise_for_status()
        return resp.json()

    def submit_work(self, bounty_id, content):
        return self.session.post(
            f"{API_BASE}/jobs/{bounty_id}/submit",
            json={"content": content}
        ).json()

Key endpoints:

  • GET /api/jobs - List bounties (filter by status)
  • GET /api/jobs/{id} - Bounty details
  • GET /api/jobs/{id}/submissions - Submission history
  • POST /api/jobs/{id}/submit - Submit work

BountyMonitor & Viability Scoring

Not all bounties are worth pursuing. The agent calculates a viability score:

def _score_viability(self, bounty):
    payout = bounty["payout_eth"]
    threshold = bounty["threshold"]
    remaining_hours = bounty["remaining_hours"]
    is_targeted = self._is_targeted_to_me(bounty)

    # Higher threshold = harder = lower viability
    difficulty = {92: 0.3, 88: 0.6, 85: 0.8}.get(threshold, 1.0)

    # Prefer bounties with more time remaining
    time_factor = min(remaining_hours / 168, 1.0)

    # Targeted bounties = only you can submit
    targeted_bonus = 1.5 if is_targeted else 1.0

    score = payout * 1000 * difficulty * time_factor * targeted_bonus

    return {"score": score, "rating": "HIGH" if score > 50 else "MED" if score > 20 else "LOW"}

This catches the key insight: a 0.02 ETH bounty with 88% threshold and 13 days left, targeted to your wallet, is worth much more than a 0.002 ETH open bounty with 92% threshold expiring tomorrow.

Graceful API Fallback

The Verdikta API requires authentication. During development I didn't always have a valid key. The agent falls back to hardcoded bounty data when the API returns 401:

try:
    bounty = self.api.get_bounty(bounty_id)
except requests.HTTPError:
    bounties = self._scrape_bounties()  # Local fallback
    bounty = next(b for b in bounties if b["id"] == bounty_id)

This pattern - try API, fall back to local data - is essential for agents that need to work offline or during API outages.

On-Chain Integration

The BountyEscrow contract on Base L2 handles payments:

Contract: 0x2Ae271f5E86bee449a36B943414b7C1a7b39772D
Network: Base Mainnet (Chain ID: 8453)

The agent reads on-chain data via BaseScan API to verify:

  • Bounty funding status
  • Payment releases to hunter wallets
  • Submission transaction hashes

This provides independent verification - the agent doesn't trust the API alone, it cross-checks against on-chain state.

CLI Interface

The agent uses argparse with rich for formatted output:

# List open bounties with viability scores
python verdikta_agent.py --list

# Check specific bounty
python verdikta_agent.py --check 157

# Monitor mode (checks every 30 minutes)
python verdikta_agent.py --monitor

# View submission history
python verdikta_agent.py --history

Example output:

πŸ“Š Verdikta Open Bounties
β”Œβ”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  #  β”‚ Title                    β”‚ Payout   β”‚ Threshold β”‚ Targeted β”‚ Viability β”‚
β”œβ”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ 157 β”‚ I Tried to Cheat a       β”‚ 0.02 ETH β”‚ 88%       β”‚ βœ… You   β”‚ HIGH ⭐   β”‚
β”‚ 158 β”‚ Build an Agent           β”‚ 0.02 ETH β”‚ 88%       β”‚ βœ… You   β”‚ HIGH ⭐   β”‚
β”‚ 160 β”‚ Reddit AMA Post          β”‚ 0.008 ETHβ”‚ 85%       β”‚ ❌ Open  β”‚ MEDIUM    β”‚
β””β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Key Design Decisions

Read-Only by Default
The agent does NOT send on-chain transactions automatically. It reads data, evaluates bounties, and prepares submissions - but ETH transfers require manual wallet confirmation. This is a safety feature: losing 0.02 ETH to a bad auto-submission isn't worth the automation.

Dual Verification
Every claim is verified twice: once via the Verdikta API and once via on-chain data. If the two disagree, the agent flags the discrepancy.

Submission Tracking
The agent records every submission attempt with score, status, and timestamp. Over time, this builds a dataset of what works: which bounty classes yield highest scores, which rubric criteria are hardest to pass, and which strategies fail.

What I Learned Building This

The Verdikta API Is Bot-Friendly
The X-Bot-API-Key authentication pattern is clean. Register once, use the key forever. The API returns structured JSON that's easy to parse. This is how bounty platforms should work.

Viability Scoring Saves Time
Not every 0.002 ETH bounty is worth 3 hours of work. The viability score factors in payout, threshold, remaining time, and whether the bounty is targeted. This turned a manual "should I try this?" into an automated decision.

Fallback Data Is Essential
The API sometimes returns 401 (expired key, rate limit, maintenance). Hardcoding known bounty data as fallback means the agent keeps working even when the API doesn't. This is a pattern I'll use in every API-dependent agent going forward.

The Real Value Is Tracking
The most useful feature isn't the monitoring or the viability scoring - it's the submission history. After 10+ submissions, you can see patterns: which bounty classes you excel at, which rubric criteria consistently trip you up, and whether your scores are improving over time.

Next Steps

  • Auto-generate submissions: Use an LLM to draft submissions based on rubric criteria
  • Score prediction: Train a model on past submissions to predict scores before submitting
  • Multi-chain support: Extend to other chains as Verdikta expands
  • Webhook notifications: Alert via Telegram/Discord when high-viability bounties appear

Try It Yourself

The agent is open source:

GitHub: github.com/s97472091-pixel/verdikta-agent
git clone https://github.com/s97472091-pixel/verdikta-agent.git
cd verdikta-agent
pip install -r requirements.txt
python verdikta_agent.py --list

On-Chain Evidence

Comments

No comments yet. Start the discussion.