Tool invocation rules
An installation may add a Tool implementation to
restrict calls by their final arguments, actor, configuration, target or prior
outcomes. Symfony autoconfiguration registers the rule. Its identifier
must return a unique, stable code matching [a-, at most
64 ASCII characters long.
The existing Tool first checks whether the tool remains
permitted. The invocation policy then calls every rule until one denies. A rule
returns Tool or
Tool. Reason codes use the same
format as identifiers; arguments and exception text never form a denial message.
No rules preserves the existing permission behavior.
The context contains the tool name, final arguments, configuration and
Tool. The latter carries the initiating actor, acting
backend user and run reference. Input resumes supply the validated human input
after it has replaced the model's values for declared input fields. Approval
resumes evaluate the same policy immediately before the approved call executes.
A refusal may carry an explanation, Tool:
one sentence for the person behind the run, in their language. The refused
call's result passes it on after the codes. It is never recorded.
A rule may also be asked before an approval card is shown, so that nobody is
asked to approve a call it refuses. It opts in by implementing
Pre, a marker without methods, and
promises that its answer comes from the call, the configuration and the
execution context alone, never from the history, and that it writes nothing.
The loop then asks it, through Pre,
where it decides whether a call suspends. A call it refuses on purpose does not
suspend; it is settled apart, refused and recorded once as an
invocation_ event, and never executed on the strength of that refusal:
if the rule allows it by then, it is refused for the approval it skipped.
A refusal that reports a failure (rule_, history_,
policy_) does not skip the card. Beside a call that waits, the
refused call stays on the card with its explanation and is refused, whatever
the rule says by then, when the turn is approved. The same rule is asked again
immediately before every call executes, so it is asked at least twice for a
call that waits for approval and has to be cheap. A rule that does not
implement the marker is asked only when the call runs, as before. The built-in
Require opts in (Editorial profile: drafts only).
Implement Tool when the rule needs a target. Return
a Tool with the authoritative kind and identifier, or
null for calls the resolver does not understand. Multiple resolvers
claiming a call, or an exception while resolving it, refuse execution. A missing
target remains null; a rule requiring a target must explicitly deny it.
Target references are stored in the history, so they must contain identifiers,
never credentials or document content.
Tool is independent of the model transcript. Each
observation contains the tool, outcome and optional target reference. Suspensions
persist it and both resume paths carry it forward. A rule whose
requires returns true is refused when a legacy or
damaged state cannot prove its history. A bare run call starts a
complete empty history only when it assembles a fresh prompt and all three seed
counters are zero. A call with skip or any nonzero seed counter
must supply authoritative Tool
to prove its prior observations; otherwise the history remains incomplete.
A rule exception refuses execution as
rule_. Denials retain the rule identifier and stable reason in the
invocation_ governance event without arguments or result content. The
event's reason is the bounded rule code, separate from the Tool
used for tool_ events.