skills/sablier-withdraw-open-ended-stream/SKILL.md
This skill should be used when the user asks to "withdraw flow stream", "withdraw from Sablier Flow", "claim flow payment", "claim from Sablier Flow", "drain my flow streams", "withdraw all my Sablier Flow streams", "withdraw from open-ended stream", "claim open-ended stream", or wants an agent to withdraw available tokens from one or more Sablier Flow open-ended payment streams on Ethereum or any EVM-compatible chain on their behalf. Supports batching across multiple streams on a single chain.
npx skillsauth add sablier-labs/sablier-skills sablier-withdraw-open-ended-streamInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Withdraw available tokens from one or more Sablier Flow open-ended payment streams on the user's behalf. The skill discovers the user's streams through the Sablier indexer, lets the user pick any subset (default: all eligible), and executes one batch(bytes[]) transaction per SablierFlow contract on the selected chain.
Sablier Flow exposes two per-stream withdraw entrypoints (flow/src/interfaces/ISablierFlow.sol:497-531):
withdraw(uint256 streamId, address to, uint128 amount) — explicit-amount withdrawal.withdrawMax(uint256 streamId, address to) returns (uint128) — drains the full currently-withdrawable balance.Batching is provided by the inherited Batch.batch(bytes[]) payable (SablierFlow.sol:13,39; @sablier/evm-utils/src/Batch.sol). batch delegatecalls every entry against address(this), so msg.sender and msg.value are reused across all sub-calls. Each sub-call can target a different stream, amount, and to address. The batch is all-or-nothing: any sub-call revert bubbles up and reverts the whole transaction. There is no per-stream skip event analogous to Lockup's InvalidWithdrawalInWithdrawMultiple.
This skill charges no markup. The only fee paid is the on-chain protocol fee (calculateMinFeeWei) set by the comptroller; it may be 0. Because batch delegatecalls and reuses msg.value, the required msg.value is max(calculateMinFeeWei across the batch), not the sum.
This skill is a coordinator for Flow withdrawal and execution routing.
| Argument | Description |
| ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| chain_name | EVM chain where the streams live (e.g. "Ethereum", "Base", "Polygon"). One chain per invocation. |
| wallet_address | The user's wallet. Must be the streams' recipient (NFT owner) or an approved third party — the skill never surfaces sender-only streams, since the non-recipient path is restricted to to == recipient. |
| token_symbol | Token symbol to narrow the search (e.g. "USDC", "SABL"). If omitted, every token the wallet has an active stream in is shown. |
Verify the user wants to withdraw from existing Sablier Flow open-ended streams.
If the user wants to create a Flow stream instead, route to sablier-create-open-ended-stream. If that skill is unavailable, recommend installing it with:
npx skills add sablier-labs/sablier-skills --skill sablier-create-open-ended-stream
If the user describes vesting, cliffs, tranches, or a fixed end date, route to sablier-withdraw-vesting. If that skill is unavailable, recommend installing it with:
npx skills add sablier-labs/sablier-skills --skill sablier-withdraw-vesting
Stop and call out unsupported requests before selecting an execution path.
withdrawMax for every selected stream — each selected stream is withdrawn at its full currently-available balance (withdrawableAmountOf). Partial withdrawals are an opt-in: ask the user to select a single stream and supply an amount, then the runbook routes that one stream through withdraw(uint256,address,uint128) instead of withdrawMax. The bulk path always drains the full available amount per stream.msg.sender must be the stream's recipient (the NFT owner) or an ERC-721-approved third party, or to == recipient. The skill defaults to to = OWNER (the connected wallet) and only surfaces streams where the wallet is the recipient or has approval, so this rule is auto-satisfied. If a non-recipient caller wants to redirect tokens elsewhere, it cannot — Flow only allows a non-recipient caller when to == recipient (SablierFlow.sol:1001).Flow.Status.VOIDED stream is not eligible — the contract reverts on _withdraw. The runbook re-checks statusOf(streamId) != VOIDED for every selected stream right before broadcast because batch is all-or-nothing: a single voided stream taints the whole group. See references/cli.md § Preflight Checks.Use the AskUserQuestion tool to fill any missing inputs. Ask only for what is missing — never re-ask for values the user already provided.
0x-prefixed EVM address — case is not enforced; the runbook lowercases it before querying the indexer. This is the address that will sign the withdraw transactions. Ask for this first — both chain and token can be inferred from the indexer once the wallet is known.chainId values, map them to chain names via the Supported Chains table, and offer them as AskUserQuestion options. If exactly one chain has streams, auto-select it and tell the user. See references/cli.md § Chain discovery.AskUserQuestion options (see references/cli.md § Stream discovery).to). Optional. Default is the recipient itself. Flow lets the recipient (or an approved operator) redirect tokens to any address by passing a different to; non-recipient callers can only pass to == recipient. Only ask if the user explicitly mentions sending withdrawn tokens elsewhere.Do not guess or silently apply defaults for these parameters. Only proceed once all inputs are confirmed.
Hand off to references/cli.md for stream discovery, multi-select, per-contract grouping, preview, confirmation, and per-group broadcast. The discovery step pipes the indexer response through scripts/filter-withdrawable.sh, which batches withdrawableAmountOf across every candidate into a single Multicall3 call — this collapses N RPC round trips into one and avoids presenting the user streams with nothing currently available.
If you encounter any issues or unexpected errors with this skill, please file an issue at sablier-labs/sablier-skills.
data-ai
This skill should be used when the user asks to "cancel a vesting stream", "cancel Sablier vesting", "stop vesting for X", "revoke a Sablier stream", "claw back unvested tokens", "refund unvested tokens", "kill a Sablier Lockup stream", or wants an agent to cancel one or more Sablier Lockup vesting streams as the stream sender on Ethereum or any EVM-compatible chain on their behalf.
data-ai
This skill should be used when the user asks to "cancel a Flow stream", "void a Sablier Flow stream", "stop streaming to X", "refund my Flow deposit", "kill a Sablier Flow payment", "claw back unstreamed funds", "stop a Sablier open-ended stream", or wants an agent to cancel one or more Sablier Flow open-ended payment streams (void + refund where applicable) on Ethereum or any EVM-compatible chain on their behalf.
data-ai
This skill should be used when the user asks to "withdraw vested tokens", "withdraw from Sablier vesting", "withdraw all my Sablier streams", "claim everything", "claim all unlocked tokens", "drain my vesting streams", "claim from Sablier", or wants an agent to withdraw unlocked tokens from one or more Sablier Lockup vesting streams on their behalf. Supports EVM chains (batched withdrawal across multiple streams on a single chain via `withdrawMultiple`) and Solana mainnet-beta (single-stream withdrawals from Lockup Linear v0.1).
data-ai
This skill should be used when the user asks to create "token vesting", "token vesting streams", "onchain vesting", "Ethereum vesting", "EVM vesting", "ERC-20 vesting", "ERC20 vesting", "BEP-20 vesting", or "BEP20 vesting" with Sablier Lockup, wants to create vesting schedules for a token or tokens on Ethereum, EVM-compatible chains, or BNB Chain, needs an agent to run onchain vesting-creation transactions on their behalf.