2026 AI & Machine LearningPrivacy & Security
WWDC26 · 25 min · AI & Machine Learning / Privacy & Security
Secure your app: mitigate risks to agentic features
Explore how to evaluate threats from indirect prompt injection, such as data exfiltration and unintended actions. Discover system safeguards and security best practices for using App Intents and the Foundation Models framework, including mitigations such as user confirmations, secure prompt design, and authentication.
Watch at developer.apple.com ↗Chapters
Code shown on screen · 8 snippets
Tools
// Tools
struct OrderTeaTool: Tool {
let name = "orderTeaTool"
let description: String = "Orders a particular quantity of a tea from the store."
// Arguments
// Implementation
}
struct PostAndFetchPublicFeedTool: Tool {
let name = "postAndFetchPublicFeedTool"
let description: String = "Posts a message to the public feed.”
// Arguments
// Implementation
} Profile
// Profile
class LooseLeafAgent {
struct DefaultProfile: LanguageModelSession.DynamicProfile {
var body: some DynamicProfile {
Profile {
Instructions("You are a helpful, tea-loving assistant ... ")
OrderTeaTool()
PostAndFetchPublicFeedTool()
}
.model(SystemLanguageModel())
}
}
} Session
// Session
class LooseLeafAgent {
struct DefaultProfile: LanguageModelSession.DynamicProfile {
var body: some DynamicProfile {
Profile {
Instructions("You are a helpful, tea-loving assistant ... ")
OrderTeaTool()
PostAndFetchPublicFeedTool()
}
.model(SystemLanguageModel())
}
}
let session: LanguageModelSession
public init() {
self.session = LanguageModelSession(profile: DefaultProfile())
}
} Confirmation via onToolCall
// Confirmation via onToolCall
var body: some DynamicProfile {
Profile {
Instructions("You are a helpful, tea-loving assistant ... ")
OrderTeaTool() // Financial impact; risky tool.
// Other Tools
}
.onToolCall { call in
guard call.toolName == "orderTeaTool" else {
return
}
guard ConfirmationAction.confirmWithUser() else {
throw LooseLeafError.userConfirmationDenied
}
}
} Spotlighting via historyTransform
// Spotlighting via historyTransform
var body: some DynamicProfile {
Profile {
Instructions("You are a helpful, tea-loving assistant ... ")
PostAndFetchPublicFeedTool() // Returns untrusted data; requires spotlighting
// Other Tools
}
.historyTransform {γentries in
entries.map { entry in
guard case .toolOutput(var toolOutput) = entry,
toolOutput.toolName == "postAndFetchPublicFeedTool"
else {
return entry
}
}
toolOutput.segments = toolOutput.segments.map { segment in
delimit(segment: segment,
startDelimiter: "<<UNTRUSTED>>",
endDelimiter: "<</UNTRUSTED>>")
}
return .toolOutput(toolOutput)
}
}
func delimit(segment: Transcript.Segment,
startDelimiter: String,
endDelimiter: String) -> Transcript.Segment Redaction via historyTransform
// Redaction via historyTransform
var body: some DynamicProfile {
Profile {
Instructions("You are a helpful, tea-loving assistant ... ")
PostAndFetchPublicFeedTool() // Returns untrusted data; requires spotlighting
// Other Tools
}
.historyTransform {γentries in
entries.map { entry in
guard case .toolOutput(var toolOutput) = entry,
toolOutput.toolName == "postAndFetchPublicFeedTool"
else {
return entry
}
}
toolOutput.segments = toolOutput.segments.map { segment in
redactPII(segment: segment,
placeHolder: "[REDACTED]")
}
return .toolOutput(toolOutput)
}
}
func redactPII(segment: Transcript.Segment,
placeHolder: String) -> Transcript.Segment Intent authentication policy
// Intent authentication policy
struct DeletePhotoIntent: DeleteIntent {
var entities: [LooseLeafPhoto]
static var authenticationPolicy: IntentAuthenticationPolicy = .requiresAuthentication
func perform() async throws -> some IntentResult {
// Implementation
}
} Schema authentication policy
// Schema authentication policy
(schema: .photos.deleteAssets)
struct DeletePhotoIntent {
var entities: [LooseLeafPhoto]
// Example: Schema default authentication policy is .requiresAuthentication
func perform() async throws -> some IntentResult {
// Implementation
}
} Resources
Related sessions
-
22 min -
38 min -
22 min -
27 min -
24 min