Logo
Search
API Docs

Async Server Tools & Background Messages

Tools

Async Server Tools & Background Messages

Overview

Most interactions between your assistant and the outside world are synchronous: the assistant asks a question or calls a tool, then waits for an answer before it continues talking. But two related patterns let you feed information into a conversation, or run a backend operation, without making the assistant pause and wait:

  • Background messages — silently insert an item into the chat history from the client side, with no server involvement and no response expected.
  • Async server tools — mark a tool call as resolved immediately on the platform side, while your own webhook keeps processing the request in the background.

Neither pattern sends a result back to the model to react to. This page covers both, along with how they differ from the default synchronous behavior of server tools.

Note: this is different from the already-published Web SDK Integration page's "Injecting Context Mid-Call" section, which covers the Web SDK's own addMessage() convenience wrapper. That wrapper is built on top of the same underlying mechanism described below. This page documents the underlying add-message mechanism directly, plus the server-side async tool pattern, which isn't documented anywhere else.


Background Messages

Background messages let you silently add information to the chat history without interrupting or notifying the user. They run entirely client-side through the SDK, using sulusVoice.send() with type: "add-message":

sulusVoice.send({
  type: "add-message",
  message: {
    role: "system",
    content: "The user has pressed the button, say peanuts",
  },
});

Message fields:

FieldDescription
typeMust be "add-message" to add a new message to the history
roleThe origin of the message. Accepted values: system, user, assistant, tool, function
contentThe text content of the message being added

Practical use cases:

  • Silent logging of user activity
  • Contextual updates in the conversation triggered by background processes
  • Non-intrusive enhancements to the conversation without breaking the user's flow

Example: triggering a background message from a button click

<button id="log-action" onClick="logUserAction()">Log Action</button>
function logUserAction() {
  sulusVoice.send({
    type: "add-message",
    message: {
      role: "system",
      content: "The user has pressed the button, say peanuts",
    },
  });
}

Async Server Tools

By default, server tools are synchronous: the assistant waits for your webhook to respond before continuing the conversation. Setting "async": true on a tool definition changes this — the tool call is marked as resolved immediately on the platform side, and your server processes the request in the background instead.

This is intended for long-running operations where the assistant shouldn't sit in silence waiting on your backend — for example, sending an email or kicking off a workflow that takes a while to complete.

{
  "name": "async_tool",
  "async": true,
  "description": "Tool that runs in the background",
  "parameters": {
    "type": "object",
    "properties": {
      "param1": {
        "type": "string",
        "description": "Parameter description"
      }
    },
    "required": ["param1"]
  }
}

When the tool is triggered, your server URL still receives a tool-calls webhook message:

{
  "message": {
    "type": "tool-calls",
    "call": { },
    "toolCallList": [
      { "id": "abc123", "name": "async_tool", "parameters": { "param1": "value" } }
    ]
  }
}

Even for async tools, your server should still respond with the standard results format and an HTTP 200:

{
  "results": [
    {
      "toolCallId": "abc123",
      "result": "Acknowledged"
    }
  ]
}

Rules for server tool responses (sync or async):

  • Always return HTTP 200, even for errors
  • Use single-line strings — no line breaks in result or error values
  • Match the toolCallId in your response exactly to the ID from the request
  • result and error must be strings, not objects or arrays

Use async tools specifically when the operation takes a long time and the model does not need the tool's output to keep reasoning. If the assistant needs the result to continue the conversation, use the default synchronous mode instead.


Comparing the No-Wait Patterns

Background messages and async server tools are both "no-wait" patterns — neither one sends a result back to the model for it to react to — but they operate at different layers:

Background MessagesAsync Server ToolsSync Server Tools (default)
Where it runsClient-side (Web SDK)Server-side, via your webhookServer-side, via your webhook
Server involvementNoneYes — webhook still processes the requestYes — webhook processes the request
Does the assistant wait?NoNo — resolves immediatelyYes — blocks until your webhook responds
Result returned to the model?NoNoYes
ConfigurationsulusVoice.send({ type: "add-message" })"async": true on the tool"async": false (default) on the tool
Best forSilent logging, injecting contextLong-running backend operationsOperations whose result the assistant needs to keep reasoning

In short: reach for a background message when you just need to slip something into the transcript from the browser with no backend involved. Reach for an async server tool when a real backend operation needs to run but the assistant shouldn't sit and wait for it. Stick with the synchronous (default) server tool whenever the assistant actually needs the tool's result to continue the conversation.