Skip to main content
POST
End a v2 conversation through the close pipeline (admin)

Authorizations

x-api-key
string
header
required

Path Parameters

conversation_id
string<uuid>
required

Body

application/json

Admin-triggered runtime end-session.

Distinct from POST /v1/sessions/{id}/close which only flips the DB status. This drives the full Runtime.end_session pipeline (AOP cleanup, memory flush, OTel session.end span, triggered_by=admin).

session_id is required: Runtime.from_authenticated falls through to get_or_create_active_session when it's missing, which would mint a fresh ACTIVE session purely to end it on the same request. Requiring the caller to name the target session prevents that ghost-session path and forces a clear 422 instead of a misleading 200.

farewell_text is intentionally omitted: the runtime ignores it under PersistStrategy.PER_TURN (used by every HTTP channel today), so accepting it would silently drop the value. Callers that want a user-visible farewell should send a final POST /v1/runtime/turn with the goodbye message before calling this endpoint.

end_user_id
string<uuid>
required
session_id
string<uuid>
required
agent_id
string<uuid> | null
reason
string | null

Response

Successful Response

Universal post-turn snapshot returned by Runtime.run_turn.

Every channel sees the same fields:

  • session_id: the session this turn ran against. Always populated when a real Runtime produced the result (the caller may have passed session_id=None and asked the runtime to resolve / create the active session — this is how it learns which one was used). Optional in the type for the benefit of test fixtures that mint TurnResults by hand without a Runtime.
  • messages: 1 message for API/voice; N (Plan 5) for SMS chunked.
  • status: snapshot of Runtime._status at end-of-turn. The caller uses this to decide whether to call end_session.
  • handoff: populated when AOP reached a HandoffNode. The dict shape mirrors the existing AOPExecutionResult.handoff_config for forward-compat — Plan 3 does not re-type it.
  • error: when AOP execution fails, this is the AOPExecutionResult.execution_error string the pipeline stamped (e.g. "node_execution_failed: ValidationError: ...", "routing_error: <node_id>", "unknown_node_type"); falls back to the legacy "max_steps_exceeded" label only when the pipeline didn't attach a reason. repr(exc) for an uncaught exception in _execute. None on success / handoff / policy-violation.
  • model_used / token_count / latency_ms: aggregate metrics surfaced for telemetry; None when the turn made no LLM call.
status
enum<string>
required

In-memory lifecycle status of a Runtime instance.

Distinct from ConversationSession.status (DB column). The DB status is the durable end-state of a session row; this enum is the per-instance live signal that channel runtimes consult after each run_turn to decide whether to call end_session.

Available options:
idle,
running_turn,
end_requested,
end_processing,
ended,
error
session_id
string<uuid> | null
messages
AssistantMessage · object[]
handoff
Handoff · object | null
call_transfer
CallTransferIntent · object | null

The resolved, ready-to-execute transfer the voice host renders after a turn.

Both authoring surfaces converge on this: the assistant transfer_call platform tool (label → destination resolved from config) and the workflow HandoffNode voice transfer (deterministic single target, or LLM-picked among many) both produce a CallTransferIntent; the voice worker reads it via VoiceRuntime.pending_transfer and issues the SIP REFER. connecting_text is the optional "one moment, connecting you…" line spoken before the transfer.

dtmf_input
DtmfInputSpec · object | null

Per-node keypad-collection tuning (authoring config + runtime directive).

All fields optional: an unset field means "leave the assistant-level default in place" (the voice config's dtmf_* values). expects_input is the intent flag — a node that explicitly expects keypad entry — used so the host can apply the retune even when no numeric override differs from the default. prefix overrides the turn-text label (collection mechanics + framing).

session_status
string | null
error
string | null
model_used
string | null
token_count
integer | null
latency_ms
integer | null