# AGENTS.md — Spiral Stake

Spiral Stake is a **context + execution layer** for leveraged yield across Ethereum mainnet (chainId 1) and Robinhood Chain (chainId 4663). This
file orients agents (coding assistants and autonomous agents) integrating with Spiral.

as-of 2026-08-20T09:34:01.325Z — live snapshot. Live data (source of truth): https://api.spiralstake.xyz/v1/strategies

## What a Spiral strategy is

A one-transaction **leveraged loop** on [Morpho](https://morpho.org). You supply a yield-bearing
collateral, borrow against it, and recycle the borrow back into more collateral — repeated to a
chosen leverage. Two shapes:

- **Correlated (max-APY loop):** collateral and loan track the same value (e.g. sUSDS/AUSD,
  PT-sUSDE/RLUSD). Leverage multiplies the underlying yield rather than adding price exposure.
- **Non-correlated (leveraged long):** e.g. wstETH/USDC, XAUt/USDT. Leverage increases directional
  exposure to the collateral; the loop's carry is a cost.

**We surface facts; the agent decides.** Every cost, leverage step, and risk fact is raw and
unit-labeled. The only Spiral opinion is namespaced under `spiralHints`, and it always ships the
thresholds behind it so you can recompute or override.

## The `/strategies` contract

- Endpoint (source of truth): `https://api.spiralstake.xyz/v1/strategies`
- Envelope: `{ asOf, chainId, count, strategies[] }`. `asOf` is snapshot assembly time.
- Per-strategy raw facts include: `collateral`/`loan` (address, symbol, decimals, category),
  `collateralApyPct`, `borrowApyPct`/`netBorrowApyPct`, `maxLeverage`, a discrete
  `leverageLadder` (`leverage` → `ltvPct` → `leverageApyPct`, 1x…max), `defaultLeverage`,
  `ltvPct` (liquidation/max), `oracle` (`type`: `nav` | `market`), and `exitLiquidity`
  (measured `slippagePct` by USD size).
- **Conventions:** percentages are strings suffixed `Pct` (2-dp). USD amounts are numbers suffixed
  `Usd`. Timestamps are ISO-8601 UTC.
- **null vs absent (critical):** `null` = measured, no value (e.g. no swap route at that size).
  A field being **absent** = unmeasured — treat as unknown, **never** as a safe 0.
- **Freshness:** each field group in `freshness` carries its own `asOf` + `staleAfterSec`. A stale
  group is served last-good (never dropped, never 0) with its age visible.
- **`spiralHints`:** optional, namespaced, overridable opinion — never interleaved with raw facts,
  always ships its thresholds.

## Reading the risk facts

Mechanics, not advice — what the fields mean so you can weigh them yourself.

- **Carry = `collateralApyPct` − `netBorrowApyPct`.** This is the per-unit edge leverage
  multiplies. Positive carry: more leverage raises APY. Negative carry: more leverage *lowers* it —
  but the 1x base yield can keep `leverageApyPct` positive, so **negative carry does not by itself
  mean a negative levered APY**. Read the `leverageLadder`; don't infer it.

- **`oracle.type` decides what can liquidate the position.**
  - `nav` — priced off the redemption/exchange rate. A DEX depeg does not move it, so a correlated
    loop is not liquidated by a transient market dislocation.
  - `market` — priced off the traded price. A depeg or thin-book dislocation moves the oracle and
    **can liquidate the position even when the collateral still redeems 1:1 at maturity.** Weigh it
    against `ltvPct.liquidation` headroom, especially on fixed-term (PT) collateral.

- **`exitLiquidity.slippagePct` is measured, per USD notional.** `null` at a size = **no route at
  that size**. A **negative** value = price improvement (you receive more than you put in), not an
  error. `noSwapRoute: true` means the position cannot currently be unwound via a swap at all —
  the headline APY is unreachable in practice.

- **`maxLeverage` is bounded by available borrow liquidity, not by safety.** Higher rungs of the
  ladder sit closer to `ltvPct.liquidation`; the ladder tells you the APY, not the headroom.

- **Sign convention on `leverageApyPct` — check `correlated` first.** For **correlated**
  strategies it is the levered yield: `collateralApyPct × leverage − netBorrowApyPct × (leverage − 1)`.
  For **non-correlated** (leveraged long) strategies the sign is **flipped**: a *positive*
  `leverageApyPct` is the annualised **carry cost you pay**, not yield earned. Your return there
  comes from the collateral's price movement, which Spiral does not forecast.

- **`collateralApySource` qualifies `collateralApyPct`.** `none` means no yield source resolved
  for that collateral — the accompanying `0.00` is *"not resolved"*, not a measured 0%. Treat those
  strategies (and any `leverageApyPct` derived from them) as **unknown**, not as zero-yield.

## Chain & protocol

- Networks: Ethereum mainnet (chainId 1) and Robinhood Chain (chainId 4663). One host serves every chain — select one with `?chainId` on the
  endpoint (default is the primary chain); each strategy also carries its own `chainId`.
- Lending protocol: Morpho (isolated markets; `id` is the Morpho market id).

## Connect via MCP

Native tool access over the Model Context Protocol (Streamable HTTP): **`https://api.spiralstake.xyz/mcp`**. Any
spec-compliant MCP client (Claude, Cursor, …) can add this URL. Tools:
- `list_strategies({ category? })` — eligible strategies with full raw facts.
- `get_strategy({ id })` — one strategy by Morpho market id.
- `get_prices()` — token USD prices.

No MCP client? The same data is plain JSON at `https://api.spiralstake.xyz/v1/strategies`.

## Links

- App: https://app.spiralstake.xyz
- MCP endpoint: `https://api.spiralstake.xyz/mcp`
- Strategy map (agents): https://app.spiralstake.xyz/llms.txt · full facts: /llms-full.txt
- Per-strategy page: `https://app.spiralstake.xyz/{chainId}/strategies/{id}/{collateral}-{loan}`
- Live JSON: `https://api.spiralstake.xyz/v1/strategies`

_This file is generated from the same `/strategies` snapshot as /llms.txt and the prerendered
pages. The static numbers are a discovery breadcrumb; poll the live JSON for current values._
