Skip to Content
JavaScript SDKExamplesClient tools

Client tools

A character’s client tools run in your page: the model decides to call one, and your code does it — open a product page, add to a basket, show a form. You create the tool in the console or with POST /v1/tools (type: "client", a name, a description telling the model when to use it, JSON Schema parameters), and attach it to the character. Then register what it does, before joining:

const stop = client.registerToolCallHandler("open_product", { onStart: async ({ toolName, arguments: args }) => { showProduct(args.productId); return { shown: true }; // the result: a string as it is, anything else as JSON }, onComplete: ({ result, executionTime }) => {}, onFail: ({ errorMessage }) => {}, // an error thrown in onStart }); stop(); // no longer handled
  • arguments follow the tool’s parameters schema, as the model filled them in.
  • The model gets onStart’s result when the tool is set to awaitResult, and has it within toolTimeoutSeconds (default 10) or hears that the app did not answer in time. Without awaitResult (the default) the model carries on at once; your handler still runs.
  • An error thrown in onStart reaches the model as its message, so it can tell the user — throw something a person could read: throw new Error("That product is out of stock").
  • A tool with no handler registered tells the model so at once.
  • Results longer than 15 KB are cut; the model reads at most the first 4,000 characters.
  • One handler per tool name; registering again replaces it.