DEV Community

Rock
Rock

Posted on

Wiring n8n into Slack: @mention the bot to run an automation workflow

Scenario

The team works in Slack; the automations live in n8n. Sending a release notice means someone leaving the channel, opening n8n, clicking Execute and pasting the result back.

Making the conversation the entry point takes two decisions on the bot side: who runs it — the message goes to n8n, not a model — and what runs — one Slack turn maps onto one n8n webhook. On 4.10 both meant a glue service you maintained; 4.11 makes "who runs it" a plugin: a processor picks a plugin-provided executor under Runner, and n8n is one. An @mention here reaches one n8n workflow, and its answer comes back.

How it works in 4.11

Runners come from plugins. 4.11 moved the built-in runners out of the host. n8n is the official langbot-team/N8nAgent plugin, runner id plugin:langbot-team/N8nAgent/default (source LangBot/docs/agent-runner-pluginization/OFFICIAL_RUNNER_PLUGINS.md:30); the same document puts it in Batch 2, the external-workflow batch with langflow-agent (webhook/workflow in and out, timeout, external conversation id, :46), and says the old built-in runner code offers no runtime fallback (:22).

Runner settings live on the processor. With method Agent and n8n under Runner, the fields appear on the AI capability tab — not the plugin page, which reports none. Fields measured 2026-10-16 on v4.11.0: Webhook URL, auth type (none here), response handling (forward as chat reply), provider user identity (sender), an "enable LangBot assets" toggle. One n8n call's ingress and egress sit on this page.

Event routing only answers "event → processor". The bot detail page binds an event pattern to a processor. An EventBinding carries id, event_pattern, target_type(agent|pipeline|discard), target_uuid, filters, priority, enabled, description; matching drops enabled=false, checks event_pattern and the filters, requires the target to declare support, takes the highest priority (ties by list order), and runs exactly one response target (official docs docs/event-based-agents/04-event-routing.md §3). External systems — Webhook, Dify, n8n, Coze — are served by the matching Runner plugin, and a plugin EventListener is not a third response-target type (§1).

What decides whether it fires is the processor's trigger conditions: key at (UI label @, description "Whether to trigger when the message mentions the bot"), from LangBot/src/langbot/templates/metadata/pipeline/trigger.yaml:19-23; the same page holds group response rules, access control, message-ignore rules and aggregation. at defaults to false in the source template; this instance shows it checked — that processor's value, not a factory default. The same restriction can live on the binding: filters offer chat_type, chat_id, message_text, message_element_types, and message_element_types supports contains, not_contains over At, AtAll (source LangBot/web/src/app/home/bots/components/bot-form/EventBindingsEditor.tsx:146-183). [Inference] The trigger condition belongs to the pipeline chain's response rules (src/langbot/pkg/pipeline/pipelinemgr.py:43; the @ rule at src/langbot/pkg/pipeline/resprule/rules/atbot.py:34), while agent routing goes through Runner Host orchestration (official docs docs/event-based-agents/04-event-routing.md §4.2) — not the same switch.

The Slack side. Fields, from LangBot/src/langbot/pkg/platform/sources/slack.yaml: bot_token (Bot Token, required), socket_mode (Socket Mode, default false), app_token (App-Level Token in socket mode, xapp- with connections:write), webhook_url (Webhook Callback URL, non-socket mode), signing_secret (non-socket mode). Socket Mode on means no public callback URL. Support depends on the adapter and platform — check the support matrix first.

Hands-on steps

Start a local demo instance (commands from this series' measured environment):

docker network create a4
docker run -d --name a4-core --network a4 --restart on-failure -e TZ=Asia/Shanghai \
  -e BOX__ENABLED=false -e SPACE__DISABLE_TELEMETRY=true -p 15800:5300 \
  -v "$PWD/deploy/a4/data:/app/data" rockchin/langbot:v4.11.0
docker run -d --name a4-runtime --network a4 --network-alias langbot_plugin_runtime --restart on-failure \
  -e TZ=Asia/Shanghai -e SPACE__DISABLE_TELEMETRY=true -v "$PWD/deploy/a4/data/plugins:/app/data/plugins" \
  rockchin/langbot:v4.11.0 uv run --no-sync -m langbot_plugin.cli.__init__ rt
Enter fullscreen mode Exit fullscreen mode

Admin demo@langbot.local / LangBot411!demo (local demo value — replace with your own).

1. Create the Slack bot

Bots → New → platform Slack; fill in the Slack app's Bot Token, scopes at least chat:write and app_mentions:read. With this demo's placeholder token, slack.com/api/auth.test errors follow — expected: the article verifies the message → n8n path.

Slack adapter: Bot Token, Socket Mode, callback URL

2. Install the n8n Runner plugin

Marketplace → search n8n → install N8nAgent (v0.2.0, langbot-team); it shows up under /home/extensions beside the built-in LocalAgent.

Marketplace search hit for N8nAgent

Installed plugins: LocalAgent and N8nAgent v0.2.0

3. Create the processor and pick the Runner

Processors → New → method Agent → Runner n8n.

The n8n option in the Runner picker

Set Webhook URL on the AI capability tab to an address the runtime container can reach: both containers share Docker network a4 with the n8n alias n8n, so the value is http://n8n:5678/webhook/langbot-slack (local demo value — replace with your own); use the 127.0.0.1 form only if the whole chain shares a single network namespace.

AI capability tab: Webhook URL and response handling

4. Build the n8n workflow

A Webhook node (HTTP Method POST, Path langbot-slack, Response Mode Respond to Webhook) into a Respond to Webhook node returning JSON, e.g. {"text": "n8n 收到:{{ $json.body.text }}(工作流已执行)"}; save and activate it.

5. Bind the event route

Bot detail page → Event Routing → one route: event pattern message.received, target the new processor; the filter panel can add message_element_types contains At to restrict it to @-carrying messages.

Event routing: message.received → the processor

6. Confirm the trigger condition

On the trigger conditions tab, confirm @ under group response rules is checked — it is here; in the source template at defaults to false.

Verify

One thing to verify: whether the runtime container can turn a message into one HTTP call that lands on the n8n webhook. This bypasses Slack — POST the address from another container:

docker exec a4-core python3 -c 'import json,urllib.request as u
r=u.urlopen(u.Request("http://n8n:5678/webhook/langbot-slack",
  data=json.dumps({"text":"@langbot 发一版通知"}).encode(),
  headers={"Content-Type":"application/json"}),timeout=20)
print(r.status, r.read().decode())'
Enter fullscreen mode Exit fullscreen mode

A working probe returns the JSON the Respond to Webhook node builds; with the workflow inactive the path is unregistered and the request fails. The measured result and control run (2026-10-16) are in series/langbot-4.11-release/evidence/demo-test-records.md.

Limits and caveats

  • A Runner is a plugin, not a host feature. The old built-in runner code provides no runtime fallback (docs/agent-runner-pluginization/OFFICIAL_RUNNER_PLUGINS.md:22), so n8n presupposes the plugin on the runtime.
  • at is instance state, not a factory default (LangBot/src/langbot/templates/metadata/pipeline/trigger.yaml:19-23).
  • One event, one response target (docs/event-based-agents/04-event-routing.md §3): a second route on message.received does not make n8n run twice — check the route first.
  • The Webhook URL must be reachable from the runtime container, not your browser: one that answers curl on the host can fail in the container.
  • Slack was not verified end to end: the demo bot's placeholder token means this article covers the message → webhook path only.

Summary and next steps

The conversation is the entry point, event routing decides who runs it, and the Runner plugin is the bridge: install langbot-team/N8nAgent, point a processor's Webhook URL at one n8n webhook, bind message.received to that processor — an @mention becomes one workflow run whose reply returns to the channel.

Primary reference: the pinned migration doc docs/pipeline-migration-config-map.zh-CN.md and the v4.11.0 release page. Article 2 covers Runner plugin sources; article 3 covers upgrading from 4.10. Managed hosting is only a conditional secondary option at space.langbot.app; this article makes no promise about it.

Top comments (1)

Collapse
 
rushdeploy profile image
Rishabh Mishra •

One thing worth adding, since Slack isn't verified end-to-end here: Slack requires an ack within 3 seconds, so any n8n workflow that runs longer should reply immediately and post the result later via response_url. Otherwise the thread silently times out.