pub struct ToolMeta {
pub name: &'static str,
pub toolset: Toolset,
pub tier: Tier,
pub summary: &'static str,
pub self_severing: bool,
pub severs_local_node: bool,
pub requires_confirmation: bool,
pub idempotent: bool,
pub varying_tier: bool,
pub min_version: Option<&'static str>,
pub platforms: Option<&'static [&'static str]>,
}Expand description
One row of the tool table.
Fields§
§name: &'static strThe tool name as the client sees it, including its surface prefix.
toolset: Toolset§tier: Tier§summary: &'static strOne sentence, shown to the model. The full description lives on the generated schema; this is what the tool table prints.
self_severing: boolWhether calling this can cut the server off from the tailnet or from the client it serves. Self-severing tools always require confirmation; the two are separate fields because the tailnet surface has irreversible operations that are not self-severing but still require it.
severs_local_node: boolWhether this tool severs the connection when its target is this node.
Where Self::self_severing is true of every call a tool makes, this
is true of some of them: tailnet_device_delete is an ordinary
destructive call against somebody else’s device and a cut cable
against this one, and only the argument tells them apart. So it cannot
imply Self::requires_confirmation — a caller managing another
device would be made to confirm something that cannot happen — and the
confirmation lives in the tool’s own parameters, where the handler can
ask for it only when the target turns out to be us (Q83).
requires_confirmation: boolWhether the caller must state intent in the call itself. No flag can pre-authorise this.
idempotent: boolRepeating the call has the same effect as making it once.
varying_tier: boolWhether Self::tier is a floor rather than the whole truth.
Set by the rows whose risk is decided by the arguments they are given
rather than by the row: the passthrough, tailnet_device_authorize and
tailnet_service_approval_set, the last two by Q70. The gate still
reads the tier, so such a tool is offered as soon as its floor is
permitted, and the handler refuses anything above what the session
allows. The annotations state the worst case, because a client reading
read_only has no way to know that this one is conditional.
the_tier_is_a_floor_only_where_it_is_documented pins that list, so a
fourth row adopting the flag is a change somebody has to write down.
min_version: Option<&'static str>The lowest tailscale version that accepts this command, where the
command is newer than our supported floor.
platforms: Option<&'static [&'static str]>The operating systems the command exists on, when it does not exist on
all of them. Values are std::env::consts::OS spellings.
A restricted tool is still listed everywhere. The table is the same on
every platform so that the documentation, the contract tests and the
tools subcommand agree wherever they run, and so that a caller asking
for something macOS-only on Linux is told why rather than finding a
tool that does not exist.
Implementations§
Source§impl ToolMeta
impl ToolMeta
pub const fn surface(&self) -> Surface
Sourcepub fn runs_here(&self) -> bool
pub fn runs_here(&self) -> bool
Whether the command behind this tool exists on the machine we are on.
Sourcepub const fn takes_confirmation(&self) -> bool
pub const fn takes_confirmation(&self) -> bool
Whether this tool exposes a confirm argument to the caller.
Three fields put one there and they mean different things — the row demands it, every call severs, or a call severs when its target turns out to be this node — but a caller sees the same argument for all three. Anything reasoning about what a session shows a model wants this question, not the three underneath it.
Sourcepub const fn annotations(&self) -> Annotations
pub const fn annotations(&self) -> Annotations
Annotations are derived, not stored, so that a tool cannot claim to be read-only while sitting at the destructive tier.