Serve Actions

When running discli serve, you send JSON objects (one per line) to stdin. Every action must include an "action" field. An optional "req_id" field will be echoed back in the response for correlation.

General request format:

{"action": "<action_name>", "req_id": "optional-correlation-id", ...fields}

General response format:

{"event": "response", "status": "ok", "req_id": "1", ...result_fields}

On error, the response contains an "error" field instead of "ok":

{"event": "response", "error": "Channel not found: 999", "req_id": "1"}

Messaging

send

Send a message to a channel.

Request:

{"action": "send", "channel_id": "123456", "content": "Hello!", "req_id": "1"}

Response:

{"event": "response", "ok": true, "message_id": "789", "req_id": "1"}
FieldRequiredTypeDescription
channel_idyesstringTarget channel ID
contentnostringMessage text
filesnostring[]Local file paths to attach
req_idnostringCorrelation ID

reply

Reply to a specific message.

Request:

{"action": "reply", "channel_id": "123456", "message_id": "111", "content": "Got it!", "req_id": "2"}

Response:

{"event": "response", "ok": true, "message_id": "222", "req_id": "2"}
FieldRequiredTypeDescription
channel_idyesstringChannel containing the message
message_idyesstringMessage to reply to
contentnostringReply text
filesnostring[]Local file paths to attach
req_idnostringCorrelation ID

edit

Edit an existing message (must be authored by the bot).

Request:

{"action": "edit", "channel_id": "123456", "message_id": "789", "content": "Updated text", "req_id": "3"}

Response:

{"event": "response", "ok": true, "req_id": "3"}
FieldRequiredTypeDescription
channel_idyesstringChannel containing the message
message_idyesstringMessage to edit
contentnostringNew message content
req_idnostringCorrelation ID

delete

Delete a message.

Request:

{"action": "delete", "channel_id": "123456", "message_id": "789", "req_id": "4"}

Response:

{"event": "response", "ok": true, "req_id": "4"}
FieldRequiredTypeDescription
channel_idyesstringChannel containing the message
message_idyesstringMessage to delete
req_idnostringCorrelation ID

message_pin

Pin a message in a channel.

Request:

{"action": "message_pin", "channel_id": "123456", "message_id": "789", "req_id": "5"}

Response:

{"event": "response", "ok": true, "req_id": "5"}
FieldRequiredTypeDescription
channel_idyesstringChannel containing the message
message_idyesstringMessage to pin
req_idnostringCorrelation ID

message_unpin

Unpin a message in a channel.

Request:

{"action": "message_unpin", "channel_id": "123456", "message_id": "789", "req_id": "6"}

Response:

{"event": "response", "ok": true, "req_id": "6"}
FieldRequiredTypeDescription
channel_idyesstringChannel containing the message
message_idyesstringMessage to unpin
req_idnostringCorrelation ID

Streaming

Streaming lets you send a response that updates in real-time (e.g., token-by-token LLM output). The flow is: stream_start to create a placeholder message, stream_chunk to append text, and stream_end to finalize. The message is flushed to Discord every 1.5 seconds during streaming.

stream_start

Start a streaming message. Creates a placeholder message ("...") in the channel.

Request:

{"action": "stream_start", "channel_id": "123456", "req_id": "10"}

Response:

{"event": "response", "stream_id": "a1b2c3d4", "message_id": "789", "req_id": "10"}
FieldRequiredTypeDescription
channel_idyesstringChannel to send in
reply_tonostringMessage ID to reply to
interaction_tokennostringInteraction token to respond to a slash command
req_idnostringCorrelation ID

stream_chunk

Append text to an active stream. Content is buffered and flushed periodically.

Request:

{"action": "stream_chunk", "stream_id": "a1b2c3d4", "content": "Hello ", "req_id": "11"}

Response:

{"event": "response", "ok": true, "req_id": "11"}
FieldRequiredTypeDescription
stream_idyesstringStream ID from stream_start
contentnostringText to append
req_idnostringCorrelation ID

stream_end

Finalize a streaming message. Performs a final edit with the complete content. If the content exceeds 2000 characters, overflow is split into follow-up messages.

Request:

{"action": "stream_end", "stream_id": "a1b2c3d4", "req_id": "12"}

Response:

{"event": "response", "ok": true, "message_id": "789", "req_id": "12"}
FieldRequiredTypeDescription
stream_idyesstringStream ID from stream_start
req_idnostringCorrelation ID

Interactions

interaction_followup

Send a follow-up response to a deferred slash command interaction.

Request:

{"action": "interaction_followup", "interaction_token": "uuid-token", "content": "Done!", "req_id": "20"}

Response:

{"event": "response", "ok": true, "req_id": "20"}
FieldRequiredTypeDescription
interaction_tokenyesstringToken from the slash_command event
contentnostringFollow-up message text
req_idnostringCorrelation ID

Typing / Presence

typing_start

Start showing a typing indicator in a channel. The indicator persists until typing_stop is sent or the bot sends a message.

Request:

{"action": "typing_start", "channel_id": "123456", "req_id": "30"}

Response:

{"event": "response", "ok": true, "req_id": "30"}
FieldRequiredTypeDescription
channel_idyesstringChannel ID
req_idnostringCorrelation ID

typing_stop

Stop the typing indicator in a channel.

Request:

{"action": "typing_stop", "channel_id": "123456", "req_id": "31"}

Response:

{"event": "response", "ok": true, "req_id": "31"}
FieldRequiredTypeDescription
channel_idyesstringChannel ID
req_idnostringCorrelation ID

presence

Set the bot’s online status and activity.

Request:

{"action": "presence", "status": "dnd", "activity_type": "watching", "activity_text": "the logs", "req_id": "32"}

Response:

{"event": "response", "ok": true, "req_id": "32"}
FieldRequiredTypeDescription
statusnostringonline, idle, dnd, or invisible (default: online)
activity_typenostringplaying, watching, listening, or competing
activity_textnostringActivity display text
req_idnostringCorrelation ID

Reactions

reaction_add

Add a reaction to a message.

Request:

{"action": "reaction_add", "channel_id": "123456", "message_id": "789", "emoji": "thumbsup", "req_id": "40"}

Response:

{"event": "response", "ok": true, "req_id": "40"}
FieldRequiredTypeDescription
channel_idyesstringChannel containing the message
message_idyesstringMessage to react to
emojiyesstringEmoji character or custom emoji string
req_idnostringCorrelation ID

reaction_remove

Remove the bot’s reaction from a message.

Request:

{"action": "reaction_remove", "channel_id": "123456", "message_id": "789", "emoji": "thumbsup", "req_id": "41"}

Response:

{"event": "response", "ok": true, "req_id": "41"}
FieldRequiredTypeDescription
channel_idyesstringChannel containing the message
message_idyesstringMessage to remove reaction from
emojiyesstringEmoji character or custom emoji string
req_idnostringCorrelation ID

Threads

thread_create

Create a new thread, optionally from an existing message.

Request:

{"action": "thread_create", "channel_id": "123456", "name": "Discussion", "message_id": "789", "req_id": "50"}

Response:

{"event": "response", "ok": true, "thread_id": "999", "thread_name": "Discussion", "req_id": "50"}
FieldRequiredTypeDescription
channel_idyesstringParent channel ID
nameyesstringThread name
message_idnostringMessage to create thread from (omit for standalone thread)
auto_archive_durationnointegerAuto-archive after N minutes (default: 1440)
contentnostringInitial message to send in the thread
req_idnostringCorrelation ID

thread_send

Send a message to an existing thread.

Request:

{"action": "thread_send", "thread_id": "999", "content": "Hello thread!", "req_id": "51"}

Response:

{"event": "response", "ok": true, "message_id": "1000", "req_id": "51"}
FieldRequiredTypeDescription
thread_idyesstringThread ID
contentnostringMessage text
filesnostring[]Local file paths to attach
req_idnostringCorrelation ID

thread_list

List active threads in a channel.

Request:

{"action": "thread_list", "channel_id": "123456", "req_id": "52"}

Response:

{
"event": "response",
"ok": true,
"threads": [
{"id": "999", "name": "Discussion", "message_count": 5, "member_count": 3, "archived": false}
],
"req_id": "52"
}
FieldRequiredTypeDescription
channel_idyesstringChannel ID
req_idnostringCorrelation ID

Polls

poll_send

Create a poll in a channel.

Request:

{
"action": "poll_send",
"channel_id": "123456",
"question": "Favorite AI?",
"answers": ["Claude", "Gemini", "ChatGPT"],
"duration_hours": 24,
"multiple": false,
"req_id": "60"
}

Answers can also be objects with emoji:

{
"action": "poll_send",
"channel_id": "123456",
"question": "Vote!",
"answers": [{"text": "Yes", "emoji": "white_check_mark"}, {"text": "No", "emoji": "x"}],
"req_id": "61"
}

Response:

{"event": "response", "ok": true, "message_id": "789", "req_id": "60"}
FieldRequiredTypeDescription
channel_idyesstringChannel ID
questionyesstringPoll question
answersyesarrayList of answer strings or &#123;"text": "...", "emoji": "..."&#125; objects (min 2)
duration_hoursnointegerDuration in hours (default: 24)
multiplenobooleanAllow multiple selections (default: false)
contentnostringOptional message text alongside the poll
req_idnostringCorrelation ID

Channels

channel_list

List channels across all servers or a specific server.

Request:

{"action": "channel_list", "guild_id": "123456", "req_id": "70"}

Response:

{
"event": "response",
"ok": true,
"channels": [
{"id": "111", "name": "general", "type": "text", "server": "My Server", "server_id": "123456"}
],
"req_id": "70"
}
FieldRequiredTypeDescription
guild_idnostringServer ID (omit for all servers)
req_idnostringCorrelation ID

channel_create

Create a channel in a server.

Request:

{"action": "channel_create", "guild_id": "123456", "name": "new-channel", "type": "text", "req_id": "71"}

Response:

{"event": "response", "ok": true, "channel_id": "222", "name": "new-channel", "req_id": "71"}
FieldRequiredTypeDescription
guild_idyesstringServer ID
nameyesstringChannel name
typenostringtext, voice, or category (default: text)
req_idnostringCorrelation ID

channel_info

Get details about a channel.

Request:

{"action": "channel_info", "channel_id": "123456", "req_id": "72"}

Response:

{
"event": "response",
"ok": true,
"id": "123456",
"name": "general",
"type": "text",
"server": "My Server",
"server_id": "789",
"topic": "General discussion",
"created_at": "2024-01-01T00:00:00+00:00",
"req_id": "72"
}
FieldRequiredTypeDescription
channel_idyesstringChannel ID
req_idnostringCorrelation ID

Members

member_list

List members of a server.

Request:

{"action": "member_list", "guild_id": "123456", "limit": 50, "req_id": "80"}

Response:

{
"event": "response",
"ok": true,
"members": [
{"id": "111", "name": "alice", "nick": null, "bot": false}
],
"req_id": "80"
}
FieldRequiredTypeDescription
guild_idyesstringServer ID
limitnointegerMax members to return (default: 50)
req_idnostringCorrelation ID

member_info

Get details about a specific member.

Request:

{"action": "member_info", "guild_id": "123456", "member_id": "111", "req_id": "81"}

Response:

{
"event": "response",
"ok": true,
"id": "111",
"name": "alice",
"nick": null,
"bot": false,
"roles": [{"id": "222", "name": "Admin"}],
"joined_at": "2024-01-01T00:00:00+00:00",
"req_id": "81"
}
FieldRequiredTypeDescription
guild_idyesstringServer ID
member_idyesstringMember user ID
req_idnostringCorrelation ID

Roles

role_list

List roles in a server.

Request:

{"action": "role_list", "guild_id": "123456", "req_id": "90"}

Response:

{
"event": "response",
"ok": true,
"roles": [
{"id": "222", "name": "Admin", "color": "#ff0000", "members": 3}
],
"req_id": "90"
}
FieldRequiredTypeDescription
guild_idyesstringServer ID
req_idnostringCorrelation ID

role_assign

Assign a role to a member.

Request:

{"action": "role_assign", "guild_id": "123456", "member_id": "111", "role_id": "222", "req_id": "91"}

Response:

{"event": "response", "ok": true, "member": "alice", "role": "Admin", "req_id": "91"}
FieldRequiredTypeDescription
guild_idyesstringServer ID
member_idyesstringMember user ID
role_idyesstringRole ID to assign
req_idnostringCorrelation ID

role_remove

Remove a role from a member.

Request:

{"action": "role_remove", "guild_id": "123456", "member_id": "111", "role_id": "222", "req_id": "92"}

Response:

{"event": "response", "ok": true, "member": "alice", "role": "Admin", "req_id": "92"}
FieldRequiredTypeDescription
guild_idyesstringServer ID
member_idyesstringMember user ID
role_idyesstringRole ID to remove
req_idnostringCorrelation ID

DMs

dm_send

Send a direct message to a user.

Request:

{"action": "dm_send", "user_id": "111", "content": "Hello!", "req_id": "100"}

Response:

{"event": "response", "ok": true, "message_id": "222", "recipient": "alice", "req_id": "100"}
FieldRequiredTypeDescription
user_idyesstringRecipient user ID
contentnostringMessage text
req_idnostringCorrelation ID

Queries

message_list

List recent messages in a channel.

Request:

{"action": "message_list", "channel_id": "123456", "limit": 20, "req_id": "110"}

Response:

{
"event": "response",
"ok": true,
"messages": [
{
"id": "789",
"author": "alice",
"author_id": "111",
"content": "Hello!",
"timestamp": "2024-01-01T12:00:00+00:00",
"attachments": []
}
],
"req_id": "110"
}
FieldRequiredTypeDescription
channel_idyesstringChannel ID
limitnointegerMax messages (default: 20)
req_idnostringCorrelation ID

message_get

Fetch a single message by ID.

Request:

{"action": "message_get", "channel_id": "123456", "message_id": "789", "req_id": "111"}

Response:

{
"event": "response",
"ok": true,
"id": "789",
"author": "alice",
"author_id": "111",
"content": "Hello!",
"timestamp": "2024-01-01T12:00:00+00:00",
"attachments": [],
"embeds": [],
"reply_to": null,
"req_id": "111"
}
FieldRequiredTypeDescription
channel_idyesstringChannel ID
message_idyesstringMessage ID
req_idnostringCorrelation ID

Search messages in a channel by content.

Request:

{"action": "message_search", "channel_id": "123456", "query": "hello", "limit": 100, "author": "alice", "req_id": "112"}

Response:

{
"event": "response",
"ok": true,
"messages": [
{"id": "789", "author": "alice", "content": "Hello world!", "timestamp": "2024-01-01T12:00:00+00:00"}
],
"req_id": "112"
}
FieldRequiredTypeDescription
channel_idyesstringChannel ID
querynostringCase-insensitive search string
limitnointegerMessages to scan (default: 100)
authornostringFilter by author name
req_idnostringCorrelation ID

Server

server_list

List all servers the bot is in.

Request:

{"action": "server_list", "req_id": "120"}

Response:

{
"event": "response",
"ok": true,
"servers": [
{"id": "123456", "name": "My Server", "member_count": 42}
],
"req_id": "120"
}
FieldRequiredTypeDescription
req_idnostringCorrelation ID

server_info

Get details about a specific server.

Request:

{"action": "server_info", "guild_id": "123456", "req_id": "121"}

Response:

{
"event": "response",
"ok": true,
"id": "123456",
"name": "My Server",
"owner": "alice",
"member_count": 42,
"channel_count": 10,
"role_count": 5,
"created_at": "2024-01-01T00:00:00+00:00",
"req_id": "121"
}
FieldRequiredTypeDescription
guild_idyesstringServer ID
req_idnostringCorrelation ID