End Call Request
Changed onHang up the call — but only if the caller is actually finished.
This replaces Vapi's built-in endCall tool for Brian J Levy. The model can now only request an ending; the hangup itself happens here, so the rule "never hang up on a caller who still wants something" is enforced by code instead of by prompt wording that measurably could not hold it (see app/vapi/end_call_gate.py for the measurements).
Flow: evaluate the last exchange of the conversation so far — read from this call's persisted CallTranscriptEvent rows, falling back to Vapi's message.artifact.messages snapshot (see end_call_gate.select_turns for why the events win); on a refusal return a tool error and the model keeps helping; on an allow, speak the goodbye and hang up via Live Call Control by POSTing {"type": "say", ..., "endCallAfterSpoken": true} to the call's monitor.controlUrl — the same mechanism /transfer-destination uses.
The goodbye text comes from message.assistant.endCallMessage, which is still set on all 12 assistants: removing the built-in endCall tool also removes the automatic goodbye Vapi speaks for it, so we speak it ourselves and the yamls stay the one source of truth.
The tool takes no arguments on purpose — a required argument makes the model treat filling it in as having done the thing (see configs/tools/brianjlevy/routetransfer.yaml). The server already has the transcript; it does not need the model to quote it back.
Trade-off accepted: the hangup path now depends on this endpoint. If it is down, calls linger until the assistant's 120s silenceTimeoutSeconds. The gate's own judge fails open, so only a full outage has that effect.
Request
- Base URL: https://api.openintake.ai (the document declares no server; this is the origin it was published from)
- URL: https://api.openintake.ai/vapi/end-call
- Auth: HTTP bearer
Request body
Response
Successful Response
Changes
- info
endpoint added
- info