Skip to main content
Sender binds to the current runtime context. For a message trigger, it represents the current IM, account, chat, and user. For a route trigger, it represents the current HTTP request. A cron / fake context does not point to a real IM chat.
const { Sender, getSenderID } = require('./middleware.js')
const sender = new Sender(getSenderID())

Read message context

These methods take no parameters and return fields from the current runtime context. When a field does not exist, they usually return an empty string, empty array, or false.
MethodPurposeParametersReturns
getImtype()Get the current IM type. Cron runs return fake.NonePromise<string>
getUserID()Get the current user ID.NonePromise<string>
getUserName()Get the current user display name.NonePromise<string>
getUserAvatarUrl()Get the current user avatar URL.NonePromise<string>
getChatID()Get the current chat ID. For groups this is the group ID; for private chats it is usually empty.NonePromise<string>
getChatName()Get the current chat name.NonePromise<string>
getGroupName()Get the group name. Same as getChatName().NonePromise<string>
isAdmin()Check whether the current user is an administrator.NonePromise<boolean>
isAI()Check whether the current message came from an AI trigger context.NonePromise<boolean>
getAIParam()Get the AI parameter.NonePromise<string>
getMessage()Get the current message text.NonePromise<string>
getMessageID()Get the current message ID.NonePromise<string>
getHistoryMessageIDs(number)Get recent message IDs.number: required, expected count.Promise<string[]>
param(index)Read a rule regex capture.index: required, starts at 1; out-of-range returns an empty string.Promise<string>
const user = await sender.getUserName()
const message = await sender.getMessage()
const firstMatch = await sender.param(1)
await sender.reply(`${user} sent: ${message}\nParameter: ${firstMatch}`)

Reply with text and media

reply* methods reply to the current runtime context: for a message trigger, they reply to the current chat; for a route trigger, reply(...) / replyMarkdown(...) writes the route response; the fake context for cron does not send a real IM reply.
MethodPurposeParametersReturns
reply(text)Reply with plain text.text: required text content.Promise<SendReceipt>
replyMarkdown(markdown)Reply with Markdown text. Whether Markdown is rendered depends on adapter support.markdown: required Markdown content.Promise<SendReceipt>
replyImage(source, options?)Reply with an image.source: required image URL, path, base64, or data URI; options: optional media options.Promise<SendReceipt>
replyVoice(source, options?)Reply with voice/audio.source: required voice URL or path; options: optional.Promise<SendReceipt>
replyVideo(source, options?)Reply with a video.source: required video URL or path; options: optional.Promise<SendReceipt>
replyFile(source, options?)Reply with a file.source: required file URL or path; options: optional.Promise<SendReceipt>
replyMixed(items, options?)Reply with a structured mixed message.items: required mixed items; options: optional and used as default options for media items.Promise<SendReceipt>
returnValue(text)Set the runtime return value without directly sending an IM message.text: required return text.Promise<string>, currently usually returns "[]" for compatibility.
await sender.reply('Plain text')
await sender.replyMarkdown('## Result\n\n- Done')
await sender.replyImage('https://example.com/a.png')
await sender.replyVoice('./voice.wav')
await sender.replyVideo('./demo.mp4')
await sender.replyFile('./report.csv', { filename: 'report.csv', mimeType: 'text/csv' })
await sender.replyMixed([
  { type: 'text', text: 'Result: ' },
  { type: 'image', source: './result.png', name: 'result.png' },
])
Current-chat reply methods such as replyImage(...) do not require you to pass imType, group ID, or user ID. To specify a target, use push(...) or push*.

MediaOptions

The second parameter of media reply methods is an optional object.
options.filename
string
File display name. You can also write fileName or file_name. The runtime normalizes it to media item name.
options.mimeType
string
MIME type. You can also write mime_type, such as image/png, video/mp4, or text/csv.
options.constraints
object
Constraints passed to the media preparation flow. Use only when you need to limit output format or size.
options.options
object
Extension options passed to the media preparation flow. Regular plugins usually do not need this.
options.timeout
number
Reserved timeout field. Current direct media reply helpers use the built-in media timeout.

replyMixed(items, options?)

items is an array. Text items use text; media items use source, and can also use file, url, or path as source aliases. The runtime discards invalid mixed items.
items
MediaItem[]
required
Mixed message array. Supports text, markdown, image, voice, video, and file. The runtime normalizes it before passing it to the adapter.
options
MediaOptions
Optional default media options. When a media item has no name / mime_type, values can be filled from here.
await sender.replyMixed([
  { type: 'text', text: 'Done: ' },
  { type: 'image', source: './result.png', name: 'result.png' },
  { type: 'file', source: './report.csv', name: 'report.csv', mime_type: 'text/csv' },
])
Supported items:
itemRequired fieldOptional fieldsDescription
{ type: 'text', text: '...' }textNoneSend a plain text segment.
{ type: 'markdown', text: '...' }textNoneThe helper passes it through. The current runtime normalization mainly accepts text and media items; adapter support depends on the implementation.
{ type: 'image', source: '...' }sourcename, mime_type, platform_payloadSend an image.
{ type: 'voice', source: '...' }sourcename, mime_type, platform_payloadSend voice/audio.
{ type: 'video', source: '...' }sourcename, mime_type, platform_payloadSend a video.
{ type: 'file', source: '...' }sourcename, mime_type, platform_payloadSend a file.
Example SendReceipt:
{
  "ok": true,
  "message_id": "msg_mixed_123",
  "message_ids": ["msg_text_1", "msg_image_1"],
  "action": "sendMixed"
}

Control flow

MethodPurposeParametersReturns
setContinue()Continue matching subsequent plugins. After a plugin is hit, later matches usually stop by default.NonePromise<boolean>
recallMessage(messageid)Recall the specified message.messageid: required message ID. You can use message_id or messageid.Promise<SendReceipt>
breakIn(content)Re-enter autClaw internal message handling with new text as a message event.content: required new message text.Promise<boolean>
if (await sender.isAdmin()) {
  await sender.setContinue()
}

const receipt = await sender.reply('This message will be recalled in 5 seconds')
setTimeout(() => {
  sender.recallMessage(receipt.message_id || receipt.messageid).catch(console.error)
}, 5000)

Next steps

Wait for input and payment

See listen(...), input(...), and waitPay(...).

User-uploaded files

See getMediaItems() and downloadAdapterFile(...).
Last modified on June 3, 2026