plugin-tereno
v0.4.0
Published
Pre-signature security layer for ElizaOS agents on Base: buy a bounded verdict (unlimited-approval, drainer, suspicious-contract, swap-limit, balance/gas anomaly) before signing, and verify third-party x402 endpoints before integrating them. Budget-capped
Maintainers
Readme
plugin-tereno
🛡️ A pre-signature security layer for ElizaOS agents on Base
Before your agent signs, it checks. One paid call flags unlimited approvals, suspicious contracts, unexpected balance changes and abnormal gas — and returns a single, standardized verdict your agent can branch on.
bun add plugin-tereno📦 What gets installed
One command is enough:
bun add plugin-terenoYou do not need to install tereno-client separately. Your package manager installs it automatically as a dependency of this plugin.
Your ElizaOS project
└─ plugin-tereno installed locally: ElizaOS actions, budgets, fail-closed policy and dry-run
└─ tereno-client installed automatically: quote, x402 payment and receipt client
└─ Tereno API (https://www.tereno.xyz) hosted: capabilities, artifacts, cache and opportunity aggregationThe Tereno backend, databases, caches, internal routes and secrets are not downloaded into your project. The plugin only calls the hosted API. A Base wallet signs x402 payments locally, and only when you turn off dry-run and the quoted price is within your configured budget.
Which package should I use? Install plugin-tereno for an ElizaOS agent. Install tereno-client directly only if you are building for another runtime and want the lower-level x402 client.
⚡ Why this exists
Autonomous agents sign transactions with no instinct for danger. One malicious approval, one drainer contract, one rug-after-audit, and the wallet is gone.
plugin-tereno gives an ElizaOS agent a pre-signature check: before it signs
a Base transaction, it buys a bounded verdict from Tereno
that simulates the call and flags the ways it could lose funds. Failed calls are
never charged — x402 settles only after a successful response.
- No API key, no signup. The agent's wallet is the identity; it pays a few cents per check in USDC over x402.
- Budget-capped. Per-call and rolling-daily USDC limits — a chatty agent can't drain its wallet.
- Fail-closed by default. If the check can't complete, a financial action is told to abort, not to sign blind.
🚦 The core check
TERENO_CHECK_TRANSACTION
{"from":"0x…","to":"0x…","data":"0x…","value":"0"}
│
▼
decision · riskLevel · reason · exposure · cost · recommendedActionEvery guard action returns the same standardized verdict:
interface TerenoVerdict {
decision: "allow" | "review" | "block";
riskLevel: "none" | "low" | "medium" | "high";
reason: string; // human-readable summary + reason codes
exposure: { // what the tx would change
balanceDeltas?: unknown;
allowanceChanges?: unknown;
unlimitedApproval: boolean;
};
cost: { paidUsd: number; capUsd: number; dailySpentUsd: number };
recommendedAction: "sign" | "review" | "abort";
receiptUrl: string | null;
raw: unknown; // full Tereno payload, unchanged
}Your agent branches on one field: recommendedAction.
🔍 What it checks
| Action | Price | The question it answers |
|---|---:|---|
| 🚦 TERENO_CHECK_TRANSACTION | $0.05 | Is this safe to sign? Simulation, gas, balance/allowance deltas, drainer & unlimited-approval flags |
| 🔁 TERENO_CHECK_SWAP | $0.05 | Will this prepared Aerodrome swap still satisfy its own encoded limit? |
| 🛡️ TERENO_CHECK_CONTRACT | $0.01–0.03 | Is this contract safe to interact with? (code, proxy, pause) |
| 🕵️ TERENO_CONTRACT_CHANGED | $0.01–0.02 | Did it change since last look? (rug-pull-after-audit detector) |
| 🪙 TERENO_TOKEN_INFO | $0.01–0.03 | What token is this, really? (name, symbol, decimals, supply) |
| 🧬 TERENO_CONTRACT_INTERFACE | $0.01–0.02 | ERC-20? NFT? Proxy? One bounded probe |
| ⛽ TERENO_CHAIN_SNAPSHOT | $0.002–0.005 | Latest Base block + gas, zero parameters |
| 📄 TERENO_COMPILE_WEB_PAGE | $0.02–0.03 | Public URL → bounded Markdown, resolved links, citations and reusable artifact |
| 🔬 TERENO_CHECK_X402_ENDPOINT | $0.03 | Is another x402 endpoint callable, well-formed and unchanged since last look? |
| ⚖️ TERENO_OBLIGATION_VERDICT | $0.001 | Was a published economic condition satisfied? |
| 🔎 TERENO_VERIFY_EVIDENCE | free | Read a public artifact reference, validity and recomputation input |
| 📈 TERENO_OPPORTUNITIES | free | Aggregate unmet agent asks — research signal, not traction |
| 🤝 TERENO_PLEDGE_DEMAND | free | Explicit intent to buy a named future capability; credit only after same-wallet paid proof |
| 🧾 TERENO_PREVIEW | free | What the checks cover, cost and current config |
| 📖 TERENO_CATALOG | free | Live catalog and prices |
Prices are asserted against the live network by
bun test, not maintained by hand. They live in one table (CAPABILITY_PRICE_USDinsrc/index.ts); if the network changes a price and this table does not, CI fails. Before 0.4.0 this table did not exist and the advertised prices drifted 10× behind the network, which put every paid check above the plugin's own per-call cap.
🚀 Quickstart (free, no wallet needed)
Dry-run mode wires the whole flow with no payment, so you can integrate first and spend later:
# .env
TERENO_DRY_RUN=true # no x402 payment; validates + shapes the verdict
TERENO_NETWORK=eip155:8453 # Base mainnetimport { terenoPlugin } from "plugin-tereno";
// add terenoPlugin to your ElizaOS character's plugins, then ask the agent:
// is it safe to sign {"from":"0x…","to":"0x…","data":"0x…"}?
// → returns a TerenoVerdict with recommendedAction, no USDC spent.A complete runnable agent lives in examples/eliza-base-agent.
Going live
TERENO_DRY_RUN=false
TERENO_PRIVATE_KEY=0x… # a dedicated hot wallet with a little USDC on Base
TERENO_MAX_PRICE_USD=0.05 # per-call cap (must cover the dearest check)
TERENO_DAILY_BUDGET_USD=0.5 # rolling daily cap
TERENO_FAIL_MODE=closed # financial checks abort if the guard can't answerNetworks. The hosted Tereno API (
www.tereno.xyz) serves Base mainnet. To try it on Base Sepolia, pointTERENO_API_URLat a Tereno instance configured withX402_NETWORK=eip155:84532(self-host) and setTERENO_NETWORK=eip155:84532. Dry-run works on any network with no wallet.
Then just talk to your agent:
you: is it safe to sign this?
{"from":"0x…","to":"0x…","data":"0x095ea7b3…"}agent: ⛔ BLOCK · risk high · → abort — UNLIMITED_ALLOWANCE: the spender gets max approval. Paid $0.05 · receipt attached.
⚙️ Configuration
| Env | Default | Purpose |
|---|---|---|
| TERENO_PRIVATE_KEY | — | Wallet that pays x402 (USDC on Base). Falls back to EVM_PRIVATE_KEY. |
| TERENO_MAX_PRICE_USD | 0.05 | Per-call USDC cap. Set below the dearest check and those calls are refused before payment, returning guard unavailable; TERENO_PREVIEW warns when that is the case. |
| TERENO_DAILY_BUDGET_USD | 0.5 | Rolling daily USDC budget. |
| TERENO_FAIL_MODE | closed | closed → financial checks abort on failure; open → degrade to review. |
| TERENO_DRY_RUN | false | true → no payment, simulated verdict. |
| TERENO_PRIVATE_ONLY | false | true → refuse paid actions from public Discord/Telegram/Twitter. |
| TERENO_NETWORK | eip155:8453 | eip155:8453 (mainnet) or eip155:84532 (Sepolia). |
| TERENO_API_URL | https://www.tereno.xyz | API origin. |
| TERENO_RPC_URL | https://mainnet.base.org | RPC for local fingerprint work. |
| TERENO_TELEMETRY | on | off → send no anonymous usage telemetry. |
| TERENO_EVIDENCE_INSTALLATION_ID | — | Optional stable random id for this installation. It is hashed only when the agent resolves evidence received from another agent; never use a wallet or secret. |
Fail-open vs fail-closed
closed(default, for financial actions): if the guard errors, times out, or the daily budget is spent,TERENO_CHECK_TRANSACTIONreturnsrecommendedAction: "abort". The agent does not sign what it couldn't verify.open: the same situations degrade torecommendedAction: "review". Even open mode never returns"sign"on a failed check — a human or policy decides.- Non-financial reads (token/chain/interface) always degrade to
review.
🔐 Privacy & telemetry
The plugin never transmits your private key, prompts, secrets or transaction content anywhere. The key is used locally to sign x402 payments and EIP-712 messages only.
Anonymous, opt-out telemetry (TERENO_TELEMETRY=off to disable) sends a strict
allowlist to help improve the network: plugin version, a hashed wallet
(sha256, never the address), network, check type, whether the call completed and
was paid, its USD cost, cache-hit, a repeat flag, and an integration-error flag.
Nothing else. See SECURITY.md.
📄 Research and demand signals
The plugin also gives a research agent a safe way to use the Tereno network without changing the pre-signature default:
- TERENO_COMPILE_WEB_PAGE turns one public URL into bounded Markdown with resolved links, citations and a content-addressed artifact. It is $0.03 for a fresh compile and $0.02 while the same page remains fresh.
- TERENO_VERIFY_EVIDENCE reads the free provenance and recomputation reference of a public artifact. It never exposes private transaction intent, paid output or payer identity. Set
TERENO_EVIDENCE_INSTALLATION_IDto a stable random value if you want this installation to count once per artifact/day in the circulation experiment. - TERENO_OPPORTUNITIES shows aggregate unmet asks. It is explicitly a research signal, not a reward pool or proof of demand.
- TERENO_PLEDGE_DEMAND is available only after an explicit request and a configured wallet. A pledge earns nothing at submission; only a later settlement by that same wallet can release a bounded, non-transferable credit.
TERENO_DRY_RUN=true accepts both safety and research inputs without a wallet, fetch or x402 payment, so an ElizaOS builder can verify action selection before enabling spend.
🌱 How it stays cheap — the cooperative layer (advanced)
Tereno is a shared-cache coordination layer, not just an API. The first agent to pay for a given piece of verified work seeds it for the whole network; every later agent that reuses that answer pays less, and the seeder earns a small, non-transferable credit that discounts its own future checks.
The game theory: safety is a public good with a private cost. By making the first computation earn from every reuse, the network turns "I paid to check this contract" into "I lowered the price of checking it for everyone, and my own checks got cheaper." More agents ⇒ deeper cache ⇒ cheaper, faster verdicts ⇒ more agents.
Advanced actions expose this loop — you never need them to use the security checks above:
| Action | Cost | What it does |
|---|---:|---|
| TERENO_BOUNTIES | free | See the work the network will pay to have seeded next |
| TERENO_SEED | free/$0.02–0.03 | Seed a bounty (publish a signed fingerprint for free, or pay to be first payer) |
| TERENO_STANDING | free | The agent's audited track record and earned credits |
| TERENO_REPORT_OUTCOME | free | Attach a signed outcome to a settled verdict |
The honest fine print: rewards are non-transferable credits, capped per artifact — they fund your agent's safety budget, they are not yield. Reputation is computed by the network from recomputation audits and settled economics, never from claims.
Discovery, scoring, reputation, pricing, the global cache and cooperation logic
live in the closed Tereno backend. This plugin and its SDK
(tereno-client) are the public,
open interface to it.
🤝 Support & community
- 💬 Questions / setup → Tereno Discord
- 🐛 Bugs → issues · ⚠️ never paste private keys or
.env - 🔒 Vulnerabilities → report privately · SECURITY.md
🔗 Links
Live catalog · OpenAPI · tereno-client SDK · Open bounties
tereno.xyz · Verdicts before signatures, for agents on Base.
