Greenlight Agent API

Pre-action security checks for blockchain addresses, URLs, and AIS-aligned agent submissions before irreversible crypto actions.
Greenlight now supports structured agent context with AIS-aligned identity, intent, and action fields — with tolerant optional field handling for gradual adoption.

Endpoints

POST/v1/pre-action-checks RECOMMENDED

Submit AIS-aligned agent context, intent, and target data for pre-action security checks. Returns machine-readable security findings immediately. Supports gradual adoption — only 4 fields are required.

POST/v1/scans

Lightweight scan endpoint. Submit an address or URL for security analysis. Returns a signed findings payload.

GET/v1/scans/{scan_id}

Retrieve a previously completed findings payload by scan ID. Results expire after 24 hours.

GET/.well-known/agent-service.json

Agent discoverability manifest with endpoints, supported chains, submission requirements, and public keys.

Example — Pre-Action Check (Recommended)

# AIS-aligned pre-action check before a swap
curl -X POST https://greenlightagent.com/v1/pre-action-checks \
  -H "Content-Type: application/json" \
  -d '{
    "agent_context": {
      "agent_id": "trading-bot-01",
      "operator_id": "fund-alpha"
    },
    "intent": {
      "intent_type": "swap",
      "chain": "ethereum",
      "protocol": "uniswap_v3"
    },
    "action_context": {
      "target_type": "address",
      "target": "0xdef456...",
      "target_role": "router"
    },
    "policy_context": {
      "risk_profile": "standard",
      "first_time_interaction": false
    }
  }'

Example Response

{
  "check_id": "pac_ece945d0562c",
  "timestamp": 1712351235,
  "deterministic_validation": {
    "payload_valid": true,
    "target_type_recognized": true,
    "required_fields_present": true
  },
  "submitted_context": {
    "agent_id": "trading-bot-01",
    "intent_type": "swap",
    "target_type": "address",
    "target": "0xdef456..."
  },
  "findings_summary": {
    "outcome": "no_issues_detected",
    "level": "none",
    "issues_count": 0,
    "signal_weight": 0
  },
  "security_findings": [],
  "signals": {
    "contract_verified": true,
    "known_malicious": false,
    "first_time_interaction": false
  },
  "attestation": {
    "type": "signed_findings_attestation",
    "issuer": "Greenlight AgentAI",
    "issued_at": 1712351235,
    "expires_at": 1712352135,
    "signature": "ed25519:f24e51a8...1a5d09"
  },
  "disclaimer": "Findings reflect checks and signals available at the time of evaluation. Absence of findings does not imply absence of risk and is not a guarantee of safety."
}

Findings Outcomes

Greenlight returns findings — it does not make proceed/stop decisions. Your policy engine defines what each outcome means for your agent.

no_issues_detected — No findings returned by any check source. signal_weight < 20.
issues_detected — One or more findings present. signal_weight 20–59.
high_risk_signals_detected — High signal-weight threshold exceeded. signal_weight ≥ 60.

AIS-Aligned Submission

Greenlight now supports AIS-aligned pre-action submissions in which agents provide minimal identity, intent, and action context before execution. This enables richer security checks while allowing gradual adoption of structured agent identity standards.

FieldRequiredDescription
agent_context.agent_idRequiredUnique identifier of the acting agent
intent.intent_typeRequiredswap, transfer, approve, lend, add_liquidity, stake, bridge, withdraw, other
action_context.target_typeRequiredaddress, url, or tx
action_context.targetRequiredThe address, URL, or transaction payload being evaluated
agent_context.operator_idOptionalHuman, team, or organization operating the agent
agent_context.wallet_addressOptionalExecution wallet when available
agent_context.ais_refOptionalAIS or AID reference for the acting agent
intent.chain / protocol / amountOptionalBlockchain, protocol, and value context
policy_context.*Optionalrisk_profile, max_value_usd, first_time_interaction

Optional fields may be omitted, null, or set to "NA" — none will fail the request.


Verify Attestation Signature

Every findings payload includes an Ed25519 signature over the canonical JSON of the signed payload fields. Use the public key from /.well-known/agent-service.json to verify.

Verify /v1/pre-action-checks responses using the check_id field. Verify /v1/scans responses using scan_id.

Node.js

import nacl from 'tweetnacl';

const publicKey = '287cc8db0d0eae7d8bf0c14cb9e7ee647a047384c02ee85aea741c36a1bfabca';

function verify(result) {
  // Reconstruct the signed payload (pre-action-checks response)
  const payload = {
    check_id: result.check_id,
    agent_id: result.submitted_context.agent_id,
    target: result.submitted_context.target,
    target_type: result.submitted_context.target_type,
    intent_type: result.submitted_context.intent_type,
    outcome: result.findings_summary.outcome,
    signal_weight: result.findings_summary.signal_weight,
    findings_count: result.findings_summary.issues_count,
    issued_at: result.attestation.issued_at,
    expires_at: result.attestation.expires_at,
  };

  // Stable JSON: sort keys recursively
  function stableStringify(obj) {
    if (obj === null || obj === undefined) return 'null';
    if (typeof obj !== 'object') return JSON.stringify(obj);
    if (Array.isArray(obj))
      return '[' + obj.map(stableStringify).join(',') + ']';
    const keys = Object.keys(obj).sort();
    return '{' + keys.map(k =>
      JSON.stringify(k) + ':' + stableStringify(obj[k])
    ).join(',') + '}';
  }

  const message = new TextEncoder().encode(stableStringify(payload));
  const sig = Buffer.from(scanResult.attestation.signature, 'hex');
  const pub = Buffer.from(publicKey, 'hex');

  return nacl.sign.detached.verify(message, sig, pub);
  // true = authentic, untampered result from Greenlight
}

Python

from nacl.signing import VerifyKey
import json

public_key = '287cc8db0d0eae7d8bf0c14cb9e7ee647a047384c02ee85aea741c36a1bfabca'

def verify(result):
    # Reconstruct the signed payload (pre-action-checks response)
    payload = {
        "agent_id": result["submitted_context"]["agent_id"],
        "check_id": result["check_id"],
        "expires_at": result["attestation"]["expires_at"],
        "findings_count": result["findings_summary"]["issues_count"],
        "intent_type": result["submitted_context"]["intent_type"],
        "issued_at": result["attestation"]["issued_at"],
        "outcome": result["findings_summary"]["outcome"],
        "signal_weight": result["findings_summary"]["signal_weight"],
        "target": result["submitted_context"]["target"],
        "target_type": result["submitted_context"]["target_type"],
    }
    # stableStringify: recursively sort keys
    def stable(obj):
        if isinstance(obj, dict):
            return json.dumps({k: json.loads(stable(v)) for k in sorted(obj)}, separators=(",", ":"))
        return json.dumps(obj, separators=(",", ":"))
    message = stable(payload).encode()
    sig_hex = result["attestation"]["signature"].replace("ed25519:", "")
    sig = bytes.fromhex(sig_hex)
    vk = VerifyKey(bytes.fromhex(public_key))
    vk.verify(message, sig)  # raises if invalid
    return True

Security Checks

Address Scans (9 checks)

GoPlus Token Security, GoPlus Malicious Address, GoPlus Approval Security, GoPlus NFT Security, Chainabuse, Moralis Wallet Reputation, Phishing Database (53K+ domains), Etherscan, CoinGecko

URL Scans (5 checks)

GoPlus Phishing Detection, GoPlus dApp Security, Phishing Database, ScamSniffer, Chainabuse

Rate Limits & Pricing

30 requests/minute per IP. Free during beta. No API key required.