WWDC26 Foundation Models adds Dynamic Profiles so you stop rebuilding sessions by hand. You declare a DynamicProfile. Its body is re-evaluated on each prompt. Conditionals pick one Profile. The framework handles the switch.
import FoundationModels
// Illustrative Dynamic Profile. Verify protocol names in the installed SDK.
struct PackedProfile: LanguageModelSession.DynamicProfile {
let pack: [ContextSlice]
let tools: [any Tool]
var body: some LanguageModelSession.DynamicProfile {
Profile {
Instructions {
"""
Answer using only the packed context.
If a fact is missing, say you do not have it.
"""
for slice in pack {
"[\(slice.lane.rawValue)] \(slice.text)"
}
}
for tool in tools {
tool
}
}
.historyTransform { history in
Array(history.suffix(8))
}
}
}
historyTransform changes what this request sees. It does not throw away the session transcript. WWDC26 session 242 is clear: prefer transforms for lossless, per-request trims. Mutating the shared history property is global and lossy.
Attach tools from the packed tool lane only. Extra tools inflate the schema and invite extra calls. Model choice is a modifier, covered in Route work to the right Apple model.
Next, measure the assembler on a real question.
Key concepts
- A
DynamicProfilebody re-evaluates on each prompt and picks oneProfile. - Put packed slices in
Instructionsand attach only the packed tools. historyTransformtrims what this request sees without mutating shared history.- One active Profile per turn.
Takeaways
- Prefer
historyTransformfor per-request trims. - Extra tools inflate schema and invite extra calls.
- Model choice is a modifier on the Profile, covered in the router course.