← Vytvářejte agenty na Cloudflare / agents / examples
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:
- Reagovat na přímé zprávy
- Odpovídejte, když jste zmíněni v kanálech
- Udržujte kontext konverzace ve vláknech
- Použití AI ke generování inteligentních odpovědí
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:
- A účet Cloudflare ↗
- Node.js ↗ nainstalovaný (v18 nebo novější)
- A workspace Slacku ↗ kde máte oprávnění instalovat aplikace
- OpenAI API key ↗ (nebo jiný poskytovatel LLM)
1. Vytvořte Slack App
Nejprve vytvořte novou Slack App, kterou bude váš agent používat ke komunikaci se Slackem:
- Přejděte na api.slack.com/apps ↗ a vyberte Create New App.
- Vyberte Od nuly.
- Pojmenujte svou aplikaci (například „Můj AI asistent“) a vyberte svůj pracovní prostor.
- 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:
chat:write: Odesílejte zprávy jako botchat:write.public: Odesílejte zprávy do kanálů bez nutnosti se k nim připojitchannels:history: Prohlížejte zprávy ve veřejných kanálechapp_mentions:read: Přijímejte zmínkyim:write: Odesílejte přímé zprávyim:history: Prohlížejte historii přímých zpráv
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:
app_mention: Když je bot zmíněn pomocí @message.im: Přímé zprávy pro 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:
- 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
- Vytvořte nový projekt pro svého Slack Agenta:
npm create cloudflare@latest -- my-slack-agent- Přejděte do svého projektu:
cd my-slack-agent- Nainstalujte požadované závislosti:
npm install agents openai3. Nastavte proměnné prostředí
- Vytvořte
.envsoubor v kořenovém adresáři projektu pro lokální vývojové secrets:
touch .env- 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"- Aktualizujte
wrangler.jsoncpro 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
-
Nejprve vytvořte základní
SlackAgenttřída nasrc/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 ↗. -
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 devVáš 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:8787Výstupem bude veřejná URL adresa podobná https://random-subdomain.trycloudflare.com.
Vraťte se do nastavení své Slack App:
-
Přejděte na Odběry událostí.
-
Přepnout Povolte Events na On.
-
Zadejte Request URL:
https://random-subdomain.trycloudflare.com/slack. -
Slack odešle ověřovací požadavek: pokud váš agent běží správně, měl by zobrazit Ověřeno.
-
V části Přihlášení k odběru událostí bota, přidejte:
app_mentionmessage.im
-
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é:
- Odešlete DM svému botovi: měl by odpovědět zprávou vygenerovanou pomocí AI.
- 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
- 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- Nasaďte svého agenta:
npx wrangler deployPo nasazení získáte produkční URL adresu, například:
https://my-slack-agent.your-account.workers.devAktualizace Slack Event Subscriptions
Vraťte se do nastavení své Slack App:
- Přejděte na Odběry událostí.
- Aktualizujte Request URL na svou produkční URL:
https://my-slack-agent.your-account.workers.dev/slack. - Vyberte Uložit změny.
Distribuujte svou aplikaci
Nyní, když je váš agent nasazený, můžete ho sdílet s ostatními:
- Jeden pracovní prostor: Nainstalujte ho pomocí
https://my-slack-agent.your-account.workers.dev/install. - Veřejná distribuce: Odešlete svou aplikaci do Slack App Directory ↗.
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:
- Každý workspace má vlastní
team_idse použije jako ID Durable Object. - Každá instance agenta ukládá vlastní přístupový token Slacku do úložiště KV.
- Konverzace se načítají na vyžádání z API Slacku.
- Veškerá logika agenta běží v izolovaném, konzistentním prostředí.
OAuth flow
Agent zpracovává tok OAuth 2.0 služby Slack:
- Uživatel navštíví
/install> přesměrováno na autorizaci Slacku. - Uživatel vybere Allow > Slack přesměruje na
/accepts autorizačním kódem. - Agent vymění kód za přístupový token.
- Agent uloží token do Durable Object daného pracovního prostoru.
Zpracování událostí
Když Slack odešle událost:
- Požadavek dorazí na
/slackkoncový bod. - Agent ověří podpis požadavku pomocí HMAC-SHA256.
- Agent směruje událost do Durable Object správného pracovního prostoru.
onSlackEventmetoda 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
- Přidejte Slack Interactive Components ↗ (tlačítka, modální okna)
- Připojte svého Agenta k server MCP
- Přidání omezování rychlosti požadavků pro prevenci zneužití
- Správa stavu konverzace
- Použijte Workers Analytics Engine ke sledování využití
- Přidejte plány pro naplánované úlohy