QueryEnginePort instance. Each engine holds a unique session_id, a list of mutable_messages, and a TranscriptStore. Sessions can be persisted to disk and reloaded later.
Session anatomy
| Field | Type | Description |
|---|---|---|
session_id | str (UUID hex) | Auto-generated unique identifier |
mutable_messages | list[str] | Ordered list of prompts submitted this session |
transcript_store | TranscriptStore | Append-only log with a flushed flag |
total_usage | UsageSummary | Cumulative input_tokens / output_tokens |
permission_denials | list[PermissionDenial] | Accumulated tool-denial records |
Flushing a transcript
flush-transcript submits a prompt, persists the session to .port_sessions/<session_id>.json, and reports the file path plus the flush state.
Submit the message
engine.submit_message(prompt) appends the prompt to mutable_messages and transcript_store.entries, then computes projected token usage.Persist the session
engine.persist_session() calls flush_transcript() internally — setting transcript_store.flushed = True — then writes StoredSession JSON under .port_sessions/.TranscriptStore.flush()
flush() simply marks the store as flushed — it does not clear the entries. Entries are retained for replay or compaction.
append() call resets flushed to False.
Loading a saved session
Sessions are stored under
.port_sessions/ relative to the working directory. The file is named <session_id>.json.Python API
Creating an engine
Restoring a saved session
from_saved_session() reconstructs the engine with:
- the stored
session_id mutable_messagespopulated from saved messagestotal_usagerestored from saved token countstranscript_store.flushed = True(marking the restored transcript as already flushed)
Persisting a session
persist_session() always calls flush_transcript() before writing, ensuring flushed=True on return.
Turn limits and budget
Max turns
Default
8. When len(mutable_messages) >= max_turns, submit_message() returns immediately with stop_reason='max_turns_reached' without appending the new prompt.Max budget tokens
Default
2000. If the projected cumulative token count exceeds this after a turn, stop_reason is set to 'max_budget_reached' (the message is still recorded).QueryEngineConfig:
Message compaction
After each turn,compact_messages_if_needed() checks whether mutable_messages exceeds compact_after_turns (default 12). If so, only the most recent compact_after_turns messages are kept. The same window is applied to transcript_store.entries.
Compaction happens in-place on the live
mutable_messages list. The persisted session file always reflects the state at the time persist_session() was called.Stop reasons
stop_reason | Meaning |
|---|---|
completed | Turn processed successfully within all limits |
max_turns_reached | len(mutable_messages) >= max_turns at time of call; prompt not recorded |
max_budget_reached | Projected token count exceeded max_budget_tokens; turn was still recorded |
Streaming events
stream_submit_message() yields a sequence of typed event dicts before and after the underlying submit_message() call:
| Event type | When emitted |
|---|---|
message_start | Always first; carries session_id and prompt |
command_match | When matched commands are non-empty |
tool_match | When matched tools are non-empty |
permission_denial | When denied tools are non-empty |
message_delta | Carries the formatted output text |
message_stop | Always last; carries usage, stop_reason, and transcript_size |