Google ADKgoogle-adk 2.8 · Python 3.10+
Dashboard
0%
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
28 small wins to finish your pathNext lesson →

Safety and guardrails: what to check

An agent with tools can do things. The question is not whether you trust the model, it is what the worst available action would do.

Earlier lessons built the two mechanisms that enforce safety. This lesson applies them deliberately.

RiskWhat you already know
It calls a dangerous toolA before_tool_callback that refuses, lesson 14
It is told to do something by a document it readsTools that read identity from state, not from parameters, lesson 10
It loops and burns moneymax_llm_calls, lesson 15
It returns the wrong shape to your codeoutput_schema, lesson 13
It gives a specialist too much reachSmall tool lists per agent, lesson 16

The two lines that do the most

First: never take an identity as a tool parameter. A tool that refunds account_id can be asked to refund somebody else's account. A tool that reads the account from state cannot, because the model does not write state.

Second: put a callback in front of anything irreversible. Money, deletion, sending. The callback is code, so no instruction and no clever prompt gets past it.

python
def guard(tool, args, tool_context):
    if tool.name in {"refund", "cancel_account", "send_email"}:
        if not tool_context.state.get("approved_by_human"):
            return {"status": "refused", "reason": "needs human approval"}

That is lesson 14's shape, applied to a list rather than one tool. Four lines, and they remove a whole category of bad afternoon.

A tool that reaches Google's APIs

The toolsets in lesson 11 are the sharpest version of this lesson's problem: one line gives a model Gmail, or a spreadsheet, or SQL over the company's data warehouse. Two things keep that sane, and neither is an instruction.

The first is the toolset's own setting. BigQuery's config decides what the model may do, and it starts at the safe end:

python
config = BigQueryToolConfig(write_mode=WriteMode.BLOCKED)
write_modeWhat SQL the agent may run
BLOCKEDReads only. The default, and where a support agent should stay
PROTECTEDWrites, but only to the temporary dataset of its own BigQuery session
ALLOWEDAny write. Permanent tables included

The second is tool_filter. A Gmail toolset with send in it is a different risk from one that only reads, and the filter is where that decision is made, once, in code.

Then the callback from lesson 14 sits in front of whatever is left, exactly as above. A cloud API makes the worst available action larger, so it makes the guard matter more, not less.

What ADK adds on top

The documentation has a safety section covering the platform side: model level safety settings, guardrail patterns, and running tool code in a sandbox rather than in your process. Worth reading before anything goes near production, and it does not change what you build here.

Prove it refuses
Test the guard, not the instruction. Write the case where the model asks for the dangerous thing, run it, and check that the refusal came back. An instruction you tested by asking politely proves nothing.
Try it yourself
  • Script the stand-in to ask for a refund and confirm your callback refuses it.
  • List every tool in your project that takes an identity as a parameter. Move them to state.

Little by little, you're building something great.