A weighted vote is ordinary Swift. Each specialist session returns a structured choice. You multiply that choice by a weight you chose. You do not ask the model to count the votes. The model is a voter, not the tally clerk.
import FoundationModels
@Generable
struct Vote {
@Guide(description: "approve, reject, or abstain")
var choice: String
@Guide(description: "One short reason")
var reason: String
}
struct Specialist {
let name: String
let weight: Double
let session: LanguageModelSession
}
func collectVotes(specialists: [Specialist], prompt: String) async throws -> [String: Vote] {
var votes: [String: Vote] = [:]
try await withThrowingTaskGroup(of: (String, Vote).self) { group in
for specialist in specialists {
group.addTask {
let reply = try await specialist.session.respond(
to: prompt,
generating: Vote.self
)
return (specialist.name, reply.content)
}
}
for try await (name, vote) in group {
votes[name] = vote
}
}
return votes
}
func approved(specialists: [Specialist], votes: [String: Vote], threshold: Double) -> Bool {
let total = specialists.reduce(0) { sum, item in
let choice = votes[item.name]?.choice.lowercased()
let point = choice == "approve" ? item.weight : 0
return sum + point
}
return total >= threshold
}
Give specialists different instructions, not different secrets. A planner proposes. A policy reader checks a local rule file. A critic looks for missing user confirmation. Keep weights in your code or in a config file you ship. Do not let a model rewrite its own weight.
If two specialists share one session transcript, they are not independent. Create separate sessions, or use phone-a-friend child sessions that do not inherit the parent transcript.
Read Pause and resume long AI jobs, Stop prompt attacks and leaks, and Talk to tools with MCP if a long vote must checkpoint, or if voter prompts include untrusted text.
Next, add a judge and a path that stops the app and asks for help.
Key concepts
- A typed vote carries a choice and a reason.
- Each specialist has a name, a weight, and its own session.
- Collect votes in a task group. Tally approve weights in app code.
- A shared transcript between specialists breaks independence.
Takeaways
- You assign weights and tally. The model only casts a typed vote.
- Keep weights in your code or shipped config, not model-writable.
- Create separate sessions for independent votes.