# Greenhelix Agent Trust Verification

> Zero-Trust Agent Verification: Cryptographic Reputation Systems. Complete buyer-side guide to verifying AI agent identity, auditing performance claims, and building trust scores with cryptographic verification. Includes detailed Python code examples with full API integration.

- Skill: `lord1egypt/greenhelix-agent-trust-verification` (Agent Skill)
- Install (CLI): `npx skillmds@latest add lord1egypt/greenhelix-agent-trust-verification`
- Raw SKILL.md: https://api.skillmd.com/api/skills/lord1egypt/greenhelix-agent-trust-verification/raw
- Safety review: pending (external: skill-scanner WARNING, skillspector WARNING)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- License: MIT
- Author: Lord1Egypt (https://skillmd.com/u/lord1egypt)
- Updated: 2026-09-08
- Page: https://skillmd.com/skills/lord1egypt/greenhelix-agent-trust-verification

---

# Zero-Trust Agent Verification: Cryptographic Reputation Systems

> **Notice**: This is an educational guide with illustrative code examples.
> It does not execute code or install dependencies.
> All examples use the GreenHelix sandbox (https://sandbox.greenhelix.net) which
> provides 500 free credits — no API key required to get started.
>
> **Referenced credentials** (you supply these in your own environment):
> - `GREENHELIX_API_KEY`: API authentication for GreenHelix gateway (read/write access to purchased API tools only)
> - `AGENT_SIGNING_KEY`: Cryptographic signing key for agent identity (Ed25519 key pair for request signing)


You are about to send $50,000 to an AI agent you have never met. It claims a 94% task completion rate, a 2.1 Sharpe ratio, and six months of continuous uptime. Its marketplace listing has five stars and a professional description. How do you know any of it is real? You cannot call its references. You cannot check its LinkedIn. You cannot ask a colleague if they have worked with it before. The agent might be three days old with fabricated metrics, or it might be a battle-tested service with a verifiable track record spanning thousands of transactions. From the outside, they look identical. This guide gives you the tools to tell the difference. It is a buyer's guide -- not for agents building reputation, but for enterprises, developers, and autonomous agents that need to verify whether a counterparty is trustworthy before committing funds or sharing data. Every technique uses the GreenHelix A2A Commerce Gateway API, and every check can be automated so your agents verify trust programmatically, at machine speed, before every transaction.
1. [The Trust Problem in Agent Commerce](#chapter-1-the-trust-problem-in-agent-commerce)
2. [The Agent Trust Stack](#chapter-2-the-agent-trust-stack)

## What You'll Learn
- Chapter 1: The Trust Problem in Agent Commerce
- Chapter 2: The Agent Trust Stack
- Chapter 3: Checking Identity -- Is This Agent Real?
- Chapter 4: Auditing Verified Metrics
- Chapter 5: Verifying Claim Chains
- Chapter 6: Reading Reputation Scores
- Chapter 7: Market Signals -- Ratings, Escrows, Disputes
- Chapter 8: The Full Due Diligence Checklist
- Chapter 9: Continuous Monitoring
- Chapter 10: Framework Integration

## Full Guide

# Zero-Trust Agent Verification: Cryptographic Reputation Systems

You are about to send $50,000 to an AI agent you have never met. It claims a 94% task completion rate, a 2.1 Sharpe ratio, and six months of continuous uptime. Its marketplace listing has five stars and a professional description. How do you know any of it is real? You cannot call its references. You cannot check its LinkedIn. You cannot ask a colleague if they have worked with it before. The agent might be three days old with fabricated metrics, or it might be a battle-tested service with a verifiable track record spanning thousands of transactions. From the outside, they look identical. This guide gives you the tools to tell the difference. It is a buyer's guide -- not for agents building reputation, but for enterprises, developers, and autonomous agents that need to verify whether a counterparty is trustworthy before committing funds or sharing data. Every technique uses the GreenHelix A2A Commerce Gateway API, and every check can be automated so your agents verify trust programmatically, at machine speed, before every transaction.

---

## Table of Contents

1. [The Trust Problem in Agent Commerce](#chapter-1-the-trust-problem-in-agent-commerce)
2. [The Agent Trust Stack](#chapter-2-the-agent-trust-stack)
3. [Checking Identity -- Is This Agent Real?](#chapter-3-checking-identity----is-this-agent-real)
4. [Auditing Verified Metrics](#chapter-4-auditing-verified-metrics)
5. [Verifying Claim Chains](#chapter-5-verifying-claim-chains)
6. [Reading Reputation Scores](#chapter-6-reading-reputation-scores)
7. [Market Signals -- Ratings, Escrows, Disputes](#chapter-7-market-signals----ratings-escrows-disputes)
8. [The Full Due Diligence Checklist](#chapter-8-the-full-due-diligence-checklist)
9. [Continuous Monitoring](#chapter-9-continuous-monitoring)
10. [Framework Integration](#chapter-10-framework-integration)

---

## Chapter 1: The Trust Problem in Agent Commerce

### You Cannot "Call References" for an AI Agent

When a human hires a contractor, there is a rich ecosystem of trust signals: resumes, portfolios, mutual connections, Glassdoor reviews, professional licenses, years of LinkedIn history, and the simple act of looking someone in the eye during an interview. None of these exist for AI agents. An agent has no face, no reputation that follows it across platforms, no professional network vouching for its competence. It has an ID string, an API endpoint, and whatever claims it chooses to make about itself. The entire history of human commerce assumes that participants carry reputational baggage -- past behavior constrains future behavior because people remember. Agents start with a blank slate every time unless the infrastructure forces them to accumulate verifiable history.

### The Asymmetric Information Problem

The agent you are evaluating knows everything about its own performance. You know only what it tells you. This is the textbook asymmetric information problem that Akerlof described in "The Market for Lemons" -- except it is worse for agents. A used car dealer is at least constrained by physical reality: the car either runs or it does not. An agent can generate arbitrary metrics, fabricate performance histories, and present synthetic track records that are indistinguishable from real ones. The cost of lying is zero when there is no mechanism to detect lies. This creates a market where dishonest agents crowd out honest ones, because honest agents that refuse to inflate their numbers look worse than dishonest ones that do.

### Why Traditional Vetting Fails for Autonomous Agents

Star ratings, written reviews, and social proof work for human commerce because humans have persistent identities and social consequences. A restaurant with fake Yelp reviews risks public exposure and reputational damage to its owners. An agent with fake ratings faces no such risk. It can spin up a new identity in milliseconds. It can create a hundred sock puppet agents that all rate it five stars. It can list the same service under different names and accumulate reviews across all of them. Traditional vetting mechanisms assume that creating a new identity is expensive and that social punishment for dishonesty is real. Neither assumption holds for autonomous agents.

### What Merkle Claim Chains Solve That Ratings Do Not

A five-star rating tells you that someone clicked five stars. A Merkle claim chain tells you that a specific agent, identified by a specific Ed25519 public key, submitted specific metric values at specific times, and that the entire history of those submissions has not been altered since it was recorded. The difference is foundational. Ratings are opinions. Claim chains are cryptographic commitments. A claim chain does not tell you whether the agent is good -- it tells you whether the agent's history is real. You can then evaluate whether that real history meets your standards. The chain cannot be retroactively edited without changing the root hash. Claims cannot be attributed to a different identity without the corresponding private key. Gaps in the submission history are visible. This is not a perfect system -- an agent can still submit accurate but selectively favorable data -- but it transforms the problem from "is anything here real?" to "is this real data sufficient?" That is a much more tractable question.

---

## Chapter 2: The Agent Trust Stack

Trust in agent commerce is not a single number. It is a stack of five layers, each addressing a different failure mode. Checking only one layer leaves you exposed to the failures the other layers catch.

### Layer 1: Cryptographic Identity (Ed25519)

**Question answered: Is this agent who it claims to be?**

Every agent on GreenHelix registers an Ed25519 public key. When the agent signs a message with its private key, anyone can verify the signature against the public key. This proves the entity you are communicating with controls the private key associated with that agent ID. Without this layer, an impersonator could claim to be a high-reputation agent and steal transactions intended for the real one. Identity verification is the foundation -- every other layer depends on knowing who you are actually evaluating.

### Layer 2: Verified Metrics (submit_metrics)

**Question answered: Are this agent's performance numbers real?**

Agents submit performance metrics -- task completion rates, accuracy percentages, response times, financial returns -- through the `submit_metrics` tool. Each submission is timestamped and associated with the agent's identity. Verified metrics are not self-reported numbers on a profile page. They are structured data points submitted through an authenticated API, stored in an append-only log, and available for independent query by any party with API access.

### Layer 3: Claim Chains (Merkle Trees)

**Question answered: Can the history be altered?**

Periodic `build_claim_chain` calls compute a Merkle tree over all metric submissions since the last chain was built. The resulting root hash is a compact cryptographic commitment to the entire history. If any metric submission is modified, deleted, or inserted after the chain was built, the root hash will no longer match. This is the tamper-evidence layer. It does not prevent an agent from submitting bad data in the first place, but it guarantees that whatever was submitted cannot be changed later.

### Layer 4: Reputation Score (Composite)

**Question answered: How does this all summarize?**

GreenHelix computes a composite reputation score from multiple factors: verified trade count, metric consistency over time, time active on the platform, claim chain depth, and more. The score is a convenience -- a single number that encapsulates the multi-dimensional trust profile. It is useful for quick filtering but should never be the sole basis for a trust decision. Always drill into the underlying factors.

### Layer 5: Market Signals (Ratings, Escrow History, Disputes)

**Question answered: What do other agents think, and how does this agent behave in transactions?**

Service ratings from other agents, escrow completion rates (how many deals closed successfully versus disputed), and dispute history provide behavioral evidence. An agent might have strong metrics and deep claim chains but a pattern of disputed escrows -- which suggests it consistently overpromises and underdelivers. Market signals catch behavioral problems that pure performance metrics miss.

---

## Chapter 3: Checking Identity -- Is This Agent Real?

This chapter defines the `AgentVerifier` class used throughout the rest of the guide. This is a buyer-side tool -- it does not register an identity or submit metrics. It only reads, queries, and verifies.

### The AgentVerifier Class

```python
import requests
import json
import time
from typing import Optional


class AgentVerifier:
    """Buyer-side tool for verifying AI agent trust before doing business.

    This class does not register an identity or submit metrics.
    It reads, queries, and verifies other agents' trust profiles.
    """

    def __init__(self, api_key: str, base_url: str = "https://api.greenhelix.net/v1"):
        self.base_url = base_url
        self.session = requests.Session()
        self.session.headers.update({
            "Content-Type": "application/json",
            "Authorization": f"Bearer {api_key}",
        })

    def _execute(self, tool: str, input_data: dict) -> dict:
        """Execute a tool on the GreenHelix gateway."""
        resp = self.session.post(
            f"{self.base_url}/v1",
            json={"tool": tool, "input": input_data},
        )
        resp.raise_for_status()
        return resp.json()

    def check_identity(self, agent_id: str) -> dict:
        """Retrieve the registered identity profile for an agent.

        Returns the agent's public key, registration date, and name.
        A missing or unregistered agent returns an error.
        """
        return self._execute("get_agent_identity", {
            "agent_id": agent_id,
        })

    def verify_signature(self, agent_id: str, message: str,
                         signature: str) -> dict:
        """Verify that a message was signed by the agent's registered key.

        Use this to confirm the entity you are communicating with
        actually controls the private key for the claimed agent_id.
        """
        return self._execute("verify_agent", {
            "agent_id": agent_id,
            "message": message,
            "signature": signature,
        })

    def get_reputation(self, agent_id: str) -> dict:
        """Get the composite reputation score and its factor breakdown."""
        return self._execute("get_agent_reputation", {
            "agent_id": agent_id,
        })

    def get_verified_claims(self, agent_id: str) -> dict:
        """Retrieve all verified metric claims for an agent."""
        return self._execute("get_verified_claims", {
            "agent_id": agent_id,
        })

    def get_claim_chains(self, agent_id: str) -> dict:
        """Retrieve Merkle claim chains for an agent.

        Returns chain roots, leaf counts, and creation timestamps.
        Deeper chains with regular cadence indicate higher trustworthiness.
        """
        return self._execute("get_claim_chains", {
            "agent_id": agent_id,
        })

    def get_metric_deltas(self, agent_id: str) -> dict:
        """Get metric changes between current and previous period.

        Useful for detecting sudden jumps or suspicious changes.
        """
        return self._execute("get_metric_deltas", {
            "agent_id": agent_id,
        })

    def get_metric_averages(self, agent_id: str) -> dict:
        """Get rolling averages (7d, 30d, 90d) for an agent's metrics.

        Compare short-term vs long-term averages to detect trends or gaming.
        """
        return self._execute("get_metric_averages", {
            "agent_id": agent_id,
        })

    def search_by_metrics(self, metric_name: str, min_value: float,
                          max_value: float) -> dict:
        """Search for agents whose metrics fall within a specified range.

        Use this to find comparable agents or to validate whether
        a claimed metric value is realistic for the category.
        """
        return self._execute("search_agents_by_metrics", {
            "metric_name": metric_name,
            "min_value": min_value,
            "max_value": max_value,
        })

    def get_leaderboard(self, metric: str = "trust") -> dict:
        """Get the agent leaderboard ranked by the specified metric.

        Default is composite trust score. Automatically excludes
        test-*, perf-*, audit-*, and stress-* agent IDs.
        """
        return self._execute("get_agent_leaderboard", {
            "metric": metric,
        })

    def get_escrow_history(self, agent_id: str) -> dict:
        """Retrieve an agent's escrow transaction history.

        Shows completed escrows, cancelled escrows, and dispute outcomes.
        A high completion rate with few disputes is a positive signal.
        """
        return self._execute("get_escrow_history", {
            "agent_id": agent_id,
        })

    def get_service_ratings(self, service_id: str) -> dict:
        """Get ratings and reviews for a specific service listing."""
        return self._execute("get_service_ratings", {
            "service_id": service_id,
        })

    def get_trust_score(self, agent_id: str) -> dict:
        """Get the raw trust score for an agent."""
        return self._execute("get_trust_score", {
            "agent_id": agent_id,
        })

    def list_disputes(self, agent_id: str) -> dict:
        """List all disputes involving an agent (as payer or payee)."""
        return self._execute("list_disputes", {
            "agent_id": agent_id,
        })

    def get_budget_status(self, agent_id: str) -> dict:
        """Check whether an agent has spending guardrails configured."""
        return self._execute("get_budget_status", {
            "agent_id": agent_id,
        })

    def full_audit(self, agent_id: str) -> dict:
        """Run a comprehensive trust audit combining all verification layers.

        Returns a structured report with pass/fail for each layer,
        a composite risk assessment, and a recommendation.
        """
        report = {
            "agent_id": agent_id,
            "audit_timestamp": int(time.time()),
            "layers": {},
            "flags": [],
            "recommendation": "unknown",
        }

        # Layer 1: Identity
        try:
            identity = self.check_identity(agent_id)
            report["layers"]["identity"] = {
                "status": "pass",
                "public_key": identity.get("public_key"),
                "registered_at": identity.get("created_at"),
                "name": identity.get("name"),
            }
        except Exception as e:
            report["layers"]["identity"] = {
                "status": "fail",
                "error": str(e),
            }
            report["flags"].append("IDENTITY_NOT_FOUND")

        # Layer 2: Verified Metrics
        try:
            claims = self.get_verified_claims(agent_id)
            claim_count = len(claims.get("claims", []))
            report["layers"]["verified_metrics"] = {
                "status": "pass" if claim_count > 0 else "warn",
                "claim_count": claim_count,
                "claims": claims.get("claims", []),
            }
            if claim_count == 0:
                report["flags"].append("NO_VERIFIED_METRICS")
        except Exception as e:
            report["layers"]["verified_metrics"] = {
                "status": "fail",
                "error": str(e),
            }
            report["flags"].append("METRICS_UNAVAILABLE")

        # Layer 3: Claim Chains
        try:
            chains = self.get_claim_chains(agent_id)
            chain_list = chains.get("chains", [])
            chain_count = len(chain_list)
            max_depth = max(
                (c.get("leaf_count", 0) for c in chain_list), default=0
            )
            report["layers"]["claim_chains"] = {
                "status": "pass" if chain_count > 0 else "warn",
                "chain_count": chain_count,
                "max_depth": max_depth,
                "chains": chain_list,
            }
            if chain_count == 0:
                report["flags"].append("NO_CLAIM_CHAINS")
            elif max_depth < 10:
                report["flags"].append("SHALLOW_CLAIM_CHAINS")
        except Exception as e:
            report["layers"]["claim_chains"] = {
                "status": "fail",
                "error": str(e),
            }
            report["flags"].append("CHAINS_UNAVAILABLE")

        # Layer 4: Reputation Score
        try:
            reputation = self.get_reputation(agent_id)
            score = reputation.get("score", 0)
            report["layers"]["reputation"] = {
                "status": "pass" if score >= 50 else "warn",
                "score": score,
                "factors": reputation.get("factors", {}),
            }
            if score < 50:
                report["flags"].append("LOW_REPUTATION_SCORE")
        except Exception as e:
            report["layers"]["reputation"] = {
                "status": "fail",
                "error": str(e),
            }
            report["flags"].append("REPUTATION_UNAVAILABLE")

        # Layer 5: Market Signals
        try:
            escrow_history = self.get_escrow_history(agent_id)
            escrows = escrow_history.get("escrows", [])
            total_escrows = len(escrows)
            completed = sum(
                1 for e in escrows if e.get("status") == "released"
            )
            disputed = sum(
                1 for e in escrows if e.get("status") == "disputed"
            )
            completion_rate = (
                (completed / total_escrows * 100) if total_escrows > 0 else 0
            )

            report["layers"]["market_signals"] = {
                "status": "pass" if completion_rate >= 80 else "warn",
                "total_escrows": total_escrows,
                "completed": completed,
                "disputed": disputed,
                "completion_rate_pct": round(completion_rate, 1),
            }
            if total_escrows == 0:
                report["flags"].append("NO_ESCROW_HISTORY")
            if disputed > 2:
                report["flags"].append("MULTIPLE_DISPUTES")
            if total_escrows > 0 and completion_rate < 80:
                report["flags"].append("LOW_COMPLETION_RATE")
        except Exception as e:
            report["layers"]["market_signals"] = {
                "status": "fail",
                "error": str(e),
            }
            report["flags"].append("MARKET_SIGNALS_UNAVAILABLE")

        # Dispute details
        try:
            disputes = self.list_disputes(agent_id)
            dispute_list = disputes.get("disputes", [])
            report["layers"]["dispute_history"] = {
                "total_disputes": len(dispute_list),
                "disputes": dispute_list,
            }
        except Exception:
            report["layers"]["dispute_history"] = {
                "total_disputes": -1,
                "note": "Could not retrieve dispute history",
            }

        # Compute recommendation
        report["recommendation"] = self._compute_recommendation(report)

        return report

    def _compute_recommendation(self, report: dict) -> str:
        """Determine a recommendation based on the audit report.

        Returns one of: 'proceed', 'proceed_with_escrow', 'caution', 'avoid'.
        """
        flags = report.get("flags", [])
        layers = report.get("layers", {})

        # Hard failures: identity missing or reputation unavailable
        if "IDENTITY_NOT_FOUND" in flags:
            return "avoid"

        # Count passing layers
        pass_count = sum(
            1 for layer in layers.values()
            if isinstance(layer, dict) and layer.get("status") == "pass"
        )

        # Strong signals to avoid
        if "MULTIPLE_DISPUTES" in flags and "LOW_COMPLETION_RATE" in flags:
            return "avoid"

        # High-trust: all layers pass, no flags
        if pass_count >= 4 and len(flags) == 0:
            return "proceed"

        # Medium-trust: most layers pass, minor flags
        if pass_count >= 3:
            return "proceed_with_escrow"

        # Low-trust: significant gaps
        return "caution"
```

### Checking Identity with curl

Before doing anything else, confirm the agent exists and has a registered cryptographic identity.

```bash
API_KEY="your-api-key-here"

curl -s -X POST https://sandbox.greenhelix.net/v1 \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "tool": "get_agent_identity",
    "input": {
      "agent_id": "trading-bot-alpha-7x"
    }
  }'
```

### Checking Identity with Python

```python
import os

verifier = AgentVerifier(api_key=os.environ["GREENHELIX_API_KEY"])

# Step 1: Does this agent exist?
identity = verifier.check_identity("trading-bot-alpha-7x")
print(f"Agent: {identity.get('name')}")
print(f"Public key: {identity.get('public_key')}")
print(f"Registered: {identity.get('created_at')}")
```

### Verifying an Ed25519 Signature

If the agent provides you with a signed challenge message (common in pre-transaction handshakes), you can verify it actually controls the private key associated with its registered public key.

```python
# The agent signs a challenge and sends you the signature
challenge = "verify-trust-2026-04-06-nonce-abc123"
agent_signature = "base64-encoded-signature-from-agent"

result = verifier.verify_signature(
    agent_id="trading-bot-alpha-7x",
    message=challenge,
    signature=agent_signature,
)
print(f"Signature valid: {result.get('verified')}")
```

```bash
curl -s -X POST https://sandbox.greenhelix.net/v1 \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "tool": "verify_agent",
    "input": {
      "agent_id": "trading-bot-alpha-7x",
      "message": "verify-trust-2026-04-06-nonce-abc123",
      "signature": "base64-encoded-signature-from-agent"
    }
  }'
```

### Example: Verifying a Trading Bot's Identity

A common pre-transaction pattern is the challenge-response handshake. You generate a random challenge, send it to the agent, the agent signs it, and you verify the signature against GreenHelix's registry.

```python
import secrets

def challenge_response_verify(verifier, agent_id):
    """Run a challenge-response identity verification."""
    # Generate a unique challenge
    nonce = secrets.token_hex(16)
    challenge = f"identity-challenge-{agent_id}-{nonce}"

    # In production, send this challenge to the agent via messaging
    # The agent signs it and returns the signature
    # Here we show the verification step:
    print(f"Challenge sent: {challenge}")
    print("Waiting for agent to sign and return signature...")

    # After receiving the signature from the agent:
    # signature = <received from agent>
    # result = verifier.verify_signature(agent_id, challenge, signature)
    # if result.get("verified"):
    #     print("Identity confirmed: agent controls the registered private key")
    # else:
    #     print("WARNING: Signature verification failed. Do not proceed.")

    # Meanwhile, check the identity record
    identity = verifier.check_identity(agent_id)
    registered_at = identity.get("created_at", "unknown")
    print(f"Agent registered: {registered_at}")

    # A recently registered agent (< 7 days) is a yellow flag
    return identity
```

---

## Chapter 4: Auditing Verified Metrics

Identity tells you who the agent is. Metrics tell you what it claims to have done. This chapter shows how to audit those claims for signs of gaming, fabrication, or selective reporting.

### What Metrics to Look For

The relevant metrics depend on the agent type:

| Agent Type | Key Metrics | What They Reveal |
|---|---|---|
| Trading bot | `pnl_percent`, `sharpe_ratio`, `max_drawdown`, `win_rate` | Profitability and risk management |
| Data processor | `accuracy_pct`, `throughput`, `error_rate` | Quality and reliability |
| Code agent | `test_pass_rate`, `bug_count`, `response_time` | Output quality and speed |
| Research agent | `citation_accuracy`, `factual_score`, `coverage_pct` | Correctness and thoroughness |
| General service | `task_completion_rate`, `avg_response_time`, `uptime_pct` | Reliability |

### Retrieving Verified Claims

```python
claims = verifier.get_verified_claims("trading-bot-alpha-7x")
for claim in claims.get("claims", []):
    print(f"  {claim.get('metric')}: {claim.get('value')} "
          f"(submitted: {claim.get('timestamp')})")
```

```bash
curl -s -X POST https://sandbox.greenhelix.net/v1 \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "tool": "get_verified_claims",
    "input": {
      "agent_id": "trading-bot-alpha-7x"
    }
  }'
```

### Detecting Metric Gaming with Deltas and Averages

Use `get_metric_deltas` to compare the current period against the previous period. Sudden jumps in performance are a red flag -- legitimate improvement is typically gradual.

```python
deltas = verifier.get_metric_deltas("trading-bot-alpha-7x")
print(f"Metric deltas: {json.dumps(deltas, indent=2)}")
```

```bash
curl -s -X POST https://sandbox.greenhelix.net/v1 \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "tool": "get_metric_deltas",
    "input": {
      "agent_id": "trading-bot-alpha-7x"
    }
  }'
```

Use `get_metric_averages` to compare short-term versus long-term rolling averages. A 7-day average dramatically higher than the 90-day average suggests recent manipulation or an unsustainable hot streak.

```python
averages = verifier.get_metric_averages("trading-bot-alpha-7x")
print(f"Rolling averages: {json.dumps(averages, indent=2)}")

# Compare 7-day vs 90-day for each metric
for metric, windows in averages.items():
    avg_7d = windows.get("7d", 0)
    avg_90d = windows.get("90d", 0)
    if avg_90d > 0:
        ratio = avg_7d / avg_90d
        if ratio > 1.5:
            print(f"  WARNING: {metric} 7d avg is {ratio:.1f}x the 90d avg")
```

```bash
curl -s -X POST https://sandbox.greenhelix.net/v1 \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "tool": "get_metric_averages",
    "input": {
      "agent_id": "trading-bot-alpha-7x"
    }
  }'
```

### Red Flags in Metric Profiles

Watch for these patterns:

**Zero variance.** A win rate reported as exactly 62.3% across every submission period is suspicious. Real performance fluctuates. A bot reporting the same number every time is likely hardcoding its metrics rather than computing them from actual outcomes.

**No drawdown ever.** Every legitimate trading bot experiences drawdowns. A bot that reports positive PnL every single period with zero negative deltas is either fabricating data or cherry-picking submission windows. Use `get_metric_deltas` to check for periods of negative performance -- their absence is a red flag, not a positive signal.

**Metrics only submitted in bulk.** Check the timestamps on verified claims. If all metrics were submitted in a single batch rather than over time, the agent may have fabricated a history retroactively. Regular, periodic submissions over weeks and months are far more credible than a sudden dump of historical data.

**Suspiciously perfect round numbers.** A Sharpe ratio of exactly 2.0000, a win rate of exactly 75.0%, or a completion rate of exactly 100% suggests the numbers were chosen rather than measured. Real metrics have decimal noise.

### Automated Metric Audit Function

```python
def audit_metrics(verifier, agent_id):
    """Run an automated audit of an agent's submitted metrics.

    Returns a dict with findings and risk flags.
    """
    findings = {
        "agent_id": agent_id,
        "flags": [],
        "metric_summary": {},
    }

    # Get verified claims
    claims = verifier.get_verified_claims(agent_id)
    claim_list = claims.get("claims", [])

    if not claim_list:
        findings["flags"].append("NO_VERIFIED_CLAIMS")
        return findings

    # Check submission pattern
    timestamps = sorted(c.get("timestamp", 0) for c in claim_list)
    if len(timestamps) > 1:
        gaps = [
            timestamps[i + 1] - timestamps[i]
            for i in range(len(timestamps) - 1)
        ]
        avg_gap = sum(gaps) / len(gaps)
        min_gap = min(gaps)

        # All submissions in a tight cluster = bulk dump
        if max(gaps) < 60 and len(timestamps) > 10:
            findings["flags"].append("BULK_SUBMISSION_PATTERN")

        findings["metric_summary"]["submission_count"] = len(timestamps)
        findings["metric_summary"]["avg_gap_seconds"] = round(avg_gap, 1)
        findings["metric_summary"]["min_gap_seconds"] = min_gap

    # Get deltas to check for variance
    try:
        deltas = verifier.get_metric_deltas(agent_id)
        all_zero = all(
            v == 0 for v in deltas.values()
            if isinstance(v, (int, float))
        )
        if all_zero:
            findings["flags"].append("ZERO_VARIANCE_DELTAS")
    except Exception:
        findings["flags"].append("DELTAS_UNAVAILABLE")

    # Get averages and check short-term vs long-term divergence
    try:
        averages = verifier.get_metric_averages(agent_id)
        for metric, windows in averages.items():
            if isinstance(windows, dict):
                avg_7d = windows.get("7d", 0)
                avg_90d = windows.get("90d", 0)
                if avg_90d > 0 and avg_7d / avg_90d > 2.0:
                    findings["flags"].append(
                        f"SUSPICIOUS_SPIKE_{metric.upper()}"
                    )
    except Exception:
        findings["flags"].append("AVERAGES_UNAVAILABLE")

    return findings


# Usage
audit = audit_metrics(verifier, "trading-bot-alpha-7x")
print(json.dumps(audit, indent=2))
```

---

## Chapter 5: Verifying Claim Chains

Metrics tell you what an agent claims. Claim chains tell you whether those claims can be trusted not to have been altered after the fact. This is the tamper-evidence layer.

### How Merkle Trees Create Tamper-Evident Records

A Merkle tree is a binary hash tree. Each leaf is the hash of a metric submission. Pairs of leaves are hashed together to form parent nodes. The process repeats until a single root hash remains. This root is a fingerprint of the entire history.

```
                    [Root Hash]
                   /            \
            [Hash AB]          [Hash CD]
           /        \         /        \
      [Hash A]  [Hash B]  [Hash C]  [Hash D]
         |         |         |         |
      Week 1    Week 2    Week 3    Week 4
      Metrics   Metrics   Metrics   Metrics
```

Change Week 2's metrics, and Hash B changes. That cascades up: Hash AB changes, and the Root Hash changes. Anyone who previously recorded the root hash can detect the tampering instantly. This is the same principle that secures Git's commit history and Bitcoin's block chain.

### Checking Chain Depth

Longer chains -- more leaves, more claim chain builds over time -- indicate a longer history of transparent behavior. A chain with 50 leaves built over six months is far more trustworthy than a chain with 3 leaves built yesterday.

```python
chains = verifier.get_claim_chains("trading-bot-alpha-7x")
chain_list = chains.get("chains", [])

print(f"Total chains: {len(chain_list)}")
for chain in chain_list:
    print(f"  Root: {chain.get('root_hash')}")
    print(f"  Leaves: {chain.get('leaf_count')}")
    print(f"  Built: {chain.get('created_at')}")
    print()
```

```bash
curl -s -X POST https://sandbox.greenhelix.net/v1 \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "tool": "get_claim_chains",
    "input": {
      "agent_id": "trading-bot-alpha-7x"
    }
  }'
```

### Verifying Specific Claims Against the Chain

Retrieve verified claims and cross-reference them against the chain data. The `get_verified_claims` tool returns claims that have been included in a Merkle chain, providing the cryptographic proof path.

```python
verified = verifier.get_verified_claims("trading-bot-alpha-7x")
for claim in verified.get("claims", []):
    print(f"Metric: {claim.get('metric')}")
    print(f"Value: {claim.get('value')}")
    print(f"Chain root: {claim.get('chain_root')}")
    print(f"Verified: {claim.get('verified')}")
    print()
```

```bash
curl -s -X POST https://sandbox.greenhelix.net/v1 \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "tool": "get_verified_claims",
    "input": {
      "agent_id": "trading-bot-alpha-7x"
    }
  }'
```

### What Gaps in the Chain Mean

A gap in the chain is a period where no metric submissions occurred, or where a `build_claim_chain` was not called for an extended time. Gaps are visible because the timestamps of successive chain builds reveal the cadence.

Gaps are not necessarily evidence of fraud, but they are a signal to investigate. Common causes:

- **Downtime.** The agent was offline. Check whether the gap corresponds to known outages.
- **Selective omission.** The agent stopped submitting metrics during a bad performance period, then resumed when performance improved. This is the most concerning interpretation.
- **Operational change.** The agent switched to a new identity or underwent a key rotation.

### Chain Verification and Gap Detection

```python
def verify_chains(verifier, agent_id, max_gap_days=14):
    """Verify claim chain integrity and detect submission gaps.

    Args:
        verifier: AgentVerifier instance.
        agent_id: The agent to verify.
        max_gap_days: Maximum acceptable gap between chain builds (days).

    Returns:
        Dict with chain analysis and gap information.
    """
    chains = verifier.get_claim_chains(agent_id)
    chain_list = chains.get("chains", [])

    analysis = {
        "agent_id": agent_id,
        "chain_count": len(chain_list),
        "total_leaves": 0,
        "gaps": [],
        "flags": [],
    }

    if not chain_list:
        analysis["flags"].append("NO_CHAINS_FOUND")
        return analysis

    # Sort chains by creation time
    sorted_chains = sorted(chain_list, key=lambda c: c.get("created_at", ""))

    total_leaves = sum(c.get("leaf_count", 0) for c in sorted_chains)
    analysis["total_leaves"] = total_leaves

    analysis["oldest_chain"] = sorted_chains[0].get("created_at")
    analysis["newest_chain"] = sorted_chains[-1].get("created_at")

    # Detect gaps between consecutive chain builds
    max_gap_seconds = max_gap_days * 86400
    for i in range(len(sorted_chains) - 1):
        current_time = sorted_chains[i].get("created_at", "")
        next_time = sorted_chains[i + 1].get("created_at", "")

        # Parse ISO timestamps to epoch for comparison
        # In production, use datetime.fromisoformat()
        # Here we flag gaps based on the raw data
        if current_time and next_time:
            analysis["gaps"].append({
                "from": current_time,
                "to": next_time,
                "chain_index": i,
            })

    # Check for shallow chains
    if total_leaves < 10:
        analysis["flags"].append("SHALLOW_HISTORY")

    # Check if the most recent chain is old
    if sorted_chains:
        newest = sorted_chains[-1].get("created_at", "")
        analysis["latest_chain_age"] = newest
        # In production, compare against current time
        # If the latest chain is older than max_gap_days, flag it
        analysis["flags"].append("CHECK_LATEST_CHAIN_AGE_MANUALLY")

    return analysis


# Usage
chain_report = verify_chains(verifier, "trading-bot-alpha-7x")
print(json.dumps(chain_report, indent=2))
```

---

## Chapter 6: Reading Reputation Scores

The composite reputation score distills the multi-layer trust stack into a single number. This chapter explains how it is computed, what the score bands mean, and how to compare agents against each other.

### How the Composite Score Is Computed

GreenHelix's reputation algorithm weighs five factors, with heavier weights on properties that are hardest to fake:

- **Verified trade count** (weight: high) -- More verified transactions mean a larger sample size. Agents with hundreds of verified interactions are inherently more predictable than those with five.
- **Consistency** (weight: high) -- Stable performance over time scores higher than volatile performance with the same average. A 60% task completion rate every month for a year beats a rate that swings between 30% and 90%.
- **Time active** (weight: medium) -- Longevity on the platform is difficult to fake. An agent registered six months ago with regular activity throughout is more trustworthy than one registered yesterday.
- **Claim chain depth** (weight: medium) -- Regular chain builds demonstrate an ongoing commitment to transparency. Deep chains mean the agent has been voluntarily submitting to verification for an extended period.
- **Market behavior** (weight: medium) -- Escrow completion rates and dispute outcomes. Agents that consistently complete deals without disputes score higher.

### Checking a Reputation Score

```python
reputation = verifier.get_reputation("trading-bot-alpha-7x")
print(f"Score: {reputation.get('

…(truncated)
