INTEGRITY Dokumentace

Slack agent

Nasaďte svého prvního Slack Agenta

Tento návod vám ukáže, jak sestavit a nasadit na Cloudflare Workers Slack bota poháněného AI, který dokáže:

Váš Slack agent bude multitenantní aplikace, což znamená, že jedno nasazení může obsluhovat více pracovních prostorů Slacku. Každý pracovní prostor získá vlastní izolovanou instanci agenta s vyhrazeným úložištěm, poháněnou Agents SDK.

Úplný kód tohoto příkladu najdete zde ↗.

Předpoklady

Než začnete, budete potřebovat:

1. Vytvořte Slack App

Nejprve vytvořte novou Slack App, kterou bude váš agent používat ke komunikaci se Slackem:

  1. Přejděte na api.slack.com/apps ↗ a vyberte Create New App.
  2. Vyberte Od nuly.
  3. Pojmenujte svou aplikaci (například „Můj AI asistent“) a vyberte svůj pracovní prostor.
  4. Vyberte Create App.

Konfigurace OAuth & Permissions

V nastavení vaší Slack aplikace přejděte na OAuth & Permissions a přidejte následující Bot Token Scopes:

Povolte Event Subscriptions

Adresu URL Event Subscriptions nakonfigurujete později, po nasazení agenta. Prozatím přejděte na Odběry událostí v nastavení vaší Slack App a připravte se na jeho povolení.

Přihlaste se k odběru následujících událostí bota:

Zatím to nezapínejte. Zapnete to až po nasazení.

Získejte přihlašovací údaje Slack

V nastavení vaší Slack App shromážděte tyto hodnoty:

  1. Základní informace > Přihlašovací údaje aplikace:
    • Client ID
    • Client Secret
    • Signing Secret

Mějte je po ruce, budete je potřebovat v dalším kroku.

2. Vytvořte svůj projekt Slack Agent

  1. Vytvořte nový projekt pro svého Slack Agenta:
npm create cloudflare@latest -- my-slack-agent
  1. Přejděte do svého projektu:
cd my-slack-agent
  1. Nainstalujte požadované závislosti:
npm install agents openai

3. Nastavte proměnné prostředí

  1. Vytvořte .env soubor v kořenovém adresáři projektu pro lokální vývojové secrets:
touch .env
  1. Přidejte své přihlašovací údaje do .env:
SLACK_CLIENT_ID="your-slack-client-id"
SLACK_CLIENT_SECRET="your-slack-client-secret"
SLACK_SIGNING_SECRET="your-slack-signing-secret"
OPENAI_API_KEY="your-openai-api-key"
OPENAI_BASE_URL="https://gateway.ai.cloudflare.com/v1/YOUR_ACCOUNT_ID/YOUR_GATEWAY/openai"
  1. Aktualizujte wrangler.jsonc pro konfiguraci vašeho Agenta:
{
	"$schema": "./node_modules/wrangler/config-schema.json",
	"name": "my-slack-agent",
	"main": "src/index.ts",
	// Set this to today's date
	"compatibility_date": "2026-08-28",
	"compatibility_flags": [
		"nodejs_compat"
	],
	"durable_objects": {
		"bindings": [
			{
				"name": "MyAgent",
				"class_name": "MyAgent",
				"script_name": "my-slack-agent"
			}
		]
	},
	"migrations": [
		{
			"tag": "v1",
			"new_classes": [
				"MyAgent"
			]
		}
	]
}
"$schema" = "./node_modules/wrangler/config-schema.json"
name = "my-slack-agent"
main = "src/index.ts"
# Set this to today's date
compatibility_date = "2026-08-28"
compatibility_flags = [ "nodejs_compat" ]

[[durable_objects.bindings]]
name = "MyAgent"
class_name = "MyAgent"
script_name = "my-slack-agent"

[[migrations]]
tag = "v1"
new_classes = [ "MyAgent" ]

4. Vytvořte svého Slack Agenta

  1. Nejprve vytvořte základní SlackAgent třída na src/slack.ts. Tato třída se stará o OAuth, ověřování požadavků a směrování událostí. Můžete si prohlédnout úplná implementace na GitHubu ↗.

  2. Nyní vytvořte implementaci svého agenta na src/index.ts:

import { env } from "cloudflare:workers";
import { SlackAgent } from "./slack";
import { OpenAI } from "openai";

const openai = new OpenAI({
	apiKey: env.OPENAI_API_KEY,
	baseURL: env.OPENAI_BASE_URL,
});

type SlackMsg = {
	user?: string;
	text?: string;
	ts: string;
	thread_ts?: string;
	subtype?: string;
	bot_id?: string;
};

function normalizeForLLM(msgs: SlackMsg[], selfUserId: string) {
	return msgs.map((m) => {
		const role = m.user && m.user !== selfUserId ? "user" : "assistant";
		const text = (m.text ?? "").replace(/<@([A-Z0-9]+)>/g, "@$1");
		return { role, content: text };
	});
}

export class MyAgent extends SlackAgent {
	async generateAIReply(conversation: SlackMsg[]) {
		const selfId = await this.ensureAppUserId();
		const messages = normalizeForLLM(conversation, selfId);

		const system = `You are a helpful AI assistant in Slack.
Be brief, specific, and actionable. If you're unsure, ask a single clarifying question.`;

		const input = [{ role: "system", content: system }, ...messages];

		const response = await openai.chat.completions.create({
			model: "gpt-4o-mini",
			messages: input,
		});

		const msg = response.choices[0].message.content;
		if (!msg) throw new Error("No message from AI");

		return msg;
	}

	async onSlackEvent(event: { type: string } & Record<string, unknown>) {
		// Ignore bot messages and subtypes (edits, joins, etc.)
		if (event.bot_id || event.subtype) return;

		// Handle direct messages
		if (event.type === "message") {
			const e = event as unknown as SlackMsg & { channel: string };
			const isDM = (e.channel || "").startsWith("D");
			const mentioned = (e.text || "").includes(
				`<@${await this.ensureAppUserId()}>`,
			);

			if (!isDM && !mentioned) return;

			const conversation = await this.fetchConversation(e.channel);
			const content = await this.generateAIReply(conversation);
			await this.sendMessage(content, { channel: e.channel });
			return;
		}

		// Handle @mentions in channels
		if (event.type === "app_mention") {
			const e = event as unknown as SlackMsg & {
				channel: string;
				text?: string;
			};
			const thread = await this.fetchThread(e.channel, e.thread_ts || e.ts);
			const content = await this.generateAIReply(thread);
			await this.sendMessage(content, {
				channel: e.channel,
				thread_ts: e.thread_ts || e.ts,
			});
			return;
		}
	}
}

export default MyAgent.listen({
	clientId: env.SLACK_CLIENT_ID,
	clientSecret: env.SLACK_CLIENT_SECRET,
	slackSigningSecret: env.SLACK_SIGNING_SECRET,
	scopes: [
		"chat:write",
		"chat:write.public",
		"channels:history",
		"app_mentions:read",
		"im:write",
		"im:history",
	],
});

5. Otestujte lokálně

Spusťte svůj vývojový server:

npm run dev

Váš agent nyní běží na adrese http://localhost:8787.

Konfigurace Slack Event Subscriptions

Nyní, když váš agent běží lokálně, musíte ho zpřístupnit Slacku. Použijte Cloudflare Tunnel pro vytvoření zabezpečeného tunelu:

npx cloudflared tunnel --url http://localhost:8787

Výstupem bude veřejná URL adresa podobná https://random-subdomain.trycloudflare.com.

Vraťte se do nastavení své Slack App:

  1. Přejděte na Odběry událostí.

  2. Přepnout Povolte Events na On.

  3. Zadejte Request URL: https://random-subdomain.trycloudflare.com/slack.

  4. Slack odešle ověřovací požadavek: pokud váš agent běží správně, měl by zobrazit Ověřeno.

  5. V části Přihlášení k odběru událostí bota, přidejte:

    • app_mention
    • message.im
  6. Vyberte Uložit změny.

Instalace aplikace do Slacku

Navštivte http://localhost:8787/install ve vašem prohlížeči. Přesměruje vás to na autorizační stránku Slacku. Vyberte Allow k instalaci aplikace do vašeho workspace.

Po autorizaci byste ve svém prohlížeči měli vidět zprávu „Successfully registered!“.

Otestujte svého agenta

Otevřete Slack. Poté:

  1. Odešlete DM svému botovi: měl by odpovědět zprávou vygenerovanou pomocí AI.
  2. Zmiňte svého bota v kanálu (např. @My AI Assistant hello), měl by odpovídat ve vlákně.

Pokud vše funguje, jste připraveni nasadit do produkčního prostředí!

6. Nasaďte do produkce

  1. Před nasazením přidejte své tajné klíče do Cloudflare:
npx wrangler secret put SLACK_CLIENT_ID
npx wrangler secret put SLACK_CLIENT_SECRET
npx wrangler secret put SLACK_SIGNING_SECRET
npx wrangler secret put OPENAI_API_KEY
npx wrangler secret put OPENAI_BASE_URL
  1. Nasaďte svého agenta:
npx wrangler deploy

Po nasazení získáte produkční URL adresu, například:

https://my-slack-agent.your-account.workers.dev

Aktualizace Slack Event Subscriptions

Vraťte se do nastavení své Slack App:

  1. Přejděte na Odběry událostí.
  2. Aktualizujte Request URL na svou produkční URL: https://my-slack-agent.your-account.workers.dev/slack.
  3. Vyberte Uložit změny.

Distribuujte svou aplikaci

Nyní, když je váš agent nasazený, můžete ho sdílet s ostatními:

Každý workspace, který nainstaluje vaši aplikaci, získá vlastní izolovanou instanci agenta s vyhrazeným úložištěm.

Jak to funguje

Multitenance pomocí Durable Objects

Váš Slack agent používá Durable Objects k poskytnutí izolovaných stavových instancí pro každý workspace Slacku:

OAuth flow

Agent zpracovává tok OAuth 2.0 služby Slack:

  1. Uživatel navštíví /install > přesměrováno na autorizaci Slacku.
  2. Uživatel vybere Allow > Slack přesměruje na /accept s autorizačním kódem.
  3. Agent vymění kód za přístupový token.
  4. Agent uloží token do Durable Object daného pracovního prostoru.

Zpracování událostí

Když Slack odešle událost:

  1. Požadavek dorazí na /slack koncový bod.
  2. Agent ověří podpis požadavku pomocí HMAC-SHA256.
  3. Agent směruje událost do Durable Object správného pracovního prostoru.
  4. onSlackEvent metoda zpracuje událost a vygeneruje odpověď.

Přizpůsobení agenta

Změňte AI model

Aktualizujte model v src/index.ts:

const response = await openai.chat.completions.create({
	model: "gpt-4o", // or any other model
	messages: input,
});

Přidání paměti konverzace

Ukládejte historii konverzace do úložiště Durable Object:

async storeMessage(channel: string, message: SlackMsg) {
  const history = await this.ctx.storage.kv.get(`history:${channel}`) || [];
  history.push(message);
  await this.ctx.storage.kv.put(`history:${channel}`, history);
}

Reagujte na konkrétní klíčová slova

Přidejte vlastní logiku do onSlackEvent:

async onSlackEvent(event: { type: string } & Record<string, unknown>) {
  if (event.type === "message") {
    const e = event as unknown as SlackMsg & { channel: string };

    if (e.text?.includes("help")) {
      await this.sendMessage("Here's how I can help...", {
        channel: e.channel
      });
      return;
    }
  }

  // ... rest of your event handling
}

Použití různých poskytovatelů LLM

Nahraďte OpenAI za Workers AI:

import { Ai } from "@cloudflare/ai";

export class MyAgent extends SlackAgent {
	async generateAIReply(conversation: SlackMsg[]) {
		const ai = new Ai(this.ctx.env.AI);
		const response = await ai.run("@cf/meta/llama-3-8b-instruct", {
			messages: normalizeForLLM(conversation, await this.ensureAppUserId()),
		});
		return response.response;
	}
}

Další kroky

Dokumentace Agents

Kompletní dokumentace frameworku Agents.

Durable Objects

Přečtěte si o podkladové stavové infrastruktuře.

Slack API

Oficiální dokumentace Slack API.

OpenAI API

Oficiální dokumentace OpenAI API.