Hulpmiddeloproep — uitgaande function-call-verzoeken
Dit document beschrijft het verzoek dat Audact naar het eigen HTTP-eindpunt van een tenant stuurt wanneer het LLM tijdens een gesprek een aangepast hulpmiddel (function call) aanroept dat op een agent is geconfigureerd.
Authenticatie — X-Signature
Wanneer een hulpmiddel een ondertekeningsgeheim heeft geconfigureerd, bevat elke uitgaande oproep:
X-Signature: <hex_hmac_sha256_of_raw_request_body>
- Algoritme: HMAC-SHA256 over de exacte ruwe JSON-body bytes die worden verzonden.
Anders dan de webhookhandtekening (zie Webhookbezorging) is er geen
tijdstempelcomponent in de handtekening van de hulpmiddeloproep — het is een gewone HMAC van alleen
de body, zonder begeleidende
X-Audact-Timestamp-stijl header. - Als er geen ondertekeningsgeheim voor het hulpmiddel is geconfigureerd, wordt
X-Signaturevolledig weggelaten — configureer een geheim op het hulpmiddel als u de aanroeper wilt verifiëren. - Verwar dit niet met
X-Audact-Signature(de webhookbezorgingshandtekening, die wel een tijdstempel bevat en ondersteuning biedt voor dubbele sleutelrotatie). Het zijn twee onafhankelijke schema's voor twee onafhankelijke vlakken (webhooks versus hulpmiddelopropen). - Verificatie aan uw kant: herbereken
hex(hmac_sha256(secret, raw_body))en vergelijk in constante tijd met de waarde van deX-Signature-header.
Structuur van de verzoekbody
Standaard (args_only = false):
json
{
"name": "<tool_name>",
"args": { "...": "LLM-supplied arguments, merged with any const fields" },
"call": {
"tenant_id": "<uuid>",
"call_id": "<uuid>",
"turn": 3,
"jurisdiction": "NL",
"direction": "inbound",
"vars": { "...": "current dynamic-variable snapshot" }
}
}call.call_idis altijd aanwezig wanneercall-context beschikbaar is — dit is de beveiligingsgrens waarop eencall_id → tenant_id-controle op uw eindpunt moet worden gebaseerd.call.tenant_idis ook altijd aanwezig naast deze waarde.call.varsis de huidige dynamische-variabelenmap van de pipeline (waarden opgelost vanuit{{varName}}-substitutie en eventuele eerder geëxtraheerde antwoordvariabelen van hulpmiddelen) — niet een veld genaamdcall.metadata. Per-gesprek metadata is een afzonderlijke functie en wordt aan dit object toegevoegd zodra het beschikbaar is.call.directionis"inbound"of"outbound".call.turnis het huidige gespreksbeurtnummer (geheel getal, 1-gebaseerd).
args_only = true: de {name, args, call}-wrapper wordt volledig weggelaten en de verzoekbody is
alleen args — een vlak JSON-object zonder wrapper, zonder name, zonder call. Dit is een
doelbewuste, expliciete per-hulpmiddel boolean (ToolConfig.ArgsOnly, JSON-veld args_only) die een
tenant instelt wanneer zijn eindpunt een vlakke body verwacht; het is geen verborgen dashboardschakelaar.
Time-out, herhalingen en verwerking van de respons
- Per-hulpmiddel time-out:
ToolConfig.Execution.TimeoutMs; wanneer niet ingesteld (nul), is de standaardwaarde 120.000 ms (120 s). Het geaccepteerde bereik bij expliciet instellen is[1, 300000]ms (max 5 minuten). - Herhalingen: maximaal 3 pogingen in totaal, met 500 ms wachttijd tussen pogingen. Een poging met time-out wordt nooit herhaald — herhalingen zijn alleen van toepassing op niet-time-out fouten (netwerkfouten, niet-2xx-responsen). Herhalingen stoppen ook onmiddellijk als de bovenliggende (in-gesprek) context wordt geannuleerd.
- Responsbody-limiet: 15.000 tekens; langere bodies worden afgekapt voordat ze aan het LLM worden teruggegeven.
- Extractie van antwoordvariabelen:
ToolConfig.ResponseVars-dotpaden worden geëxtraheerd uit de JSON-respons in de dynamische-variabelenopslag van de pipeline (alleen string/getal/bool-bladeren; arrays en objecten worden niet geëxtraheerd) en worden beschikbaar voor volgende{{varName}}-substituties en toekomstige hulpmiddelaanroepen in hetzelfde gesprek. - De HTTP-client voor hulpmiddelen is beveiligd tegen SSRF: adresopzoekingen worden gevalideerd tegen privé-, loopback- en link-local-bereiken vóór het verbinden, bij elke poging.
Voorbeeld: een hulpmiddeloproepaanvraag verifiëren en lezen (pseudocode)
sig := request.header("X-Signature")
if sig != hex(hmac_sha256(secret, raw_body)):
reject()
body := json.parse(raw_body)
call_id := body.call.call_id # always present
tenant_id := body.call.tenant_id # always present
args := body.args # or the whole body if args_only