SDK
Judgments from code
The same judgment memory as oort judge: record an expert's decisions, then predict how they would judge a new item from those precedents. Local mode only.
Record, confirm and apply
An expert-role handle records a person's decision. An agent-role handle derived from it records a draft, which counts only after the expert confirms it. Then judge.apply predicts a verdict for a new item.
import { createOort } from 'oortmem';
// The expert role is for code paths where a person really decided: a review UI, an import job.
await using expert = await createOort({
mode: 'local',
judge: { role: 'expert', operator: 'ada' },
config: { judge: { experts: ['ada'] } },
});
await expert.judge.record({
subject: 'Post claims a cure for diabetes',
verdict: 'rejected',
reason: 'A medical claim with no source.',
domain: 'content',
by: 'ada',
});
// Model-facing code runs in the agent role: it records only for listed experts, and what it
// records waits for a person to confirm it before it counts as a precedent.
const agent = expert.scoped({ judgeRole: 'agent' });
const draft = await agent.judge.record({
subject: 'Post claims a miracle cure for colds',
verdict: 'rejected',
reason: 'No source.',
domain: 'content',
by: 'ada',
});
console.log(draft.status); // 'agent-recorded'
await expert.judge.confirm(draft.id);
const r = await agent.judge.apply({ summary: 'Post claims a miracle cure', domain: 'content' });
// 'suggested' | 'needs-expert' | 'precedents-only'. A prediction is never the expert's decision.
console.log(r.status, r.prediction?.verdict, r.precedents.length);| status | Meaning |
|---|---|
suggested | A prediction at or above threshold (default 0.7) that at least two close precedents agree with. prediction holds the verdict and its probability. |
needs-expert | No trustworthy prediction. why says which: no-precedents, too-far, too-few, precedents-disagree, low-confidence, no-decider or decider-failed. |
precedents-only | No TypeSafe key: the close precedents and their reasons, and no verdict. |
Every result lists its precedents, with similarity and who decided each one. Show them next to the prediction, so a person can check it.
Agent and expert roles
Your code is an agent by default, because the rule protects the expert's record from the model, not from you. The expert role is one explicit option, for code paths where a person really decided: a review screen, or an import job.
- How
- Agent (default)The default.
- Expert
judge: { role: 'expert', operator: 'marcus' } - Records for
- Agent (default)Experts listed in
judge.expertsonly. - ExpertAnyone.
- Daily cap
- Agent (default)50 a day per Oort home.
- ExpertNone.
- Stored as
- Agent (default)Agent-recorded and unconfirmed (
via: 'mcp'), exactly like an MCP agent's. - ExpertA person's judgment (
via: 'sdk'). - Counts in
judge.apply - Agent (default)Only after a person confirms it.
- ExpertYes.
judge.confirm- Agent (default)Refused (
expert-only). - ExpertConfirms an agent's record.
scoped({ judgeRole: 'agent' }) narrows a handle back to the agent role, and nothing widens it. Framework tools, the oortmem/ai-sdk ones included, always run in the agent role.
Listing experts: judge.experts
An agent may record only for the experts listed in judge.experts: in the home config, or in the config option as above.
- With none listed,
judge.recordis refused withexperts-not-listed. - A
bythat is not listed is refused withnot-an-expert.
The daily cap
Agents record at most 50 judgments a day per Oort home. The count is shared with the MCP server's record_judgment tool (the same counter file, so 0.5.x counts too).
- Over the cap:
OortRefusedErrorwith reasondaily-limit. A person records more withoort judge record. - When the count cannot be kept, nothing is saved:
cap-unavailable, which is retryable.
Confirm an agent's record
judge.apply leaves agent-recorded judgments out until a person confirms them, and an agent's record never corrects a person's. A person confirms one with oort judge confirm in a terminal, or your code calls judge.confirm(id) on an expert-role handle, as the example above does.
judge.confirmreturns{ id, changed }.judge.list({ domain, by })finds the judgments to review.changedisfalsewhen the judgment was already confirmed.- A judgment that is no longer current is refused with
not-current. - In host code,
judge.apply(item, { includeAgentRecorded: true })also uses unconfirmed records, andincludeImporteduses judgments from packs. Model-facing tools never offer either.
Cost
judge.record makes one Voyage embed. judge.apply makes one Voyage embed and one TypeSafe judge call. judge.list and judge.confirm call no model. In cloud mode every judge method is refused (local-only). See What costs usage.