> ## Documentation Index
> Fetch the complete documentation index at: https://yieldxyz.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Guardrails

> Follow the non-custodial rules an agent must respect before it signs or broadcasts a transaction.

An agent acting on the Yield API, whether through the [MCP server](/documentation/ai-agents/mcp-server), a generated integration, or a direct API call, only ever constructs unsigned transactions. These are the rules that keep that boundary intact and stop an agent from guessing at arguments it should have looked up.

## Non-custodial execution

`actions_enter`, `actions_exit`, and `actions_manage` build unsigned transactions; they never sign or broadcast. No tool on the MCP server accepts a private key, seed phrase, or wallet credential; signing happens entirely in your own wallet or signer, outside the API.

<Warning>
  Get explicit confirmation from the person controlling the wallet before signing any transaction an agent has built, and before submitting a `manage` action such as `CLAIM_REWARDS` or `UNLOCK`. Every one of these moves funds or changes a position on-chain.
</Warning>

## Validate before you build

Don't hardcode a yield's arguments from memory or from another yield; schemas differ per protocol and per chain.

1. Call `yields_get` before `actions_enter` or `actions_exit`. Read `mechanics.arguments.enter` / `.exit`: each field lists its `name`, `type`, whether it's `required`, static `options` or a dynamic `optionsRef` (fetch it; e.g. call `yields_get_validators` for a validator field), and any `minimum`/`maximum`. Also read `mechanics.entryLimits` and `requiresValidatorSelection` before entering.
2. Call `yields_get_balances` before `actions_manage`. The `action` type and `passthrough` value must come from that response's `pendingActions[]`; never construct or guess a `passthrough`.
3. Call `yields_get_kyc_status` before `actions_enter` on a yield whose `mechanics.requirements.kycRequired` is `true`. If the status isn't approved, route the wallet to the returned `authorizeUrl` instead of attempting the deposit.

## Amounts, types, and arguments

Tool calls fail validation if these don't match exactly:

| Field | Rule |
| - | - |
| `amount` | Human-readable decimal string, e.g. `"1.5"`; never wei, never a number |
| `limit` / `offset` | Numbers, e.g. `20`; never strings |
| `network` | Lowercase string, e.g. `"base"`; `networks` is an array of them |
| `token` | Uppercase symbol, e.g. `"USDC"`; `inputTokens` / `yieldIds` / `providers` are arrays |
| `types` | An array of exact enum values (`staking`, `lending`, `vault`, `real_world_asset`, …); never a bare `type` string |

## Transaction order and confirmation

Every action returns transactions in `stepIndex` order. Sign and broadcast them in that order; never in parallel, never reordered.

<Warning>
  For the `synchronous` execution pattern, wait for on-chain confirmation of each transaction before signing the next. Skip a transaction that's already terminal (`SKIPPED`, `CONFIRMED`, or `FAILED`) rather than re-signing or re-submitting it; calling `submit_hash` on an already-terminal transaction returns HTTP 412.
</Warning>

Call `submit_hash` exactly once per transaction, with the `transactionId` and the on-chain hash from your own broadcast; this is what lets `get_transaction` and `actions_get` track it through to `CONFIRMED`, `FAILED`, or `SKIPPED`. When an HTTP status doesn't match what you expected, check it against the live spec with `yield_troubleshoot_error` or `yield_get_api_spec` before assuming it's a bug.

## Keys and spend

Authenticate with your own API key via the `x-api-key` header (or `?api_key=` on the MCP `POST` endpoint) rather than relying on the shared default; a key you supply is billed to your account and bypasses free-tier metering, so track it like any other credential and never hardcode it in generated code.

The four wallet tools (`yields_get_balances`, `actions_enter`, `actions_exit`, `actions_manage`) are metered per wallet address and can require an [x402](https://github.com/coinbase/x402) micropayment once the free tier is used. An agent that retries automatically should back off on failure rather than resubmitting the same call in a loop; each accepted call is billed once. See [MCP server](/documentation/ai-agents/mcp-server) for limits and pricing.

## Next steps

<Columns cols={2}>
  <Card title="Actions" icon="arrow-right-to-bracket" href="/documentation/earn/core-concepts/actions">
    How enter, exit, and manage actions work.
  </Card>

  <Card title="MCP tool reference" icon="wrench" href="/documentation/ai-agents/mcp-server#tool-reference">
    Every tool's exact inputs and the transaction format.
  </Card>

  <Card title="Rate limits" icon="gauge" href="/documentation/plans-limits/rate-limits">
    API-level rate limits by plan tier.
  </Card>

  <Card title="Yield API reference" icon="book" href="/api-reference/getting-started">
    The REST API behind every tool.
  </Card>
</Columns>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.