aethexDocs

Tools

Tools let an agent take action mid-call. Two ship built-in (hang up, transfer), and you can register your own that call your own HTTPS endpoints.

How tools work

Mid-call, the agent decides when to invoke a tool based on what the caller said and what your tool's description says it does. For a custom tool, Aethex makes a server-to-server HTTPS call to your endpoint and feeds the response back into the conversation:

CALLERon the callAETHEX AGENTyour voice agentYOUR ENDPOINTyour webhookcaller speaksagent repliesGET or POST200 OK · JSONYour endpoint must respond within 9 seconds.

The whole loop runs inside the call, with the caller waiting on the line. Keep your endpoint fast: sub-second response is ideal. The agent always gets an answer within 9 seconds, and that limit covers the DNS lookup, the connection and the whole response.

Built-in tools

Every agent gets these two automatically. They are enabled by configuration on the agent (end_call_enabled, transfer_phone_number), not by registering anything.

end_callBuilt-in

Hang up the call cleanly.

The agent says any closing line, waits a short grace window for goodbye TTS to finish, then disconnects. Cancellable by user barge-in during the grace window.

When to trigger: After the caller confirms they have what they need, after a clear goodbye on either side, or per your Guardrails (e.g. abusive caller).

transfer_to_numberBuilt-in

Transfer the call to a human agent.

Dials the number configured on the agent (`transfer_phone_number`, or the `transfer_phone_numbers` fallback list in order) while the caller hears hold audio, briefs whoever answers privately with the agent's summary, then connects them to the caller. With `transfer_mode: conference` on a SIP call the agent stays on the line, silent, recording and transcribing both of them.

When to trigger: For account-specific requests the agent cannot handle (refunds, fraud claims, escalations), or when the caller explicitly asks for a human.

Custom tools

Register your own tool with one POST. The pipeline picks it up on the next call against that agent.

Fields

  • namestringrequired

    Identifier the LLM uses when it invokes the tool. Lowercase, alphanumeric + underscores. Must not collide with a built-in (end_call, transfer_to_number, voicemail_detected); collisions are skipped at pipeline build.

  • descriptionstringoptional

    Plain-English description of what the tool does and when to use it. The LLM reads this when deciding whether to invoke. Be specific; vague descriptions cause the model to skip the tool.

  • parameters_schemaobject (JSON Schema)optional

    JSON Schema for the arguments the LLM must produce. Standard properties / required shape. Aethex passes these through to the LLM as an OpenAI-style function definition.

  • endpoint_urlstring (HTTPS)required

    HTTPS endpoint Aethex calls when the LLM invokes the tool. For POST (default): receives a JSON body. For GET: receives LLM arguments as URL query parameters. Must be reachable from our outbound IP range. HTTP (no TLS) is rejected at create time.

  • http_methodstringoptional

    HTTP method used to call your endpoint. POST (default) sends LLM arguments and context IDs in a JSON body. GET sends LLM arguments as URL query parameters and context IDs as X-Aethex-Agent-Id / X-Aethex-Conversation-Id / X-Aethex-Call-Id request headers — no body is sent. Scalar values (string, number, boolean) are stringified directly; non-scalar values (objects, arrays) are JSON-encoded per parameter. Query arguments above 8 KiB total are refused with an error. Any query parameter already in the endpoint_url takes precedence over a same-named LLM argument.

  • headersobjectoptional

    Headers attached to every outbound request. Use this for bearer auth or routing headers. Stored on our side; redacted from logs.

  • tool_typestringoptional

    Currently always "function". Reserved for future tool types (data sources, MCP, etc.).

Register a tool

register_tool.py
python
import os, requests

API_KEY = os.environ["AETHEX_API_KEY"]
BASE_URL = "https://api.aethexai.com/api/v1"
AGENT_ID = "ag_..."

resp = requests.post(
    f"{BASE_URL}/agents/{AGENT_ID}/tools",
    headers={"X-API-Key": API_KEY, "Content-Type": "application/json"},
    json={
        "name": "lookup_order",
        "description": (
            "Look up the status of a customer order by order ID. "
            "Use when the caller asks about an order or shipment they have placed."
        ),
        "parameters_schema": {
            "type": "object",
            "properties": {
                "order_id": {
                    "type": "string",
                    "description": "The order ID, alphanumeric. Example: A1B2C3.",
                },
            },
            "required": ["order_id"],
        },
        "endpoint_url": "https://orders.example.com/aethex/lookup",
        "headers": {"Authorization": "Bearer your-shared-secret"},
    },
)
resp.raise_for_status()
print(resp.json())

Endpoint contract

When the LLM invokes a custom tool, Aethex dispatches to your endpoint_url using the tool's http_method (POST by default). You have 9 seconds to respond, counting the DNS lookup, the connection and the whole response.

POST request (default)

POST your endpoint_url
json
{
  "arguments": {
    "order_id": "A1B2C3"
  },
  "agent_id": "ag_...",
  "conversation_id": "co_...",
  "call_id": "ca_..."
}

GET request

For http_method: GET, LLM arguments are appended to the URL as query parameters and the contextual IDs are forwarded as headers. No body is sent. Note: arguments land in your web server's access logs.

GET your endpoint_url?arg=value
http
GET /aethex/lookup?order_id=A1B2C3&in_stock=true&tags=%5B%22prime%22%5D
Host: orders.example.com
X-Aethex-Agent-Id: ag_...
X-Aethex-Conversation-Id: co_...
X-Aethex-Call-Id: ca_...
(no body)

Response

Return a JSON body with whatever the agent should know. Aethex feeds the entire response into the LLM as the tool result, so structure it so the LLM can read it (key/value pairs, plain English fields).

200 OK
json
{
  "status": "shipped",
  "tracking_number": "1Z999AA10123456784",
  "estimated_delivery": "Tomorrow, 3 PM"
}

Errors

Any 4xx, 5xx, timeout, or network failure is captured as a tool error and surfaced to the LLM as a JSON object like {"error": "<reason>"}. The agent then handles it gracefully (acknowledges the failure, offers to transfer). The call is never killed because your endpoint is down. If a tool fails, it still answers the agent, so the call never stalls waiting on it.

Limits and safety

Timeout
9 seconds

Per tool invocation, covering the DNS lookup, the connection and the whole response. Not configurable. At that point Aethex stops waiting and closes the request. A GET is reported to the agent as unanswered. A POST may already have reached your endpoint, so the agent is told its outcome is unknown and not to repeat it: make POST handlers finish or roll back on their own if the connection closes. A caller interrupting the agent no longer cancels a POST.

Response size
32 KiB

A larger response is returned to the agent as an error, not cut short. Requests ask for an uncompressed response (Accept-Encoding: identity): a gzip or deflate response is still read, and stacked or any other encodings are refused.

Retries
None

Single dispatch per invocation: a request is never sent a second time once your endpoint may have received it, and redirects are not followed. The LLM can retry a failed GET on the next turn; a POST whose outcome is unknown is not to be repeated.

Tip
Headers you set on the tool are sent verbatim on every outbound request and are redacted from server-side logs. Use them for bearer tokens or shared secrets so your endpoint can verify the call came from Aethex.

Next

Once your agent has tools, give it grounded knowledge: see Knowledge base for uploading reference documents the agent can pull from at call time.