Agents governed by the case
The static agent settles one question when its loop starts: which tools may this agent ever call. In a CMMN case the answer changes while the case runs. A discretionary item is not planned yet, an applicability rule does not hold, a role has not been granted the item. Case mode makes the case’s own state the agent’s tool list, re-read on every turn, and expresses every rule about it in the case model.
What changes when a spec sets manifest: case
Section titled “What changes when a spec sets manifest: case”A spec with manifest unset or set to static is the static agent. A
spec with manifest: case keeps the same loop and changes one input to
it: at the top of every turn the loop reads the tools the case grants
now, through a ManifestSource the host supplies.
The grants come from the one construct each standard has for work that is authorised and not yet scheduled:
- CMMN: the discretionary items the agent’s role may plan on its
planning table right now.
cmmn.ToolGrantsprojects them. An item counts when its planner is in a state that permits planning, the planning table authorises the agent’s role, its applicability rules hold, and it is not already planned. An item with no repetition rule can be planned once. - BPMN: the parked entry points of an open ad-hoc sub-process marked
<kirto:planning mode="external"/>.bpmn.ToolGrantsprojects them. BPMN declares no planner roles, so there is no role narrowing.
Only items that carry a <kirto:taskDefinition type="ns:op"> become
tools. Human tasks and bare tasks stay plannable by people and are never
offered to the model.
A case grant only narrows the static allowlist. allowedToolNamespaces
stays the outer boundary, and the case decides what is live inside it.
A call to a tool the allowlist permits and the case does not grant this
turn is refused with TOOL_NOT_AVAILABLE, which goes back to the model
as a tool error. The loop carries on.
An input marked <kirto:input pinned="true"> on the item is set by the
model author. The tool’s schema leaves it out, and a value the model
supplies for it is dropped.
Attaching an agent to a case or to one task
Section titled “Attaching an agent to a case or to one task”An agent attaches to the whole case with <kirto:orchestrator> on the
case plan model:
<casePlanModel id="root"> <extensionElements> <kirto:orchestrator id="orch" type="agent:orchestrate" role="assistant"> <kirto:input name="agentRef" value="researcher"/> <kirto:input name="prompt" value="orchestrate the case"/> <kirto:output name="answer" source="text"/> </kirto:orchestrator> </extensionElements> <!-- plan items, tasks, planning tables --></casePlanModel>The parser rewrites it into an ordinary root-level plan item that starts
with the case, and no engine or host code knows the item was
synthesised. Its role, assistant, is the role it plans under: any item
the root planning table authorises for that role is a tool it can call.
It completes when its loop returns, and terminating the case tears it
down like any other task.
An agent attaches to one task with plannerRole on its task
definition:
<task id="t-triage" name="Triage" isBlocking="true"> <extensionElements> <kirto:taskDefinition type="agent:run" plannerRole="triage-agent"> <kirto:input name="agentRef" value="triage-bot"/> </kirto:taskDefinition> </extensionElements></task>Its planner scope is the stage that encloses the task. An agent inside a stage is granted what that stage’s planning table authorises for its role, and nothing from the rest of the case.
Every call as a plan item
Section titled “Every call as a plan item”With planToolCalls: true, a granted call is planned into the case as
its discretionary item instead of being dispatched directly. The item
runs the whole plan-item lifecycle: its sentries are evaluated, sentries
watching it fire on its completion, and the case’s completion rules see
it. The model’s arguments are laid over the item’s inputs, except the
pinned ones, and the loop waits for the item’s result.
A tool call the model made is then a line in the case’s own history, recorded the same way as an item a person planned.
Suggest, then a person decides
Section titled “Suggest, then a person decides”The suggestion mechanism is CMMN’s own manualActivationRule on the
discretionary item. With planToolCalls on and the rule set, a planned
call lands in Enabled and waits:
- The model calls a granted tool, and the item is planned.
- The rule holds, so the item enters Enabled and is shown to a person as a suggestion.
- A
ManualStartaccepts it. The item becomes Active and the tool runs with the model’s arguments. - A
ManualDisablerejects it. The item moves to Disabled, the tool never runs, and the agent’s waiting call is released with a discarded result.
The approval is a property of the case model, visible to whoever reads
it, and it composes with what CMMN already does with plan items:
sentries, exit criteria, autoComplete.
Park instead of spending turns
Section titled “Park instead of spending turns”With manifestPark: true, a turn with nothing granted does not call the
model with an empty tool list. The loop parks until the case’s grants
change, at no token cost. The park is still bounded by
deadlineSeconds.
Misconfiguration fails the run
Section titled “Misconfiguration fails the run”A case-mode spec on a host with no case-aware manifest source fails with
AGENT_MANIFEST_UNAVAILABLE. It never falls back to the static
allowlist. manifestPark or planToolCalls against a source that
cannot honour them fails the same way, and either flag on a static spec
is an AGENT_SPEC_ERROR. A misconfigured deployment does not run the
agent; the model never receives a wider tool list than the model author
intended.
Where case mode runs
Section titled “Where case mode runs”Case mode runs on the DBOS host, for CMMN cases and for BPMN processes,
and on the in-process CMMN runner used in tests and development. The
broker’s agent engine does not support it yet: it has no per-turn grant
event, and it refuses a case-mode spec with AGENT_SPEC_ERROR when the
loop starts.
The grants are read once per turn. A grant revoked mid-turn takes effect at the next turn, and a model call already in flight finishes.
Sentries as tool gates sets out the case for this design for architects and risk owners.