[{"data":1,"prerenderedAt":443},["ShallowReactive",2],{"navigation_docs":3,"-connectors-slack":139,"-connectors-slack-surround":438},[4,8,12,16,20,24,28,32,59,63,117,121,135],{"title":5,"path":6,"stem":7},"Introduction","\u002Fintroduction","1.introduction",{"title":9,"path":10,"stem":11},"Memory","\u002Fmemory","10.memory",{"title":13,"path":14,"stem":15},"Customization","\u002Fcustomization","11.customization",{"title":17,"path":18,"stem":19},"Deployment","\u002Fdeployment","12.deployment",{"title":21,"path":22,"stem":23},"Reference","\u002Freference","13.reference",{"title":25,"path":26,"stem":27},"Quickstart","\u002Fquickstart","2.quickstart",{"title":29,"path":30,"stem":31},"Installation","\u002Finstallation","3.installation",{"title":33,"icon":34,"path":35,"stem":36,"children":37,"page":58},"Connectors","i-lucide-cable","\u002Fconnectors","4.connectors",[38,42,46,50,54],{"title":39,"path":40,"stem":41},"Telegram","\u002Fconnectors\u002Ftelegram","4.connectors\u002F1.telegram",{"title":43,"path":44,"stem":45},"Slack","\u002Fconnectors\u002Fslack","4.connectors\u002F2.slack",{"title":47,"path":48,"stem":49},"Email","\u002Fconnectors\u002Femail","4.connectors\u002F3.email",{"title":51,"path":52,"stem":53},"API","\u002Fconnectors\u002Fapi","4.connectors\u002F4.api",{"title":55,"path":56,"stem":57},"Terminal","\u002Fconnectors\u002Fterminal","4.connectors\u002F5.terminal",false,{"title":60,"path":61,"stem":62},"Attachments","\u002Fattachments","5.attachments",{"title":64,"icon":65,"path":66,"stem":67,"children":68,"page":58},"Tools","i-lucide-wrench","\u002Ftools","6.tools",[69,73,77,81,85,89,93,97,101,105,109,113],{"title":70,"path":71,"stem":72},"File Manager","\u002Ftools\u002Ffile-manager","6.tools\u002F1.file-manager",{"title":74,"path":75,"stem":76},"Text-to-Speech","\u002Ftools\u002Ftext-to-speech","6.tools\u002F10.text-to-speech",{"title":78,"path":79,"stem":80},"Confirmations","\u002Ftools\u002Fconfirmations","6.tools\u002F11.confirmations",{"title":82,"path":83,"stem":84},"Adding Custom Tools","\u002Ftools\u002Fadding-custom-tools","6.tools\u002F12.adding-custom-tools",{"title":86,"path":87,"stem":88},"Image Manager","\u002Ftools\u002Fimage-manager","6.tools\u002F2.image-manager",{"title":90,"path":91,"stem":92},"Web Request","\u002Ftools\u002Fweb-request","6.tools\u002F3.web-request",{"title":94,"path":95,"stem":96},"Reminders","\u002Ftools\u002Freminders","6.tools\u002F4.reminders",{"title":98,"path":99,"stem":100},"Heartbeats","\u002Ftools\u002Fheartbeats","6.tools\u002F5.heartbeats",{"title":102,"path":103,"stem":104},"Email Manager","\u002Ftools\u002Femail-manager","6.tools\u002F6.email-manager",{"title":106,"path":107,"stem":108},"Calendar","\u002Ftools\u002Fcalendar","6.tools\u002F7.calendar",{"title":110,"path":111,"stem":112},"Read Database","\u002Ftools\u002Fread-database","6.tools\u002F8.read-database",{"title":114,"path":115,"stem":116},"Headless Browser","\u002Ftools\u002Fbrowser","6.tools\u002F9.browser",{"title":118,"path":119,"stem":120},"Tinker","\u002Ftinker","7.tinker",{"title":122,"icon":123,"path":124,"stem":125,"children":126,"page":58},"Skills","i-lucide-sparkles","\u002Fskills","8.skills",[127,131],{"title":128,"path":129,"stem":130},"Overview","\u002Fskills\u002Foverview","8.skills\u002F1.overview",{"title":132,"path":133,"stem":134},"Adding Custom Skills","\u002Fskills\u002Fadding-custom-skills","8.skills\u002F2.adding-custom-skills",{"title":136,"path":137,"stem":138},"Personas","\u002Fpersonas","9.personas",{"id":140,"title":43,"body":141,"description":431,"extension":432,"links":433,"meta":434,"navigation":435,"path":44,"seo":436,"stem":45,"__hash__":437},"docs\u002F4.connectors\u002F2.slack.md",{"type":142,"value":143,"toc":422},"minimark",[144,148,152,156,168,197,204,208,219,257,260,288,291,321,329,337,340,352,356,363,367,370,382,389,392,411,415,418],[145,146,5],"h2",{"id":147},"introduction",[149,150,151],"p",{},"The Slack connector handles direct messages with the owner and threaded conversations in any channel where the bot has been mentioned. It uses Slack's Events API.",[145,153,155],{"id":154},"webhook-authentication","Webhook Authentication",[149,157,158,159,163,164,167],{},"Every request to ",[160,161,162],"code",{},"\u002Fslack\u002Fwebhook"," is verified by the ",[160,165,166],{},"VerifySlackSignature"," middleware before any Laraclaw code touches it. The middleware:",[169,170,171,183,186],"ol",{},[172,173,174,175,178,179,182],"li",{},"Reads ",[160,176,177],{},"X-Slack-Request-Timestamp"," and ",[160,180,181],{},"X-Slack-Signature"," from the request headers. Missing either header returns 403.",[172,184,185],{},"Rejects any request whose timestamp is more than 300 seconds (5 minutes) off from the server clock — this is Slack's recommended replay window.",[172,187,188,189,192,193,196],{},"Computes ",[160,190,191],{},"v0=hash_hmac('sha256', \"v0:{timestamp}:{body}\", $signingSecret)"," and compares it to the supplied signature with ",[160,194,195],{},"hash_equals"," (timing-safe).",[149,198,199,200,203],{},"If the signing secret is wrong or missing, every Slack webhook will 403. There is no fallback path. Make sure ",[160,201,202],{},"LARACLAW_SLACK_SIGNING_SECRET"," is set in production.",[145,205,207],{"id":206},"setup","Setup",[149,209,210,211,218],{},"Create a Slack app at ",[212,213,217],"a",{"href":214,"rel":215},"https:\u002F\u002Fapi.slack.com\u002Fapps",[216],"nofollow","api.slack.com\u002Fapps"," and add the following bot token scopes:",[220,221,222,227,232,237,242,247,252],"ul",{},[172,223,224],{},[160,225,226],{},"chat:write",[172,228,229],{},[160,230,231],{},"reactions:add",[172,233,234],{},[160,235,236],{},"files:read",[172,238,239],{},[160,240,241],{},"files:write",[172,243,244],{},[160,245,246],{},"im:write",[172,248,249],{},[160,250,251],{},"im:history",[172,253,254],{},[160,255,256],{},"channels:history",[149,258,259],{},"Then run:",[261,262,267],"pre",{"className":263,"code":264,"language":265,"meta":266,"style":266},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","php artisan laraclaw:setup-connector slack\n","bash","",[160,268,269],{"__ignoreMap":266},[270,271,274,278,282,285],"span",{"class":272,"line":273},"line",1,[270,275,277],{"class":276},"sBMFI","php",[270,279,281],{"class":280},"sfazB"," artisan",[270,283,284],{"class":280}," laraclaw:setup-connector",[270,286,287],{"class":280}," slack\n",[149,289,290],{},"The wizard asks for the bot token, signing secret, bot user ID, and your Slack user ID, and writes:",[261,292,296],{"className":293,"code":294,"language":295,"meta":266,"style":266},"language-env shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","LARACLAW_SLACK_ENABLED=true\nLARACLAW_SLACK_BOT_TOKEN=xoxb-...\nLARACLAW_SLACK_SIGNING_SECRET=...\nLARACLAW_SLACK_BOT_USER_ID=U...\n","env",[160,297,298,303,309,315],{"__ignoreMap":266},[270,299,300],{"class":272,"line":273},[270,301,302],{},"LARACLAW_SLACK_ENABLED=true\n",[270,304,306],{"class":272,"line":305},2,[270,307,308],{},"LARACLAW_SLACK_BOT_TOKEN=xoxb-...\n",[270,310,312],{"class":272,"line":311},3,[270,313,314],{},"LARACLAW_SLACK_SIGNING_SECRET=...\n",[270,316,318],{"class":272,"line":317},4,[270,319,320],{},"LARACLAW_SLACK_BOT_USER_ID=U...\n",[149,322,323,324,328],{},"In your Slack app settings, point the ",[325,326,327],"strong",{},"Event Subscriptions"," request URL at:",[261,330,335],{"className":331,"code":333,"language":334},[332],"language-text","https:\u002F\u002Fyour-app.com\u002Fslack\u002Fwebhook\n","text",[160,336,333],{"__ignoreMap":266},[149,338,339],{},"Subscribe to the following bot events:",[220,341,342,347],{},[172,343,344],{},[160,345,346],{},"message.channels",[172,348,349],{},[160,350,351],{},"message.im",[145,353,355],{"id":354},"direct-messages","Direct Messages",[149,357,358,359,362],{},"Slack DMs have a channel ID starting with ",[160,360,361],{},"D",". Only the registered owner may DM the bot. Each DM is one persistent conversation, keyed by the user's Slack ID. Replies don't thread.",[145,364,366],{"id":365},"channels-and-threads","Channels and Threads",[149,368,369],{},"In channels, the bot only responds when:",[220,371,372,379],{},[172,373,374,375,378],{},"It's ",[160,376,377],{},"@mentioned"," in the message, or",[172,380,381],{},"The message is a reply in a thread the bot has already participated in.",[149,383,384,385,388],{},"Each channel conversation is keyed by ",[160,386,387],{},"channel:thread_ts",", so every thread has its own context. Replies are always posted back into the same thread.",[145,390,60],{"id":391},"attachments",[149,393,394,395,398,399,402,403,406,407,410],{},"Inbound files are downloaded with the bot token and saved to ",[160,396,397],{},"inbound\u002F{message_uuid}\u002F",". Outbound files go through Slack's external upload flow: ",[160,400,401],{},"files.getUploadURLExternal",", then a ",[160,404,405],{},"POST"," to the signed URL, then ",[160,408,409],{},"files.completeUploadExternal",".",[145,412,414],{"id":413},"confirmation-flow","Confirmation Flow",[149,416,417],{},"Confirmation prompts are stored in Redis. When the user replies in the same thread, their answer is parsed as the response and the tool either runs or is cancelled.",[419,420,421],"style",{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":266,"searchDepth":305,"depth":305,"links":423},[424,425,426,427,428,429,430],{"id":147,"depth":305,"text":5},{"id":154,"depth":305,"text":155},{"id":206,"depth":305,"text":207},{"id":354,"depth":305,"text":355},{"id":365,"depth":305,"text":366},{"id":391,"depth":305,"text":60},{"id":413,"depth":305,"text":414},"Connect Laraclaw to a Slack workspace for DMs and threaded channel conversations.","md",null,{},true,{"title":43,"description":431},"-DK5vDV4fXEzE43vELonHyxjMU0_roV1GFLg3m_cV0c",[439,441],{"title":39,"path":40,"stem":41,"description":440,"children":-1},"Wire Laraclaw up to a Telegram bot for direct messages and group chats.",{"title":47,"path":48,"stem":49,"description":442,"children":-1},"Let Laraclaw read incoming email via IMAP and reply via SMTP.",1786661906119]