@adonis-agora/agent
Version:
Governed, durable-backed AI agent (chat + tool-calling + governance) for AdonisJS — part of the Agora ecosystem.
54 lines • 2.54 kB
JavaScript
import { approvalPosterior } from '../approval-prior.js';
/** {@link ApprovalRiskScorer}'s stable name. */
export const APPROVAL_RISK_SCORER = 'approval-risk';
/**
* How likely a human is to reject what this run proposed — BEFORE a human looks at it.
*
* {@link import('./approval-outcome.scorer.js').ApprovalOutcomeScorer} reads verdicts that already
* exist; this turns the same corpus into a prediction, so a pending approvals inbox can be drained
* riskiest-first and a run that is about to be rejected can be caught while it is still cheap. It is
* the statistical family, not the rule-based one: the number is a smoothed frequency estimate over
* past decisions, and its `metadata` carries the sample it rests on so a 1-of-1 rejection is never
* mistaken for certainty.
*
* A run scores as its WORST proposed action, not the average of them. A turn that proposes one tool
* humans reject nine times in ten is a risky turn no matter how many safe reads it made alongside.
*
* `null` for a run that proposed no action — the same "not applicable, not perfect" rule as the
* outcome scorer.
*/
export class ApprovalRiskScorer {
prior;
name = APPROVAL_RISK_SCORER;
kind = 'statistical';
constructor(prior) {
this.prior = prior;
}
async score(run) {
const actions = run.toolCalls.filter((call) => call.toolType === 'action');
if (actions.length === 0) {
return null;
}
const proposed = [...new Set(actions.map((call) => call.toolName))]
.sort()
.map((toolName) => {
const counts = this.prior.get(toolName);
return {
toolName,
approved: counts?.approved ?? 0,
rejected: counts?.rejected ?? 0,
pApprove: approvalPosterior(counts),
};
});
const riskiest = proposed.reduce((worst, candidate) => candidate.pApprove < worst.pApprove ? candidate : worst);
const decided = riskiest.approved + riskiest.rejected;
return {
score: riskiest.pApprove,
reason: decided === 0
? `no human has ever decided on ${riskiest.toolName}, the riskiest of ${proposed.length} proposed action(s)`
: `the riskiest proposed action is ${riskiest.toolName} — humans approved ${riskiest.approved} of its ${decided} past calls`,
metadata: { riskiestTool: riskiest.toolName, proposed },
};
}
}
//# sourceMappingURL=approval-risk.scorer.js.map