Transcripts
A session’s transcript is the full conversation: instructions, prompts, tool calls, tool outputs, reasoning and
responses. Maps to Apple’s Transcript.
const transcript = await session.getTranscript();
transcript.entries; // typed, for UI and inspection
transcript.json; // Apple's lossless Codable encoding, for persistence
session.transcript; // the same snapshot, synchronously (maps to LanguageModelSession.transcript)
session.transcript encodes the whole conversation on the JS thread every time it is read. Read it once into a
variable; prefer getTranscript() for long conversations or inside render functions.
Entry types
type TranscriptEntry =
| { type: 'instructions'; segments; toolDefinitions: { name; description }[] }
| { type: 'prompt'; segments; options: { temperature; maximumResponseTokens }; responseFormat: { name } | null; reasoningLevel? }
| { type: 'toolCalls'; calls: { id; toolName; arguments }[] }
| { type: 'toolOutput'; toolName; segments }
| { type: 'response'; segments }
| { type: 'reasoning'; segments } // iOS 27
| { type: 'unknown'; description }; // future Apple entry types
type TranscriptSegment =
| { type: 'text'; text }
| { type: 'structure'; schemaName; content } // structured output (parsed)
| { type: 'attachment'; kind: 'image'; label; uri } // iOS 27
Tool calls are never dropped. entryText(entry) returns the plain text of an entry.
Each respond() result also includes transcriptEntries: just the entries that request added.
Persist & restore
// save
const { json } = await session.getTranscript();
await AsyncStorage.setItem(`chat:${id}`, json);
// later
const saved = await AsyncStorage.getItem(`chat:${id}`);
const session = await createSession({ transcript: saved!, tools: sameTools });
await session.respond('Where were we?');
Maps to LanguageModelSession(model:tools:transcript:). The transcript already contains the instructions, so don’t
pass instructions again. Pass the same tools so the model can keep calling them.
transcript accepts the Transcript object or its json string. Invalid JSON → INVALID_TRANSCRIPT.
Starting from plain messages
When the conversation was not produced by this package (history stored by another library, an imported chat), there is no Apple transcript to restore. Pass plain messages instead:
const session = await createSession({
instructions: 'Be brief.',
tools: [getWeather],
messages: [
{ role: 'user', content: 'Weather in Delhi?' },
{ role: 'toolCalls', calls: [{ id: 'call-1', toolName: 'getWeather', arguments: { city: 'Delhi' } }] },
{ role: 'toolOutput', id: 'call-1', toolName: 'getWeather', content: '31°C' },
{ role: 'assistant', content: 'It is 31°C in Delhi.' },
],
});
await session.respond('And tomorrow?');
The package builds a Transcript from them (Transcript.Prompt, .ToolCalls, .ToolOutput, .Response) and adds
the instructions entry itself, so here you do pass instructions. messages and transcript cannot be
combined (INVALID_ARGUMENT). Prefer transcript whenever you have one: plain messages carry text only, so
images, structured segments, reasoning and per-prompt options are lost.
Keeping transcripts within the context window
The on-device context is small (see getModelInfo().contextSize). Options:
- Measure:
await AppleFoundationModels.tokenCount({ transcript })(iOS 26.4+). - Start a new session with a summary: ask the model to summarize, then
createSession({ instructions: summary }). - iOS 27: use a profile
historystrategy to limit what the model sees without losing the stored transcript. - iOS 27:
transcriptErrorHandling: 'revert'keeps failed turns out of the transcript.
Privacy
Transcripts contain user content. Store them like any other user data (e.g. encrypted storage for sensitive apps).