> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ancha.io/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> These docs describe the Ancha CLI, npm package @ancha-labs/cli version 0.1.4, and the hosted workspace at app.ancha.io. Coding agents should start at https://docs.ancha.io/coding-agents. Run the CLI as `ancha` after `npm install -g @ancha-labs/cli`, or as `npx -y @ancha-labs/cli@0.1.4` without installing. Pass --json for machine-readable output, or set ANCHA_JSON=1. Every command ends with a `next:` line naming the next command. Exit codes: 0 pass, 1 a check failed or a comparison regressed, 2 usage, config or authentication error, 3 infrastructure error, 4 unimplemented endpoint with --strict.

# Slack

> A stateful replica of Slack's Web API for bot tokens: channels, direct messages, messages, threads, reactions and users, with Events API delivery and an MCP server.

The Slack replica implements 22 Web API methods for a bot token, with Events API delivery for messages and reactions. Its key is `slack`. It was tested with `@slack/web-api` and `@slack/bolt`.

## Connect

| Variable | Value |
| - | - |
| `SLACK_API_URL` | Base URL of the Web API. It ends in `/api/`, so append the method name: `SLACK_API_URL + "chat.postMessage"`. |
| `SLACK_BOT_TOKEN` | Fake bot token. Send it as `Authorization: Bearer <token>`. |
| `SLACK_SIGNING_SECRET` | Signs HTTP event deliveries. Verify signatures against the raw request body. |
| `SLACK_APP_TOKEN` | Fake app-level token for Socket Mode. |

```js Node theme={null}
import { WebClient } from '@slack/web-api';
const slack = new WebClient(process.env.SLACK_BOT_TOKEN, { slackApiUrl: process.env.SLACK_API_URL });
await slack.conversations.list();
```

```python Python theme={null}
import os
from slack_sdk import WebClient
slack = WebClient(token=os.environ['SLACK_BOT_TOKEN'], base_url=os.environ['SLACK_API_URL'].rstrip('/') + '/')
slack.conversations_list()
```

These are the snippets `ancha connect slack --lang ts` and `--lang py` print. The SDKs call every method with `POST`, which matters for [trace checks](https://docs.ancha.io/concepts/checks.md#trace-patterns).

For Bolt in Socket Mode, set the local URL on both the app's `clientOptions` and the receiver's `installerOptions.clientOptions`. Otherwise the receiver opens its socket against real Slack.

## Endpoints

Every method is called with `POST` at `/api/<method>`, so trace checks look like `POST /api/chat.postMessage`.

| Method | Support | Notes |
| - | - | - |
| `auth.test` | supported | Also allowed while an SDK starts up, before the attempt's clock starts. |
| `conversations.list` | partial | `types=im` lists the bot's direct messages. `mpim` is accepted and matches nothing: multi-person direct messages are not modeled. |
| `conversations.info` | supported | |
| `conversations.history` | supported | Newest first, with cursors. |
| `conversations.replies` | supported | Parent first, then replies oldest first. |
| `conversations.join` | supported | |
| `conversations.create` | supported | |
| `conversations.members` | supported | |
| `conversations.open` | partial | One user opens a direct message, created on first use, or returns an existing one; `return_im` and `prevent_creation`. Multi-person direct messages are a gap. |
| `chat.postMessage` | partial | Text and a subset of blocks. A user ID as `channel` posts in the direct message with that user. Emits `message` events in channels where the bot is a member and in its direct messages. |
| `chat.update` | partial | Text and blocks; `metadata` and `attachments` are coverage gaps. Emits `message_changed`. |
| `chat.delete` | partial | The bot's own messages. Emits `message_deleted`. Deleting a thread parent leaves its replies in place. |
| `chat.getPermalink` | supported | Returns a fictional workspace address. |
| `reactions.add` | supported | Emits `reaction_added`. |
| `reactions.remove` | partial | Emits `reaction_removed`. |
| `reactions.get` | supported | |
| `search.messages` | partial | Needs a user token. The bot token, the only token Ancha provides, is rejected. |
| `users.list` | supported | |
| `users.info` | supported | |
| `users.lookupByEmail` | supported | |
| `users.conversations` | partial | `types=im` lists the bot's direct messages; `mpim` matches nothing. |
| `apps.connections.open` | partial | Socket Mode only, with `SLACK_APP_TOKEN`. One live socket per attempt. |

Any other method returns HTTP 200 with `{"ok": false, "error": "unknown_method"}`, an `ancha_gap` message and the header `x-ancha-gap: 1`.

## Events

Posting, editing and deleting messages and adding or removing reactions emit Events API envelopes for channels where the bot is a member. A person in the world who mentions the bot also emits `app_mention`. Starter history does not emit events.

`ancha run` delivers events in one of three ways, set by `agent.slack_transport` in `ancha.yaml`:

| Transport | How the agent receives events |
| - | - |
| `feed` | Polls `ANCHA_EVENTS_URL` with `ANCHA_EVENTS_TOKEN`. The default for command agents. |
| `http` | Ancha POSTs signed requests to the agent's URL, after the Slack `url_verification` handshake. The default for endpoint agents. |
| `socket` | Socket Mode through `apps.connections.open`. Command agents only. |

See [ancha.yaml](https://docs.ancha.io/reference/ancha-yaml.md) and [Environment variables](https://docs.ancha.io/reference/environment-variables.md).

## MCP server

`ancha mcp serve --sandbox <id>` runs a Slack MCP server over stdio, profile `ancha-slack-v1`, against a running sandbox. `ancha mcp config --sandbox <id>` prints the `mcpServers` entry to add to your MCP host. It exposes 19 tools that call the same Web API and appear in the same trace:

`slack_auth_test`, `slack_conversations_list`, `slack_conversations_info`, `slack_conversations_history`, `slack_conversations_replies`, `slack_conversations_members`, `slack_conversations_join`, `slack_conversations_create`, `slack_chat_postMessage`, `slack_chat_update`, `slack_chat_delete`, `slack_chat_getPermalink`, `slack_reactions_add`, `slack_reactions_remove`, `slack_reactions_get`, `slack_users_list`, `slack_users_info`, `slack_users_lookupByEmail`, `slack_users_conversations`.

The MCP server writes plain-text messages only and has no reset or admin tools. See [`ancha mcp`](https://docs.ancha.io/cli/mcp).

## Starter data

The `slack-starter` dataset is the workspace **Acme**: a bot, nine people and ten channels, with 52 messages of history. Worlds, sandboxes and the hosted console use it. Scene files carry their own `seed`.

| Ref | User |
| - | - |
| `$slack_bot` | `@ancha` ("Ancha assistant"), a bot. Your agent acts as this user. |
| `$slack_ben` | Ben Carter, `ben@acme.example` |
| `$slack_rachel` | Rachel Moore, `rachel@acme.example` |
| `$slack_mike` | Mike Turner, `mike@acme.example` |
| `$slack_greg` | Greg Wilson, `greg@acme.example` |
| `$slack_laura` | Laura Kim, `laura@acme.example` |
| `$slack_tom` | Tom Hughes, `tom@acme.example` |
| `$slack_ellen` | Ellen Price, `ellen@acme.example` |
| `$slack_victor` | Victor Lane, `victor@acme.example` |
| `$slack_anna` | Anna Fischer, `anna@acme.example` |

| Ref | Channel | Members |
| - | - | - |
| `$slack_general` | `#general`, "Company updates" | Everyone, including the bot |
| `$slack_support` | `#support`, "Customer questions and follow-ups" | Bot, Ben, Mike, Greg, Laura, Anna |
| `$slack_growth` | `#growth`, "Ridgeway Robotics pilot" | Bot, Ben, Mike, Tom, Ellen |
| `$slack_orders` | `#orders-incident`, "Orders API operations" | Bot, Ben, Rachel, Greg |
| `$slack_leadership` | `#leadership`, private, "Private planning" | Ben and Mike. The bot is not a member. |
| `$slack_product` | `#product`, "Roadmap and customer feedback" | Bot, Ben, Ellen, Greg, Laura |
| `$slack_sales` | `#sales`, "Deals and pipeline" | Bot, Tom, Mike, Anna, Ben |
| `$slack_success` | `#customer-success`, "Renewals and onboarding" | Bot, Laura, Mike, Tom |
| `$slack_data` | `#data-platform`, "Warehouse sync and pipelines" | Bot, Victor, Greg, Rachel |
| `$slack_random` | `#random`, "Anything else" | Everyone except the bot |

The messages tell one story: a support channel with customer questions and answers, an Orders API incident that was rolled back two hours ago, a sales pipeline, a product roadmap and a data platform team. The ones with refs, which checks can name:

| Ref | Message |
| - | - |
| `$slack_question` | Mike in #support, 35 minutes before start: "Ridgeway Robotics cannot find last month's CSV export. Where should I point them?" |
| `$slack_answer`, `$slack_followup` | Ben's answer in that thread ("Reports → Exports. Choose the month, then Download CSV. The export can take two minutes to appear.") and Mike's thanks. |
| `$slack_access` | Ben in #support, 20 minutes before start: a second customer needs help inviting a teammate; an admin can use Settings → Members → Invite. |
| `$slack_sso`, `$slack_double`, `$slack_seats` | Three more support threads: Bluefield Logistics asking about SSO with Okta and SCIM, Kestrel Credit Union's dashboard showing yesterday's numbers twice (fixed in 4.12), and Pinecrest Health adding 20 seats mid-contract (prorated). |
| `$slack_brief`, `$slack_brief_reply` | Ben in #growth: the Ridgeway Robotics pilot is this week's focus; Mike's reply about the discovery call. |
| `$slack_case_study` | Ellen in #growth: the warehouse-to-pipeline case study draft is ready for review, with a thread. |
| `$slack_ops`, `$slack_docs` | Rachel in #orders-incident: the Orders API is healthy and the slow-request incident is resolved. Ben: a draft runbook update is in GitHub. |
| `$slack_latency` | Rachel in #orders-incident, 3 hours before start: p95 latency above 700 ms, with a thread about the 4.12.1 deploy and the rollback. |
| `$slack_welcome`, `$slack_roadmap`, `$slack_signed`, `$slack_hello_victor` | #general: a welcome, Thursday's roadmap review, Pinecrest Health signing for 120 seats, and Victor joining the data platform team. |
| `$slack_feedback`, `$slack_spec` | #product: this month's top feedback and the scheduled reports spec. |
| `$slack_renewal` | Mike in #sales: the Kestrel Credit Union renewal moves to contract next week. |
| `$slack_connector` | Victor in #data-platform: the Snowflake connector upgrade is tomorrow at 9am. |
| `$slack_private` | Ben in #leadership: a draft planning note. |
| `$slack_sourdough` | Greg in #random, about a sourdough starter. |

`ancha sandbox configuration --tools slack --json` prints every message with its text and time.

## Checks

Use `slack.message` to check what ended up in a channel:

```yaml theme={null}
- id: answered_in_thread
  state:
    slack.message:
      channel: $slack_support
      from: $slack_bot
      in_thread_of: $slack_question
      text_contains: "Exports"
```

It counts messages in `channel` that match every condition you set and passes when there are at least `count_gte` (default 1). `text_contains` ignores case. `in_thread_of` counts replies, not the parent. Set `from`, or a message from the starter history can satisfy the check. See [Checks reference](https://docs.ancha.io/reference/checks.md#slack-message).

## Limits

* Bot token only: no user OAuth and no user-token search. The bot can open and post in a direct message with one user; multi-person direct messages are not modeled.
* No file uploads, no Slack UI and no rate-limit model.
* Unsupported message arguments, such as `attachments`, `metadata` and broadcast replies, return an error and change nothing.


## Related topics

- [Test a Slack bot](https://docs.ancha.io/guides/test-a-slack-bot.md)
- [Test file (scene.yaml)](https://docs.ancha.io/reference/test-file.md)
- [Checks reference](https://docs.ancha.io/reference/checks.md)
- [Troubleshooting](https://docs.ancha.io/troubleshooting.md)
- [ancha mcp](https://docs.ancha.io/cli/mcp.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.