> For the complete documentation index, see [llms.txt](https://docs.gage.cash/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.gage.cash/ai-agents/sdk.md).

# TypeScript SDK

Install gage-sdk, connect to Robinhood Chain mainnet, read gage, prepare transactions and carry actions out with your own signer.

`gage-sdk` is the engine of gage's hosted MCP server, for your own app, bot or agent: the same reads, the same prepares and the same tools, and four actions more. Given a signer your own code holds, it also carries an action out; gage never sees or holds the key. MIT licensed, with its source on [GitHub](https://github.com/DebenLabs/gage-sdk). It needs Node.js 22 or later, or any bundler: viem 2 is a peer dependency, so your app and the SDK share one copy.

```sh
npm install gage-sdk@0.6.0 viem
```

## Connect to mainnet

```ts
import { createGage } from "gage-sdk";

const gage = createGage(); // Robinhood Chain, 4663
```

The SDK serves Robinhood Chain mainnet by default: the mainnet manifest bundled with the package, the chain's public RPC and gage.cash's own services; `rpcUrl`, `indexerUrl`, `ratesUrl` and `valuationUrl` point it elsewhere. Every amount there is real money.

## Read

| Method                                                                     | Answers                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| -------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `capabilities()`                                                           | Network, chain, contracts, allowed terms, origination fee, pause, the actions, the rules and the stock tokens gage also lends (`lendAssets`).                                                                                                                                                                                                                                                                                              |
| `assets()`                                                                 | The tokens gage takes as collateral now: each one's minimum, `maxPerLoan` (`null` for no per-loan cap, as on the core new loans use; the minimum still applies), whether leverage buys it, and its `link`, `https://gage.cash/borrow/<link>` or `null`.                                                                                                                                                                                    |
| `borrowQuote({ token, maxCollateral, term, wallet?, lendAsset? })`         | The largest loan the partner vaults fund now, with a `prepare` object.                                                                                                                                                                                                                                                                                                                                                                     |
| `borrowQuote({ token, collateral, principal, term, wallet?, lendAsset? })` | One exact loan, priced as gage.cash prices a chosen amount: its repayment, cost and fee, whether the vaults fund it now (`fundsNow`) or it would wait (`waitsFor`), the largest they take at that cost, and a `prepare` object.                                                                                                                                                                                                            |
| `leverageQuote({ token, own, multiple, term, wallet? })`                   | A loop's amounts, cost and the most its purchase costs.                                                                                                                                                                                                                                                                                                                                                                                    |
| `loan({ loanId, engine? })`                                                | One loan's state, amounts and deadlines; `actions`, what its holder can do now (rolling over and cashing out among them where the deployment offers them); `closedBy`, `"roll"`, `"cash_out"` or `null`; and `autoRoll`, its instruction to roll over by itself (`borrower`, `executor`, `term`, `window`, `rollsLeft`, `withRewards`, `until`, `maxCost`, `maxTopUp`), or `null`. A loan a roll or a cash-out repaid offers no `collect`. |
| `portfolio(wallet)`                                                        | The wallet's loans, each with `sgageClaimable` (raw sGAGE earned and not yet claimed; a loan on an earlier engine may pay it in parts) and `autoRoll` (`true` while an instruction to roll it by itself stands), its partner vault holdings with each vault's `link`, its USDG credit and each lend asset's apart (`credits`).                                                                                                             |
| `earnVaults()`                                                             | The partner vaults: asset, tokens, performance fee, size, free cash, share value and `link`, `https://gage.cash/v/<link>` (`null` when the vault has none).                                                                                                                                                                                                                                                                                |
| `balances(wallet)`                                                         | ETH for gas, USDG, the lend assets and the collateral tokens the wallet holds.                                                                                                                                                                                                                                                                                                                                                             |
| `waitForFill({ loanId, engine? })`                                         | Waits for a listing to be funded, every 10 seconds for 5 minutes by default: `funded`, `waiting`, `expired`, `cancelled` or `closed`.                                                                                                                                                                                                                                                                                                      |

```ts
const { assets } = await gage.assets();
const nvda = assets.find((a) => a.symbol === "NVDA");
if (!nvda) throw new Error("gage does not take NVDA as collateral now");

// The largest loan the partner vaults fund now for at most 5 NVDA (18 decimals), for 7 days.
const quote = await gage.borrowQuote({ token: nvda.token, maxCollateral: "5000000000000000000", term: 604800 });
console.log(quote.summary, quote.prepare);

// Or one exact loan: 500 USDG on 5 NVDA.
const exact = await gage.borrowQuote({ token: nvda.token, collateral: "5000000000000000000", principal: "500000000", term: 604800 });
```

A pledge under the token's minimum is refused with that minimum (`COLLATERAL_BELOW_MINIMUM`, the least amount also in `details.minimum`), and an exact amount the pledge cannot support with the most it can (`PRINCIPAL_TOO_HIGH`, `details.maxPrincipal`).

## Prepare

`prepare({ action, wallet, … })` returns the next unsigned transaction, simulated now, the steps after it and a summary. It signs nothing, and carries no review link: the hosted service adds those. Prepare again after each transaction is mined; [Prepare a transaction](/ai-agents/transactions.md) has the whole flow.

```ts
// wallet: the address that will sign.
const step = await gage.prepare({ ...quote.prepare, wallet });
// { status: "approval_required", next: { label: "Approve NVDA", final: false, transaction: { … } }, then: ["Borrow"], … }
```

The actions are `borrow`, `leverage`, `cancel`, `reclaim` (repay), `cash_out`, `roll`, `auto_roll`, `cancel_auto_roll`, `earn_deposit`, `earn_redeem` and `collect`, and on mainnet `feedback`. None funds a loan: lending is a deposit into a partner vault. Rolling over needs a core with a rollover router (and gage's keeper, to roll by itself), cashing out one with a cash-out router: on mainnet, the Intent core and each lend asset's core.

* `cash_out` sells a running loan's whole collateral through an aggregator, repays the loan from the sale and pays the rest to the wallet, less gage's 0.5% fee, in one transaction. The sale is quoted again when it is sent, and refused if it would pay less than planned (`PRICE_MOVED`), less than the `minNet` you name (`BELOW_MIN_NET`), or more than 1% less than gage's own route for the collateral (`SALE_BELOW_ROUTE`). The net never falls more than `maxSlippageBps` below the quote. A loan on an earlier engine cashes out on gage.cash (`CASHOUT_CLOSED`).
* `roll` rolls a running loan into a new loan of the same size on the same pledge, in one transaction: the wallet adds the old loan's fixed cost and the new loan's fee, or keeps what is over. Its price is signed for 30 seconds when it is prepared; rolled before its last day, the loan is repaid early and the new term starts then.
* `auto_roll` leaves a listing or a running loan to roll over by itself: gage's keeper rolls it in its last hours into a loan of the same size and term, at most `maxCost` each (its fixed cost and fee, never more than the loan's principal; when omitted, twice today's roll quote, held to four times the loan's own cost, or on a listing not yet funded twice the loan's own cost), up to four times. It is the one action that leaves standing approvals: gage's rollover router may move the wallet's loans on that core and spend the repayments of four rolls, until you withdraw them in your wallet. `cancel_auto_roll` ends it.
* A deposit into, or withdrawal from, a partner vault with a loan past its end not yet booked settles that loan first: `next` is **Settle the vault's loans** and the answer carries `again: true`. Once it is mined, prepare again; `run()` does so itself.
* `collect` gathers what the current cores and partner vaults hold for the wallet ("Collect what is ready"). It calls only partner vaults the chain bears out as gage's, plans at most twenty claims at a time (a note says when more are ready) and no claim of sGAGE under a millionth. Each claim is simulated first, and one that would revert now is left out with a note: collect again later. Claims on gage's earlier surfaces (the original vault, the earlier engines' lender recoveries, the retired Earn strategies, the GAGE/sGAGE pool's rewards and the drip) are collected on gage.cash.
* `feedback` rates gage, agent #8845 in ERC-8004: `{ action: "feedback", wallet, score }`, the wallet's own score from 0 to 100, once a wallet. It is optional, and gage offers nothing for a rating (see [Rate gage](/ai-agents/mcp.md#rate-gage)).

## Carry it out with your own signer

```ts
import { createGage, privateKeySigner } from "gage-sdk";

const gage = createGage();
const signer = privateKeySigner(process.env.WALLET_KEY!); // your own key, held in memory

const { vaults } = await gage.earnVaults();
const vault = vaults.find((v) => v.lends);
if (!vault) throw new Error("No partner vault lends now");
const result = await gage.run({ action: "earn_deposit", vault: vault.vault, amount: "10000000" }, signer); // 10 USDG
// { status: "done", sent: [{ label: "Approve USDG", hash, outcome: "succeeded" }, { label: "Deposit", hash, outcome: "succeeded" }], … }
```

`run(action, signer)` acts for the signer's own wallet only. It plans once, then builds, simulates, sends and waits for each step in order: exact-amount approvals first, the one-time action once. A refusal found before any step throws an `ApiError`. Once planned, it answers with `status` (`done`, `nothing_to_do` or `stopped`), each transaction sent with its outcome (`succeeded`, `reverted` or `pending`), the steps never sent, if it stopped, the reason in fixed words, and `loan`: the loan a borrow, a loop or a roll opened. A deposit lends through the partner vault's loans: you may end up holding the collateral instead of USDG.

A borrow lists the loan, and gage's keeper funds it from the partner vaults on its next pass. Wait for that, then collect the USDG:

```ts
const listed = await gage.run({ ...exact.prepare, action: "borrow" }, signer);
const funded = await gage.waitForFill({ loanId: listed.loan!.loanId });
if (funded.status === "funded") await gage.run({ action: "collect" }, signer);
```

* `privateKeySigner(key)` holds a raw key in memory and sends through the chain's public RPC, or `rpcUrl`.
* `viemSigner(walletClient)` wraps a viem wallet client that carries an account, for that client's chain. The SDK exports `robinhoodMainnet` to build one.
* Any object with `address` and `sendTransaction(tx)` fits, such as an ethers wallet in a few lines.

A signer refuses another chain's transaction (`CHAIN_MISMATCH`).

## Tools for agent frameworks

`gageTools(gage)` returns gage's tools: seven reads and one prepare per action, eleven, and on mainnet a twelfth, the rating. The hosted MCP server serves the prepares its review page shows, seven and the rating; rolling, rolling by itself, ending that and cashing out answer `ACTION_NOT_SERVED` there (`createGage({ actions })` serves fewer actions the same way). Each has a name, a title, a description, a zod `inputSchema`, MCP hints and `execute(input)`, which answers in plain JSON with amounts as decimal strings. MCP servers, the Vercel AI SDK, and OpenAI's and Anthropic's agent SDKs take that shape. With the Vercel AI SDK:

```ts
import { tool } from "ai";
import { createGage, gageTools } from "gage-sdk";

const gage = createGage();
const tools = Object.fromEntries(
  gageTools(gage).map((t) => [t.name, tool({ description: t.description, inputSchema: t.inputSchema, execute: t.execute })]),
);
```

With a signer, `gageTools(gage, { signer, limit })` adds the tools that sign for that wallet. `limit`, a spend limit, is shown each action's plan before anything is sent and may refuse it (`gage-mcp` builds its spend limits on it). Whether an agent signs under one is the wallet owner's choice: without it, the tools sign whatever the agent asks within the wallet's balance.

## Errors

Refusals are `ApiError`s: a fixed `code`, fixed words in `message`, an HTTP `status`, `retryable` and, for some, `details`: figures to act on, computed by the SDK, such as `details.minimum`. No RPC or upstream text reaches your code through them.

```ts
import { ApiError } from "gage-sdk";

try {
  await gage.prepare({ action: "borrow", wallet, token, collateral, principal, cap, term: 604800 });
} catch (error) {
  if (!(error instanceof ApiError)) throw error;
  console.error(error.code, error.message, error.retryable);
}
```

| Code                                  | Means                                                                                                                                                                 |
| ------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `TERM_NOT_ALLOWED`                    | The term is not one that `capabilities()` lists.                                                                                                                      |
| `INSUFFICIENT_BALANCE`                | The wallet holds less than the action needs.                                                                                                                          |
| `SIMULATION_FAILED`                   | The transaction would revert now: check balances, allowances and the loan's state.                                                                                    |
| `ALREADY_RATED`                       | The wallet has rated gage already: one rating a wallet.                                                                                                               |
| `OWN_ENTRY`                           | The wallet owns or operates gage's ERC-8004 entry, whose rating the registry refuses.                                                                                 |
| `INVALID_INPUT`                       | A field does not match its schema; the message names it.                                                                                                              |
| `PRICE_ABOVE_LIMIT`                   | The loop costs more now than `maxCostBps`.                                                                                                                            |
| `NETWORK_MISMATCH`                    | The manifest passed in is not the named network's.                                                                                                                    |
| `COLLATERAL_BELOW_MINIMUM`            | The pledge is under the token's minimum, in `details.minimum`.                                                                                                        |
| `PRINCIPAL_TOO_HIGH`                  | The pledge supports less than the amount asked; the most is in `details.maxPrincipal`.                                                                                |
| `PRICE_MOVED`                         | A price moved against the plan before it was sent; prepare again.                                                                                                     |
| `SEND_UNKNOWN`                        | `run` only: the signer failed after the wallet sent a transaction, which may be this step's. Look up the wallet's latest transaction before sending the action again. |
| `ACTION_NOT_SERVED`                   | This Gage, or the hosted service, does not serve the action.                                                                                                          |
| `NOT_ROLLABLE`, `ROLLOVER_PAUSED`     | The loan cannot roll over in its state (by hand, only a running loan rolls), or rolling over is paused now.                                                           |
| `ROLL_COST_HIGH`, `MAX_COST_TOO_HIGH` | A roll costs more now than four times the loan's own cost (name `maxCost` to accept it), or `maxCost` is more than the loan's principal.                              |

The package's README on npm lists every code.

Do not retry a prepare, or send a transaction from an earlier answer, after the state has changed: prepare again. Amounts are raw integers as decimal strings; use `BigInt` for arithmetic. The SDK does not enforce a budget or judge a loan: see [Data and limits](/ai-agents/data-and-limits.md).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.gage.cash/ai-agents/sdk.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
