Files
libredesk/scripts/tools-server/README.md
T
Abhinav Raut 08e6801fc4 polish widget UI and fix proactive message delete
Widget:
- home background stays pinned while the content scrolls, fade sits on it
- one radius and shadow scale across cards, buttons and inputs
- live search in the help tab with a "no results" state
- attachment-only messages show "Image" in the conversation preview
- launcher and panel use the same shadows as the header

Admin:
- preview column is a fixed width so zoom does not resize it, hidden on small screens
- preview matches the real widget again
- search spinner replaces the magnifier instead of covering the page

Fixes:
- deleting a proactive message did nothing, the dialog cleared the pending
  id before the handler read it
- an inbox created through the API could not be saved from the form, it
  jumped to the pre-chat tab with no error

Adds livechatWidgetTabs.cy.js covering the proactive message and help
center tabs.
2026-09-20 18:48:51 +05:30

3.4 KiB

AI assistant custom tools test server

A small HTTP server for trying out custom tools without wiring up a real backend. It holds two fake accounts and looks them up by the contact's external user id, which libredesk sends in the X-Libredesk-Contact-External-Id header. Add your own test users by editing the users map in main.go.

AI assistants call every enabled custom tool. Copilot and Generate Reply call the ones with "Available in Copilot" or "Available in Generate Reply" turned on, and a tool with "Require agent approval" on waits for the agent to approve the call there. "Require verified contact" applies to assistant runs only, since an agent is the one asking on the Copilot and Generate Reply surfaces.

Run

go run ./scripts/tools-server

It listens on :7070, or pass -addr to change that. Every request logs the contact headers and the raw args JSON the model sent, which is usually enough to work out why a tool call did not do what you expected.

Headers libredesk sends

Libredesk injects the contact and conversation context on every custom tool call. This happens server-side, so the model cannot see or change any of it:

Header Value
X-Libredesk-Contact-Id internal contact id
X-Libredesk-Contact-External-Id external user id (from the livechat JWT), if any
X-Libredesk-Contact-Type contact or visitor
X-Libredesk-Contact-Email contact email, if known
X-Libredesk-Contact-Verified true only after OTP/JWT identity verification
X-Libredesk-Conversation-UUID conversation uuid
X-Libredesk-Inbox-Id inbox id

A visitor can type any email address into a chat, so only trust X-Libredesk-Contact-Email for account data when X-Libredesk-Contact-Verified is true. This server returns a 403 otherwise.

Work out who the customer is from these headers and nothing else. The request body holds the model's arguments, written from whatever the customer typed, so it must never decide which account you return.

Endpoints

Endpoint Returns
/account name, email, plan, KYC status
/orders recent orders with status
/balance account balance

Tool setup (Admin -> AI -> Tools)

Create one tool per endpoint:

  • Method: POST
  • Auth header: X-Api-Key
  • Auth value: test-secret-token
  • Parameters: leave empty

For example, name get_account, URL http://localhost:7070/account, description "Get the customer's account details: name, email, plan, and KYC status."

Grant the tools to an assistant under Admin -> AI -> Assistants, then assign a conversation to that assistant. Nothing gets called until you do both.

Test contacts

Set the contact's external user id and email to one of:

Error paths: bad API key -> 401, unverified contact -> 403, missing external id -> 400, unknown id -> 404, email mismatch -> 403.