June 11, 2026 · engineering · ai-risk · architecture · security · arbitrum
How the Watcher Works: An Autonomous Risk Agent With a Deterministic Core
Tokenized stocks trade 24/7, but the company behind the stock doesn't. The underlying market closes; the token keeps moving. A position that looked safe on Friday can gap through its liquidation line over the weekend, and the borrower wakes up liquidated — often paying a penalty on top. The structural answer is not a louder alert. It is an agent that watches every position continuously and, with your permission, acts before the line is crossed.
We call that agent the Watcher. This post explains exactly how it works: what decides to move money (a deterministic core), what never does (the language model), how often it looks (about every 10 seconds), how it can repay your debt without ever holding your funds, and what happens if the agent itself goes down. We will also be clear about what it cannot do.
Status: live on testnet only
Tessera runs on Robinhood Chain (an Arbitrum Orbit L2, chain 46630) and is not open to real funds. The on-chain price feed is a testnet mock today; a real licensed feed is a mainnet gate. The permissionless backstop described below is built but disabled on testnet (delay = 0, agent-only). Everything else here is running code.
The one idea that matters: a deterministic core, a language model on the edge
Most "AI agent" products let a language model decide what to do and then do it. That is fine for drafting an email. It is not acceptable when the action is spending your money. Language models are non-deterministic, they can be steered by crafted inputs, and they cannot be formally reasoned about. We do not want any of that anywhere near a transaction.
So the Watcher is split in two, with a hard wall between the halves:
- The deterministic core decides *whether* to act and *how much* to repay. It is plain, testable arithmetic on numbers read from the chain — no model in the loop, no randomness. Given the same inputs it always reaches the same decision.
- The language model only writes the sentence a human reads. It turns structured facts (a safety score, a risk band) into one calm, plain-English line. It never sees a private key, never chooses an amount, and never triggers a transaction.
Concretely: the function that generates alert copy is the *only* place the model is invoked. The health classification, the repay sizing, and the transaction itself live in separate modules that never call it. The model's prompt forbids inventing any fact, and if the model is slow, errors, or has no API key at all, the agent falls back to a deterministic template that echoes the same numbers. A degraded model can make the prose blander. It can never corrupt a decision or a dollar amount.
Why route the copy through a model at all?
Because clear, reassuring, human language is genuinely better than a template at 3am — but only for the words. We treat the model the way a newsroom treats a copy editor: it can rewrite the sentence, it cannot change the facts. The facts come from the chain and the deterministic core.
Health factor: the one number everything keys off
Before the loop makes sense, you need one term. The health factor (HF) is your risk-weighted collateral value divided by your debt, scaled so that 1.0 is the liquidation line. Above 1.0 you are solvent; the higher, the safer. At or below 1.0 the position can be liquidated. Everything the Watcher does is a reaction to where your HF sits and which direction it is heading.
The core sorts every position into a band purely from its HF — no judgment calls, just thresholds:
| Health factor | Band | What the Watcher does |
|---|---|---|
| 1.5 and above | Safe | Watches. No action. |
| 1.2 to 1.5 | Healthy | Watches. Comfortable buffer. |
| 1.1 to 1.2 | Watch | Monitors closely; may alert. |
| 1.0 to 1.1 | At risk | Alerts; auto-repays if you opted in. |
| Below 1.0 | Liquidating | Position is wound down to protect lenders. |
The same HF also produces a 0–100 Safety Score that we show users instead of jargon — it is a direct rescaling of the health factor, computed with exact fixed-point math so it never drifts from the on-chain truth.
The loop: one coherent snapshot, about every 10 seconds
The Watcher runs a tick loop with a default interval of 10 seconds (pollIntervalMs: 10_000). Each tick is one self-contained pass that never throws — any error is recorded as a structured log entry and the loop continues. A single tick does five things:
- Pin a block. It reads the current block number once and uses it for every read in the tick, so the whole pass reflects a single, coherent snapshot of the chain rather than a smear of different moments.
- Find the borrowers. A lightweight event indexer tracks who currently has debt, persisting its progress so it survives restarts. Repaid positions are dropped from the active set; a re-borrow re-activates instantly.
- Batch-read health. It reads HF and debt for every tracked borrower in a single multicall at the pinned block (one round trip, not two per user), falling back to per-user reads if multicall is unavailable.
- Triage. Zero-debt positions are evicted. Healthy positions are cleared. The at-risk subset is collected and sorted most-endangered-first, so the position closest to the line is handled before the next tick begins.
- Act. For each at-risk position, in order: liquidate if it is already below 1.0; otherwise (if opted in) auto-repay to restore the buffer; then send a plain-English alert.
A blind spot is treated as an incident, not a pass
If an HF read fails — for example, a non-archive RPC rejecting a read at the pinned block — the position is counted as a read failure and escalated to a critical on-call page. We never treat an unreadable position as 'fine'. Being knowingly degraded is acceptable; being silently blind is not. The agent even probes the RPC for archive support at startup and warns loudly if it is missing.
Acting ahead of the gap, not after it
Because the whole point is the overnight and weekend gap, the core widens its protection target when the underlying equity market is closed, on a weekend, or near an earnings date. The thresholds it aims for are pushed higher in those windows, so a position is restored to a bigger buffer and protection kicks in *earlier* than a static rule would allow. This regime adjustment is — like everything else in the core — deterministic; the model has no part in it.
Auto-repay: spending your money without ever holding it
This is the differentiator, and it is also the part that demands the most care, because it moves funds. Here is the model that keeps it safe: the Watcher can reduce *your* debt using *your* pre-approved USDC, and it can do literally nothing else with those funds.
When you opt in, you grant a standard ERC-20 allowance of USDC to the vault. That allowance is the spending ceiling. The agent calls a single permissioned vault entrypoint, agentRepayFor(user, amount), which the contract enforces can only ever *reduce* that user's debt with that user's own approved funds. It cannot withdraw, transfer, or extract value of any kind. The Watcher never custodies anything.
Every auto-repay passes through the same five-step safety pipeline as a liquidation, so all autonomous money movement goes through one audited path:
- Idempotency — at most one action per user per block, so a position can't be repaid twice in the same moment.
- Budget — the agent may pull at most
min(needed, your allowance, your balance). A zero allowance means you haven't opted in (or you revoked), and it does nothing. - Gas cap — if gas price exceeds the configured ceiling, it skips rather than overpay.
- Simulation — it runs the exact
agentRepayForcall as aneth_callfirst and only proceeds if it would succeed, so it never broadcasts a transaction it expects to revert. - Submit and confirm — only then does it broadcast, then waits for the receipt so an on-chain revert is never logged as a successful repay.
The repay amount is computed, not guessed. The core sizes it to lift your health factor back to the protection target — repay = debt × (target − HF) ÷ target — and the reasoning (which regime, which HF, the math) is written into a public action log so every autonomous move is auditable after the fact.
On-chain caps: defending against a compromised key, not just buggy code
The agent's own pipeline is careful, but careful code is not a security boundary — the agent's signing key could be stolen. So the real limits are enforced *on-chain by the vault itself*, where the agent's behavior is irrelevant:
| Cap | Limit | Enforced where |
|---|---|---|
| Per user, per transaction | 10,000 USDC | Vault contract |
| Per user, per day | 25,000 USDC | Vault contract |
| Total ceiling | Your ERC-20 allowance | Vault contract |
The per-user, per-day cap is charged inside agentRepayFor precisely so that a compromised agent *key* — not just compliant agent code — cannot drain a user's full allowance in one burst. The contract caps the spend regardless of what the off-chain agent tries to do.
The kill switch is one transaction
To turn the Watcher off entirely, revoke the USDC allowance. The moment it is zero, auto-repay does nothing — the budget check fails first. There is also a separate on-chain admin fail-safe at the protocol level. You are never locked into the agent's protection.
The heartbeat and the backstop: what if the agent dies?
An autonomous protector raises an obvious question: what protects you when the protector is down? Our answer is a dead-man's switch built into the vault.
The agent stamps an on-chain heartbeat on a slow cadence (default every 3 minutes), even on quiet ticks where it took no action. Liquidations and auto-repays stamp it too, so the heartbeat only matters during genuinely idle periods. The point is to distinguish a *live-but-idle* agent (nothing to do) from a *dead* one (process crashed, key gone, host offline).
On top of that sits a permissionless backstop. When enabled, if the agent's heartbeat goes silent past a configured delay (on testnet the design target is more than 15 minutes), liquidation opens up to anyone — not just the agent — so a frozen agent can never trap an unhealthy position. Crucially, a backstop liquidation runs the *identical* close-factor, bonus, and post-liquidation health-improvement guards as an agent liquidation, so it is provably as safe as the normal path; it just removes the single point of failure.
On testnet the backstop is intentionally off
The backstop delay is currently 0, which keeps liquidation strictly agent-only — the conservative MVP default. The heartbeat is already being stamped today so the machinery is proven and ready; flipping the delay to a positive value is an explicit mainnet gate, taken at the audited mainnet build, not something silently live now.
The honest limits
We would rather lose your trust to clarity than to a surprise, so here is what the Watcher does not and cannot do.
- It cannot guarantee you won't be liquidated. A severe enough gap — the token falling straight through your liquidation line faster than a repay can land, or with no funds left in your allowance — can still liquidate a position. The Watcher reduces the odds and acts early; it does not repeal market risk.
- It never decides with a language model whether to move money. Every financial decision is made by deterministic code. The model only writes the human-readable sentence.
- It never custodies funds. It can only reduce your own debt via an allowance you set and can revoke at any time.
- It depends on a working price feed and RPC. On testnet the price feed is a mock; a licensed feed is a mainnet gate. If the agent goes blind on a read, it escalates rather than guesses.
- It is testnet software. No audit, no real funds, no real users, no returns, no insurance. Those are mainnet gates, named as such — never implied as shipped.
The design philosophy underneath all of this is simple: the more autonomous a system is, the more conservative its boundaries must be. The Watcher is given exactly one power — to reduce your debt with your own pre-approved funds, bounded by caps the contract enforces — and a clean way to be switched off. Everything intelligent happens inside those walls; nothing important depends on a language model behaving.
Tessera is open-source. The agent, the vault, the price-policy contract, and the read-only data layer are all public, so none of the above has to be taken on faith — it can be read.
The safest place to borrow against tokenized stocks.