Skip to main content
Python (pip install 'sentrial[google-adk]') and TypeScript (@sentrial/sdk, with @google/adk). Sentrial attaches to Google’s Agent Development Kit as a Runner-level Plugin (the recommended surface); Python also offers a per-agent callbacks helper. ADK is an optional, duck-typed peer dependency in both SDKs — neither ever imports it, so the SDK loads with or without ADK installed.
Read on — the sections below cover the Python Plugin, the per-agent callbacks helper, and the full mapping.

What Gets Tracked Automatically

Sessions

One session per ADK run (invocation) — agent name from the root agent, aggregated tokens and cost, final output.

Model Calls

Every model call as a per-call event — model, prompt/completion tokens from usage_metadata, auto-calculated cost, duration.

Tool Calls

Each tool execution with the tool name, arguments, result, and errors.

Errors

on_tool_error / on_model_error and any LlmResponse.error_code become errors and fail the session.

Conversation Linkage

The ADK session id becomes the Sentrial convoId, threading multi-turn runs together.

Fail-safe

Every callback is containment-wrapped — a Sentrial error is logged and swallowed, never crashing your agent.

Installation

Register one Plugin on your Runner. Then run your agents exactly like before — the Plugin fires globally across every agent, tool, and model call in the invocation.
Already constructed the Runner? Attach after the fact with instrument_adk:

Per-Agent Callbacks (alternative)

When you can’t register a Runner-level Plugin, attach the callbacks to a single agent. This only observes the agent(s) you attach it to — sub-agents need their own attachment — so prefer the Plugin for full coverage.
sentrial_adk_callbacks() returns the before_/after_agent, before_/after_model, and before_/after_tool callback dict; the session is bracketed by the agent’s before_agent / after_agent.

Configuration Options

Both SentrialAdkPlugin(...), instrument_adk(runner, ...), and sentrial_adk_callbacks(...) take the same options:
Idempotent registration — instrument_adk() is idempotent per runner: calling it again on the same runner returns the first plugin instead of registering a duplicate (which would mirror every run into two sessions). ADK also dedups plugins by name, so passing two identically-named plugins is rejected by ADK itself.

How Runs Map to Sessions

Additional mapping notes:
  • Session metadata carries integration: "google-adk" plus the ADK invocation_id and app_name.
  • Streaming: partial model responses are skipped so tokens aren’t double-counted — the final response carries usage_metadata and is the one counted.
  • Model duration is measured from before_model → after_model; tool duration from before_tool → after_tool (correlated by the ToolContext instance, so parallel tools are timed correctly).

Don’t Combine with wrap_google

wrap_google() wraps a raw google.generativeai.GenerativeModel so each generate_content call is tracked inside a session you manage with begin(). This integration instead observes the ADK runtime (Agent + Runner) from the outside. If you use ADK, prefer this integration; do not combine both on the same run (LLM calls would be double-counted), and do not attach both the Plugin and the callbacks helper.

Batching & Short-Lived Processes

ADK invokes Plugin/callbacks inline on the run’s event loop, so an explicit client with batching enabled is recommended — each track call then enqueues and returns immediately instead of waiting on a network round-trip per event:
In short-lived processes (scripts, serverless functions), don’t exit before queued events are sent — call client.flush() after your last run when batching is enabled.

TypeScript (adk-js)

The TypeScript SDK ships the same integration for adk-js (@google/adk). It attaches as a Runner-level Plugin — @google/adk is an optional, duck-typed peer dependency the SDK never imports, so @sentrial/sdk loads with or without ADK installed. The run→session mapping is identical to Python’s.
Callback naming. ADK-JS callbacks are camelCase and take a single params object (e.g. afterModelCallback({ callbackContext, llmResponse })) — unlike Python’s snake_case keyword args. The mapping is otherwise the same. There is no per-agent callbacks helper on the TS side (yet); use the Runner-level Plugin.

Installation

Already constructed the Runner? Attach after the fact with instrumentAdk (idempotent per runner):

Configuration Options

new SentrialAdkPlugin(options) and instrumentAdk(runner, options) take the same options:
Batching — ADK invokes plugin callbacks inline on the run’s event loop, so an explicit client with batching enabled is recommended: new SentrialClient({ apiKey, batching: { enabled: true } }). Each track call then enqueues and returns immediately. In short-lived processes, call client.flush() after your last run.
Don’t combine with wrapGoogle() on the same run. wrapGoogle() wraps a raw @google/genai model so each generateContent call is tracked inside a session you manage with begin(); this integration observes the ADK runtime from the outside. Pick one, or LLM calls are double-counted.

Next Steps

Python SDK Reference

Full SDK documentation with all methods and options.

OpenAI Agents SDK

The same processor-style integration for the OpenAI Agents SDK.