72322a4d72
## Summary Lets workspace members talk to the Twenty CRM agent from Slack — `@mention` the bot in a channel or DM it, and it answers in-thread using the `slack-assistant` agent and its assigned role. ## How it works Slack Events webhook → app route verifies signature → **ack in <3s** and enqueue a `slackAssistantRequest` → worker posts a placeholder immediately, then fetches recent thread/DM history (excluding the current message and placeholder), runs `runAgent`, and updates the placeholder with the answer. After a successful reply, the thread stays subscribed (24h TTL, renewed on each reply) so follow-ups work without re-mentioning. ## App-owned orchestration Protocol + orchestration live in `twenty-apps/public/twenty-slack` (events resolver, enqueue, worker, team claim KV, thread subscription). The server provides shared primitives (app routes, `runAgent`, app KV, connection OAuth). ## Notes - Agent role is bound via `roleUniversalIdentifier` on install. Default **Slack Assistant** role: read/create/update/soft-delete on people, companies, opportunities, notes, and tasks; **workspace members stay read-only**; hard destroy stays off. Admins can tighten the role in Settings. - Setup (signing secret, event subscriptions, scopes) is in the app README. - Long-lived Slack bot tokens (no refresh token) are treated as non-expiring. - Multi-turn: recent Slack thread/DM messages are prepended into the agent prompt. - Replies are non-streaming for now (placeholder + final `chat.update`); progressive streaming is a follow-up. ## Follow-ups - **Streaming replies** — progressive edits while the agent runs. - **Per-user / per-channel permissions** — Slack→Twenty user mapping and optional channel rules (open by default; admins can narrow). - **Other platforms** — Discord/Teams can reuse the same patterns; only Slack protocol is in this PR. ## Screenshots https://github.com/user-attachments/assets/3a72770a-93fa-411d-b4aa-2f741afbcee1 <img width="426" height="686" alt="Screenshot 2026-07-27 at 3 58 38 PM" src="https://github.com/user-attachments/assets/b0a62e7c-c5e4-4c96-9389-5e47d7ef8c77" /> <img width="1053" height="726" alt="Screenshot 2026-07-29 at 12 54 45 AM" src="https://github.com/user-attachments/assets/4e14b3fb-fbe5-4f4d-a380-cc45cc60a01a" />
43 lines
923 B
JSON
43 lines
923 B
JSON
{
|
|
"compileOnSave": false,
|
|
"compilerOptions": {
|
|
"sourceMap": true,
|
|
"declaration": true,
|
|
"outDir": "./dist",
|
|
"rootDir": ".",
|
|
"jsx": "react-jsx",
|
|
"moduleResolution": "bundler",
|
|
"allowSyntheticDefaultImports": true,
|
|
"emitDecoratorMetadata": true,
|
|
"experimentalDecorators": true,
|
|
"importHelpers": true,
|
|
"allowUnreachableCode": false,
|
|
"strict": true,
|
|
"alwaysStrict": true,
|
|
"noImplicitAny": true,
|
|
"strictBindCallApply": false,
|
|
"target": "es2020",
|
|
"module": "esnext",
|
|
"lib": ["es2020", "dom"],
|
|
"skipLibCheck": true,
|
|
"skipDefaultLibCheck": true,
|
|
"resolveJsonModule": true,
|
|
"paths": {
|
|
"src/*": ["./src/*"],
|
|
"~/*": ["./*"]
|
|
}
|
|
},
|
|
"exclude": [
|
|
"node_modules",
|
|
"dist",
|
|
"**/*.test.ts",
|
|
"**/*.spec.ts",
|
|
"**/*.integration-test.ts"
|
|
],
|
|
"references": [
|
|
{
|
|
"path": "./tsconfig.spec.json"
|
|
}
|
|
]
|
|
}
|