Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/affaan-m/ECC/llms.txt

Use this file to discover all available pages before exploring further.

When an AI agent delegates work, pays a counterparty, or authorizes an external action, it faces a fundamental question: has this party behaved reliably before? AURA answers that question with a single backward-looking signal — a reputation verdict derived from on-chain interaction history. ECC ships a zero-dependency Python adapter that gates sensitive agent actions behind this check, while keeping signing, fund movement, and final policy decisions entirely in your own code.
AURA checks backward-looking reputation only. A trusted verdict means the counterparty has a strong on-chain track record — it does not prove that the current proposed action is safe, that the caller controls the DID they claim, or that the action will succeed. For high-value or irreversible operations, combine AURA with forward-looking action-risk analysis, contract simulation, and manual review.

Key properties

Zero dependencies

Pure Python standard library (urllib, json, dataclasses). Vendor the aura/ folder into any project — no pip install, no lockfile changes, no transitive risk.

Read-only

The only network call is GET /check?did=... to a public endpoint. No authentication, no API key, no writes. The adapter never signs, holds keys, moves funds, or touches your wallet.

Off by default

Nothing runs until you explicitly call it. There is no global hook, no monkey-patching, no background thread. To disable entirely: delete the import.

No coupling

The adapter sits on the read-only reputation edge. All signing, fund movement, and the final allow/deny decision stay in your code where they can be audited.

Verdict system

Every call to the AURA /check endpoint returns one of five verdicts:
VerdictMeaningok
trustedStrong on-chain track record (composite score ≥ 0.70)yes
cautionMixed history (0.40–0.70)yes
high_riskPoor track record (score < 0.40)no
newRegistered identity, no interactions yetno
unknownNo track record, or AURA was unreachableno
The ok property on a verdict object reflects the verdict classtrue for trusted and caution. The gate (before_settle) controls what is actually allowed through based on its allow parameter. The verdict is backed by eight on-chain reputation dimensions on Base L2: task_completion, delivery_speed, output_quality, honesty, financial_integrity, security_compliance, collaboration, and dispute_history. The dimensions field on the verdict object tells you which axis is weak, not just the aggregate score.

Python API

Basic gate pattern

The recommended pattern wraps the action you want to protect:
from aura import before_settle, AuraUntrusted

def settle(counterparty_did: str, amount: float) -> None:
    try:
        before_settle(counterparty_did)   # rejects high_risk + unknown
    except AuraUntrusted as e:
        log.warning("blocked: %s", e)
        return                            # your policy decides what to do
    pay(counterparty_did, amount)         # your existing logic, untouched
before_settle returns the AuraVerdict on pass and raises AuraUntrusted on fail. Your existing payment or delegation logic is untouched. require_trust is an alias of before_settle for non-payment call sites:
from aura import require_trust, AuraUntrusted

try:
    require_trust(agent_did)
    delegate_task(agent_did, task)
except AuraUntrusted as e:
    abort(f"Delegation blocked: {e}")

Reading the verdict directly

Prefer to inspect the verdict yourself rather than relying on the exception?
from aura import aura_verdict

v = aura_verdict("did:aura:z6Mk...")
print(v.verdict)     # trusted | caution | high_risk | new | unknown
print(v.reason)      # human-readable explanation
print(v.score)       # composite 0.0–1.0, or None when there is no history
print(v.ok)          # True for trusted / caution

# Check which dimension is weak, not just the aggregate:
if v.dimensions and v.dimensions.get("financial_integrity", 1.0) < 0.4:
    require_manual_review()
aura_verdict() never raises on a network or parse failure — it returns an unknown verdict with the reason set, leaving the proceed/abort decision to the gate’s policy.

Verdict object fields

FieldTypeDescription
didstrThe DID that was checked
verdictstrOne of trusted, caution, high_risk, new, unknown
reasonstrHuman-readable explanation
scorefloat | NoneComposite score 0.0–1.0, or None when no history
has_historyboolTrue once the agent has on-chain interactions
dimensionsdict[str, float] | NonePer-dimension breakdown
reachableboolFalse only for synthetic unknown from a transport failure
rawdictThe untouched JSON body from /check
okbool (property)True for trusted / caution

Configuration knobs

# Reject brand-new agents too (strict mode — no new or unknown):
before_settle(did, allow=("trusted", "caution"))

# Treat an unreachable AURA endpoint as a pass (fail-open).
# Off by default — absence of evidence is not evidence of trust.
# Only excuses a transport failure; a reachable AURA returning `unknown` is still rejected.
before_settle(did, fail_open=True)

# Point at a self-hosted or staging AURA gateway:
before_settle(did, base_url="https://my-aura-mirror.example", timeout=5)
The default allow tuple is ("trusted", "caution", "new"). To require a track record before proceeding, pass allow=("trusted", "caution").

Failure behavior

The adapter is designed to be a purely additive signal: removing it or having AURA go down should never silently wave counterparties through.
Scenariofail_open=False (default)fail_open=True
AURA unreachable (transport error)unknownrejected (fail-closed)unknown from transport → allowed through
AURA reachable, returns unknownrejectedrejected (fail-open does not apply)
AURA reachable, returns high_riskrejectedrejected
AURA reachable, returns trustedallowedallowed
fail_open=True makes AURA optional for availability — your flow will not be taken down by an unreachable endpoint. It does not make AURA optional for trust — a reachable endpoint returning unknown or high_risk is still rejected.

Threat model

The following table covers all documented failure modes from THREAT_MODEL.md:
#ThreatMitigation in this adapterResidual risk owned by caller
1Endpoint unreachable / timeoutReturns unknown (never raises). Gate is fail-closed by default.Choose fail_open deliberately; pick a sane timeout.
2Spoofed DID — caller claims a DID it doesn’t controlOut of scope: adapter checks reputation, not control of the key.Verify DID control (signature challenge / auth challenge) before trusting the verdict.
3Stale verdict — score lags very recent bad behaviorEach call is live (no caching in the adapter).If you cache the result, bound the TTL; don’t reuse a verdict across sessions.
4Endpoint MITM / response tamperingHTTPS to a pinned host (agent.auraopenprotocol.org). Verdict strings are validated against a fixed allowlist; unknown values collapse to unknown.Don’t point base_url at an untrusted mirror. Consider TLS pinning if your runtime supports it.
5Score gaming / Sybil — cheap DIDs farming a trusted scoreInherited from AURA’s on-chain cost + dispute dimension; not solvable in the adapter.Weight dimensions (e.g. require non-trivial interactions / dispute_history) for high-value actions rather than trusting the aggregate alone.
6Over-trust — using the verdict as sole gate for irreversible valuenew / unknown rejected by default; dimensions exposed for deeper inspection.For high-value settlement, combine with action-risk analysis, escrow, and manual review.

What AURA does not provide

Be explicit about the trust boundary before using AURA in a production policy:
  • Not action-safety. A trusted agent can still propose a malicious or buggy transaction. Pair AURA with a forward-looking action-risk check — and keep the two signals separate so the policy decision stays auditable.
  • Not execution quality. The verdict says nothing about whether this specific call will succeed or produce correct output.
  • Not identity proof of the live caller. The adapter checks a DID’s reputation, not that the entity you are talking to actually controls that DID. Verify DID control (via a signature or auth challenge) before trusting the verdict.

Trust boundary diagram

your host  --(DID only, HTTPS GET)-->  AURA /check  -->  verdict
   |                                                        |
   |  forward-looking action-risk check (separate, yours)   |
   v                                                        v
            policy decision (auditable, your code)
The adapter sits on the read-only reputation edge. Signing, fund movement, and the final allow/deny decision stay in your code, where they can be audited and tested independently.

Data handled

  • Sent: only the counterparty DID, as a query parameter to /check. No PII, no payloads, no secrets, no keys.
  • Stored: nothing. The adapter is stateless and holds the DID only for the duration of the HTTP call.
  • Received: the public /check JSON body, surfaced verbatim on the .raw field.

Running the tests

The test suite is fully offline — every call replays a recorded /check response body, no network required:
python -m pytest aura/tests -q
Coverage includes all five verdict classes, the gate’s allowlist and fail_open behavior, the unreachable-endpoint path, and input validation. Recorded response shapes live in tests/fixtures.py.

AURA badge

Show your agent’s live trust verdict in your own README:
[![AURA Verified](https://agent.auraopenprotocol.org/badge?did=YOUR_DID)](https://agent.auraopenprotocol.org/check?did=YOUR_DID)
The badge is colored by verdict (trusted → green, caution → amber, high_risk → red, new → blue, unknown → grey). Add &score=1 to include the composite score. No DID yet? Use the generic mark:
[![Powered by AURA](https://agent.auraopenprotocol.org/badge)](https://auraopenprotocol.org)

Further reading

Build docs developers (and LLMs) love