First-party app
Twist

Twist

Post and read Twist threads, comments and conversations; manage channels, groups, workspace users, reactions and the inbox.

stable CommunicationProductivity

About

Twist ships in the w6w first-party pack. It declares 111 actions, 3 health checks, and the host runs its code in a sandbox that never sees the credential.

App id
io.w6w.twist
Version
0.1.0
Author
w6w
Licence
MIT
Categories
Communication · Productivity

Overview

Twist is Doist’s async team messaging tool: conversations live in threads inside channels, so a message is a post that can be answered whenever people get to it. This app puts that structure in a workflow.

It covers the working loop of a team that uses Twist: post a thread to a channel, comment on it, close or reopen it, pin or star it, and move it between channels; send direct messages in a conversation; add reactions; and read the inbox, unread threads and search results to decide what needs a reply.

Beyond messaging, the app manages the structure around it — workspaces, channels, groups, and workspace members — plus notification settings, join links, loop-in email addresses and event webhooks, so a workflow can react to Twist events instead of polling for them. Sign in with OAuth for a shared connection, or paste a personal test token for development.

Twist’s file-upload endpoint takes multipart bytes and is not offered, and the user-account endpoints that handle passwords or rotate the API token are deliberately left out, so a workflow can never change or expose the login behind a connection.

Build with Twist

Three routes to the same 111 actions. The Workflow tab is generated from Twist's own manifest and carries its real ids, so it is copy-pasteable; the Code and CLI examples are the same call for any action on any app, so every app-specific value in them is a blank you fill in.

Remove Attachment

attachment-remove

Remove an attachment from a thread, comment or conversation message. Uploading is not offered: it needs multipart file bytes.

Archive Channel

channel-archive

Archive a channel.

Create Channel

channel-create

Create a channel in a workspace.

Favorite Channel

channel-favorite

Favorite a channel.

Get Channel

channel-get

Get a channel by id.

List Channels

channel-list

List all channels in a workspace.

Remove Channel

channel-remove

Delete a channel. Twist requires it to be archived first.

Unarchive Channel

channel-unarchive

Unarchive a channel.

Unfavorite Channel

channel-unfavorite

Unfavorite a channel.

Update Channel

channel-update

Update a channel. Twist requires the name on every update.

Add User to Channel

channel-user-add

Add a person to a channel.

Remove User from Channel

channel-user-remove

Remove a person from a channel.

Add Users to Channel

channel-users-add

Add several people to a channel.

Remove Users from Channel

channel-users-remove

Remove several people from a channel.

Create Comment

comment-create

Post a comment on a thread.

Get Comment

comment-get

Get a comment by id.

List Comments

comment-list

List the comments in a thread.

Mark Comment Position

comment-mark-position

Mark the user's reading position in a thread.

Remove Comment

comment-remove

Delete a comment. Only its author or an admin may.

Update Comment

comment-update

Edit a comment.

Archive Conversation

conversation-archive

Archive a conversation.

Get Conversation

conversation-get

Get a conversation by id.

Get or Create Conversation

conversation-get-or-create

Get the conversation with a set of users, creating it if it does not exist.

List Conversations

conversation-list

List the user's conversations in a workspace.

Mark Conversation Read

conversation-mark-read

Mark a conversation as read. Give a message id or an object index.

Mark Conversation Unread

conversation-mark-unread

Mark a conversation as unread. Give a message id or an object index.

Mute Conversation

conversation-mute

Mute a conversation for a number of minutes.

Unarchive Conversation

conversation-unarchive

Unarchive a conversation.

Unmute Conversation

conversation-unmute

Unmute a conversation.

List Unread Conversations

conversation-unread-list

List the user's unread conversations in a workspace.

Update Conversation

conversation-update

Update a conversation's title or archived flag.

Add User to Conversation

conversation-user-add

Add a person to a conversation.

Add Users to Conversation

conversation-users-add

Add several people to a conversation.

Create Group

group-create

Create a group in a workspace.

Get Group

group-get

Get a group by id.

List Groups

group-list

List all groups in a workspace.

Remove Group

group-remove

Delete a group.

Update Group

group-update

Rename a group.

Add User to Group

group-user-add

Add a person to a group.

Remove User from Group

group-user-remove

Remove a person from a group.

Add Users to Group

group-users-add

Add several people to a group.

Remove Users from Group

group-users-remove

Remove several people from a group.

Archive All Inbox Threads

inbox-archive-all

Archive every inbox thread in a workspace.

Archive Inbox Thread

inbox-archive-thread

Archive one thread in the inbox.

Get Inbox Count

inbox-count-get

Get the inbox count for a workspace.

List Inbox

inbox-list

List the threads in the user's inbox for a workspace.

Mark Inbox Read

inbox-mark-all-read

Mark every inbox thread in a workspace as read.

Unarchive Inbox Thread

inbox-unarchive-thread

Unarchive one thread in the inbox.

Disable Loop-in Email

loop-in-disable

Disable a loop-in email address.

Get or Create Loop-in Email

loop-in-get-or-create

Get the email address that posts into a channel, thread or conversation, creating it if needed.

Send Message

message-create

Send a message in a conversation.

Get Message

message-get

Get a conversation message by id.

List Messages

message-list

List the messages in a conversation.

Remove Message

message-remove

Delete a message you sent.

Update Message

message-update

Edit a message you sent.

Update Notification Setting

notification-setting-update

Change one notification setting.

Get Notification Settings

notification-settings-get

Get the user's notification settings for a workspace.

Update Notification Settings

notification-settings-update-many

Change several notification settings at once.

Add Reaction

reaction-add

React to a thread, comment or conversation message.

Get Reactions

reaction-get

Get the reactions on a thread, comment or conversation message. Twist documents this as a POST.

Remove Reaction

reaction-remove

Remove a reaction.

Search

search

Full-text search over threads, conversations and messages in a workspace. Page with the returned `next_cursor_mark`.

Search Within Conversation

search-conversation

Search a conversation; returns matching message ids (latest 10,000 at most).

Search Within Thread

search-thread

Search a thread; returns matching comment ids (latest 10,000 at most).

Find Threads by Title

thread-autocomplete

Find threads whose title contains some text, across every channel the user can reach.

Close Thread

thread-close

Close a thread by posting a comment with `thread_action: close`. Twist has no separate close endpoint.

Create Thread

thread-create

Post a new thread in a channel.

Get Thread

thread-get

Get a thread by id.

List Threads

thread-list

List the threads in a channel.

Mark Thread Read

thread-mark-read

Mark a thread as read up to a comment index.

Mark Thread Unread

thread-mark-unread

Mark a thread as unread.

Mark Thread Unread for Others

thread-mark-unread-for-others

Mark a thread as unread for everyone else, to draw attention to a change.

Move Thread

thread-move

Move a thread to another channel.

Mute Thread

thread-mute

Mute a thread for a number of minutes.

Pin Thread

thread-pin

Pin a thread.

Remove Thread

thread-remove

Delete a thread.

Reopen Thread

thread-reopen

Reopen a closed thread by posting a comment with `thread_action: reopen`.

Star Thread

thread-star

Star a thread.

Unmute Thread

thread-unmute

Unmute a thread.

Unpin Thread

thread-unpin

Unpin a thread.

List Unread Threads

thread-unread-list

List the user's unread threads in a workspace.

Unstar Thread

thread-unstar

Unstar a thread.

Update Thread

thread-update

Edit a thread's title or content.

Clear Unread Threads

threads-clear-unread

Clear the unread threads in a workspace.

Mark All Threads Read

threads-mark-all-read

Mark every thread in a workspace or a channel as read. Give one of the two ids.

Disable Join Link

url-join-disable

Disable a workspace's URL join link.

Get Join Link

url-join-get

Get the URL join link of a workspace, if one exists.

Get or Create Join Link

url-join-get-or-create

Get a workspace's URL join link, creating it if needed.

Get Current User

user-get-current

Get the user that owns the token making the request. The API token Twist returns on this object is removed.

Reset Presence

user-presence-reset

Reset the user's presence in a workspace.

Set Presence

user-presence-set

Mark the user as active in a workspace.

Update Current User

user-update

Update the logged-in user's profile. Password changes and away mode are not exposed.

Subscribe to Event

webhook-subscribe

Register a URL that Twist calls whenever the chosen event happens. A 403 means the token's scope does not cover the event.

Unsubscribe from Event

webhook-unsubscribe

Stop Twist calling a registered URL.

Create Workspace

workspace-create

Create a new workspace.

Get Workspace

workspace-get

Get a workspace by id.

Get Default Workspace

workspace-get-default

Get the user's default workspace.

Join Workspace by Link

workspace-join-by-url

Join the workspace a URL join link belongs to.

List Workspaces

workspace-list

List all of the user's workspaces.

List Public Channels

workspace-public-channels-list

List the public channels of a workspace.

Update Workspace

workspace-update

Rename a workspace.

Add User to Workspace

workspace-user-add

Invite a person to a workspace by email.

Get Workspace User

workspace-user-get

Get a workspace user by id.

Get Workspace User by Email

workspace-user-get-by-email

Get a workspace user by email address.

List Workspace User IDs

workspace-user-ids-list

List the user ids of a workspace.

Get Workspace User Info

workspace-user-info-get

Get a user's info in the context of a workspace.

Resend Workspace Invite

workspace-user-invite-resend

Send the workspace invitation again.

List Workspace Users

workspace-user-list

List the users of a workspace. Uses /api/v4; the v3 endpoint is deprecated.

Get User Local Time

workspace-user-local-time-get

Get a user's local time. Twist answers a bare date-time string, returned as `result`.

Remove User from Workspace

workspace-user-remove

Remove a person from a workspace.

Update Workspace User

workspace-user-update

Change a user's type in a workspace. Twist requires either an email or a user id.

A workflow step names the app and the action, and the editor fills in the connection when you pick one. This is the Step shape from the workflow spec, carrying Twist's real ids.

{
  "manifestVersion": "2",
  "name": "twist-example",
  "steps": [
    {
      "id": "channel-create",
      "uses": {
        "app": "io.w6w.twist",
        "action": "channel-create",
        "connection": "conn_YOUR_CONNECTION_ID"
      },
      "with": {
        "workspaceId": "<workspaceId>",
        "name": "<name>"
      }
    }
  ]
}

Here are some of the things you can do

  • Create Channel

    perform
    channel-create
  • Favorite Channel

    perform
    channel-favorite
  • Get Channel

    read
    channel-get
  • List Channels

    read
    channel-list
  • Unarchive Channel

    perform
    channel-unarchive

+106 more actions available

Every app-specific value here is a blank you have to fill in. An app action is reached through the connection that authenticates it, so the address is a connection id, not the app id — and connections belong to your account, so a public page cannot know yours. Create one for Twist, then fill in the three blanks: conn_YOUR_CONNECTION_ID, the action key, and the parameters that action declares. The call itself is real — the shape is transcribed from the studio's own snippet builder, which prints the same kind of blanks — but nothing in it is specific to Twist. The Workflow tab is where this app's real ids are.

Install
npm install @w6w/sdk
yarn add @w6w/sdk
pnpm add @w6w/sdk
deno add npm:@w6w/sdk
Code
import { W6wClient, isActionRun } from "@w6w/sdk";

// Reads W6W_BASE_URL and W6W_TOKEN from the environment when omitted.
const client = new W6wClient();

const envelope = await client.run({
  urn: "conn_YOUR_CONNECTION_ID",
  action: "channel-create",
  payload: {
    workspaceId: "<value>",
    name: "<value>",
    // tempId: "<value>",
    // userIds: "<value>",
    // color: "<value>",
    // public: "<value>",
    // description: "<value>",
    // defaultGroups: "<value>",
    // defaultRecipients: "<value>",
    // isFavorited: "<value>",
    // icon: "<value>",
  },
});

if (isActionRun(envelope)) console.log(envelope.value);
Install the CLI
npm install -g @w6w/cli
CLI
w6w run conn_YOUR_CONNECTION_ID --action channel-create --payload '{"workspaceId":"<value>","name":"<value>"}'

Give an AI agent Twist — without giving it Twist's credentials. One MCP endpoint exposes every app, function and workflow the caller is entitled to, as tools it can discover and run. Access is granted per team while we onboard.

One tool call
{
  "name": "w6w_invoke",
  "arguments": {
    "ref": "app:io.w6w.twist#channel-create",
    "input": {
      "workspaceId": "<workspaceId>",
      "name": "<name>"
    }
  }
}

Every tool names its target with a single ref. The app: form above doesn't name a connection at all — the host resolves which of the caller's Twist connections to sign with, and refuses rather than guesses when the answer is ambiguous.

What the agent gets

Credentials it can't read

The token is attached host-side, at the moment of the call. It is never a tool argument, never in the model's context, and never in a transcript — so a prompt injection has nothing to exfiltrate.

A tool surface scoped to the caller

Tools are derived per end user from what that person has actually connected and is entitled to — not one shared bot identity carrying the union of everyone's access.

A durable workflow in one call

Multi-step work runs on the workflow engine and returns a run handle the agent can poll — retries, branching and state survive the conversation that started them.

Health-aware discovery

Twist's declared health checks are on the surface too, so an agent can tell "the vendor is down" from "your credential expired" before it burns a retry on either.

The MCP surface is part of the hosted platform. Twist itself is MIT, and the runtime that executes it is source-available (FSL).

Request MCP access

Health checks

Twist declares its own checks, so its health is a property of the app rather than something the host guesses at.

service

Twist platform status

Instatus feed for status.twist.io. Verdict from the `Web application & API` component only; the `Website` component is ignored. Unauthenticated and unsigned.

dependency

API reachable

Unauthenticated GET https://api.twist.com/api/v3/workspaces/get. Twist's JSON auth error (`error_code` + `error_string`) passes — it proves the API is serving. Credential validity is the derived `auth:*` check's job.

quota

API rate-limit headroom