Skip to content

Arete documentation

Reactions, metadata, and live data

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 .md to the URL or sending Accept: 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/automation.md.

A protocol can progress when time passes or observed state changes, even when an application is not making a request. Reactions connect those changes to specific supported actions.

Reaction triggers are at, when, onTransition, and onConfirmed. Actions are emit, runKeeperStep, and proposeSquads.

The tip jar emits a named event when its state becomes closed:

reactions: [{
id: "announceClosed",
trigger: {
kind: "onTransition",
machine: "instance",
from: [],
to: ["closed"],
},
action: { kind: "emit", event: "tipJar.closed" },
}],
events: { "tipJar.closed": "instance" },

A keeper step must satisfy the supported permissionless constraints. An admin step proposed to Squads still needs the team’s multisig process: Arete’s proposer does not vote or execute on behalf of members. Configure and test those capabilities before relying on unattended execution.

An emit names an event, not a destination. Applications can follow instance events or receive subscribed named emissions through signed webhooks. Custom business logic and end-user notifications run in your own application.

Events and backend integration →

Reactions can only run steps that need no particular user: keeper steps, or admin steps proposed to a multisig. A participant step, such as a deposit from the user’s wallet or a claim, waits for the user to sign it.

To run those steps for users while they are away, emit an event for the moment they should run and handle it with @usearete/automations in your backend. Users opt in by signing a consent with limits, and your backend signs within them through a wallet provider. Design these steps so they can only move funds between the user’s own positions: then a wrong trigger can at worst move a user’s funds between places they own.

Automate steps for users →

Metadata adds application information such as a title or milestone evidence. Declare schemas and writers for instance or participant metadata. Metadata is not an on-chain balance or proof of settlement.

Clients use client.metadata.instance(id) or client.metadata.participant({ instance, wallet }). Updates are JSON merge patches: null removes a field. Participant-writer updates require a wallet proof; the client can produce the message to sign with proofMessage. Only fields declared filterable support metadata filters when listing instances.

A resource is a schema-checked document the protocol declares, such as shared launch defaults. Publish a value when deploying using --resource <name>=<file> or [protocol.resources] in arete.toml. Deployments select resource versions, keeping those inputs explicit alongside the release.

A resource is configuration, not a secret store. Handler code has no general secret-access capability.

The generated protocol stack exposes instances, participants, and configured activity. Inspect it with a4 stream --dev, or follow one instance:

Terminal window
a4 stream --dev --instance <instance-id>

Declare activity mappings against real instructions and account relationships. Where supported by those mappings, direct program activity can be attributed to registered instance accounts. A signature or memo alone should not make unrelated activity part of an instance.

Add custom stacks for richer data, such as aggregates or joined accounts. a4 dev up watches and deploys your project’s stacks into the same environment. Use canonical protocol reads and prepare results for workflow decisions, and live views for your interface’s data presentation.