A split vote is not a yes. When the tally is below the threshold, or when voters disagree on the action text, send the packet to a judge. The judge is another session, or the judge seat on a Dynamic Profile. It sees the votes, not a chance to invent a new action.
@Generable
struct Judgment {
@Guide(description: "approve, reject, or escalate")
var decision: String
var reason: String
}
func judgeVotes(packet: String) async throws -> Judgment {
let board = ReviewBoard()
board.seat = .judge
let session = LanguageModelSession(profile: ReviewProfile(board: board))
let reply = try await session.respond(to: packet, generating: Judgment.self)
return reply.content
}
enum Gate: String {
case allow
case block
case escalate
}
func resolve(specialists: [Specialist], votes: [String: Vote], threshold: Double) async throws -> Gate {
if approved(specialists: specialists, votes: votes, threshold: threshold) {
return .allow
}
let packet = votes.map { "\($0.key): \($0.value.choice) \($0.value.reason)" }.joined(separator: "\n")
let judgment = try await judgeVotes(packet: packet)
switch judgment.decision.lowercased() {
case "approve": return .allow
case "escalate": return .escalate
default: return .block
}
}
Escalation is a UI state. Show the proposed action, the votes, and the judge reason. Wait for a person. Do not call the side-effect tool from the judge session. If you need a safer model for the judge, set .model(SystemLanguageModel.default) and keep the work on device. Use Private Cloud Compute only when you have already redacted the packet. That redaction is in Stop prompt attacks and leaks.
Read Pause and resume long AI jobs, Stop prompt attacks and leaks, and Talk to tools with MCP if the wait for a person must survive backgrounding.
Next, bind the gate to the tool so the app cannot skip it.
Key concepts
- A split vote goes to a judge session or a judge seat.
- The judge returns approve, reject, or escalate.
- Escalate means stop and show a person, not try the action anyway.
- The judge sees votes, not permission to invent a new action.
Takeaways
- Do not call a side-effect tool from the judge session.
- Keep the judge on-device unless you redact first.
- Escalation is a UI state that waits for a person.