Skip to content

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 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 is user_message.
  • ctx.decision — the approval decision, {"approved": bool, "approver"?: str}. Only on turns whose reason is approval_decision.

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_STARTED envelopes with a user_message reason — and the transcript already includes this invocation’s start event, so the current user message is already in ctx.messages. Don’t append it again.
  • Assistant messages are rebuilt from MESSAGE_START/DELTA/END (text deltas merged into content, reasoning deltas into reasoning_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.
  • ctx.pending_tool_call — the unanswered tool call on an approval-resume turn: {name, arguments, tool_call_id, ...} (or None).
  • ctx.execute(name, call_id=..., **arguments) — run a registered tool. On a gated tool during a user_message turn it raises ApprovalRequired (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 raises ApprovalRequired: for gating an action no single tool expresses.

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.