pub struct ApprovalRequest {
pub request_id: String,
pub tool_call_id: String,
pub tool_name: String,
pub description: String,
pub input: Value,
pub side_effect_level: Option<ToolSideEffectLevel>,
}Expand description
What the agent wants to do, as put to an Approver.
Deliberately not #[non_exhaustive], though hosts read it far more often
than they build one. The struct has no constructor and no builder, so
sealing it would make an ApprovalRequest unconstructable outside this
crate — and every host testing its own approver builds one, as basis-acp
and basis-cli both do. Sealing would trade a compile error that names the
new field, on the day a field is added, for a permanent one with no way past
it.
Fields§
§request_id: String§tool_call_id: String§tool_name: String§description: StringWhy approval is being asked for.
input: ValueThe tool’s input, parsed when it is JSON.
side_effect_level: Option<ToolSideEffectLevel>How far outside this process the call reaches, when basis knows.
This is what lets a policy be written about what a call does rather
than about which tools happen to be installed —
LocalState for an edit to this
checkout, External for an MCP server
or a declared tool that leaves the machine. See Approver for the
worked example.
None means unknown, never harmless. Read-only calls do not reach
an approver at all (is_consequential), so nothing that arrives here
is a read; a None is only ever basis failing to recover a fact it
could not carry. The fail-closed reading is to treat it as
External — judge it by the most it
could be doing, the same rule the rest of this module runs on.
It is an Option because mentra types the classification as one:
since mentra#21 the
PermissionRequested event carries the call’s classification, and
mentra documents it as always present on a live request — but that is
mentra’s invariant to keep, not basis’s to unwrap, so basis passes on
what the event says. An approver reads None by the rule above:
unknown, never harmless.