Sending custom telemetry and metadata to frontend

Hi everyone,

I’m deploying a custom ADK agent (LlmAgent subclass) to Vertex AI Agent Engine (Reasoning Engine) and I’m running into an issue where custom telemetry events seem to be stripped or filtered out before reaching the client.

The Goal: I need to send real-time telemetry (cost per turn, energy usage, RAG source URIs) to my Nuxt 3 frontend. I implemented a “Sidecar Pattern” where I yield a final, synthetic Event containing a JSON payload after the LLM generation finishes.

The Implementation: In my _run_async_impl, I manually yield a final event after the generator loop finishes:

Python

# agent.py
telemetry_payload = { "total_cost": 0.005, "sources": [...] }
sidecar_event = Event(
    invocation_id=ctx.invocation_id,
    author="system_telemetry",  # I've also tried author="model"
    content=types.Content(
        role="model",
        parts=[types.Part.from_text(text=json.dumps(telemetry_payload))]
    )
)
yield sidecar_event

The Problem:

  1. Local Dev Works: When running locally (adk web), the event arrives perfectly.

  2. Cloud Deployment Fails: When deployed to Vertex AI, the stream closes immediately after the final LLM token. The custom sidecar event never arrives at the client.

  3. Logs Confirm Injection: My Cloud Logging stderr confirms the code is executing and injecting the event: INFO: 💉 Injecting Sidecar Telemetry: 2072 bytes

  4. Client Stream: The client receives all standard text chunks, but the stream ends without receiving the final JSON chunk.

Hypothesis: It seems the managed Agent Engine service (the A2A conversion layer) is sanitizing or filtering the output stream.

Questions:

  1. Does the Reasoning Engine enforce a strict schema that drops events with custom author tags (like system_telemetry)?

  2. If I set author="model" (which I tried), does the engine filter out events that look like “data” or don’t match the internal generation state?

  3. Is there a recommended way to pass custom metadata (like citations or cost) through the Reasoning Engine stream without it being stripped?

Environment:

  • ADK Python v1.19.0

  • Vertex AI Agent Engine (Europe-West4)

  • Frontend: Nuxt 3 consuming the streaming API

Any insights on how to bypass this sanitization or properly structure the event would be appreciated!