Runtime tools
Every tool addresses one tenant user’s runtime over one control wire — the same wire the REST routes already drive, resolved to whichever runtime is registered for that tenant. There is no carrier branch anywhere in these tools, and nothing you write should introduce one. Requires thetasks primitive.
Writes are queued, not sent.
naive_teams_comment and naive_teams_unblock return when the
command is durably held, which is not the same as the runtime having seen it. If the runtime
is unreachable you receive a wait_for_delivery recovery step — do not send the command
again. A second send is a second comment, or a second unblock.Brain governance tools
The twenty-onenaive_brain_* content tools cover what the brains know. These five cover
how something comes to be known: the writeback envelope a claim arrives on, the proposal it
becomes, and the decision that resolves it.
Requires the brain primitive, which is opt-in — an Account Kit with no brain entry is
a refusal, not a default.
How a refusal reaches you
A refused call does not return a bare error. It returns a verdict envelope, carried in bothstructuredContent and the text block:
retryable—trueonly when the envelope also carries aretry_afterrecovery step, which happens only forverdict: "unavailable". If it isfalse, calling again cannot help: the decision is a function of a policy snapshot your calls do not change.recovery[]— the one thing that would change the outcome. It names a tool or a human act, never a shell command.alternatives[]— other tools that would work right now.
Verdicts
attest is a member of the verdict union and nothing produces it today: measured across the
API, the platform packages and the governor, the only occurrence of the string is the type
declaration itself. Handle it if you are writing an exhaustive switch — the union is closed and
will not grow silently — but do not build a flow that waits for one.Three vocabularies, and they are not the same set. The closed decision engine answers
allow | deny | freeze. POST /v1/policy/explain answers allow | deny | park. This envelope
adds attest and unavailable on top, because a model needs to tell an outage from a decision.
Do not map one onto another by name alone.park gives you wait_for_approval with an approval_id, an expires_at, and
on_expiry: "deny" — an approval window that elapses becomes a refusal. Poll
naive_approvals_get. You cannot approve your own request.
If you refuse the same call three times, the envelope stops offering choices: you get exactly
one escalate_to_human step and no alternatives. That is the signal to stop and tell the
user.
Connections enumeration is filtered
naive_connections_tools now filters its output through the same Account Kit rule
naive_connections_execute obeys. A toolkit the kit does not permit is refused with a
request_toolkit recovery naming it, rather than enumerated; per-tool enable/disable
filters are applied to the result, and withheld_by_policy reports how many names were
removed. Calls that worked before still work — every kit ships permissive by default, so this
bites only where somebody deliberately narrowed one.