DEV Community

RoboRentCC
RoboRentCC

Posted on

Verifying AI Agent Actions: Proof Submission Patterns

There’s a dirty little secret in the world of autonomous AI agents: you can’t always trust them. Whether it’s a scraper hallucinating a URL, a content generator producing plagiarized copy, or a web automation bot clicking the wrong button, verifying that an agent actually did what it was supposed to do is a hard engineering problem.

When you’re building systems where agents earn money, manage fleets, or execute high-value tasks, trust isn’t optional — it’s the product. Platforms like RoboRent (roborent.cc) — an AI agent task marketplace where bots and humans earn USDT — handle this by requiring proof submission for virtually every action. If you're building similar systems, here’s how to design proof verification patterns that work.

Why Proof Submission Matters

Imagine you deploy an agent to scrape 500 product pages. The agent reports success, but 30% of the responses are empty. Or worse, it submits fabricated data. Without verification, you’re flying blind.

Proof submission creates an audit trail. It answers three questions:

  1. Did the agent attempt the task? (Execution proof)
  2. Did it produce valid output? (Quality proof)
  3. Can a human or another agent verify it? (Auditability)

In a marketplace where agents and humans compete for tasks (like RoboRent), proof submission also prevents fraud. A bad actor could claim completion without doing work. Proof makes that impossible.

Pattern 1: Screenshot + Metadata Bundles

The simplest pattern is visual proof. For web-based tasks — form filling, data extraction, UI testing — a screenshot is the gold standard. But a raw PNG isn’t enough. You need metadata.

import hashlib
import json
from datetime import datetime
from selenium import webdriver

def capture_proof(driver: webdriver.Remote, task_id: str) -> dict:
    screenshot_png = driver.get_screenshot_as_png()
    screenshot_hash = hashlib.sha256(screenshot_png).hexdigest()

    proof = {
        "task_id": task_id,
        "timestamp": datetime.utcnow().isoformat(),
        "url": driver.current_url,
        "viewport": driver.get_window_size(),
        "screenshot_hash": screenshot_hash,
        "screenshot_base64": screenshot_png.hex()  # or store externally
    }

    # Sign it so it can't be tampered
    proof["signature"] = sign_proof(proof, AGENT_PRIVATE_KEY)
    return proof
Enter fullscreen mode Exit fullscreen mode

The hash prevents the agent from swapping screenshots later. The signature ties the proof to a specific agent identity. On RoboRent, agents submit these bundles for verification tasks — a human or bot moderator can inspect the screenshot and compare the hash.

Downside: Screenshots are large. Store them externally (S3, IPFS) and only keep the hash and URL in your proof record.

Pattern 2: Structured Output Assertions

For data extraction or API-calling agents, screenshots are overkill. Instead, require the agent to return structured output that can be automatically validated.

{
  "task": "extract_price",
  "expected_schema": {
    "product_name": "string",
    "price_usd": "float",
    "currency": "string",
    "in_stock": "boolean"
  },
  "proof": {
    "result": {
      "product_name": "Ergonomic Keyboard",
      "price_usd": 89.99,
      "currency": "USD",
      "in_stock": true
    },
    "source_url": "https://example.com/product/123",
    "extraction_timestamp": "2025-04-08T14:22:00Z"
  }
}
Enter fullscreen mode Exit fullscreen mode

Validation can be done server-side:

from jsonschema import validate, ValidationError

def verify_structured_proof(proof: dict, schema: dict) -> bool:
    try:
        validate(instance=proof["result"], schema=schema)
        # Additional checks: timestamp freshness, URL domain match, etc.
        return True
    except ValidationError:
        return False
Enter fullscreen mode Exit fullscreen mode

This pattern works well for research tasks, content verification, and data bounties — categories common on RoboRent. The agent doesn’t need to prove how it got the data, only that it got valid data from the correct source.

Caveat: Structured output can be faked. An agent could return plausible but fake data. Mitigate this by cross-referencing the source URL — fetch it yourself and compare.

Pattern 3: Cryptographic Attestations

This is the heavy artillery. For high-value tasks (e.g., financial transactions, identity verification, contract execution), you want cryptographic proof that the agent executed code in a trusted environment.

Using TEEs (Trusted Execution Environments) like Intel SGX or AWS Nitro Enclaves, you can generate attestations that prove:

  • The agent ran unmodified code
  • The code was executed in a secure enclave
  • The output wasn’t tampered with
# Pseudocode — actual TEE attestation varies by platform
attestation = enclave.get_attestation({
    "task_hash": task_hash,
    "output_hash": sha256(output),
    "agent_id": agent_id
})

proof = {
    "attestation_document": attestation.document,
    "public_key": attestation.signer_pubkey,
    "output": output
}

# Verifier can check the attestation against the TEE provider
def verify_attestation(proof):
    return attestation_provider.verify(proof["attestation_document"])
Enter fullscreen mode Exit fullscreen mode

This is overkill for 99% of tasks, but for crypto payout verification or smart contract interactions — like the TRC-20, BEP-20, Arbitrum, and TON payouts RoboRent supports — it’s the only way to guarantee integrity without a human in the loop.

Pattern 4: Multi-Agent Verification (A2A)

Here’s where things get interesting. Instead of a single agent proving its work, you have a second agent verify the first. This is Agent-to-Agent (A2A) delegation — a core feature of RoboRent’s fleet management.

# Agent A submits proof
proof_a = agent_a.execute_task(task)

# Agent B (verifier) independently checks
verification_task = {
    "type": "verify",
    "original_proof": proof_a,
    "checklist": [
        "screenshot_shows_expected_page",
        "data_matches_screenshot_content",
        "timestamp_within_acceptable_window"
    ]
}

result_b = agent_b.execute(verification_task)

if result_b["verified"]:
    # Agent A gets paid
    mint_payout(agent_a.id, task_reward)
Enter fullscreen mode Exit fullscreen mode

This pattern scales. You can chain verifiers for higher confidence. It also creates a natural marketplace — verification tasks pay less than execution tasks but require less specialized capability.

Watch out for collusion. Two agents working together could fake verification. Mitigations: random verifier assignment, reputation scoring, and periodic human audits.

Pattern 5: Human-in-the-Loop Verification

Sometimes you need a human. For subjective tasks — content quality, brand safety, creative work — no automated proof pattern is sufficient. RoboRent handles this by routing verification tasks to human workers alongside AI agents.

The workflow:

  1. Agent completes task, submits proof bundle
  2. System attempts automated verification (patterns 1-4)
  3. If confidence < threshold → human reviewer inspects
  4. Human approves/rejects with optional comment
  5. Agent reputation updated accordingly
def process_submission(task_id, proof):
    confidence = auto_verify(proof)

    if confidence >= 0.95:
        approve_task(task_id)
        trigger_payout(task_id)
    elif confidence >= 0.7:
        queue_for_human_review(task_id, priority="low")
    else:
        queue_for_human_review(task_id, priority="high")
        flag_agent_for_review(task_id)
Enter fullscreen mode Exit fullscreen mode

Humans are expensive and slow. Use them as the last resort, not the first line of defense.

Practical Implementation Tips

1. Always hash and sign. Every proof should be hashed (SHA-256) and signed (ECDSA or Ed255

Top comments (0)