maple-agent-tracing-ag…
Trace Agno agents with Maple: installs the OpenInference Agno instrumentor with an OTLP…
Trace Google ADK (Agent Development Kit) agents with Maple, in Python (google-adk) and TypeScript (@google/adk): register an OTLP tracer provider, get the transcript and tool calls into the GenAI attributes Maple reads (env switches + a plugin in Python, a span processor in
$ npx -y skills add mapletechlabs/maple --skill maple-agent-tracing-google-adk --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/maple-agent-tracing-google-adkContext preview
The summary Claude sees to decide when to auto-load this skill.
Trace Google ADK (Agent Development Kit) agents with Maple, in Python (google-adk) and TypeScript (@google/adk): register an OTLP tracer provider, get the transcript and tool calls into the GenAI attributes Maple reads (env switches + a plugin in Python, a span processor in
name: maple-agent-tracing-google-adk description: "Trace Google ADK (Agent Development Kit) agents with Maple, in Python (google-adk) and TypeScript (@google/adk): register an OTLP tracer provider, get the transcript and tool calls into the GenAI attributes Maple reads (env switches + a plugin in Python, a span processor in TypeScript), and keep one session per ADK session id. Triggers on 'trace my ADK agent', 'add Maple to Google ADK', 'add Maple to @google/adk', 'agent sessions for Google ADK', 'OpenTelemetry for google-adk'."
Goal: one conversation = one ADK session id = one Maple Agent Session, with the transcript (user, assistant, tool calls and results), model calls, tool calls with arguments/results, failures, and tokens.
ADK emits its own OTel spans (scope `gcp.vertex.agent`): `invocation` > `invoke_agent {agent}` > `call_llm` > `generate_content {model}`, plus `execute_tool {tool}`. No instrumentation package is needed. You add: a tracer provider (Runner apps only), the env vars below, one plugin, one span processor.
**TypeScript (`@google/adk` in `package.json`): follow [references/typescript.md](references/typescript.md) instead of Steps 0-7 below.** Step 1 (key and region) applies to both. ADK for TypeScript records content differently (Gemini-shaped JSON on `gcp.vertex.agent.*` attributes, no `generate_content` span), so the Python env switches and plugin do not apply there.
pip install "google-adk>=2.10" opentelemetry-exporter-otlp-proto-http
Add `litellm` only if the app uses `google.adk.models.lite_llm.LiteLlm`. Use the repo's package manager (`uv add`, `poetry add`).
Env vars (all runtimes, including `adk web`/`api_server`):
OTEL_SERVICE_NAME=<service-name> OTEL_EXPORTER_OTLP_ENDPOINT=https://ingest.maple.dev OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer <key>" OTEL_SEMCONV_STABILITY_OPT_IN=gen_ai_latest_experimental OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT=SPAN_ONLY ADK_CAPTURE_MESSAGE_CONTENT_IN_SPANS=false
For Runner apps, create `telemetry.py` next to the entry point:
# telemetry.py
import json
from google.adk.plugins.base_plugin import BasePlugin
from opentelemetry import trace
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
class SkipDuplicateToolSpans(BatchSpanProcessor):
"""Drops two ADK tool spans that would count a call twice: the
`execute_tool (merged)` summary of parallel calls, and the span of a call
paused for confirmation (it runs again, in its own span, once approved)."""
def on_end(self, span):
if span.name != "execute_tool (merged)" and not span.attributes.get("adk.awaiting_confirmation"):
super().on_end(span)
class ToolCallAttributes(BasePlugin):
"""Records each tool call's arguments and result on its `execute_tool` span,
and marks the span of a call that is waiting for confirmation."""
def __init__(self):
super().__init__(name="tool_call_attributes")
async def before_tool_callback(self, *, tool, tool_args, tool_context):
trace.get_current_span().set_attribute("gen_ai.tool.call.arguments", json.dumps(tool_args, default=str))
async def after_tool_callback(self, *, tool, tool_args, tool_context, result):
span = trace.get_current_span()
if tool_contRepo: mapletechlabs/maple
Trace Agno agents with Maple: installs the OpenInference Agno instrumentor with an OTLP…
Trace Claude Agent SDK agents (TypeScript and Python) and Claude Code CLI sessions with…
Trace Cloudflare Agents SDK agents (AIChatAgent, Agent on Durable Objects, npm `agents` /…
Trace CrewAI crews and flows with Maple: OpenInference CrewAI instrumentor plus the model-SDK…
Trace DSPy programs and ReAct agents with Maple: OpenInference DSPy instrumentor with GenAI…
Trace Genkit (TypeScript/Node.js) agents with Maple: export Genkit's OpenTelemetry spans to…