Skip to main content

What we send

A single HTTPS POST per invocation. No retries on our side — if your endpoint errors, the AI handles it and moves on.

URL

The endpoint URL you saved, exactly as configured. No path rewriting, no query string injection.

Headers

HeaderValueNotes
Content-Typeapplication/jsonAlways.
User-AgentSmartAlex/1.0 (+https://docs.getsmartalex.com/http-tools)Pinned.
AuthorizationBearer <your-token>Only when auth_scheme = bearer.
<Your-Header-Name><your-token>Only when auth_scheme = custom_header.
X-SmartAlex-Signaturet=<epoch_ms>,v1=<hex>HMAC-SHA256 — see Signature verification.
X-SmartAlex-Tenant-IdUUIDTenant making the call.
X-SmartAlex-ToolTool nameSame as what you configured.
X-SmartAlex-Call-IdUUID or emptyEmpty string on test fires.

Body

Stable, alphabetically-key-sorted JSON for reproducible signing. You can pass it back through JSON.stringify and still get a verifiable signature.
{
  "agent_id": "00000000-0000-0000-0000-000000000000",
  "arguments": {
    "query": "billing"
  },
  "call_id": "11111111-1111-1111-1111-111111111111",
  "caller_number": "+27821234567",
  "tenant_id": "22222222-2222-2222-2222-222222222222",
  "timestamp": 1733839200123,
  "tool": "lookup_routing"
}
FieldTypeNotes
toolstringSame as the X-SmartAlex-Tool header.
tenant_idUUID stringYour tenant.
agent_idUUID string or nullnull on test fires.
call_idUUID string or nullnull on test fires.
caller_numberE.164 string or nullCaller’s phone number when known.
timestampintegerEpoch milliseconds. Same number as t= in the signature header.
argumentsobjectThe LLM’s call args, schema-validated before we send.
For signing, the canonical body is serialized with alphabetical key ordering at every level. If you re-serialize the body yourself before HMAC-verifying, do the same — or hash the raw bytes from the wire (preferred — see Signature verification).

What we expect back

We accept anything JSON or text under 64 KB. The body is passed verbatim to the AI as the tool result.

Accepted content types

  • application/json — parsed as JSON, re-stringified for the AI.
  • text/plain
  • text/html (the AI can summarize HTML, but you’ll get a better response by sending JSON or plain text).
  • text/csv and other text/* subtypes.

Rejected content types

  • application/octet-stream and any binary content type → HTTP_TOOL_INVALID_RESPONSE_TYPE.
  • Missing Content-Type is tolerated.

Status codes

StatusResult
2xxBody becomes the AI’s tool result.
3xxWe don’t follow redirects → HTTP_TOOL_TOO_MANY_REDIRECTS. Resolve your URL to its final destination and re-save.
4xxHTTP_TOOL_CUSTOMER_ERROR. AI says “the lookup service returned an error” and continues without your data.
5xxSame as 4xx, different mental model — your service is down.
Timeout > 10sHTTP_TOOL_TIMEOUT. AI says “the lookup timed out” and continues.
See Error codes for the full taxonomy. The AI parses whatever you return as text. To get the best behavior, give the AI a hint about what to say next.
{
  "extension": 6105,
  "hint": "Transfer the caller to extension 6105 (billing queue)."
}
The AI reads the entire response body. Include a hint (or instruction, or next_action — any natural-language one-liner) so the AI knows exactly what to say next. Without it, the AI guesses, and the conversation gets generic.

Response examples for common tools

Request:
{ "arguments": { "query": "I have a billing question" } }
Response:
{
  "extension": 6105,
  "queue_name": "Billing",
  "estimated_wait_seconds": 45,
  "hint": "Transfer to extension 6105 for billing. Mention the ~45s wait."
}
Request:
{ "arguments": { "phone": "+27821234567" } }
Response:
{
  "found": true,
  "name": "Sarah Patel",
  "tier": "gold",
  "open_tickets": [{"id": 4421, "subject": "Refund pending"}],
  "hint": "Greet Sarah by name. She has an open refund ticket — offer to check status."
}
Request:
{ "arguments": { "date": "2026-05-20", "service": "consult" } }
Response:
{
  "available_slots": ["09:00", "11:30", "15:00"],
  "hint": "Offer 9:00, 11:30, or 15:00. Ask which works."
}
{
  "found": false,
  "hint": "We don't have a record. Ask the caller for their account number."
}

What you should NOT return

  • Raw stack traces — the AI may verbalize them. Strip / wrap in a friendly summary.
  • Provider names (Twilio, Asterisk, etc.) — the AI may say them. The dashboard preview obfuscates these but the wire-side AI gets the verbatim response.
  • Sensitive PII you didn’t intend to expose (national IDs, full card numbers). Once it crosses the wire the AI can speak it.
  • Megabytes of data. We cap at 64 KB; design responses to fit in 4 KB ideally.

Next: Signature verification

How to verify every request is actually from us, with code samples.