Transcript API Reference¶
Rich transcript modeling for context engineering.
Transcript¶
Main class for loading and manipulating transcripts.
Constructor¶
Transcript(
path: str | Path | None = None,
auto_load: bool = True,
validate: Literal["strict", "warn", "none"] = "warn",
include_archived: bool = False,
include_meta: bool = False,
)
| Parameter | Description |
|---|---|
path |
Path to transcript JSONL file |
auto_load |
Load file immediately (default True) |
validate |
Unknown block handling: strict=error, warn=warning, none=silent |
include_archived |
Include pre-compaction entries in views |
include_meta |
Include system meta entries in views |
Properties¶
| Property | Type | Description |
|---|---|---|
entries |
list[TranscriptEntry] |
Current context window entries |
archived |
list[TranscriptEntry] |
Pre-compaction entries |
all_entries |
list[TranscriptEntry] |
archived + entries |
user_messages |
list[UserMessage] |
User message entries |
assistant_messages |
list[AssistantMessage] |
Assistant message entries |
tool_uses |
list[ToolUseBlock] |
All tool use blocks |
tool_results |
list[ToolResultBlock] |
All tool result blocks |
errors |
list[ToolResultBlock] |
Tool results with is_error=True |
turns |
list[Turn] |
Entries grouped by requestId |
compact_boundaries |
list[CompactBoundary] |
Compaction markers |
stats |
TranscriptStats |
Aggregated statistics |
CRUD Methods¶
# Insert
transcript.insert(index: int, entry: Entry) -> None
transcript.append(entry: Entry) -> None
# Remove
transcript.remove(entry: Entry, relink: bool = True) -> None
transcript.remove_tree(entry: Entry) -> list[Entry]
# Replace
transcript.replace(old: Entry, new: Entry) -> None
# Persistence
transcript.load() -> None
transcript.save() -> None
# Batch operations
with transcript.batch():
# Auto-commit on success, rollback on exception
...
Query Methods¶
transcript.query(
include_archived: bool | None = None,
include_meta: bool | None = None,
) -> TranscriptQuery
Lookup Methods¶
transcript.find_by_uuid(uuid: str) -> Entry | None
transcript.find_tool_use(tool_use_id: str) -> ToolUseBlock | None
transcript.find_tool_result(tool_use_id: str) -> ToolResultBlock | None
transcript.find_snapshot(message_id: str) -> FileHistorySnapshot | None
transcript.get_parent(entry: Entry) -> Entry | None
transcript.get_children(entry: Entry) -> list[Entry]
transcript.get_logical_parent(entry: Entry) -> Entry | None
Export Methods¶
# To string
transcript.to_markdown(**kwargs) -> str
transcript.to_html(**kwargs) -> str
transcript.to_json(indent: int = 2) -> str
transcript.to_jsonl() -> str
# To file
transcript.to_file(
path: str | Path,
format: Literal["md", "html", "json", "jsonl"] = "md",
**kwargs
) -> None
TranscriptQuery¶
Fluent query builder for filtering entries.
Type Filters¶
query.users() -> TranscriptQuery
query.assistants() -> TranscriptQuery
query.system() -> TranscriptQuery
query.with_tools() -> TranscriptQuery
query.with_errors() -> TranscriptQuery
query.with_thinking() -> TranscriptQuery
Filtering¶
query.filter(**kwargs) -> TranscriptQuery
query.where(predicate: Callable) -> TranscriptQuery
query.exclude(**kwargs) -> TranscriptQuery
Supported lookups:
| Lookup | Example | Description |
|---|---|---|
exact |
filter(type="user") |
Exact match (default) |
contains |
filter(text__contains="error") |
Substring |
startswith |
filter(uuid__startswith="abc") |
Prefix |
endswith |
filter(text__endswith="!") |
Suffix |
regex |
filter(text__regex=r"\d+") |
Regex match |
in |
filter(type__in=["user", "assistant"]) |
In list |
gt |
filter(timestamp__gt=datetime(...)) |
Greater than |
gte |
filter(timestamp__gte=datetime(...)) |
Greater or equal |
lt |
filter(timestamp__lt=datetime(...)) |
Less than |
lte |
filter(timestamp__lte=datetime(...)) |
Less or equal |
isnull |
filter(parent_uuid__isnull=True) |
Is None |
Time Filters¶
query.since(ts: datetime | str) -> TranscriptQuery
query.until(ts: datetime | str) -> TranscriptQuery
Ordering¶
query.order_by(*fields: str) -> TranscriptQuery
# Prefix with - for descending: order_by("-timestamp")
Pagination¶
Terminals¶
query.all() -> list[TranscriptEntry]
query.first() -> TranscriptEntry | None
query.last() -> TranscriptEntry | None
query.one() -> TranscriptEntry # Raises if 0 or >1 results
query.count() -> int
query.exists() -> bool
Entry Types¶
Entry (Base)¶
class Entry:
type: str
uuid: str
parent_uuid: str | None
timestamp: datetime | None
session_id: str
cwd: str
version: str
git_branch: str
is_sidechain: bool
is_synthetic: bool
UserMessage¶
class UserMessage(Entry):
type: Literal["user"] = "user"
# Properties
content: str | list[ToolResultBlock]
text: str # Empty if tool result
is_tool_result: bool
tool_results: list[ToolResultBlock]
# Factory
@classmethod
def create(
cls,
content: str,
*,
parent: Entry | None = None,
context: Entry | None = None,
**overrides
) -> UserMessage
AssistantMessage¶
class AssistantMessage(Entry):
type: Literal["assistant"] = "assistant"
request_id: str
# Properties
message_id: str
model: str
content: list[ContentBlock]
stop_reason: str | None
usage: dict
text: str
thinking: str
tool_uses: list[ToolUseBlock]
has_tool_use: bool
# Factory
@classmethod
def create(
cls,
content: str | list[ContentBlock],
*,
parent: Entry | None = None,
context: Entry | None = None,
model: str = "synthetic",
stop_reason: str = "end_turn",
**overrides
) -> AssistantMessage
SystemEntry¶
CompactBoundary¶
class CompactBoundary(SystemEntry):
subtype: Literal["compact_boundary"] = "compact_boundary"
logical_parent_uuid: str
compact_metadata: dict
Content Blocks¶
TextBlock¶
ToolUseBlock¶
class ToolUseBlock:
type: Literal["tool_use"] = "tool_use"
id: str
name: str
input: dict
# Property - finds matching result
result: ToolResultBlock | None
ToolResultBlock¶
class ToolResultBlock:
type: Literal["tool_result"] = "tool_result"
tool_use_id: str
content: str
is_error: bool
# Property - finds matching tool use
tool_use: ToolUseBlock | None
ThinkingBlock¶
class ThinkingBlock:
type: Literal["thinking"] = "thinking"
thinking: str
signature: str # Cryptographic signature (read-only)
Turn¶
Groups assistant entries by requestId.
class Turn:
request_id: str
entries: list[AssistantMessage]
# Properties
thinking: str
text: str
tool_uses: list[ToolUseBlock]
is_complete: bool
has_error: bool
TranscriptStats¶
class TranscriptStats:
input_tokens: int
output_tokens: int
cache_read_tokens: int
cache_creation_tokens: int
tool_calls: dict[str, int]
error_count: int
message_count: int
turn_count: int
compact_count: int
duration_seconds: float
slug: str
Factory Functions¶
inject_tool_result¶
from fasthooks.transcript import inject_tool_result
inject_tool_result(
transcript: Transcript,
tool_name: str,
tool_input: dict,
result: str,
*,
is_error: bool = False,
position: int | Literal["start", "end"] = "end",
) -> tuple[AssistantMessage, UserMessage]
Creates a matching ToolUseBlock + ToolResultBlock pair and inserts them.