Trust and safety
How the trusted flag on a Tool shapes the executor's render envelope, why it does not propagate to Media results, and where the safety boundary actually lives (the handler, via gates — not the registry).
Tools covers the Tool constructor; Trust tiers covers what each envelope means at render time; Gates covers the suspension primitive every authorisation flow attaches to.
Trust on the tool, not on the battery
Every tool's output flows through the executor's untrusted envelope by default. trusted: true on a tool flips that for the rendering of its string / Uint8Array / artifact results: the executor reads Tool.trusted at render time and routes the output through the trusted envelope instead. The flag exists because trust is a property of the content the tool produces, not a property of how a particular battery happens to be configured — putting it on the tool means the trust signal travels with the tool wherever it is registered. Q&A tools that surface operator-authored answers, human-in-the-loop approval gates, configuration tools that return developer-authored constants — those are the canonical cases. Anything returning content from the open web, an external API, or a search index stays untrusted, which is the default for a reason.
What Tool.trusted set to true means at render time is the same thing it would mean if the operator had typed the content into the system prompt themselves: the executor surfaces the result to the model as developer/operator intent, which the model is allowed to read as policy, configuration, or first-party guidance rather than as third-party data that needs to be quoted, summarised, or otherwise held at arm's length. That is exactly the level of authority you do not want to grant to content the tool fetched from anywhere it does not fully control. If a tool's output could ever be authored — even indirectly — by someone outside your trust boundary, the flag stays off.
Tool.trusted does not propagate to Media results
Media carries its own trustTier and the battery reads it directly when rendering a Media result. Tool.trusted is not consulted, does not override, and does not launder it. A trusted tool that returns a third-party-public image renders that image in the untrusted envelope, every time — the same principle that already governs Retrievable.trustTier inside a trusted tool's output. Trust is a property of where the content came from, not who fetched it. If your tool produces Media, the trust decision is made at construction (Media.userAttachment, Media.toolGenerated, Media.retrievedPublic, Media.retrievedPrivate, or the bare constructor) and Tool.trusted has nothing further to say.
Trust framing is the executor's job — but you fill in the flag
The ADK records trusted and hands it to the executor; the executor decides what to render and how. A battery that ignores tool.trusted and renders everything in one envelope is a battery that has voluntarily disabled the only signal the tool gave it. Picking that battery is your call — the ADK will not second-guess it, but it will also not paper over it.
Safety, authorisation, and human approval
The ADK cannot make your tools safe
A tool's handler is the last line of defence before a side effect happens. The ADK cannot tell you which actions to allow, which to require approval for, which to deny outright — those are application decisions, not framework decisions. What the ADK gives you is the primitive every one of those defences attaches to: Gates.
Gate inside the handler, not in middleware downstream. Middleware can be misordered, replaced, or skipped under a particular configuration; the handler is the one piece of code that always runs at the exact moment the side effect is about to fire. If a tool can do something you would not let a stranger trigger, the handler is where await TurnContext.waitFor belongs.
See Gates for the ADK's position on safety, the canonical patterns (RBAC, per-call human approval, second-factor elevation, external-system handoffs), and the worked tool-handler examples that put gates in the right place.