Starting a conversation

const channel = app.channel({
  to: "C01234567",
  platform: "slack",
  teamId: "TEAM_ID",
});

await channel.send("Hello from Skyline.");

Message extras

When message.platform === "slack", Skyline surfaces:
FieldTypeDescription
isFromMebooleanWhether the message was sent by the bot.
slack.subtypestring (optional)Slack message subtype, such as "bot_message".
slack.threadTsstring (optional)Thread timestamp if the message is in a thread.
slack.tsstring (optional)Message timestamp.
slack.teamIdstringWorkspace team id.
for await (const [channel, message] of app.messages) {
  if (message.platform !== "slack") continue;
  console.log(message.slack?.teamId, message.slack?.ts, message.isFromMe);
}

Supported features

FeatureSupport
Text messagesSend and receive
Media / filesSend (channel.sendFile)
ReactionsSend and receive
Threaded repliesSend and receive
Typing indicatorsAccepted (no-op — Slack Web API has no bot typing)
Message editsSend and receive (channel.edit, edited signal)
UnsendNot supported by Slack for bots

Send and reply

const channel = app.channel({ to: "C01234567", platform: "slack" });

await channel.send("Order confirmed — we'll message you here.");
await channel.reply("1710000000.000100", "Tracking link is on the way.");
await channel.edit("1710000000.000100", "Updated: tracking is on the way.");

Reactions

await channel.react("1710000000.000100", "white_check_mark");
await channel.react("1710000000.000100", "white_check_mark", { remove: true });

Inbound

With Socket Mode (appTokens when you pass credentials, or an app token saved in the dashboard), inbound messages merge into app.incoming with message.platform === "slack". Without Socket Mode, configure a project webhook and handle Slack Events API deliveries.

Signals

SignalWhen
reactionUser adds or removes an emoji reaction
editedA message body changes (message_changed)