Tool parameters

Install DotSIP, open the web admin, connect real SIP, and decide each call from your own HTTP API.

This is the object stored on a tool as Parameters JSON. The text model reads it as the function schema. A wrong object means the model calls the tool with empty arguments, or the call is dropped before your server sees it.

The tool’s own description is a different field. It says when to choose this tool. Each argument’s description says how to fill that one field. Do not paste the schema into the agent prompt or the router prompt. No token is replaced in this JSON or in the tool description. {{CALLER_NAME}} and {{ENABLED_TOOLS}} stay as written. How to write the agent prompt is on Agent prompt.

Why it looks like this

The live voice model does not fill these fields. When it delegates, the text model receives one function per allowed tool: the tool id as the function name, the tool description, and this parameters object, with strict mode turned on.

The text model must return a JSON object whose keys are exactly properties. Strict mode is why every property is also listed in required. An optional key is not available. If a value may be empty, still require the key and say in the description to send "", 0, or false.

DotSIP then parses that object. If the parse fails, your endpoint is not called.

The shape

{
  "type": "object",
  "properties": {
    "day": {
      "type": "string",
      "minLength": 1,
      "maxLength": 32,
      "description": "The day the caller asked for, as YYYY-MM-DD. Not a weekday name."
    }
  },
  "required": ["day"],
  "additionalProperties": false
}
KeyRule
typeobject.
propertiesOne entry per argument. The key is the argument name the model must send.
requiredEvery key of properties, and no key that is not in properties. If you omit one, DotSIP adds it before the session starts. Write it yourself so the stored JSON matches what the model sees.
additionalPropertiesfalse.
description on a propertyWhat the value is, the format, and what the model must not put there.
x-dotsip-waitOptional. Sits on this object, beside properties, never inside a property.

A tool with no arguments is still an object:

{
  "type": "object",
  "properties": {},
  "required": [],
  "additionalProperties": false
}

What a property may be

typeUse it forAlso set
stringNames, dates, free text, ids the tool itself minteddescription. minLength and maxLength when the length matters.
integerCounts, seconds, a closed numeric rangedescription, minimum, maximum.
booleanA yes or no the model must decidedescription that says when to send true.
numberA decimaldescription. Prefer integer when the value is a count.

Values that arrive at your server are only a string, an integer, a number, a boolean, or null. These do not arrive: an array, even a list of strings; an object nested more than one level; more than 16 keys in one object; more than 4096 bytes of argument JSON. If the model sends any of those, the arguments are discarded and the tool is not called.

When you need several values, use several string properties, or one string and say in the description that items are separated by commas. Your server splits that string. Do not declare "type": "array".

One nested object is allowed. The object inside it may hold only strings, numbers, booleans, and null. Do not put another object or a list in there. Prefer flat fields. A nested object is harder for the model and still counts toward the 16 keys at each level.

{
  "type": "object",
  "properties": {
    "slot": {
      "type": "object",
      "description": "The time the caller accepted.",
      "properties": {
        "day": { "type": "string", "description": "YYYY-MM-DD." },
        "time": { "type": "string", "description": "HH:MM in 24 hours." }
      },
      "required": ["day", "time"],
      "additionalProperties": false
    }
  },
  "required": ["slot"],
  "additionalProperties": false
}

A closed set of strings uses enum. The description repeats the meaning of each value, because the model follows the description when two enums look alike.

{
  "type": "object",
  "properties": {
    "reason": {
      "type": "string",
      "enum": ["goodbye", "no_target", "busy_no_alternative"],
      "description": "goodbye when the caller is leaving. no_target when nothing matched. busy_no_alternative when the line was busy and they refused another one."
    }
  },
  "required": ["reason"],
  "additionalProperties": false
}

How to write description

Write it for the text model, in the language that model should copy into the value when the value is speech. Say what the field is, the exact format with one example, and what must not be sent: an extension, a SIP URI, a phone number, a guess.

The tool description, the field above Parameters JSON, is the place for when to call the tool at all. The property description is only how to fill that property.

WeakUsable
queryWords the caller used for the place or the service. Not an extension, not a phone number, not a SIP URI.
dayThe day they asked for, YYYY-MM-DD, for example 2026-09-28. If they said tomorrow, convert it. Do not send a weekday name.
messageThe message already in the third person, starting with the caller’s name. Do not include the words “tell him” or a phone number.

Do not put the endpoint URL, a token, a password, or a SIP URI in any description. The model reads them.

x-dotsip-wait

On the parameters object, outside properties.

ValueWhat happens
Omitted, or trueThe model waits. Your JSON is the tool result.
falseThe model is told the tool has started. When your server answers, the outcome is appended as instructions.

Use false only when the lookup is slow and the caller should hear that it has started. The flag is not an argument. Do not add it to required or to properties.

{
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "description": "The name the caller gave, as they said it."
    }
  },
  "required": ["name"],
  "additionalProperties": false,
  "x-dotsip-wait": false
}

A full tool

Description field: when to call it. Parameters JSON: how to fill the arguments.

{
  "id": "search_slots",
  "description": "Find free times on a day the caller named. Call this before offering any time. Do not invent a time that is not in the result.",
  "parameters": {
    "type": "object",
    "properties": {
      "day": {
        "type": "string",
        "minLength": 10,
        "maxLength": 10,
        "description": "The day they asked for, YYYY-MM-DD, for example 2026-09-28."
      },
      "service": {
        "type": "string",
        "minLength": 0,
        "maxLength": 80,
        "description": "The service they named, or an empty string if they did not name one. Not an extension."
      }
    },
    "required": ["day", "service"],
    "additionalProperties": false
  }
}

service is required even when it may be empty. The description says to send "".

Check before you save

  • The value is one JSON object, not a bare list and not a JSON string wrapped in quotes twice. In the admin field and in POST /v1/tools it is an object.
  • required lists every property key.
  • No property has "type": "array".
  • No property description is only the key name.
  • Nothing in the object is a URL, a token, or a SIP URI.
  • A trial call with those arguments is under 16 keys and under 4096 bytes.