SessionContext
sectr.SessionContext is the single argument of every handler. One
SessionContext = one invocation: the rehydrated transcript plus the
polymorphic reason that started it.
The reason — input and decision
Section titled “The reason — input and decision”The reason is polymorphic; these sugars raise TypeError on the wrong kind
so misuse fails loudly:
ctx.input— the user’s message payload. Only on turns whose reason isuser_message.ctx.decision— the approval decision,{"approved": bool, "approver"?: str}. Only on turns whose reason isapproval_decision.
ctx.messages — the conversation fold
Section titled “ctx.messages — the conversation fold”The canonical transcript view: OpenAI-style message dicts covering the full multi-turn conversation. Framework adapters project this into their native state; hand-written loops feed it straight to a provider.
- User turns come from
INVOCATION_STARTEDenvelopes with auser_messagereason — and the transcript already includes this invocation’s start event, so the current user message is already inctx.messages. Don’t append it again. - Assistant messages are rebuilt from
MESSAGE_START/DELTA/END(text deltas merged intocontent, reasoning deltas intoreasoning_content). - Tool calls attach to the most recent assistant message as OpenAI
tool_calls; tool results become{role: "tool"}messages. - An unanswered tool call (the approval pause) is preserved exactly as the LLM left it — the resumed turn appends the tool result message.
- Compaction snapshots (
TRANSCRIPT_COMPACTED) positionally reset the fold — see compaction. - Crash stitching: a message interrupted by a session error is continued with a synthesized “please continue” user message, derived from the journal — never persisted.
Approval resume helpers
Section titled “Approval resume helpers”ctx.pending_tool_call— the unanswered tool call on an approval-resume turn:{name, arguments, tool_call_id, ...}(orNone).ctx.execute(name, call_id=..., **arguments)— run a registered tool. On a gated tool during auser_messageturn it raisesApprovalRequired(the platform journals the approval request and suspends the turn). On an approval-resume turn the decision is already in hand, so executing the pending tool proceeds.ctx.request_approval(name, arguments)— explicit sugar that always raisesApprovalRequired: for gating an action no single tool expresses.
Transcript shape
Section titled “Transcript shape”ctx.transcript is the raw list of sectr.events.Envelopes (journal rows)
— ctx.messages is a view over it. ctx.session_id / ctx.invocation_id
identify the session and this invocation.