Arete documentation
Govern steps with your Squads multisig
For the complete documentation index optimized for AI agents, see llms.txt or llms-full.txt. A markdown version of this page is available by appending.mdto the URL or sendingAccept: text/markdown.
For AI agents: the documentation index is at llms.txt (full corpus: llms-full.txt). A markdown source for this page is /building-protocols/squads.md.
Some steps should never run on one person’s say-so: moving a treasury,
withdrawing a raise, changing a fee. Give those steps the squadsProposer
authority and they are proposed to your team’s Squads v4 multisig. Arete’s
proposer only proposes. Your members approve and execute in Squads, as they
would any other transaction.
Set up Squads on the dashboard
Section titled “Set up Squads on the dashboard”Open app.arete.run/dashboard/squads. It works with any standard browser wallet (Phantom, Solflare, Backpack), including a Ledger connected through one of them, so members who sign with hardware wallets can do everything there. The page asks one question:
- You already have a Squads multisig. Enter its address. The page shows
its members and status, and gives two ways to add Arete’s proposer:
- Here: connect a member wallet that can initiate, sign the add-proposer proposal, then approve and execute it (each member signs), here or in the Squads app.
- In the Squads app: open the multisig, go to Members → Add member, paste the proposer, give it the Initiate permission only, then approve and execute the proposal. The page updates when the member appears.
- You don’t have one. Create it on the page: choose a label, the members and the threshold, and connect the wallet that pays. Arete’s proposer is a member from the start, so there is nothing else to add.
Once the multisig is active, the page shows its address and the
arete.toml snippet to put in your protocol’s deployment config. Attach a
multisig once; every protocol you deploy can use it.
How it works
Section titled “How it works”- Your account has one proposer: a public key Arete signs proposals with. Every protocol you deploy uses the same proposer.
- The proposer is a member of your multisig with the Initiate permission only. It can create proposals; it can never vote or execute, and it does not count toward the threshold.
- Your account attaches each multisig it uses. An attachment is
pendinguntil the proposer is an Initiate-only member,activewhile it is, andarchivedif the proposer is removed or its permissions change (andactiveagain once it is added back). The dashboard anda4 squads statusshow the state. - A production deployment of a protocol with Squads steps is refused unless
the multisig in its deployment config is an
activeattachment of your account. A multisig that already has the proposer is attached automatically when you deploy. - The proposer pays the fee and rent of each proposal, so it needs a little SOL. The dashboard shows its balance.
- When a reaction fires
proposeSquads, Arete wraps the step’s instructions in a vault transaction and a proposal on your multisig. Your members approve and execute it. The protocol’s derive rules observe the result.
Point a step at your multisig
Section titled “Point a step at your multisig”Declare the multisig as a resource and read it in the step’s authority:
const vault = 'pda("squads", "vault", resources.treasury.multisig, 0)';
export default defineProtocol({ // ... programs: { system, squads }, resources: { treasury: { schema: { type: "object", properties: { multisig: { type: "string", format: "pubkey" } }, required: ["multisig"], additionalProperties: false, }, description: "The team's Squads v4 multisig.", }, }, steps: { pay: { scope: "instance", title: "Pay the recipient from the team vault", authority: { kind: "squadsProposer", multisig: "resources.treasury.multisig" }, guards: { not_requested: 'instance.state == "requested"' }, transitions: [{ from: ["requested"], to: "proposed" }], build: [ ix(system, "transfer", { args: { lamports: "params.amount" }, accounts: { fundingAccount: vault, recipientAccount: "instance.roles.recipient" }, }), ], }, }, reactions: [{ id: "proposePayout", trigger: { kind: "onTransition", machine: "instance", from: [], to: ["requested"] }, action: { kind: "proposeSquads", step: "pay" }, }],});squads is the Squads v4 program
(a4 install program squads-multisig-program --as squads --ts). Set the
resource’s value for each deployment in arete.toml:
[protocol.resources]treasury = "treasury.json" # { "multisig": "<your multisig address>" }Put the address of a multisig attached on the dashboard there. The page shows the snippet for each active multisig.
The multisig must come from the deployment config: the step’s multisig
reads a resource (resources.<name>) and nothing else. A protocol never
creates a multisig, and a step that reads it from the instance or its
arguments is refused when the protocol is checked. Because the multisig is
fixed for the deployment, Arete checks it when the deployment is created
and when it activates.
The step acts from vault 0 unless it sets vaultIndex. Use different vault
indexes to keep protocols that share a multisig apart. The vault the step’s
instructions use must match, so change the vault expression too:
const vault = 'pda("squads", "vault", resources.treasury.multisig, 1)';
// in the stepauthority: { kind: "squadsProposer", multisig: "resources.treasury.multisig", vaultIndex: 1 },When a deploy is refused
Section titled “When a deploy is refused”If the multisig in the deployment config is not set up, a4 protocol deploy
(deployment create or activation) fails with protocol-squads-setup-required.
The error names the step, the multisig and why (not_member,
permissions_invalid, …), and links to the multisig’s dashboard page,
where the multisig is already waiting as pending:
Step 'finalize' proposes to Squads multisig <M>, which is not set up for your account (not_member). ... Set it up: https://app.arete.run/dashboard/squads/<M>Add the proposer there (or in the Squads app), then deploy again.
From the command line
Section titled “From the command line”a4 squads reads your account’s setup and attaches a multisig by address.
Each command prints the multisig’s dashboard link first and, while it is
pending, the Squads-app steps to add the proposer. It builds no
transactions.
a4 squads status # setup, proposer, attached multisigsa4 squads status <M> # one multisig: members, deployments, proposalsa4 squads lista4 squads attach <M> --label Treasury # attach an existing multisigAgents use the MCP tools squads_status and squads_attach. They point the
user to the dashboard or the Squads app and never sign for a member.
From code (scripts and hot wallets)
Section titled “From code (scripts and hot wallets)”Arete builds no Squads transactions. To create a multisig with the proposer already a member, or to add the proposer to an existing one, from code, install the Squads v4 program SDK and use its Arete setup helpers:
a4 install program squads-v4The member’s own wallet signs, as for any other transaction; Arete never
asks for or holds a member key. Then read the multisig again (a4 squads status <M> or the dashboard) to see it turn active.
One multisig for several protocols
Section titled “One multisig for several protocols”The proposer is per account, so once a multisig is attached and active,
every protocol you deploy can point its resource at that multisig with no
further setup. Proposals from all of them land in the same Squads queue. Give
each protocol its own vaultIndex if their funds should stay apart.
Try it in a dev environment
Section titled “Try it in a dev environment”Dev environments are separate: they have their own proposer, are never
checked against your account’s attachments, and the dashboard does not
apply. The Squads app cannot see a dev environment either, so
a4 dev squads stands in for it with your dev wallets:
a4 protocol squads proposer --dev # the proposer <P>a4 dev squads create --members alice,bob --threshold 1 --proposer <P> # proposer already a member# or add it to an existing dev multisig:a4 dev squads add-proposer --multisig <M> --proposer <P> --wallet alice # prints the index <n>a4 dev squads approve --multisig <M> --index <n> --wallet alicea4 dev squads execute --multisig <M> --index <n> --wallet alicea4 dev fund <P> 1a4 protocol squads status --dev --multisig <M>When a step is proposed, approve it the same way and run it with
a4 dev squads vault-execute --multisig <M> --index <n> --wallet alice.
When a proposal waits
Section titled “When a proposal waits”If a step is proposed while the proposer is not a valid member (for example,
someone removed it after the deployment activated), nothing is signed. The proposal waits and
retries for up to 24 hours, and the instance’s event stream reports
arete.squads.proposerMissing with the multisig, the proposer and the
problem. The attachment turns archived and the dashboard lists the
deployments affected. Add the proposer back (on the dashboard or in the
Squads app) and it goes through on the next retry; after 24 hours it is
dropped.