A fresh call names a role with agentType. A role has a fixed model and effort (its pair), a role family (executor and
executor-t1 form one, architect, reviewer, explorer and critic are alone) and a sandbox:
workspace-write for executor and executor-t1, the only roles that write (to their call's own cwd), read-only for
the others. The role table is the helper role store's six pairs, read once per run (see the policy paragraph of the
run options above); a test with no store runs on the fake backend's placeholder pairs and the same alias table.
- With a role key as
agentType, amodeloption must be absent, the role's model or an alias of its model family (haiku:executorandexplorer;sonnet:executor-t1;opus:architect;ocx-gpt-6-1-sol:reviewerandcritic); otherwise the call isrefusedwith reasonpair_refused. - A call without a role key is looked up in the alias table by (a non-role
agentTypestring, else themodelalias;effort;isolation), the most specific matching row deciding:opusisarchitect;haikuwithisolation: 'worktree'isexecutor;sonnetisexecutor-t1;ocx-gpt-6-1-sol(asmodelor asagentType) isreviewerat any effort (aneffort: 'xhigh'is recorded inrequestedPair, and the thread runs on the reviewer's pair). No alias row namescritic: a critic call names it byagentType. haikuwithout isolation is ambiguous. Claude runs it in a shared checkout; a CRW call has a write cwd of its own that no other call shares, so the call isrefusedwith reasonpolicy_refused, causealias_ambiguous(the intent row and the refusal row carrycause), and the detail names both fixes:isolation: 'worktree'for a build (roleexecutor) andagentType: 'explorer'for an investigation. Anything else outside the table ispolicy_refusedtoo.- A fresh call's requested
effortis never applied and never refused; a differing one is kept inmeta.requestedPairwhilemeta.configuredPairis the pair the thread reads back (the role's), for an alias call and for an explicitagentTypecall alike. - A fresh
executor-t1call needsstepDecision(the idcrw.tierStepreturned), otherwise it isrefusedwith reasonmissing_step_decision. - The thread's configured pair is read back; a mismatch is
refusedwith reasonpair_refused. - The run record (the
startedrow) keepspolicy_sourceandpolicy_digest, and every intent row the digest and the call'ssandbox. A run that resumes a journal under a policy of another digest writespolicy_repinned(old,new) before its first call; a new thread then takes the new pair, a continuation keeps the pair of its handle.