Skip to content

Action Types Reference ​

Warp Protocol v3 supports 12 action types, each designed for specific use cases. This guide provides detailed specifications for each action.

Overview ​

TypePurposeCreates Transaction
transferSend tokens/assets✅ Yes
contractExecute smart contract✅ Yes
queryRead contract state❌ No
collectHTTP data collection❌ No
computeLocal-only transform execution❌ No
stateRead/write key-value store❌ No
mountActivate a warp trigger in a room❌ No
unmountDeactivate a warp trigger in a room❌ No
loopRe-execute the warp continuously❌ No
linkNavigate to URL❌ No
mcpExecute MCP tools❌ No
promptAI text generation❌ No

Transfer ​

The transfer action type sends native tokens, ERC20/SPL tokens, or NFTs to an address.

Structure ​

json
{
  "type": "transfer",
  "label": "Send Funds",
  "address": "0xRecipientAddress...",
  "value": "1000000000000000000"
}

Properties ​

PropertyTypeRequiredDescription
typestring✅Must be "transfer"
labelWarpText✅Button text
addressstring❌Recipient address (can use input)
valuestring❌Native token amount in smallest unit (wei/lamports)
transfersstring[]❌Token transfers (format: token|nonce|amount)
datastring❌Additional transaction data
inputsWarpActionInput[]❌User inputs

Chain-Specific Notes ​

  • EVM Chains (Ethereum, Base, etc.):
    • value is in wei (18 decimals).
    • ERC20 tokens usually require a contract action (calling transfer), unless the chain supports native token transfers in the protocol layer.
  • MultiversX:
    • value is in wei (18 decimals for EGLD).
    • Use transfers array for ESDT/NFTs: ["TOKEN-ID|nonce|amount"]. Nonce is 0 for fungible tokens.
  • Solana:
    • value is in lamports (9 decimals).
  • Sui:
    • value is in MIST (9 decimals).

Contract ​

The contract action type executes smart contract functions on the blockchain.

Structure ​

json
{
  "type": "contract",
  "label": "Execute",
  "address": "0xContractAddress...",
  "func": "functionName",
  "gasLimit": 100000
}

Properties ​

PropertyTypeRequiredDescription
typestring✅Must be "contract"
labelWarpText✅Button text
gasLimitnumber✅Gas limit for transaction
addressstring❌Contract address
funcstring❌Function name to call
argsstring[]❌Fixed typed arguments (e.g. ["uint256:100"])
valuestring❌Native token amount to send with call
transfersstring[]❌Token transfers with call (MultiversX)
abistring❌Function ABI signature (EVM) or URL
inputsWarpActionInput[]❌User inputs mapped to arguments

Argument Types ​

Arguments in args and input type must use the typed format type:value.

Basic Types:

TypeExampleDescription
stringstring:helloText string
uint256uint256:1000Unsigned integer (8-256 bits)
boolbool:trueBoolean
addressaddress:0x...Blockchain address
byteshex:1234abHex encoded bytes
tokentoken:USDC-123Token Identifier

Advanced Types:

TypeSyntaxExampleDescription
Optionoption:type:valoption:u64:123Nullable value. Use option:type for null.
Listlist:type:val,vallist:u8:1,2,3Array of values.
Variadicvariadic:type:valvariadic:u64:1,2Variable arguments (last arg).
Composite`composite(t1t2):v1v2`

Query ​

The query action type reads data from smart contracts without creating a transaction.

Structure ​

json
{
  "type": "query",
  "label": "Check Balance",
  "address": "0xContractAddress...",
  "func": "balanceOf"
}

Properties ​

PropertyTypeRequiredDescription
typestring✅Must be "query"
labelWarpText✅Button text
addressstring❌Contract address
funcstring❌View function name
argsstring[]❌Fixed typed arguments
abistring❌Function ABI signature
autoboolean❌Auto-execute on load

Output Mapping ​

Query results are captured in the root output object.

json
{
  "output": {
    "BALANCE": "out.1"
  }
}

Collect ​

The collect action type sends HTTP requests to external endpoints.

Structure ​

json
{
  "type": "collect",
  "label": "Submit Form",
  "destination": {
    "url": "https://api.example.com/submit",
    "method": "POST"
  }
}

Properties ​

PropertyTypeRequiredDescription
typestring✅Must be "collect"
labelWarpText✅Button text
destinationobject❌HTTP config (url, method, headers)
inputsWarpActionInput[]❌User inputs (sent as body or query params)

Destination Config ​

json
{
  "destination": {
    "url": "https://api.example.com/endpoint",
    "method": "POST",
    "headers": {
      "Authorization": "Bearer {{API_KEY}}",
      "Content-Type": "application/json"
    }
  }
}

Compute ​

The compute action type executes local-only JavaScript transforms. It never makes HTTP requests or blockchain calls — all logic runs client-side. Always returns success, making it ideal for hidden input derivation, conditional value computation, and pure data transformation steps inside a warp chain.

Structure ​

json
{
  "type": "compute",
  "label": "Calculate",
  "inputs": [
    {
      "name": "result",
      "as": "result",
      "type": "uint64",
      "source": "hidden",
      "modifier": "transform:() => Math.floor(Math.random() * 100) + 1"
    }
  ]
}

Properties ​

PropertyTypeRequiredDescription
typestring✅Must be "compute"
labelWarpText✅Button/step label
inputsWarpActionInput[]❌Hidden inputs with transform: modifiers to derive values
descriptionWarpText❌Additional context
primaryboolean❌Marks this as the primary action
autoboolean❌Auto-execute on load
nextstring❌Warp ID or URL to navigate to after success
whenstring❌Conditional expression — skips this action if false

Key Differences from collect ​

computecollect
ExecutionAlways localSends HTTP request if destination is set
Result statusAlways successunhandled if no destination
Use casePure transforms, derivationsSubmitting data to an endpoint

Example: Random Number Generation ​

json
{
  "type": "compute",
  "label": "Generate secret",
  "inputs": [
    {
      "name": "secret",
      "as": "secret",
      "type": "uint64",
      "source": "hidden",
      "modifier": "transform:() => Math.floor(Math.random() * 100) + 1"
    }
  ]
}

After execution, {{secret}} is available in all subsequent actions.


State ​

The state action type reads from or writes to a persistent key-value store scoped to the current room and agent. Backed by the existing store infrastructure — no external services required.

Structure ​

json
{ "type": "state", "op": "write", "store": "game", "data": { "secret": "{{secret}}", "active": true } }
{ "type": "state", "op": "read",  "store": "game", "keys": ["secret", "active"] }
{ "type": "state", "op": "clear", "store": "game" }

Properties ​

PropertyTypeRequiredDescription
typestring✅Must be "state"
opstring✅Operation: "read", "write", or "clear"
storestring✅Store namespace (e.g. "game", "quiz")
keysstring[]❌Keys to read (required for op: "read")
dataobject❌Key-value pairs to write (required for op: "write")
whenstring❌Conditional expression

Reading State ​

After a read, all keys merge into the injectable context as state.KEY — available as {{state.KEY}} in all subsequent actions within the same execution.

json
{
  "type": "state",
  "op": "read",
  "store": "guessing-game",
  "keys": ["secret", "active"]
}

Use the values in later actions:

json
{
  "modifier": "transform:() => parseInt('{{JOAI_MESSAGE_TEXT}}') === {{state.secret}}"
}

Writing State ​

json
{
  "type": "state",
  "op": "write",
  "store": "guessing-game",
  "data": { "secret": "{{secret}}", "active": true }
}

Clearing State ​

json
{
  "type": "state",
  "op": "clear",
  "store": "guessing-game"
}

Mount / Unmount ​

The mount and unmount action types manage warp triggers in a specific room. When a warp is mounted, its trigger pattern is tested against every incoming message in that room — if it matches, the warp executes automatically (suppressing the LLM for that turn).

Mount ​

Activates a warp's trigger in the current room:

json
{
  "type": "mount",
  "warp": "check-guess"
}

Unmount ​

Deactivates a previously mounted trigger:

json
{
  "type": "unmount",
  "warp": "check-guess"
}

Properties ​

PropertyTypeRequiredDescription
typestring✅"mount" or "unmount"
warpstring✅The warp identifier to mount/unmount
whenstring❌Conditional expression

Trigger Declaration ​

The mounted warp must declare a trigger at the root level:

json
{
  "protocol": "warp:3.0.0",
  "name": "check-guess",
  "trigger": { "type": "message", "pattern": "^\\d+$" },
  "actions": [...]
}
FieldTypeDescription
typestring"message" — pattern-matched against incoming message text
patternstringRegular expression (anchored as needed)

How It Works ​

  1. mount stores (room_id → warp_identifier) in the room-scoped cache
  2. On every incoming message, the system checks mounted warps for the room
  3. If trigger.pattern matches the message text → execute the warp, skip the LLM
  4. unmount removes the entry from the cache

Triggers only fire in rooms where mount was explicitly called — no background noise in other rooms.

See Mini-Apps for a complete example using state, mount, unmount, and compute together.


Loop ​

The loop action type re-executes the entire warp after each iteration. It is a cortex-native action — no transaction is created. Use it for continuous polling, recurring sends, or any pattern that needs to keep running until a condition changes.

Structure ​

json
{
  "type": "loop",
  "label": "Keep sending",
  "delay": 0,
  "maxIterations": 10000
}

Properties ​

PropertyTypeRequiredDescription
typestring✅Must be "loop"
labelWarpText✅Step label
whenstring❌Condition evaluated before each iteration. Loop stops when falsy. Omit to run indefinitely.
delaynumber❌Milliseconds to wait between iterations. Default: 0 (runs as fast as possible).
maxIterationsnumber❌Hard cap on total iterations as a safety stop. Default: 10000.

How It Works ​

Each time the loop action is reached, it schedules a full re-execution of the same warp — including re-reading all state, re-evaluating all when conditions, and re-running all SDK actions. This means every iteration picks up the latest state.

The when condition is evaluated against the current output bag (including values from state reads and previous action outputs). When it evaluates to false, the loop stops cleanly and resets its counter — so it can restart if conditions change later.

Example: Conditional Continuous Transfer ​

Send tokens on every iteration while a state flag is active. Stop when it flips to inactive.

json
{
  "protocol": "warp:3.0.0",
  "name": "continuous-send",
  "chain": "multiversx",
  "actions": [
    {
      "type": "state",
      "label": "Load active flag",
      "op": "read",
      "store": "control",
      "keys": ["active"]
    },
    {
      "type": "transfer",
      "label": "Send EGLD",
      "address": "erd1target...",
      "value": "native:0.001",
      "when": "{{state.active}} == 1"
    },
    {
      "type": "loop",
      "label": "Repeat",
      "maxIterations": 10000
    }
  ]
}

Another warp (e.g. triggered by a webhook) writes active = 0 to the same store to stop the loop on the next iteration.

Notes ​

  • loop is a cortex-native action — the SDK skips it automatically (auto: false). It only executes inside the JoAi agent runtime.
  • With delay: 0, iterations run back-to-back as fast as the event loop allows.
  • The iteration counter is scoped to warpIdentifier + roomId. It resets when when evaluates to false, allowing the loop to restart later.

The link action type navigates to an external URL or another Warp.

Structure ​

json
{
  "type": "link",
  "label": "Learn More",
  "url": "https://example.com"
}

Properties ​

PropertyTypeRequiredDescription
typestring✅Must be "link"
labelWarpText✅Button text
urlstring✅Target URL

URL Patterns ​

  • Global Variables: {{CHAIN_EXPLORER}}, {{USER_WALLET}}
  • Warp Links: https://usewarp.to/alias

MCP ​

The mcp action type executes tools on Model Context Protocol servers.

Structure ​

json
{
  "type": "mcp",
  "label": "Run Tool",
  "destination": {
    "url": "http://localhost:3000/sse",
    "tool": "my_tool"
  }
}

See MCP Actions for full details.


Prompt ​

The prompt action type generates text using AI/LLM models.

Structure ​

json
{
  "type": "prompt",
  "label": "Generate",
  "prompt": "Write a story about {{topic}}."
}

See Prompt Actions for full details.


Inline ​

The inline action type executes another Warp as a sub-action within the current flow. The sub-warp runs its full action chain, and its outputs are available to subsequent actions.

This enables composition — you can chain generic warps together without duplicating logic.

Structure ​

json
{
  "type": "inline",
  "label": "Create Contact",
  "warp": "@joai/contact-create",
  "when": "{{hours}} > 0"
}

Properties ​

PropertyTypeRequiredDescription
warpstring✅Identifier of the warp to execute
outputobject❌Map sub-warp outputs to named variables (see below)
whenstring❌Conditional expression to skip this action
silentboolean❌Suppress WARP_VIEW events for this action

Output Mapping ​

Use the output field to extract values from the sub-warp's execution result and make them available to subsequent actions via placeholders.

json
{
  "type": "inline",
  "warp": "@joai/service-create?name=Hourly%20Rate&price={{hourlyRate}}",
  "when": "hourlyRate !== '0'",
  "output": {
    "newServiceId": "out.id",
    "serviceName": "out.name"
  }
}

The path follows the same resolution rules as the warp-level output field — out.data.id traverses the sub-warp's response.

Append to Array (append:) ​

To add the resolved value to an existing array instead of replacing it, prefix the path with append:.

json
{
  "type": "inline",
  "warp": "@joai/service-create?name=Hourly%20Rate&price={{hourlyRate}}",
  "when": "hourlyRate !== '0'",
  "output": {
    "serviceIds": "append:out.id"
  }
}

When the when condition is false (the action is skipped), no output mapping occurs and the existing variable stays untouched.

Passing Inputs ​

Query parameters in the warp identifier are passed as inputs to the sub-warp. Template variables in query values are resolved from the parent warp's accumulated outputs.


Common Action Properties ​

All actions support these properties:

PropertyTypeDescription
descriptionWarpTextAdditional context displayed to user
primarybooleanHighlights the action as the main call-to-action
autobooleanExecutes automatically when the Warp loads
nextstringWarp ID or URL to navigate to after success
whenstringConditional expression (e.g. > 0)