Dunfey · Hotel WWDC as data, est. 1983
Front desk everything
Years
Topics

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 ↗

Transcript all transcripts

Chapters

Code shown on screen · 8 snippets

Tools swift · at 12:50 ↗
// 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 swift · at 13:13 ↗
// 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 swift · at 13:28 ↗
// 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 swift · at 14:33 ↗
// 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 swift · at 15:56 ↗
// 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 swift · at 16:48 ↗
// 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 swift · at 23:08 ↗
// Intent authentication policy

struct DeletePhotoIntent: DeleteIntent {
    var entities: [LooseLeafPhoto]

    static var authenticationPolicy: IntentAuthenticationPolicy = .requiresAuthentication

    func perform() async throws -> some IntentResult {
        // Implementation
    }
}
Schema authentication policy swift · at 23:27 ↗
// Schema authentication policy

@AppIntent(schema: .photos.deleteAssets)
struct DeletePhotoIntent {
    var entities: [LooseLeafPhoto]

    // Example: Schema default authentication policy is .requiresAuthentication

    func perform() async throws -> some IntentResult {
        // Implementation
    }
}

Resources