Skip to main content

Known limitations

Everything here is a deliberate scope decision or an unfinished piece, not a hidden surprise. None of it makes the shipped behavior incorrect; it bounds what you should expect from it.

About the guarantees

The agent can only call execute_pull, and every pull is checked, so its reach is bounded by four things at once:
  • Per pull: at most per_call_cap.
  • Per window: at most velocity_cap — or up to 2× across a window boundary.
  • Lifetime: at most the S&A delegation’s remaining amount, which never resets.
  • Where: only to the policy’s allowlisted token accounts.
And it all stops the moment you pause the policy, or when the delegation expires. The agent cannot change any of these limits itself — only the human can sign update_policy.
No. update_policy and set_paused require the human’s signature, enforced on-chain by a has_one = human constraint in the program. To be precise about the evidence: the integration tests cover the agent side (a signer who isn’t the registered agent can’t pull), but they don’t include a test of a non-human attempting update_policy or pause. That protection is in the program’s source and not yet exercised by a test of its own.
No. Tokens stay in the human’s token account until a pull executes, and the transfer is performed by S&A’s own program. Shugo’s program decides whether to let that CPI happen; it never takes custody. See Zero-Custody Architecture.
No. Pausing stops Shugo from forwarding pulls, but the underlying S&A delegation still exists with its remaining allowance. To remove it entirely, use S&A’s own revoke_delegation, which the Shugo SDK doesn’t currently wrap.
A policy has exactly one agent. Use distinct policy_id values to create several policies for the same (human, mint) — for example one per agent. Their caps are independent; there’s no shared budget across policies today.

Token-2022

Not yet, and the specifics matter. Subscriptions & Allowances itself supports Token-2022 mints, including mints with an active transfer hook — provided the caller appends the hook’s extra accounts to the transfer. Shugo’s execute_pull doesn’t append them yet, so a pull against a hook-enabled mint fails at the S&A boundary. Plain SPL Token mints are the tested path. Token-2022 mints without a configured hook haven’t been tested through Shugo, so they’re not claimed as supported either.
init_policy succeeds — it doesn’t validate the mint yet — and pulls then fail. Nothing is misdirected and no funds are at risk; the failure is just a confusing error at pull time instead of a clear one at creation time. Both gaps already have their extension points in the SDK (resolveExtraAccountsForMint and checkMintSupported), so adding support is a contained change.

Running your own copy

That message is a misleading wrapper around a network failure — in practice, the public devnet RPC choking on the program upload, which sends many chunked transactions in quick succession. A single getHealth ping can succeed while a deploy fails.Switch to a private RPC, and pass its full URL as the cluster:
Setting solana config set --url ... isn’t enough: --provider.cluster devnet is a keyword Anchor maps to its own built-in URL, independent of your Solana CLI config.
Not necessarily. During development, the CLI reported a rate-limit failure for an airdrop whose funds had in fact arrived. Check solana balance <address> --url <rpc> before retrying. If the faucet genuinely keeps refusing, a web faucet is the usual fallback.
The program’s address is baked into the SDK (GUARD_PROGRAM_ID) and into PDA derivation. A redeploy under a different address needs anchor keys sync, a rebuild, and the SDK constant updated to match — otherwise derived policy addresses won’t line up with the deployed program.