Skip to main content

Documentation Index

Fetch the complete documentation index at: https://agents.candu.ai/llms.txt

Use this file to discover all available pages before exploring further.

Already using Candu? Candu Actions runs alongside the classic Candu SDK. If you have candu.umd.js installed for content rendering, you can add the Actions snippet below in the same app — both load from cdn.candu.ai and don’t conflict. See the classic Candu install guide.

What you’ll see after install

With the snippet installed, open your app and type into the chat:
“Create a segment of inactive enterprise users”
Candu Actions will match the request to your segments_create action, ask for any missing inputs one at a time, show a confirmation panel with the exact payload before anything fires, execute the POST to your API, and log the run. Nothing executes until the user confirms.

See the full flow

Watch the segment wizard end to end: every tool call, payload, and log.

1

Add the snippet

Paste this into your app just before </body>. You only need to change four values: clientToken, userId, identifiers, and your auth header in fetchFn. The last two are optional.
<script>
(function initCanduGateway(params) {
  /* ... full gateway snippet ... */
})({
  snippetVersion: "0.2.0",
  clientToken: "YOUR_CLIENT_TOKEN",   // from Candu Actions dashboard
  userId: "CURRENT_USER_ID",          // logged-in user's ID
  identifiers: {                      // optional — any runtime context the AI may need
    role: "admin",                    // controls role-based action access
    organizationId: "org-456",        // used in action endpoint templates
  },
  fetchFn: function (url, opts) {     // optional — only needed for auth headers/CSRF
    opts = opts || {};
    opts.headers = Object.assign({}, opts.headers, {
      "Authorization": "Bearer YOUR_TOKEN_HERE"
    });
    return fetch(url, opts);
  }
});
</script>
Your clientToken is in the Candu Actions dashboard under Settings → Installation. Your userId should match the identifier you use to identify users elsewhere in your product.
Candu Actions executes actions inside your app using your authentication context. Your APIs are never called from an external service.
<script>
(function initCanduGateway(params) {
  var SDK_SRC = "https://cdn.candu.ai/agentik/agentik-sdk.js";
  var CONFIG_BASE = "https://api.candu.ai/api/agentik/available-actions";

  function invariant(value, message) {
    if (typeof value !== "string" || value.length === 0)
      throw new Error(message);
    return value;
  }

  params = params || {};
  var userId = invariant(params.userId, "[Candu] userId is required");
  var clientToken = invariant(params.clientToken, "[Candu] clientToken is required");
  var snippetVersion = invariant(params.snippetVersion, "[Candu] snippetVersion is required");
  var fetchFn = typeof params.fetchFn === "function" ? params.fetchFn : null;
  var actionRegistry = {};

  function loadSdk() {
    if (window.canduAgentik && typeof window.canduAgentik.init === "function")
      return Promise.resolve();
    return new Promise(function (resolve, reject) {
      var script = document.createElement("script");
      script.src = SDK_SRC;
      script.async = true;
      script.setAttribute("data-candu-agentik-sdk", "true");
      script.addEventListener("load", resolve);
      script.addEventListener("error", function () {
        reject(new Error("SDK_LOAD_FAILED"));
      });
      document.head.appendChild(script);
    });
  }

  /* ... buildUrl, fetchActions, attachGatewayListener ... */

  Promise.all([loadSdk(), fetchActions()])
    .then(function () {
      attachGatewayListener();
      window.canduAgentik.init({ userId, clientToken, snippetVersion });
      window.canduAgentik.launchChat();
    })
    .catch(console.error);
})({
  snippetVersion: "0.2.0",
  clientToken: "YOUR_CLIENT_TOKEN",
  userId: "CURRENT_USER_ID",
  fetchFn: function (url, opts) {
    opts = opts || {};
    opts.headers = Object.assign({}, opts.headers, {
      "Authorization": "Bearer YOUR_TOKEN_HERE"
    });
    return fetch(url, opts);
  }
});
</script>
2

Wire your auth (optional)

If your app uses session cookies, omit fetchFn entirely — the snippet includes credentials: "include" by default and no extra setup is needed. For bearer tokens, CSRF signatures, or custom headers, pass a fetchFn that returns a fetch() with the headers you need. Keep it short — it runs on every action call.
fetchFn: function (url, opts) {
  opts = opts || {};
  opts.headers = Object.assign({}, opts.headers, {
    "Authorization": "Bearer " + myApp.getAuthToken()
  });
  return fetch(url, opts);
}
3

Define your actions

Your action registry is a JSON file referenced by your clientToken. Each action maps to one API endpoint.
Getting Started, 3 Define Your Actions
{
  "version": "poc-1",
  "actions": [
    {
      "id": "segments_create",
      "name": "Create Segment",
      "description": "Create a new user segment with targeting rules.",
      "method": "POST",
      "endpoint": "/api/segments",
      "execution_policy": "confirm",
      "input_schema": {
        "type": "object",
        "properties": {
          "payload": {
            "type": "object",
            "properties": {
              "name": { "type": "string" },
              "description": { "type": "string" }
            },
            "required": ["name"]
          }
        }
      }
    }
  ]
}
Set execution_policy: "confirm" on write actions where you want the user to review the payload before it fires. Not every write needs confirmation — use your judgement based on the risk of the action.
4

See it work

Reload your app. The chat is now in the bottom right. Try the example from the top of this page.

React and Next.js

The snippet works in any framework that can run a script tag. In React or Next.js, run it inside a useEffect in your root layout. Pass clientToken, userId, and your auth via fetchFn — same shape as the vanilla setup. Reach out if you want help with your specific framework.
Both the chat widget and wizard UI run inside a shadow DOM, so your app’s styles won’t conflict with Candu’s and vice versa. Wizards render inline; the chat widget renders as a floating panel.
Now that the SDK is installed, your team can start building wizards. Send your CX or product team to the user-facing wizard documentation to learn about configuring wizards in the Candu UI.