# Slack Integration (n8n + Claude)

## Euno MCP Slack Integration (n8n + Claude)

The Euno MCP Slack Integration lets users query their data catalog directly from Slack. It works by connecting a Slack bot to Euno's MCP server via [n8n](https://n8n.io/), an open-source workflow automation tool, with Claude acting as the AI layer in between.

This setup is an example implementation — teams can adapt it to their own n8n configuration and Slack workspace.

> **Note:** This template is designed for Anthropic's Claude, which supports MCP natively via the `mcp_toolset` type. Adapting it to other providers may require changes to the API request format.

***

### How It Works

When a user mentions the Slack bot, n8n captures the message and forwards it to Claude via the Anthropic Messages API. Claude connects to Euno's MCP server to retrieve relevant metadata and returns an answer, which n8n posts back into the Slack thread.

```
Slack ──► n8n ──► Claude ──► Euno MCP
            ▲         │
            └─────────┘
Slack ◄── n8n
```

Each Slack thread maintains conversation context — follow-up questions are aware of previous exchanges in the same thread.

***

### Prerequisites

Before setting up the integration, you'll need:

* **n8n instance** — self-hosted or cloud. See [n8n docs](https://docs.n8n.io/) for setup.
* **Anthropic API key** — available from the [Anthropic Console](https://console.anthropic.com/)
* **Euno API key and Account ID** — available in your Euno account settings
* **Slack app with bot token** — a Slack app installed in your workspace with the following scopes:
  * `app_mentions:read` — receive @mention events
  * `chat:write` — post messages
  * `channels:history` — read thread history in public channels
  * `groups:history` — read thread history in private channels
  * `im:history` — read thread history in direct messages (if DM support is needed)

***

### Setup

#### 1. Create a Slack App

1. Go to [api.slack.com/apps](https://api.slack.com/apps) and click **Create New App**
2. Choose **From scratch**, give it a name (e.g. `Euno Data Bot`) and select your workspace
3. Under **OAuth & Permissions**, add the bot token scopes listed above
4. Install the app to your workspace and copy the **Bot User OAuth Token**
5. Under **Event Subscriptions**, enable events and subscribe to `app_mention`
6. Invite the bot to the Slack channels where you want it to be available

#### 2. Configure n8n Credentials

In n8n, add a **Slack** credential using the Bot User OAuth Token from step 1. For the Anthropic API key, you can either hardcode it in the HTTP Request node header (simpler) or store it as an n8n **Header Auth** credential (`x-api-key`) and reference it in the node (more secure — the key is encrypted in n8n's credential store and not visible in the workflow JSON).

#### 3. Set Up the n8n Workflow

You can build the workflow from scratch or use the example template provided in the Workflow section below as a starting point.

If using the template:

1. In n8n, go to **Workflows → Import from JSON** and import the file
2. Replace the placeholders with your own values:
   * `YOUR_SLACK_CREDENTIAL_ID` — your n8n Slack credential
   * `YOUR_ANTHROPIC_API_KEY` — your Anthropic API key
   * `YOUR_EUNO_API_KEY` — your Euno API key
   * `YOUR_ACCOUNT_ID` — your Euno account ID
3. Activate the workflow

***

### Workflow

The workflow consists of 6 nodes:

| Node                | Type          | Description                                                                                           |
| ------------------- | ------------- | ----------------------------------------------------------------------------------------------------- |
| **Slack Trigger**   | Slack Trigger | Listens for `app_mention` events (and optionally `message.im` for DMs)                                |
| **Edit Fields**     | Set           | Extracts the user's message text and thread timestamp                                                 |
| **Get Thread**      | HTTP Request  | Fetches the full thread history via `conversations.replies` for multi-turn context                    |
| **Format Messages** | Code          | Converts the thread history into Claude's message format (user/assistant roles, strips bot @mentions) |
| **HTTP Request**    | HTTP Request  | Calls the Anthropic Messages API with the Euno MCP server and prompt caching enabled                  |
| **Send a message**  | Slack         | Posts Claude's response back as a thread reply                                                        |

#### Example Template

Download [euno-slack-bot.json](/ai-assistant/slack-integration-n8n-+-claude/euno-slack-bot-json.md) (located in the same directory as this document in the repository) and import it into n8n via **Workflows → Import from JSON**. Replace all `YOUR_*` placeholders before activating.

***

### Webhook Variant

The template above uses n8n's native **Slack Trigger** node, which handles the Slack connection via OAuth. Some setups may require a **Webhook-based** approach instead — for example, if you need to handle Slack's URL verification challenge, or if your n8n instance is behind a proxy.

The key differences:

|                          | Slack Trigger                  | Webhook                                         |
| ------------------------ | ------------------------------ | ----------------------------------------------- |
| **Setup**                | Simpler — OAuth handled by n8n | Requires manual URL verification handling       |
| **Slack event delivery** | Events API                     | Events API                                      |
| **URL verification**     | Handled automatically          | Requires a dedicated response node              |
| **Retry handling**       | Automatic                      | Must filter `x-slack-retry-num` header manually |

In the Webhook variant, the flow starts with a **Webhook** node instead of a Slack Trigger. An **If** node then splits the flow: URL verification challenges are responded to immediately, while real messages continue to Claude. A **Respond to Webhook** node must also acknowledge the request within 3 seconds to prevent Slack from retrying.

**Use the Slack Trigger variant** unless you have a specific reason to use webhooks.

***

### Token Cost & Caching

Because n8n is stateless, every Slack message triggers a fresh API call to Claude. Without caching, Claude re-fetches all MCP tool definitions on every message — roughly 27,000 input tokens per request (depending on your account configuration).

The template addresses this with **Anthropic prompt caching**. The `cache_control` setting on the `mcp_toolset` tells Anthropic to cache the tool definitions:

```json
"tools": [{ "type": "mcp_toolset", "mcp_server_name": "euno", "cache_control": { "type": "ephemeral", "ttl": "1h" } }]
```

The `ttl` field controls cache duration — `"5m"` (default) or `"1h"`. The template uses `"1h"`, which costs 2x the standard cache write price but survives gaps between messages. Omitting `ttl` defaults to 5 minutes.

The beta header enables both MCP and caching — check [Anthropic's MCP docs](https://docs.anthropic.com/en/docs/build-with-claude/mcp) for the latest value:

```
anthropic-beta: mcp-client-2025-11-20,prompt-caching-2024-07-31
```

#### What to expect

* **First message in a session** — cache is created. Input tokens will be higher (\~27K) and cost slightly more. This is expected.
* **Subsequent messages** — cache is read. Billed input tokens drop to \~350, reducing cost significantly.
* **Cache expiry** — after 1 hour since the last Anthropic API call, the next message re-warms the cache.
* **Complex queries** — queries requiring multiple tool calls will naturally cost more, regardless of caching.

> Costs vary by model and Anthropic's pricing. Check [Anthropic's pricing page](https://www.anthropic.com/pricing) for current rates.

***

### Slack Bot Persona (Optional)

You can create a dedicated **Euno persona** for the Slack bot to control how Claude behaves when responding to Slack users — tone, formatting, URL style, and response length.

This is optional. Without a persona, Claude uses your account-level instructions. A dedicated persona is useful when you want Slack-specific behavior that differs from how Claude behaves in other contexts (e.g. the Euno web assistant).

#### Creating the Persona

1. In Euno, go to **Settings → Personas** and click **Add Persona**
2. Set the **Name** to something identifiable (e.g. `slack_bot`)
3. Set the **Permission set** appropriate for your users (e.g. `Maintainer`)
4. Assign the service account user associated with your Euno API key
5. Add **AI Instructions** tailored for Slack (see example below)

#### Example AI Instructions

```
This persona is for conversing with business users over Slack.

STRICT RULES:
- Maximum 3-5 sentences per response
- No lengthy introductions or conclusions
- No "I'll help you..." preamble — just answer directly
- Use bullet points only when listing 3+ items
- Never repeat the question back
- If you need to look something up, do it silently without narrating your steps

Text formatting (Slack uses different markdown than standard):
- Use *bold* not **bold**
- Use _italic_ not *italic* (in Slack, * means bold)
- Never use ## or ### headers — use *Bold Text* instead
- Use • for bullet points, not * or -
- Links must be formatted as <URL|display text>
- Never use backtick code blocks for regular text
```

The example above covers generic Slack behavior. You may also want to add customer-specific instructions, such as how to format or resolve links to your BI tool (e.g. resolving Euno proxy URLs to native Looker or Tableau URLs).

**Tip:** Formatting instructions in the persona reduce inconsistencies, but for fully reliable output formatting consider also adding a post-processing step in n8n to convert Claude's markdown to Slack format programmatically.

***

### Troubleshooting

**Duplicate bot responses**\
Slack retries events that don't receive a response within 3 seconds. If your workflow is slow, Slack may send the same event multiple times. Filter these out by checking the `x-slack-retry-num` header in your workflow — if it exists, return a 200 immediately without processing.

**MCP server unreachable or auth errors**\
Verify your Euno API key and Account ID are correct. The MCP URL format is `https://api.app.euno.ai/mcp?account_id=YOUR_ACCOUNT_ID&api_key=YOUR_EUNO_API_KEY`.

**High cost on first message after idle period**\
This is expected — the cache expires after 1 hour since the last Anthropic API call and is re-created on the next message. Subsequent messages in the session will be cheap again.

**Bot not responding in a channel**\
Make sure the bot has been invited to the channel (`/invite @your-bot-name`) and that the channel is included in your Event Subscriptions configuration.

**Thread history missing or incomplete**\
If `conversations.replies` returns an error or empty list, the bot will still respond but without prior context — it will treat the message as a fresh conversation. This can happen if the Slack API rate limit is hit or if the bot lacks permission to read the channel. Check that the correct history scopes (`channels:history`, `groups:history`) are granted and that the bot is a member of the channel.

***

### Security

* **Anthropic API key** — stored directly in the workflow node by default. For production, use n8n's credential manager instead (Header Auth with `x-api-key`) — the key is then encrypted at rest and not visible in the workflow JSON.
* **Euno API key** — passed as a URL query parameter (`api_key=...`). This is a known trade-off of the MCP protocol. Ensure your n8n instance communicates with Euno over HTTPS (the default) to prevent the key from being exposed in transit.
* **Slack request verification** — the Slack Trigger node verifies incoming requests using your app's signing secret automatically. If you use the Webhook variant instead, implement signing secret verification manually to prevent spoofed events.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.euno.ai/ai-assistant/slack-integration-n8n-+-claude.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
