Skip to content

Live support chat with AI triage for Cloud and dedicated instances - #1155

Merged
helpcodeai merged 6 commits into
mainfrom
feat/support-chat
Oct 19, 2026
Merged

helpcodeai merged 6 commits into
mainfrom
feat/support-chat

Conversation

@helpcodeai

@helpcodeai helpcodeai commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Summary

This adds a live support chat for the instances we run: AnythingMCP Cloud and the dedicated instances of enterprise customers. The goal is to help people during the trial when a connector won't set up, without anyone having to ask for their workspace details first. The desk is our own Libredesk (AGPL, self-hosted, unmodified) at support.anythingmcp.com.

The widget's identity is signed by the backend and carries a snapshot of the workspace: plan, trial end, connectors, and the connector errors of the last 24 hours with credentials redacted. Every new conversation then goes through an AI triage that sets the category, priority, team and segment tags, and adds a private note with a summary and a reply draft. Nothing is sent to the customer automatically; a person reviews the draft.

Changes

  • ee/support/ (new, AnythingMCP Commercial License):
    • GET /api/support/widget (JWT auth): returns the widget settings plus an HS256 user JWT (external_user_id = <instance host>:<user id>, contact attributes). The snapshot is cached for 5 minutes, and every query is filtered by organizationId.
    • POST /api/support/webhook: accepts Libredesk conversation.created. It checks the X-Libredesk-Signature HMAC on the raw body, refuses deliveries older than 10 minutes, answers right away and runs the triage in the background.
    • Triage: uses the existing knowledge-graph/llm-client (on Cloud: Anthropic claude-haiku-4-5). Customer text is passed through redactPii and redactSecrets before it reaches the LLM. Billing and enterprise conversations are always High. Without an LLM it falls back to tags and priority only.
    • The module loads only when SUPPORT_CHAT_* (widget) or LIBREDESK_* (triage) are set.
    • AI assistant routing (LIBREDESK_AI_ASSISTANT_USER_ID): after setting the team, the triage assigns live chats in connector-setup, connector-error, new-connector-request, account and other to the Libredesk AI assistant, which answers from the knowledge base and hands back to the Support team when it can't help. Billing, bugs, feature requests, sales, email conversations and enterprise customers always go to a person. The team is set before the user because Libredesk clears the user assignee whenever the team changes.
  • main.ts: the JSON parser keeps the raw body, but only for /api/support/webhook.
  • email-verified.guard.ts: /api/support/widget added to the allowlist, so people whose verification code never arrived can still reach us.
  • Frontend: SupportChat is mounted in Providers. It renders nothing, loads widget.js only when the backend returns a session, refreshes the identity when the token changes and logs the widget out when the user signs out.
  • docker-compose.cloud.yml: passes the seven new variables through.

Cloud and self-hosted

  • Cloud: the widget appears for every signed-in user, trials included. The triage runs here; this is the only instance that holds the Libredesk API key.
  • Dedicated enterprise instances (self-hosted mode, run by us): they set only SUPPORT_CHAT_*. Contacts are tagged self-hosted and enterprise and routed to the Enterprise team with High priority.
  • Self-hosted installations of customers: no variables are set, so the module is not loaded and /api/support/widget returns 404. The frontend makes one request at sign-in, gets the 404 and loads nothing else. No third-party script.

Type

  • New feature

Testing

  • Added unit tests: src/ee/support/*.spec.ts. They cover JWT claims and verification, per-instance external id, org-scoped queries, redaction, cache, the 404 gates, signature and staleness checks, the triage flow, routing to Enterprise, the no-LLM fallback, idempotency and partial failure.
  • Tested manually against the live desk:
    • Signed a JWT with SupportIdentityService; auth/exchange created a verified contact with all attributes.
    • Started a conversation through the widget API and ran SupportTriageService against it with Haiku.
    • Result: tags connector-setup, cloud, trial, ai-triaged, priority High, Support team, and a private note with the right diagnosis (Etsy redirect URI mismatch, taken from the connector-issues snapshot) and an Italian reply draft.
    • Rendered the widget in headless Chromium under the cloud.anythingmcp.com origin: no console errors, user recognised, previous conversation listed.

Commands and results:

  • packages/backend: npx tsc --noEmit -p tsconfig.json → clean.
  • packages/backend: npx eslint on the changed files → 0 errors. The full npm run lint also reports only existing warnings; the --fix rewrites it made in two unrelated spec files were reverted.
  • packages/backend: npx jest → 682 suites passed, 1 failed (connectors/parsers/curl.parser.spec.ts). That suite passes when run alone (43/43); this branch doesn't touch it, so it fails only in the full parallel run.
  • packages/frontend: npx tsc --noEmit -p tsconfig.json and npx eslint on the changed files → clean.

Checklist

  • My code follows the existing code style
  • I have tested my changes locally
  • I have updated documentation (ee/README.md)
  • All existing tests pass (npm test): see the note on curl.parser.spec.ts above
  • This PR has a descriptive title

Related Issues

None. There is no schema change.

Live check of the assistant path: a conversation with a needs_reauth Google Calendar connector was triaged as connector-error, assigned to the assistant, and got a correct answer (re-authorize; publish the OAuth app if it is in Testing) about 3 s after the triage.

Cloud and our dedicated enterprise instances load a Libredesk chat widget
for signed-in users. The backend signs an HS256 identity carrying a
workspace snapshot (plan, trial end, connectors, last-24h connector
errors, redacted), so agents and the triage see the context.

A signed webhook triages new conversations: category, priority, team,
segment tags and a private note with a reply draft. Nothing is sent to
the customer automatically.

The module loads only when SUPPORT_CHAT_* or LIBREDESK_* are set, so
self-hosted installations are unaffected.
Comment thread packages/backend/src/ee/support/support-triage.service.ts Fixed
helpcodeai and others added 5 commits October 19, 2026 16:39
With LIBREDESK_AI_ASSISTANT_USER_ID set, the triage assigns live chats
in categories the assistant can handle (connector setup and errors,
connector requests, account, other) to the Libredesk AI assistant after
the team, so it answers from the knowledge base and hands back to the
Support team when it cannot help. Billing, bugs, feature requests,
sales, email conversations and enterprise customers still go straight
to a person.
@helpcodeai
helpcodeai enabled auto-merge (squash) October 19, 2026 17:15
@helpcodeai
helpcodeai merged commit 10257b0 into main Oct 19, 2026
14 checks passed
@helpcodeai
helpcodeai deleted the feat/support-chat branch October 19, 2026 17:23
@github-actions github-actions Bot locked and limited conversation to collaborators Oct 19, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants