> Fetch clean Markdown by appending `.md` to any page URL under https://signalwire.com/docs or requesting it with the HTTP header `Accept: text/markdown`. The root index at https://signalwire.com/docs/llms.txt lists the available documentation indexes. # on_call_end > Register a handler that receives the conversation transcript when a call ends. [on-summary]: /docs/server-sdks/reference/python/agents/agent-base/on-summary [post-prompt]: /docs/server-sdks/reference/python/core/post-prompt/normalize-post-prompt Register a handler that runs when the call ends, with the transcript. Usable as a decorator or called directly. Handlers run in registration order. Under the hood this registers the platform's reserved `hangup_hook` function, which fires on hangup and is never offered to the model, so it can't be called early or skipped. Registering a handler also turns on the `swaig_post_conversation` parameter. Without it the hook still fires but carries no transcript, and the handler would receive an empty list forever with nothing to indicate why. If you have explicitly set that parameter to `False`, the SDK leaves it alone and logs a warning. The handler's return value is ignored, since the call is over. Exceptions are caught and logged rather than raised, so a failing handler doesn't turn into a failed hangup. For the post-prompt summary, see [`on_summary()`][on-summary]. ## Parameters **`handler`** `Callable[[list[dict[str, Any]], dict[str, Any]], None]` — required Called as `handler(call_log, raw_data)`. * `call_log` -- the conversation as the platform recorded it, already resolved from whichever field carried it. * `raw_data` -- the complete SWAIG request, including `global_data` and `call_id`. --- ## Returns The handler, unchanged, so the method works as a decorator. ## Example ```python {6-10} from signalwire import AgentBase agent = AgentBase(name="dispatch", route="/dispatch") agent.set_prompt_text("You are Ada, the dispatcher for Bayview Taxi.") @agent.on_call_end def archive(call_log, raw_data): conversation_id = raw_data.get("global_data", {}).get("conversation_id") # Write the transcript to your system of record. print(conversation_id, len(call_log), "turns") agent.serve() ``` To handle voice and chat transcripts with one shape, pass `raw_data` through [`normalize_post_prompt()`][post-prompt]. > Register a handler that receives the conversation transcript when a call ends.