Skip to content

Actions and intents

Actions let a sender present choices. An intent carries the recipient’s selected action.

Type ID: coinbase.com/actions:1.0. The payload is JSON-encoded Actions. Its fallback contains the description, a numbered action list, and an instruction to reply with a number. shouldPush defaults to true on Browser, Node, Kotlin, and Swift.

The encoder requires 1 to 10 actions and unique action IDs. Each action has an id, a label, an optional image URL, and an optional style. The style is primary, secondary, or danger. Both the message and each action can have an expiry. The codec preserves expiry values. Your app must check expiry before it accepts a selection.

Actions fieldMeaning
idAction set ID
descriptionText shown before the choices
actions1 to 10 action entries when encoding
expiresAtOptional expiry for the full set
Action fieldMeaning
idUnique action ID
labelDisplay label
imageUrlOptional image URL
styleOptional primary, secondary, or danger style
expiresAtOptional expiry for this action

Type ID: coinbase.com/intent:1.0. The payload is JSON-encoded Intent with an ID, action ID, and optional metadata. The encoder limits serialized metadata to 10 KiB. Its fallback names the selected action. shouldPush defaults to true on Browser, Node, Kotlin, and Swift.

Intent fieldMeaning
idIntent ID
actionIdSelected action ID
metadataOptional JSON metadata; encode limit is 10 KiB

The SDK Intent record exposes the wire metadata object as an optional JSON string named metadataJson. Action expiry fields use SDK timestamps; the codec writes RFC 3339 UTC strings with millisecond precision.

The Agent SDK receives selections with the intent event. The actions fallback numbers the choices so an app without actions rendering can show them.

const agent: Agent<unknown>
agent
.
NodeJS.EventEmitter<EventHandlerMap<unknown>>.on<"intent">(eventName: keyof EventEmitterEventMap | "actions" | "attachment" | "conversation" | "group-update" | "dm" | "group" | "inline-attachment" | "intent" | "leave-request" | "markdown" | "message" | "multi-attachment" | "reaction" | "read-receipt" | "reply" | "start" | "stop" | "text" | "transaction-reference" | "unhandledError" | "unknownMessage" | "wallet-send-calls", listener: (ctx: MessageContext<Intent, unknown>) => void): Agent<unknown>

Adds the listener function to the end of the listeners array for the event named eventName. No checks are made to see if the listener has already been added. Multiple calls passing the same combination of eventName and listener will result in the listener being added, and called, multiple times.

server.on('connection', (stream) => {
console.log('someone connected!');
});

Returns a reference to the EventEmitter, so that calls can be chained.

By default, event listeners are invoked in the order they are added. The emitter.prependListener() method can be used as an alternative to add the event listener to the beginning of the listeners array.

import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.on('foo', () => console.log('a'));
myEE.prependListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
// b
// a

@since ― v0.1.101

@param ― eventName The name of the event.

@param ― listener The callback function

on
("intent", async (
ctx: MessageContext<Intent, unknown>
ctx
) => {
var console: Console
console
.
Console.log(...data: any[]): void

The console.log() static method outputs a message to the console.

MDN Reference

log
(`Selected action: ${
ctx: MessageContext<Intent, unknown>
ctx
.
MessageContext<Intent, unknown>.content: Intent

Replace the middleware value without changing the SDK message.

The decoded value selected by the content type.

content
.
actionId: string
actionId
}`);
});