tool_name und tool_description
Name in lower_snake_case, maximal 128 Zeichen, nicht identisch mit eingebauten oder internen Tools.
Die Beschreibung ist der wichtigste Hinweis für das Modell, wann das Tool passt.
Custom Tools verbinden einen LIVOI-Agenten mit beliebigen HTTP-APIs. Ein Tool beschreibt, welche Eingaben das Modell liefern darf, und getrennt davon, wie daraus ein konkreter HTTP-Request entsteht. Das Modell sieht nur das Eingabeschema. URL, Methode, Header, API-Key und feste Body-Bestandteile bleiben Konfiguration, die der Agent nicht verändern kann.
Beim Laden des Agenten wird jede Tool-Definition erneut validiert. Danach durchläuft jeder Tool Call Validierung, Request-Aufbau, HTTP-Aufruf und Auswertung. Ergebnis und geschwärzter Request-Snapshot landen getrennt in der Chat-Historie.
Die Grafik zeigt den Standardpfad eines Custom Tool Calls. Die Tool-Suche ist nur aktiv, wenn mindestens ein Tool des
Agenten defer_loading nutzt. Preview und Test laufen ohne Agent und ohne Modell, aber über denselben
Request-Builder.
request_config, input_schema und optionalen Laufzeitwerten.path-, query- oder body-Parameter deklariert.body_template legt die Body-Struktur fest; {“$livoi_input”: “name”} markiert die Stellen, an denen validierte Eingaben eingesetzt werden.tool_call-Teil der Historie. Das Modell erhält sie nie.defer_loading: true bleiben Tools aus dem initialen Kontext heraus und werden über search_tools gefunden.Custom Tools gehören immer zu genau einem Agenten und werden als Agent-Tool gespeichert. Der Tool-Name ist pro Agent eindeutig.
tool_name und tool_description
Name in lower_snake_case, maximal 128 Zeichen, nicht identisch mit eingebauten oder internen Tools.
Die Beschreibung ist der wichtigste Hinweis für das Modell, wann das Tool passt.
request_config
Ziel-URL, HTTP-Methode, Authentifizierung, zusätzliche Header, optionales body_template und Timeout.
input_schema
Liste der Parameter, die das Modell befüllt, jeweils mit Typ, Ort und optional Default oder Auswahlwerten.
Laufzeitwerte
response_config für eine Erfolgsbedingung, max_retries für fehlerhafte Argumente und
defer_loading für die Tool-Suche.
api_key
Optionaler Schlüssel für das Zielsystem. Er wird nie zurückgegeben; Antworten enthalten nur has_api_key.
{ "tool_name": "search_companies", "tool_description": "Searches companies by name and returns their ID, name, and email address.", "request_config": { "api_url": "https://api.example.com/v1/contacts/search", "http_method": "POST", "api_key_location": "header", "auth_param": "Authorization", "api_key_prefix": "Bearer", "additional_headers": { "X-Workspace-Id": "example" }, "timeout_seconds": 15, "body_template": { "filter": { "name": { "contains": { "$livoi_input": "name" } }, "type": "company" }, "fields": ["id", "name", "email"], "limit": 10 } }, "input_schema": { "parameters": [ { "name": "name", "type": "string", "location": "body", "description": "Company name to search for." } ] }, "response_config": { "success_condition": { "path": ["errors"], "operator": "absent_or_empty_list" } }, "max_retries": 1, "defer_loading": true, "api_key": "sk_tool_live_123456"}| Feld | Standard | Bedeutung |
|---|---|---|
api_url | – | Muss mit http:// oder https:// beginnen. {name} markiert Pfad-Platzhalter. |
http_method | – | GET, POST, PUT, PATCH oder DELETE. |
api_key_location | header | Ob der API-Key als Header oder als Query-Parameter übertragen wird. |
auth_param | Authorization | Name des Headers oder Query-Parameters für den API-Key. |
api_key_prefix | Bearer | Präfix vor dem Key. Leer oder null sendet den Key ohne Präfix. |
additional_headers | {} | Feste Header. Namen und Werte werden getrimmt; Zeilenumbrüche werden abgelehnt. |
body_template | – | Optionale feste JSON-Struktur des Request-Bodys mit Verweisen auf Body-Parameter. |
unwrap_single_body_parameter | false | Ohne Template: sendet einen einzelnen Body-Parameter als gesamten Body statt als Objekt. |
timeout_seconds | Plattform | Timeout pro Request in Sekunden, größer als 0. Ohne Wert gilt der Plattform-Standard (30 Sekunden). |
Jeder Parameter wird zu einem Feld im Eingabemodell des Tools. Aus diesem Modell entsteht das JSON-Schema, das das Modell sieht, und dieselbe Definition validiert später die Argumente.
name, type, location
description
required (Standard true)
default (nur bei optionalen Parametern)
choices (nur string, integer, number)
properties bei object, items bei array
string
integer
number
boolean
object
array
| Ort | Regeln |
|---|---|
path | Pflichtfeld mit skalarem Typ. Jeder Platzhalter in api_url braucht genau einen passenden Path-Parameter und umgekehrt. Werte werden URL-kodiert eingesetzt. |
query | Kein object. Arrays sind erlaubt, wenn ihre Items skalar sind. |
body | Alle Typen. Mit Template muss jeder Body-Parameter im Template referenziert sein; ohne Template bilden alle Body-Parameter zusammen ein JSON-Objekt. |
Viele APIs erwarten verschachtelte Request-Bodys mit Filtern, Feldlisten oder Limits. Ohne Template müsste das Modell
diese Struktur selbst erzeugen. Mit body_template gehört die Struktur dem Tool, und das Modell liefert
nur die deklarierten Variablen, etwa {“name”: “Acme”}.
{ "filter": { "name": { "contains": { "$livoi_input": "name" } }, "type": "company" }, "fields": ["id", "name", "email"], "limit": 10}Mit dem Argument {“name”: “Acme”} sendet LIVOI exakt diesen Body:
{"filter":{"name":{"contains":"Acme"},"type":"company"},"fields":["id","name","email"],"limit":10}Typerhaltende Ersetzung
Ein Verweis wird durch den validierten Wert ersetzt, nicht durch Text. Zahlen bleiben Zahlen, Objekte bleiben Objekte. Strings werden immer als ein JSON-String eingesetzt, auch wenn sie Anführungszeichen oder JSON-ähnlichen Inhalt enthalten.
Feste Werte
Alles außer den Verweisen ist feste Konfiguration. Es taucht nicht im Eingabeschema auf, und da unbekannte Argumente abgelehnt werden, kann das Modell diese Werte nicht überschreiben.
null bedeutet „nicht angegeben“
Bei Tools mit Template wird ein null vom Modell wie ein fehlendes Argument behandelt, auch in
verschachtelten Objekten: Der Default greift, sonst wird das referenzierende Objekt-Member entfernt.
| Regel | Grenze |
|---|---|
| Wurzel | JSON-Objekt oder Array. Für einen einzelnen Wert als ganzen Body dient unwrap_single_body_parameter. |
| Größe | Maximal 65.536 Bytes als kompaktes JSON. |
| Tiefe | Maximal 32 Ebenen. |
| Verweise | Maximal 64. Ein Verweis-Objekt enthält ausschließlich $livoi_input. |
| Ziel eines Verweises | Nur existierende Parameter mit location: body. |
| Vollständigkeit | Jeder Body-Parameter muss im Template referenziert sein. |
| Arrays | Ein optionaler Parameter ohne Default darf nicht als Array-Element referenziert werden, weil dort kein Member entfernt werden kann. |
| Kombination | Nicht zusammen mit unwrap_single_body_parameter: true. |
path, query und body aufgeteilt.api_url werden URL-kodiert ersetzt.api_key_location: query, der API-Key werden an die URL gehängt.additional_headers und, bei api_key_location: header, der API-Key mit Präfix werden gesetzt.timeout_seconds wird an den Request gebunden.Der Response-Body wird als JSON geparst, wenn möglich, sonst als Text übergeben. HTTP-Fehler werden in stabile Fehlertypen übersetzt, damit das Modell sinnvoll reagieren kann, ohne rohe Upstream-Fehler zu interpretieren.
| Auslöser | error.type |
|---|---|
| HTTP 408, 425, 429, 5xx | upstream_unavailable |
| HTTP 401, 403 | authorization_error |
| HTTP 404 | not_found |
| HTTP 400, 409, 422 | request_rejected |
| Andere 4xx | request_failed |
| Timeout | timeout_error |
| Verbindungsfehler | connection_error |
| Erfolgsbedingung nicht erfüllt | application_error |
| Erfolgsbedingung nicht auswertbar | unexpected_response |
{ "status": "completed", "status_code": 200, "response": [{ "id": 7, "name": "Acme GmbH" }] }{ "status": "failed", "retryable": false, "status_code": 404, "error": { "type": "not_found", "message": "The connected service could not find the requested resource." } }Manche APIs antworten mit HTTP 200, obwohl die Operation fehlgeschlagen ist. response_config.success_condition
prüft dafür nach der HTTP-Fehlerbehandlung einen Pfad im geparsten Body. Pfade bestehen aus Objekt-Keys und
nicht-negativen Array-Indizes, maximal 16 Segmente.
equals
Vergleicht einen skalaren Wert ohne Typumwandlung. Integer und Float werden numerisch verglichen, Booleans sind nie gleich Zahlen.
absent_or_empty_list
Erfolg, wenn der Pfad fehlt oder auf eine leere Liste zeigt, etwa [“errors”]. Andere Typen gelten als
unerwartete Antwort.
Beide Endpunkte nehmen eine vollständige Tool-Definition plus Beispielargumente entgegen. Damit lassen sich auch
ungespeicherte Entwürfe prüfen. Mit agent_tool_id werden fehlende Werte aus dem gespeicherten Tool
ergänzt.
Preview
Validiert Konfiguration und Argumente, baut Methode, URL, Header und Body und kontaktiert das Zielsystem nicht. Der
gespeicherte API-Key wird dafür nicht einmal aus der Datenbank geladen; an seiner Stelle steht
<redacted>.
Testrequest
Sendet genau einen echten Request und liefert Status, Dauer, geschwärzte Header, einen begrenzten Body und das Ergebnis, das der Agent erhalten würde. Es wird nichts gespeichert.
{ "agent_tool_id": "7300000000000000002", "tool_name": "search_companies", "tool_description": "Searches companies by name and returns their ID, name, and email address.", "request_config": { "api_url": "https://api.example.com/v1/contacts/search", "http_method": "POST" }, "input_schema": { "parameters": [{ "name": "name", "type": "string", "location": "body" }] }, "arguments": { "name": "Acme" }, "confirm_upstream_request": true}| Feld im Request | Verhalten |
|---|---|
api_key weggelassen | Nutzt den gespeicherten Key des Tools (setzt agent_tool_id voraus). |
api_key: null | Baut den Request ohne Key. |
api_key: ”…” | Nutzt den übergebenen Key. |
body_template, response_config weggelassen | Übernimmt mit agent_tool_id den gespeicherten Wert; null entfernt ihn für diesen Aufruf. |
confirm_upstream_request | Nur beim Test, muss exakt true sein. |
outcome | Bedeutung |
|---|---|
completed | Erfolgreiche Antwort, Erfolgsbedingung erfüllt. |
http_error | Das Zielsystem antwortete mit einem HTTP-Fehlerstatus. |
response_error | HTTP-Erfolg, aber die Erfolgsbedingung schlug fehl. |
timeout | Zeitüberschreitung. |
connection_error | Keine Verbindung zum Zielsystem. |
response_too_large | Antwort größer als 1 MiB; kein agent_result. |
Upstream-Fehler, Timeouts und Verbindungsfehler kommen mit HTTP 200 und stehen im Response-Body.
request_possibly_processed ist nur dann false, wenn der Request das Zielsystem sicher nicht
erreicht hat, etwa bei Verbindungsaufbau-, Pool- oder Proxy-Fehlern. Validierungsfehler der Argumente liefern 422 mit
Pfad unter body.arguments.
Jeder Custom Tool Call speichert unter metadata.custom_tool_inspection am tool_call-Teil der
Historie, was tatsächlich gesendet wurde. Lesbar ist das für alle, die die Chat-Historie lesen dürfen. Das Modell
erhält diese Daten nicht.
Validierte Argumente (bis 8 KiB, sonst als ausgelassen markiert)
Methode, URL, Header, Body und Timeout des Requests
Statuscode, Dauer und Body-Größe der Antwort
Transportfehlertyp und request_possibly_processed
Ergebnisstatus und Fehler, wie sie der Agent sah
API-Key, auch URL-kodiert, JSON-escaped oder byte-escaped
Alle Werte aus additional_headers
Authorization, Proxy-Authorization, Cookie, Set-Cookie
Passwörter in der URL
| Grenze | Historie | Preview und Test |
|---|---|---|
| URL | 2.048 Zeichen | 8.192 Zeichen |
| Header | 32 Header, je 512 Zeichen | 64 Header, je 1.024 Zeichen |
| Body | 16.384 Zeichen | 65.536 Zeichen |
Gekürzte Werte sind über url_truncated, headers_truncated und body_truncated
erkennbar.
Jedes Tool kostet Kontext: Name, Beschreibung und Schema gehen mit jedem Model-Request mit. Bei großen Katalogen,
etwa vollständigem CRUD auf ein ERP mit über hundert Tools, verdrängt das den eigentlichen Gesprächskontext. Mit
defer_loading: true bleiben solche Tools aus dem ersten Request heraus.
defer_loading, erhält der Agent das Tool search_tools.Persistenz
Such-Austausche werden mit tool_kind: tool-search gespeichert und beim nächsten Lauf typisiert
wiederhergestellt. Gefundene Tools bleiben im Chat verfügbar; neue Chats starten ohne sie. Gelöschte Tools bleiben
unerreichbar.
Sichtbarkeit
Suchen sind für das Modell sichtbar, in den Tool-Logs für Nutzer aber ausgeblendet.
Katalog bleibt lokal
Die native Tool-Suche des Providers ist deaktiviert, weil sie Namen und Beschreibungen des Katalogs an den Provider senden würde. Für den Standard-OpenAI-Endpunkt werden neue Schemas angehängt; Custom Endpoints erhalten normale Function Definitions.
Alle Endpunkte liegen unter /v1/agent/tools und verwenden die Ressource agent_tools aus dem
RBAC-Permission-Katalog.
| Operation | Endpunkt | Permission |
|---|---|---|
createCustomToolForAgent | POST /{agent_id}/custom/create | agent_tools.create |
getCustomToolForAgent | GET /{agent_tool_id}/custom | agent_tools.read |
updateCustomToolForAgent | PATCH /{agent_tool_id}/custom/update | agent_tools.update |
previewCustomToolRequest | POST /{agent_id}/custom/preview | agent_tools.read |
sendCustomToolTestRequest | POST /{agent_id}/custom/test | agent_tools.update |
deleteAgentTools | DELETE /{agent_id}/delete | agent_tools.delete |
Anlegen
Mehrere Tools pro Aufruf möglich. Doppelte Namen innerhalb des Requests liefern 422, Namen, die am Agenten bereits existieren, liefern 409.
Lesen zum Bearbeiten
getCustomToolForAgent liefert die gespeicherte Konfiguration mit erhaltenen JSON-Typen, inklusive
response_config, max_retries, defer_loading und has_api_key. Dynamic Query
gibt Skalare aus den Tool-Metadaten als Strings zurück und eignet sich deshalb nicht, um ein
body_template in einen Editor zu laden.
Aktualisieren
Die Definition wird vollständig gesendet. Weggelassene Felder body_template,
response_config, defer_loading und api_key behalten ihren gespeicherten Wert;
null entfernt body_template, response_config und api_key.
| Risiko | Gegenmaßnahme |
|---|---|
| Modell manipuliert feste Request-Werte | Nur deklarierte Eingaben sind Teil des Schemas; unbekannte Argumente werden abgelehnt. |
| Injection über String-Eingaben | Typerhaltende Ersetzung im Template, URL-Kodierung im Pfad, keine Zeilenumbrüche in Headern. |
| Key-Leak in Logs oder Historie | Schwärzung in allen gängigen Kodierungen; API liefert nur has_api_key. |
| Key-Umleitung über Testrequest | Gespeicherte Keys nur an den gespeicherten Origin, inklusive Host-Header-Prüfung. |
| Cookie-Übertrag zwischen Tenants | Eigener HTTP-Client ohne Cookie-Speicher. |
| Doppelte Schreiboperationen | Upstream-Fehler sind terminal und werden nicht automatisch wiederholt. |
| Katalog-Abfluss an Provider | Tool-Suche läuft lokal; native Provider-Suche ist deaktiviert. |
body_template und defer_loading liegen in den bestehenden Tool-Metadaten; ältere Tools brauchen keine Anpassung.body_template bauen ihre Requests wie bisher; Tools ohne defer_loading bleiben eager.-Input- und -Output-Varianten. Das Wire-Format ist identisch, generierte Clients sehen aber getrennte Typen.Ein Builder
Laufzeit, Preview und Test erzeugen Requests über denselben Code. Es gibt keine Abweichung zwischen Vorschau und Realität.
Struktur gehört dem Tool
Das Modell liefert Werte, nicht Request-Strukturen.
Früh validieren
Fehler in Konfiguration, Templates und Defaults werden beim Speichern abgelehnt, nicht im laufenden Chat.
Nachvollziehbar
Jeder Call hinterlässt einen geschwärzten Snapshot dessen, was wirklich gesendet wurde.
Sparsam im Kontext
Große Kataloge werden bei Bedarf gefunden statt vollständig mitgeschickt.
Sicher im Fehlerfall
Upstream-Fehler sind terminal, Keys bleiben an ihren Origin gebunden.