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

# Skills

> Higher-order workflows that chain multiple atomic tools into a single orchestrated call

Skills are **higher-order workflows** that compose multiple atomic MCP tools into a single orchestrated call. Instead of the agent manually chaining four or five tools (quote → bytecode → quote → bytecode → verify), a skill handles the full flow deterministically and returns all transaction bytecode in execution order, plus warnings and next-step guidance.

The Pods MCP ships with **4 skill tools** and **2 skill prompts** — collectively "the skills layer". Skill tools execute code; skill prompts guide the agent through analytical workflows.

<Info>
  Every workflow skill also has a dedicated markdown documentation resource accessible at runtime via `ReadMcpResource` — the URIs are listed at the bottom of this page.
</Info>

***

## When to use a skill vs atomic tools

| If you want to...                           | Use                                                | Why                                                                             |
| ------------------------------------------- | -------------------------------------------------- | ------------------------------------------------------------------------------- |
| Swap then deposit in one step               | `swap_and_deposit`                                 | Deterministic chain; partial-success preserves swap bytecode on deposit failure |
| Find the best-APY strategy for an asset     | `find_best_yield_for_asset`                        | Auto-resolves via `get_yield_by_identifier`; returns alternatives               |
| Move capital between strategies             | `rebalance_position`                               | Orchestrates withdraw + deposit; auto-resolves destination by APY               |
| Verify an integration works end-to-end      | `diagnose_integration`                             | Pre-flight check of API key, health, and endpoint reachability in one call      |
| Generate a conversational portfolio summary | `portfolio_briefing` *(prompt)*                    | LLM synthesizes across positions, history, and yield alternatives               |
| Audit existing code for common bugs         | `integration_review` *(prompt)*                    | Checklist-driven review with file:line findings                                 |
| Preview cost/APY before committing bytecode | any workflow skill with `dryRun: true`             | Returns quotes + analysis without generating transaction data                   |
| Chain custom logic between steps            | **Don't use a skill** — call atomic tools directly | Skills are opinionated; custom logic needs atomic composition                   |

***

## Shared features

All three workflow skills (`swap_and_deposit`, `find_best_yield_for_asset`, `rebalance_position`) support three capabilities that fundamentally change how agents and integrators interact with them.

### `dryRun: true` — preview mode

When set, the skill **skips bytecode generation entirely** and returns only quotes + resolved strategy + estimated output. Useful for:

* Cost/APY estimation before committing the user to sign transactions
* UX flows that show "you will receive \~X tokens" before the confirm button
* Analyzing rebalance viability without consuming a quote window

```json title="Example: swap_and_deposit with dryRun" theme={null}
{
  "fromChain": "ethereum",
  "toChain": "base",
  "fromToken": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
  "toToken":   "0x4200000000000000000000000000000000000006",
  "amountIn":  "100000000",
  "wallet":    "0xAbCd...1234",
  "depositIdentifier": "eth",
  "dryRun": true
}
```

Response has `dryRun: true` at the top level and omits `swap.bytecode` / `deposit.bytecode`.

### Partial-success returns

If a later step fails **after** earlier bytecode was already produced, the skill returns a partial-success payload with the usable work preserved. The result carries `isError: false` deliberately — the MCP host should treat the partial payload as normal structured data and let the caller decide how to proceed.

```json title="Partial-success shape" theme={null}
{
  "status":   "partial",
  "partial":  { "swap": { "quoteId": "...", "bytecode": {...} } },
  "failedAt": "deposit_chain",
  "failure":  { "httpStatus": 404, "code": "STRATEGY_NOT_FOUND", "resolution": [...] }
}
```

Preservation boundaries per skill:

| Skill                       | Preserved on failure                   | `failedAt` label      |
| --------------------------- | -------------------------------------- | --------------------- |
| `swap_and_deposit`          | Swap quote + swap bytecode             | `deposit_chain`       |
| `find_best_yield_for_asset` | Best strategy + alternatives + quote   | `bytecode_generation` |
| `rebalance_position`        | Withdraw bytecode + APY delta + amount | `deposit_chain`       |

Recovery pattern: sign and broadcast the preserved bytecode (e.g. the swap), then call the atomic tool for the failed step separately once the underlying issue is resolved.

### Skill-level error codes

Orchestration-layer validation failures raise `SkillValidationError` with dedicated codes — distinct from API errors. These flow through the same `McpErrorResult` shape, so `get_error_explanation` returns resolution steps for them just like for `QUOTE_EXPIRED` or `INSUFFICIENT_LIQUIDITY`.

| Code                        | Meaning                                                                         | Typical fix                                                                     |
| --------------------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
| `MISSING_DEPOSIT_TARGET`    | `swap_and_deposit` received neither `depositStrategyId` nor `depositIdentifier` | Pass one of the two                                                             |
| `ZERO_SWAP_OUTPUT`          | Swap quote returned `tokenOut.amount === "0"` (no liquidity / bad route)        | Smaller `amountIn`, different pair, or verify token addresses                   |
| `NO_STRATEGY_FOR_ASSET`     | `get_yield_by_identifier` didn't resolve for the given asset                    | Try a different symbol or browse `list_strategies`                              |
| `SOURCE_POSITION_NOT_FOUND` | `rebalance_position` with `fromStrategyId` the wallet doesn't hold              | Call `get_wallet_positions` first to see actual positions                       |
| `ZERO_POSITION_BALANCE`     | Could not determine a non-zero source balance, no `amount` given                | Pass explicit `amount` in smallest unit                                         |
| `SAME_STRATEGY_REBALANCE`   | Auto-resolver returned the same strategy as the source                          | Pass explicit `toStrategyId`, or accept the current strategy is already optimal |

***

## Workflow skills

<AccordionGroup>
  <Accordion title="swap_and_deposit — swap then earn yield in one call">
    Swaps token A into token B on the destination chain and deposits the proceeds into a yield strategy. Chains `get_swap_quote` → `execute_swap_bytecode` → `get_strategy_quote` → `get_deposit_bytecode` internally.

    **When to use:**

    * User wants to earn yield on a token they don't currently hold
    * You have both a swap target and a deposit target in one user intent
    * You need both transaction batches returned in guaranteed execution order

    **Inputs:**

    | Field               | Type    | Required | Description                                          |
    | ------------------- | ------- | -------- | ---------------------------------------------------- |
    | `fromChain`         | string  | yes      | Source chain name (e.g. `ethereum`, `base`)          |
    | `toChain`           | string  | yes      | Destination chain where the strategy lives           |
    | `fromToken`         | string  | yes      | Source token contract address                        |
    | `toToken`           | string  | yes      | Destination token — gets deposited into the strategy |
    | `amountIn`          | string  | yes      | Amount in smallest unit of `fromToken`               |
    | `wallet`            | string  | yes      | Signs both txs and receives the swap output          |
    | `depositStrategyId` | string  | one of   | Exact strategy ID                                    |
    | `depositIdentifier` | string  | one of   | Asset symbol/category (`"usdc"`, `"eth"`)            |
    | `dryRun`            | boolean | no       | Preview without generating bytecode. Default `false` |

    **Example response** (truncated):

    ```json theme={null}
    {
      "swap": {
        "quoteId": "qx_...",
        "provider": "teleswap",
        "tokenIn":  { "symbol": "USDC", "amount": "100000000" },
        "tokenOut": { "symbol": "ETH",  "amount": "28500000000000000" },
        "deadline": 1700000000,
        "bytecode": { "id": "...", "transactionData": [ {"to": "...", "data": "0x...", "value": "0", "chainId": "8453"} ] }
      },
      "deposit": {
        "strategyId": "aave-eth-base",
        "resolvedVia": "identifier",
        "quote": { "estimatedOutput": "28450000000000000", "priceImpact": 0.1 },
        "bytecode": { "id": "...", "bytecode": [{"to": "...", "data": "0x...", "value": "0", "chainId": 8453}] }
      },
      "executionOrder": [
        { "step": "swap",    "transactionCount": 1 },
        { "step": "deposit", "transactionCount": 1 }
      ],
      "warnings":  [...],
      "nextSteps": [...]
    }
    ```

    <Warning>
      **Execution order is mandatory** — sign and broadcast all swap transactions and wait for confirmation BEFORE submitting the deposit transactions. The deposit spends the swap output; if you send deposit first it will revert on-chain.
    </Warning>

    <Info>
      The deposit is sized from the swap quote's expected output (`tokenOut.amount`). If real swap output is lower due to slippage, the deposit may revert — warn the user about this before they sign.
    </Info>
  </Accordion>

  <Accordion title="find_best_yield_for_asset — highest APY + alternatives in one call">
    Given an asset (symbol, name, or category), returns the highest-APY strategy with a deposit quote, ready-to-sign bytecode, and the top 3 alternatives.

    **When to use:**

    * User doesn't know a specific `strategyId` and wants "the best yield" for USDC / ETH / etc.
    * You want to present alternatives so the user can compare before committing
    * You need a deposit bytecode produced automatically for the winner

    **Inputs:**

    | Field     | Type    | Required | Description                                       |
    | --------- | ------- | -------- | ------------------------------------------------- |
    | `asset`   | string  | yes      | Symbol, name, or category (`"usdc"`, `"eth"`)     |
    | `wallet`  | string  | yes      | Wallet that will deposit                          |
    | `amount`  | string  | yes      | Amount in smallest unit                           |
    | `network` | string  | no       | Filter for alternatives search (e.g. `"polygon"`) |
    | `dryRun`  | boolean | no       | Skip bytecode generation. Default `false`         |

    **Example response** (truncated):

    ```json theme={null}
    {
      "best": {
        "strategyId": "aave-usdc-polygon",
        "protocol": "aave",
        "network": "polygon",
        "apy": 6.21,
        "assetName": "usdc"
      },
      "alternatives": [
        { "id": "compound-usdc-polygon", "protocol": "compound", "apy": 5.52 },
        { "id": "morpho-usdc-polygon",   "protocol": "morpho",   "apy": 4.81 }
      ],
      "quote": { "estimatedOutput": "999850000", "priceImpact": 0.015 },
      "bytecode": { "id": "...", "bytecode": [...] },
      "warnings":  [...],
      "nextSteps": [...]
    }
    ```

    <Info>
      Alternatives are filtered to the same `assetName` as the best match and exclude paused strategies. Passing a `network` only narrows alternatives — the best match from `get_yield_by_identifier` may be on a different chain.
    </Info>
  </Accordion>

  <Accordion title="rebalance_position — move capital between strategies">
    Moves capital from one yield strategy to another (typically for better APY), returning withdraw + deposit bytecode in execution order.

    **When to use:**

    * User has an existing yield position and a better alternative exists
    * You want the skill to auto-resolve the destination to the best-APY strategy for the same asset
    * You want the full position balance used when `amount` is omitted

    **Inputs:**

    | Field            | Type    | Required | Description                                          |
    | ---------------- | ------- | -------- | ---------------------------------------------------- |
    | `wallet`         | string  | yes      | Owns the source and destination positions            |
    | `fromStrategyId` | string  | yes      | Current strategy to exit                             |
    | `toStrategyId`   | string  | no       | If omitted, auto-resolved to best-APY for same asset |
    | `amount`         | string  | no       | Defaults to full current position balance            |
    | `dryRun`         | boolean | no       | Skip bytecode generation. Default `false`            |

    **Example response** (truncated):

    ```json theme={null}
    {
      "from":     { "strategyId": "aave-usdc-polygon", "apy": 4.0 },
      "to":       { "strategyId": "morpho-usdc-polygon", "apy": 7.5, "resolvedVia": "auto-best-apy" },
      "apyDelta": 3.5,
      "amount":   "250000000000",
      "withdraw": { "bytecode": { "id": "...", "bytecode": [...] } },
      "deposit":  { "quote": {...}, "bytecode": {...} },
      "executionOrder": [
        { "step": "withdraw", "transactionCount": 1 },
        { "step": "deposit",  "transactionCount": 2 }
      ],
      "warnings":  [...],
      "nextSteps": [...]
    }
    ```

    <Warning>
      **Execution order is mandatory** — broadcast all withdraw transactions and wait for confirmation before the deposit. The deposit spends withdrawn funds.
    </Warning>

    <Info>
      If the auto-resolver returns a destination with worse APY than the source, a high-priority warning is prepended — the skill still produces bytecode so the caller can confirm intent.
    </Info>
  </Accordion>
</AccordionGroup>

***

## Diagnostic skill

<AccordionGroup>
  <Accordion title="diagnose_integration — pre-flight integration health check">
    Runs API key validation, API health, and reachability probes on strategies and tokens endpoints in a single call. Optionally probes `get_wallet_positions` if a `wallet` is passed.

    **When to use:**

    * Before shipping an integration to production
    * When something stopped working downstream and you want a one-shot diagnosis
    * Onboarding a new developer — faster than running `validate_api_key` + `get_health` + a test call separately

    **Inputs:**

    | Field    | Type   | Required | Description                                     |
    | -------- | ------ | -------- | ----------------------------------------------- |
    | `wallet` | string | no       | If provided, also probes `get_wallet_positions` |

    **Example response** (truncated):

    ```json theme={null}
    {
      "overall": "pass",
      "summary": { "total": 5, "passed": 4, "failed": 0, "skipped": 1 },
      "checks": [
        { "name": "api_key",              "status": "pass", "durationMs": 42.1 },
        { "name": "api_health",           "status": "pass", "durationMs": 28.9 },
        { "name": "strategies_reachable", "status": "pass", "durationMs": 55.3, "details": { "totalDocs": 42 } },
        { "name": "tokens_reachable",     "status": "pass", "durationMs": 61.2 },
        { "name": "wallet_positions",     "status": "skipped" }
      ],
      "nextSteps": [...]
    }
    ```

    <Info>
      The skill itself never returns `isError: true` — individual checks fail independently and the overall report captures them. A failed `api_key` check cascades: every subsequent check will fail until the key is fixed, so always resolve the first failing check first.
    </Info>
  </Accordion>
</AccordionGroup>

***

## Skill prompts

Prompts guide the agent through analytical workflows where the value is in natural-language synthesis, not deterministic bytecode. Invoke them by name from your AI host.

<AccordionGroup>
  <Accordion title="portfolio_briefing — conversational portfolio summary">
    Guides the agent to produce a briefing of a wallet's yield portfolio: positions, recent activity, underperformers, and recommended rebalances.

    **Inputs:** `wallet` (required), `includeHistoryDays` *(optional, default "7")*

    **What the prompt instructs the agent to do:**

    1. Call `get_wallet_positions` to snapshot current positions and total USD
    2. For each position, record strategyId, protocol, network, assetName, APY, balance
    3. Call `get_wallet_history` for top 2 positions (by USD value) with the configured window
    4. Call `get_yield_by_identifier` for each position's asset and compare APY (\~0.5pp threshold for "underperforming")
    5. Produce a summary: total value, top performers, recent activity, underperformers, recommended actions pointing to `rebalance_position` or `find_best_yield_for_asset`
  </Accordion>

  <Accordion title="integration_review — audit your code against Pods best practices">
    Audits the workspace's Pods integration code against a checklist of common pitfalls. Produces a file:line-level report with concrete fixes.

    **Inputs:** `workspacePath` *(optional)*, `feature` *(optional: `swap`, `yield`, `webhook`, `all`)*

    **Checklist highlights:**

    * **Common:** API key from env (not hardcoded), try/catch around API calls, fetch timeout, retry on `QUOTE_EXPIRED`/`SLIPPAGE_EXCEEDED`
    * **Swap:** quote TTL awareness, `rawQuote` forwarding to `execute_swap_bytecode`, response field is `transactionData` (not `transactions`), EIP-1193 value hex encoding, status polling uses `quoteId` (not bytecode id), cross-chain lifecycle assumptions
    * **Yield:** `action="lend"` (not `"deposit"`), `wallet` param (not `fromAddress`/`owner`), amount as string in smallest unit, swap→deposit ordering
    * **Webhook:** signature verification, idempotency via `quoteId`, fast 2xx ack, explicit event-type handling

    <Info>
      The prompt does NOT auto-edit — it only produces a report. You can then request specific fixes interactively.
    </Info>
  </Accordion>
</AccordionGroup>

***

## Runtime documentation resources

Every skill has a markdown documentation resource accessible at runtime via `ReadMcpResource`. Agents can load these on demand when they need fuller context than the tool description provides.

| URI                                  | Content                                    |
| ------------------------------------ | ------------------------------------------ |
| `pods://skills/swap-and-deposit`     | Full guide for `swap_and_deposit`          |
| `pods://skills/find-best-yield`      | Full guide for `find_best_yield_for_asset` |
| `pods://skills/rebalance-position`   | Full guide for `rebalance_position`        |
| `pods://skills/diagnose-integration` | Full guide for `diagnose_integration`      |
| `pods://skills/portfolio-briefing`   | Full guide for `portfolio_briefing` prompt |
| `pods://skills/integration-review`   | Full guide for `integration_review` prompt |

***

## Next Steps

<CardGroup cols={2}>
  <Card title="MCP Server Overview" icon="plug" href="/ai-tools/mcp-server">
    What the server does, capabilities, and minimal tool set
  </Card>

  <Card title="Setup Guide" icon="gear" href="/ai-tools/mcp-setup">
    Install and configure in Claude Desktop, Cursor, Windsurf
  </Card>

  <Card title="Tools Reference" icon="list" href="/ai-tools/mcp-tools-reference">
    Full accordion reference for all 25 tools and 9 prompts
  </Card>

  <Card title="Error Codes" icon="triangle-exclamation" href="/error-codes">
    Complete error reference including skill-level codes
  </Card>
</CardGroup>
