Attaching Tools to Agents

Overview

Tools are standalone resources — you create them once and they live independently. An agent can only call the tools listed in its tools.items array. Attaching a tool means adding its ID to that list and updating the agent; every session started afterwards picks up the change.

The Attachment Shape

The agent's tools object holds a list of items — each item is a tool_id plus optional static_values (covered below). A top-level tool_choice controls whether the LLM is free to decide (auto) or must call a tool every turn (required).

{
  "tools": {
    "items": [
      { "tool_id": "tool_8f3kq2" },
      { "tool_id": "tool_orders_search", "static_values": { "tenant": "acme" } }
    ],
    "tool_choice": "auto"
  }
}

Attaching a Tool

Use PATCH /agents/{agentId} and include the full tools object. The patch replaces the existing tools block — to add a tool to an agent that already has tools, send the combined list.

curl -X PATCH "https://api.d-id.com/agents/agt_xyz789" \
  -H "Authorization: Basic <YOUR KEY>" \
  -H "Content-Type: application/json" \
  -d '{
    "tools": {
      "items": [
        { "tool_id": "tool_8f3kq2" },
        { "tool_id": "tool_orders_search" }
      ],
      "tool_choice": "auto"
    }
  }'
{
  "id": "agt_xyz789",
  "tools": {
    "items": [
      { "tool_id": "tool_8f3kq2" },
      { "tool_id": "tool_orders_search" }
    ],
    "tool_choice": "auto"
  }
}

Static Values

static_values lets you fix specific parameters that the LLM should not control. Common cases: tenant IDs, environment flags, locale, an account ID derived from the session.

{
  "items": [
    {
      "tool_id": "tool_orders_search",
      "static_values": {
        "tenant": "acme",
        "region": "eu-west-1"
      }
    }
  ]
}

At call time, static_values are merged into whatever arguments the LLM produced. The LLM never sees these fields in its schema — keep them out of the tool's properties if you don't want the model to think about them. If a key appears in both the LLM's arguments and static_values, the static value wins.

Tool Choice

ValueBehavior
autoThe LLM decides whether to call a tool each turn. Use this for almost every agent.
requiredThe LLM must call one of the available tools on every turn. Use for narrow agents whose entire job is to dispatch tool calls (e.g. a router or a structured-extraction agent).

Triggers and End-of-Call Tools

Tools attached through tools.items are available to the LLM at every turn of the conversation. Sometimes you want a tool to run only at a specific point in the session — for example, when the chat ends — and not be available mid-conversation. That's what triggers are for.

A trigger binds a set of tools (and, optionally, an instruction prompt) to a session lifecycle event. When the event fires, the LLM is briefly given access to those tools and prompted to act.

The currently supported event is chat/end. Common use cases:

  • Save a structured summary of the conversation to your CRM.
  • File a ticket if the user expressed a complaint.
  • Send a follow-up email through a third-party tool.
curl -X PATCH "https://api.d-id.com/agents/agt_xyz789" \
  -H "Authorization: Basic <YOUR KEY>" \
  -H "Content-Type: application/json" \
  -d '{
    "triggers": {
      "chat/end": {
        "tools": [
          { "tool_id": "tool_save_summary" },
          { "tool_id": "tool_open_ticket" }
        ],
        "prompt_instructions": "Summarize the conversation in two sentences and save it. If the user reported a problem, open a ticket with the relevant details.",
        "tool_choice": "auto"
      }
    }
  }'

prompt_instructions tells the LLM what to do when the event fires. The tools you list under a trigger do not have to also be listed in tools.items — they can be event-scoped only.

Webhooks: A Lighter Alternative

If your end-of-call action doesn't need the LLM — for example, just POST the raw transcript to your own service — use the webhooks field on the same chat/end trigger instead of tools. Webhooks fire as a direct HTTP call at event time with no LLM reasoning, no tool-choice decision, and no extra latency. Reach for trigger-tools when the LLM's judgment matters (deciding what to summarize, which ticket fields to fill, whether to act at all); reach for webhooks when you just need the data to leave the system on schedule.

Detaching a Tool

Send an updated list without the tool ID. To remove all tools, send items: [].

curl -X PATCH "https://api.d-id.com/agents/agt_xyz789" \
  -H "Authorization: Basic <YOUR KEY>" \
  -H "Content-Type: application/json" \
  -d '{
    "tools": {
      "items": []
    }
  }'

Deleting the tool itself with DELETE /tools/{toolId} does not automatically detach it from agents that reference it — clean up the agent first or expect the tool call to fail at runtime.

FAQ