Voting, Polls & Outcomes
Cast argument votes, create polls, submit real-world outcomes, and retrieve decision intelligence scores with the AskVerdict SDK.
Beyond generating verdicts, AskVerdict tracks how well its AI recommendations hold up in the real world. This page covers three closely related features:
- Voting — cast agree/disagree votes on individual argument claims
- Polls — create audience polls tied to a debate
- Outcomes — record what actually happened after a decision was made, and compare it to the AI verdict
- Decision Intelligence — retrieve accuracy scores and streaks that reflect your track record
Voting on Arguments
After a debate completes, each argument published by an AI agent contains one or more claims. Users can vote "agree" or "disagree" on each claim to signal how persuasive they found it.
Get current vote tallies
import { AskVerdictClient, type VoteMap } from "@askverdict/sdk";
const client = new AskVerdictClient({ apiKey: process.env.ASKVERDICT_API_KEY! });
const votes: VoteMap = await client.getVotes("dbt_abc123");
// VoteMap is Record<claimId, ClaimVoteTally>
for (const [claimId, tally] of Object.entries(votes)) {
console.log(`Claim ${claimId}:`);
console.log(` Agree: ${tally.agree}`);
console.log(` Disagree: ${tally.disagree}`);
if (tally.userVote !== undefined) {
console.log(` Your vote: ${tally.userVote}`); // "agree" | "disagree" | "neutral"
}
}VoteMap shape:
| Key | Type | Description |
|---|---|---|
| (claimId) | ClaimVoteTally | Tally object for that claim |
ClaimVoteTally shape:
| Field | Type | Description |
|---|---|---|
agree | number | Total agree votes |
disagree | number | Total disagree votes |
userVote | VoteValue | undefined | Caller's own vote (only when authenticated) |
Cast a vote
Pass "agree", "disagree", or "neutral" as the vote value. Calling castVote again with a different value updates the existing vote — each user can hold at most one vote per claim.
await client.castVote("dbt_abc123", "claim_pro_001", "agree");Remove a vote explicitly
await client.removeVote("dbt_abc123", "claim_pro_001");
// Equivalent to castVote(..., "neutral")Vote on every claim after a debate completes
const { verdict } = await client.getVerdict("dbt_abc123");
if (verdict.status !== "completed" || !verdict.verdict) {
throw new Error("Debate is not yet complete");
}
// Fetch current tallies so we know which claims exist
const votes = await client.getVotes("dbt_abc123");
// Vote agree on all claims we haven't voted on yet
for (const [claimId, tally] of Object.entries(votes)) {
if (tally.userVote === undefined) {
await client.castVote("dbt_abc123", claimId, "agree");
console.log(`Voted agree on ${claimId}`);
}
}Polls
Polls let the debate owner solicit structured audience input — for example, asking "Which argument was most convincing?" after a debate completes.
Get polls for a debate
import type { Poll } from "@askverdict/sdk";
const polls: Poll[] = await client.getPolls("dbt_abc123");
for (const poll of polls) {
console.log(`\n${poll.question} [${poll.status}]`);
console.log(`Total votes: ${poll.totalVotes}`);
for (const option of poll.options) {
const count = poll.tallies[option.id] ?? 0;
const pct = poll.totalVotes > 0
? Math.round((count / poll.totalVotes) * 100)
: 0;
console.log(` ${option.label}: ${count} (${pct}%)`);
}
if (poll.userVote !== null) {
const chosen = poll.options.find((o) => o.id === poll.userVote);
console.log(` Your vote: ${chosen?.label ?? poll.userVote}`);
}
}Poll shape:
| Field | Type | Description |
|---|---|---|
id | string | Poll ID |
debateId | string | Parent debate |
question | string | Poll question text |
options | PollOption[] | Array of { id, label } |
status | "open" | "closed" | Whether voting is still open |
tallies | Record<string, number> | Vote counts keyed by option ID |
totalVotes | number | Sum of all option votes |
userVote | string | null | Option ID the caller voted for (null if not voted) |
createdAt | string | ISO 8601 creation time |
closedAt | string | null | ISO 8601 close time, or null if still open |
Create a poll
Creating a poll requires debate ownership. Provide 2–6 option labels.
const poll = await client.createPoll(
"dbt_abc123",
"Which argument changed your mind most?",
[
"The scalability argument (Pro Round 2)",
"The cost projection (Con Round 1)",
"Neither — I was already decided",
],
);
console.log(`Poll created: ${poll.id}`);
// poll.options[0].id → "opt_001" (server-generated IDs)Vote on a poll
// Get the option ID to vote for
const polls = await client.getPolls("dbt_abc123");
const poll = polls[0]!;
const firstOption = poll.options[0]!;
await client.votePoll("dbt_abc123", poll.id, firstOption.id);
console.log(`Voted for: ${firstOption.label}`);Close and delete polls
// Close a poll — prevents further votes, results are still visible
await client.closePoll("dbt_abc123", "poll_pqr789");
// Delete a poll entirely
await client.deletePoll("dbt_abc123", "poll_pqr789");closePoll and deletePoll require debate ownership. They will throw AskVerdictError with status 403 if called by a non-owner.
Outcomes
An outcome is a record of what actually happened after a decision was made. Submitting outcomes is what powers AskVerdict's decision intelligence: over time, it tells you how accurate the AI's recommendations were.
Submit an outcome
After a real-world decision plays out, record what happened and whether the AI verdict was correct.
const outcome = await client.submitOutcome("dbt_abc123", {
actualOutcome: "Adopted Kubernetes — deployment time down 40% after 3 months",
verdictWasCorrect: true,
notes: "The scalability argument proved decisive for the infrastructure team.",
});
console.log(`Outcome recorded: ${outcome.id}`);
console.log(`Recorded at: ${outcome.recordedAt}`);OutcomeRecord shape:
| Field | Type | Description |
|---|---|---|
id | string | Outcome record ID |
debateId | string | Parent debate |
actualOutcome | string | Description of what happened |
notes | string | null | Optional notes |
verdictWasCorrect | boolean | null | Whether the AI verdict matched reality |
recordedAt | string | ISO 8601 timestamp |
Get an existing outcome
const outcome = await client.getOutcome("dbt_abc123");
if (outcome.verdictWasCorrect === true) {
console.log("The AI verdict was correct.");
} else if (outcome.verdictWasCorrect === false) {
console.log("The AI verdict was incorrect.");
} else {
console.log("Verdict accuracy not yet assessed.");
}Get pending outcomes
Debates that have completed but have no outcome recorded yet.
const pending = await client.getPendingOutcomes();
console.log(`${pending.length} debates awaiting outcome recording:`);
for (const p of pending) {
console.log(` ${p.debateId}`);
}Get outcome history
// Most recent 50 outcomes
const history = await client.getOutcomeHistory({ limit: 50 });
// Filter by domain (if you tag debates by domain)
const businessHistory = await client.getOutcomeHistory({
limit: 20,
domain: "business",
});
// Paginate through history
const page2 = await client.getOutcomeHistory({ limit: 20, offset: 20 });Decision Intelligence Scores
After recording several outcomes, you can retrieve accuracy metrics that show how well you (and the AI) have been doing.
Get your decision score
const score = await client.getScore();
console.log(`Overall accuracy: ${Math.round(score.overallAccuracy * 100)}%`);
console.log(`Total decisions tracked: ${score.totalDecisions}`);
console.log(`Correct predictions: ${score.correctPredictions}`);
if (score.brierScore !== null) {
// Brier score: 0.0 = perfect, 1.0 = worst possible
console.log(`Brier score: ${score.brierScore.toFixed(3)}`);
}
if (score.calibrationScore !== null) {
console.log(`Calibration: ${Math.round(score.calibrationScore * 100)}%`);
}DecisionScore shape:
| Field | Type | Description |
|---|---|---|
overallAccuracy | number | Fraction of verdicts that proved correct (0–1) |
totalDecisions | number | Total decisions with recorded outcomes |
correctPredictions | number | Count of correct verdicts |
brierScore | number | null | Probabilistic calibration (0 = best, 1 = worst) |
calibrationScore | number | null | Normalized calibration fraction (0–1) |
Get your debate streak
const streak = await client.getStreak();
console.log(`Current streak: ${streak.currentStreak} days`);
console.log(`Longest streak: ${streak.longestStreak} days`);
console.log(`Total debates: ${streak.totalDebates}`);
for (const milestone of streak.milestones) {
const status = milestone.reached
? `reached ${milestone.reachedAt ? `on ${milestone.reachedAt}` : ""}`
: "not yet reached";
console.log(` ${milestone.count}-debate milestone: ${status}`);
}End-to-End Workflow
This example shows the complete lifecycle from creating a debate, engaging with it through polls and votes, then recording the outcome and checking the impact on your score.
import { AskVerdictClient, AskVerdictError } from "@askverdict/sdk";
const client = new AskVerdictClient({ apiKey: process.env.ASKVERDICT_API_KEY! });
async function fullWorkflow() {
// 1. Create a verdict and wait for it to complete
console.log("Creating verdict…");
const { id } = await client.createVerdict({
question: "Should we expand into the European market in Q3?",
mode: "thorough",
context: "We have $500K budget, a 10-person team, and 80% US revenue.",
});
// 2. Stream events until complete
console.log(`Streaming debate ${id}…`);
for await (const event of client.streamVerdict(id)) {
if (event.type === "agent:argument") {
const data = event.data as { agentName: string; content: string };
console.log(` [${data.agentName}] ${data.content.slice(0, 80)}…`);
}
if (event.type === "debate:complete") break;
}
// 3. Fetch the completed verdict
const { verdict } = await client.getVerdict(id);
if (!verdict.verdict) {
throw new Error("Verdict is not complete");
}
console.log(`\nVerdict: ${verdict.verdict.recommendation.recommendation}`);
console.log(`Confidence: ${Math.round(verdict.verdict.confidence * 100)}%`);
console.log("Key findings:");
for (const finding of verdict.verdict.keyFindings) {
console.log(` - ${finding}`);
}
// 4. Vote on argument claims
const votes = await client.getVotes(id);
const claimIds = Object.keys(votes);
if (claimIds.length > 0) {
// Agree with the first claim as an example
await client.castVote(id, claimIds[0]!, "agree");
console.log(`\nVoted agree on claim ${claimIds[0]}`);
}
// 5. Create an audience poll
const poll = await client.createPoll(
id,
"After reading the debate, what is your decision?",
["Expand into Europe in Q3", "Delay until Q4", "Do not expand at all"],
);
console.log(`\nPoll created: ${poll.id}`);
// 6. Vote on the poll
await client.votePoll(id, poll.id, poll.options[0]!.id);
console.log(`Voted on poll: "${poll.options[0]!.label}"`);
// --- Later, after the decision plays out ---
// 7. Record the outcome
const outcome = await client.submitOutcome(id, {
actualOutcome: "Launched EU operations — $120K revenue in first month",
verdictWasCorrect: true,
notes: "The market timing argument proved accurate. GDPR compliance was harder than estimated.",
});
console.log(`\nOutcome recorded: ${outcome.id}`);
// 8. Check updated decision score
const score = await client.getScore();
console.log(`\nUpdated score: ${Math.round(score.overallAccuracy * 100)}% accuracy`);
console.log(`Total decisions tracked: ${score.totalDecisions}`);
}
fullWorkflow().catch((error) => {
if (error instanceof AskVerdictError) {
console.error(`[${error.code}] ${error.message}`);
} else {
console.error(error);
}
process.exit(1);
});TypeScript Types Reference
import type {
// Votes
VoteValue, // "agree" | "disagree" | "neutral"
ClaimVoteTally, // { agree, disagree, userVote? }
VoteMap, // Record<claimId, ClaimVoteTally>
// Polls
PollOption, // { id, label }
Poll, // Full poll object with tallies
// Outcomes
OutcomeRecord, // { id, debateId, actualOutcome, notes, verdictWasCorrect, recordedAt }
SubmitOutcomeParams, // { actualOutcome, notes?, verdictWasCorrect? }
// Decision intelligence
DecisionScore, // { overallAccuracy, totalDecisions, correctPredictions, brierScore, calibrationScore }
StreakInfo, // { currentStreak, longestStreak, totalDebates, milestones }
} from "@askverdict/sdk";Was this page helpful?