New to the adapters? Start with the wrapping overview and comparison
table.
Compatible versions: see the compatibility
table for the verified
google-adk range.HexgateRunner. It’s constructed up front
with the agent, app name, and session service (mirroring the ADK Runner
constructor) — the underlying ADK Runner is built once and reused since role
resolution happens at call time. run / run_async then yield ADK events.
Under the hood
- At construction,
HexgateRunnercallswrap_google_agent, which builds aPolicySet, constructs onePolicyEnforcer, and returnsagent.model_copy(update={"tools": guarded_tools})— your originalagentis untouched. - Each tool is normalized first: bare callables in
agent.toolsare wrapped intoFunctionTool(matching what ADK does internally) so the guard has a stableBaseToolsurface. Each tool is thencopy.copy’d and itsrun_asyncreplaced with an enforcer-gated version. - Each
run/run_asynccall opens aHexgateContextscope (hexgate_context.sync_scope()/async with hexgate_context:) and dispatches to the cached underlyingRunner. On non-allow, the guard returnsdecision.as_error_message()so the ADK runtime forwards it to the model as the tool output instead of aborting the run. - Observability is set up lazily on each call:
GoogleADKInstrumentor().instrument()plusnest_asyncio.apply()(ADK’s runner spins its own loop), and the run executes insidepropagate_attributes(user_id=..., session_id=..., metadata={"user_roles": ...}, tags=["google.runner.run.<agent_name>"]).
Runnable example
examples/devops_google.py — HexgateRunner (Google ADK) end-to-end with
InMemorySessionService.