Documentation / Core concepts / Lifecycle
From ActiveCall to Closure¶
After setup passes preflight, VAANI owns the call attempt. That owned attempt
produces exactly one immutable CallResult, even when providers fail, the
participant disconnects, teardown times out, or the owner is cancelled.
stateDiagram-v2
[*] --> ACCEPTED
ACCEPTED --> VALIDATING
VALIDATING --> STARTING
STARTING --> CONNECTING
CONNECTING --> WAITING_FOR_PARTICIPANT
WAITING_FOR_PARTICIPANT --> GREETING
GREETING --> CONVERSING
CONVERSING --> ENDING: graceful EndRequest
CONVERSING --> TEARING_DOWN: forced terminal signal
ENDING --> TEARING_DOWN
TEARING_DOWN --> FINALIZING
FINALIZING --> CLOSED: publish CallResult
CLOSED --> [*]
Some failures skip phases. Progress is always forward; a late signal cannot reopen or reverse a committed transition.
Start and run¶
Use run() when the owner only needs the terminal result:
Use start() when consumer code needs the call handle:
active = await runtime.start(invocation, setup)
print(active.call_id, active.revision)
receipt = await active.update(update)
await active.end(EndRequest(EndRequestSource.ACTIVE_CALL, "complete"))
result = await active.wait()
ActiveCall.update(), end(), and wait() are the public operations. The async
context manager is also an ownership boundary: normal exit requests a graceful
end; exceptional exit forces cancellation if the call is still active.
Exactly one result¶
Closure is the atomic publication point. All successful waiters receive the same frozen result. Cancelling a result observer does not end the call; cancelling the lifecycle owner does.
Before ownership, configuration/controller-installation problems raise a typed startup error and produce no result. After ownership, terminal failures appear inside the result's normalized failure evidence.
Deadlines do not reset on retry¶
Each bounded phase receives an absolute monotonic cutoff. A retry spends the remaining budget; it cannot create a new full timeout. Completion observed by the cutoff wins, and later completion is quarantined rather than mutating the result.
Separate budgets exist for:
- connection, participant readiness, greeting, terminal media, drain, teardown, and finalization;
- provider operations, tools, updates, transfer, recording, and result publication.
Graceful and forced endings¶
All healthy completion sources submit an EndRequest. The first accepted
request is canonical; later requests join the same ending and remain as
suppressed evidence. A forced terminal signal can pre-empt terminal media but
cannot erase that canonical request.
Next: tools and state or result evidence.