Skip to content

feat: add zest-yield-manager (BFF Skills Comp winner by @secret-mars)#246

Open
diegomey wants to merge 1 commit intoaibtcdev:mainfrom
diegomey:bff-comp/zest-yield-manager
Open

feat: add zest-yield-manager (BFF Skills Comp winner by @secret-mars)#246
diegomey wants to merge 1 commit intoaibtcdev:mainfrom
diegomey:bff-comp/zest-yield-manager

Conversation

@diegomey
Copy link

zest-yield-manager

Author: @secret-mars (Secret Mars)
Competition PR: BitflowFinance/bff-skills#11


This skill was submitted to the AIBTC x Bitflow Skills Pay the Bills competition, reviewed by judging agents and the human panel, and approved as a Day 1 winner.

Frontmatter has been converted to the aibtcdev/skills metadata: convention. Command paths updated to match this repo root-level skill layout.

Files

  • zest-yield-manager/SKILL.md — Skill definition with AIBTC-format frontmatter
  • zest-yield-manager/AGENT.md — Agent behavior rules and guardrails
  • zest-yield-manager/zest-yield-manager.ts — TypeScript implementation

Attribution

Original author: @secret-mars. The metadata.author field in SKILL.md preserves their attribution permanently.


Automated by BFF Skills Bot.

Copy link
Contributor

@arc0btc arc0btc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adds autonomous sBTC yield management for Zest Protocol — supply, withdraw, claim rewards, monitor positions. Competition-validated with mainnet proof, and the implementation holds up.

What works well:

  • Pre-flight safety checks (gas, balance, spend limit) are thorough and consistently applied across all write paths
  • Promise.all for parallel fetches in runStatus, runSupply, runWithdraw, runClaim — good pattern
  • Structured SkillOutput contract with explicit blocked vs error vs success states makes agent routing deterministic
  • getStxBalance correctly subtracts locked STX — that would silently break agents running Stacking positions
  • SKILL.md constraints section is honest and specific: pool utilization failure, oracle outages, borrow-helper versioning

[suggestion] Dead try/catch in runSupply (zest-yield-manager.ts:340–354)

The try/catch wraps only output() — which never throws. The actual network calls (getStxBalance, getSbtcBalance) happen in the Promise.all above it, outside the try block. The catch branch (error("supply_failed", ...)) is unreachable dead code. Either remove the try/catch entirely, or wrap the whole function body including the Promise.all:

  output({
    status: "success",
    action: "Execute supply transaction via MCP zest_supply tool",
    data: {
      operation: "supply",
      asset: "sBTC",
      amount_sats: amountSats,
      contract: BORROW_HELPER,
      function: "supply",
      args: {
        asset: SBTC_TOKEN,
        amount: amountSats.toString(),
        note: "Uses borrow-helper-v2-1-7 which handles Pyth oracle fee automatically",
      },
      mcp_command: {
        tool: "zest_supply",
        params: { asset: "sBTC", amount: amountSats.toString() },
      },
      pre_checks_passed: {
        gas_sufficient: true,
        balance_sufficient: true,
        within_spend_limit: true,
        stx_balance: stxBalance,
        sbtc_balance: sbtcBalance,
      },
    },
    error: null,
  });

[suggestion] Unused ZSBTC constant (zest-yield-manager.ts:42)

ZSBTC = "SP2VCQJGH7PHP2DJK7Z0V48AGBHQAW3R3ZW1QF4N.zsbtc-v2-0" is defined but never referenced anywhere in the implementation. If it's for future borrow support, add a comment; otherwise remove it.

[nit] install-packs --pack arg is vestigial

SKILL.md shows install-packs --pack all but the --pack arg is never read in the implementation — it always checks all deps. Either remove the --pack flag from the documented example or implement pack filtering. As-is, the flag is documented but silently ignored.

Code quality notes:

The 5 doctor checks run sequentially. Promise.all would cut the diagnostic time by ~4x — small improvement for a command that hits external APIs. Not blocking, just worth noting for follow-up.

Operational context:

We run Zest V2 (SP2VCQJGH7PHP2DJK7Z0V48AGBHQAW3R3ZW1QF4N.pool-borrow-v2-3) in production for task #6808. Contract addresses here match what we know — pool-borrow-v2-3, borrow-helper-v2-1-7, same deployer. The sBTC token principal also matches our arc-payments skill config.

Worth making explicit for new integrators: this skill generates MCP command parameters for zest_supply/zest_withdraw/zest_claim_rewards — it doesn't broadcast transactions itself. The MCP server must be running with Zest tools loaded. SKILL.md's requires: "wallet, signing, settings" hints at this but calling it out directly in AGENT.md's decision order would save confusion.

Copy link

@biwasxyz biwasxyz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: zest-yield-manager (BFF Competition Winner)

Great submission — the skill has solid design (structured output contract, spend-limit guardrails, on-chain proof of mainnet testing). Congrats to @secret-mars on the Day 1 win!

The main issue is that the competition-to-registry conversion is incomplete. The bff-skills repo has different conventions than aibtcdev/skills, and the automated conversion only partially bridged the gap. Here's what still needs attention:

CI Blocker

zest-yield-manager/AGENT.md is missing YAML frontmatter. The bff-skills repo doesn't require it, but our validator does. Needs:

---
name: zest-yield-manager-agent
skill: zest-yield-manager
description: Autonomous sBTC yield management on Zest Protocol — supply, withdraw, claim rewards, and monitor positions with safety controls.
---

Convention Alignment

These aren't blockers but would bring the skill in line with the rest of the registry:

  1. Commander.js — The competition repo uses a custom parseArgs + switch pattern. Skills in this repo use Commander.js for argument parsing (see CLAUDE.md CLI Script Conventions).

  2. Shared infrastructure — The script hardcodes https://api.hiro.so and rolls its own wallet address resolution via env vars. Existing skills use src/lib/services/hiro-api.ts, src/lib/services/wallet-manager.ts, and src/lib/config/networks.ts for this.

  3. Transaction pattern — The skill outputs MCP command payloads (mcp_command.tool: "zest_supply") for the agent framework to execute, rather than building and broadcasting transactions directly. This is the bff-skills convention and works fine, but it's worth noting it differs from how most skills in this repo handle writes.

What's Valuable Here

The withdraw and claim rewards capabilities don't exist in the current yield-hunter or yield-dashboard skills, so this is a genuine addition to the ecosystem. The doctor pre-flight check pattern and the standardized {status, action, data, error} output envelope are well thought out.

Thanks @diegomey for bringing this over from the competition, and @secret-mars for the original work!

@biwasxyz
Copy link

@whoabuddy — wanted to get your take on how we should handle competition winners coming in from bff-skills. This one has a CI failure (missing AGENT.md frontmatter) and uses the competition's conventions (custom arg parser, no shared infra) instead of ours.

Should we:

  1. Ask the submitter to align with our conventions before merging (Commander.js, shared wallet-manager/hiro-api, AGENT.md frontmatter)?
  2. Merge as-is and clean up in a follow-up PR?
  3. Establish a standard process for competition skill imports going forward?

The skill itself adds real value (Zest withdraw + claim rewards), just needs the conversion finished.

@secret-mars
Copy link
Contributor

Thanks for upstreaming this, @diegomey. The frontmatter conversion to aibtcdev/skills convention looks right. Happy to address any changes needed for the registry format.

For reference, the skill is actively running on mainnet — our agent (SP4DXVEC16FS6QR7RBKGWZYJKTXPC81W49W0ATJE) has a live Zest position using these exact functions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants