Skip to content

fix: Port credential and inline-data field exclusions in logs, reprs and spans to v1 - #6797

Merged
GWeale merged 5 commits into
v1from
backport-v1-pr14
Aug 19, 2026
Merged

fix: Port credential and inline-data field exclusions in logs, reprs and spans to v1#6797
GWeale merged 5 commits into
v1from
backport-v1-pr14

Conversation

@GWeale

@GWeale GWeale commented Aug 18, 2026

Copy link
Copy Markdown
Collaborator

This PR ports six field-exclusion changes to the v1 branch:

  1. Credential repr and error messages (beb66ee1)
    • repr() and str() of the credential models render the secret field names with no values; model_dump() and model_dump_json() keep the values.
    • A credential ValidationError reports the field name and error type only.
    • The McpTool auth-scheme ValueError and RestApiTool.__repr__ omit the credential.
  2. Traced request config (59868ea8, 761f1ac7)
    • Spans exclude http_options.{headers, extra_body, client_args, async_client_args} and the three live httpx/aiohttp client objects. Headers are still sent to the model API.
  3. Inline binary data on spans (fbf5bd5f)
    • Inline parts render as <inline_data: audio/pcm, 9 bytes>. The model still receives the bytes.
  4. Gemini debug logs (d63a2558)
    • Request logs exclude http_options; live connect logs the model, content count and response modalities.
  5. Live request logs in base_llm_flow (6fb5e04f)
    • Logs the agent name, model, content count and response modalities.

The File Content Compliance check fails here for a pre-existing reason; this PR adds no endpoint URL.

GWeale added 5 commits August 17, 2026 23:01
…ges to v1

Calling repr() or str() on a credential model, interpolating one into an
f-string, or letting pydantic reject a malformed value rendered the secret in
full: the API key, password, bearer token, OAuth access, refresh and id tokens,
the PKCE verifier, and the service-account private key. Two tools made that
worse by interpolating a whole credential into a message a caller sees, one in
an McpTool ValueError and one in RestApiTool.__repr__.

Now the secret fields are marked repr=False, so only the field names are
rendered. The credential base model sets hide_input_in_errors, so a
ValidationError reports the field name and the error type without echoing the
rejected value. Extra keys, which extra="allow" lets a caller attach and which
pydantic renders unconditionally, have their values replaced by a placeholder.
The McpTool error message and the RestApiTool repr no longer mention the
credential at all.

Behaviour change: anyone who debugs by printing a credential object now sees
the field name with no value. model_dump() and model_dump_json() are untouched,
so the credential services keep round-tripping secrets correctly.
The traced request config was serialized with only response_schema excluded, so
everything a caller put in GenerateContentConfig.http_options was exported to
the tracing backend as a span attribute on every model call. That includes
headers, which commonly carries an Authorization bearer token, and extra_body,
client_args and async_client_args, which are free-form passthroughs callers use
for auth material. Separately, a live httpx or aiohttp client passed through the
same field made the serialization raise PydanticSerializationError, because
those are transport objects pydantic cannot serialize.

Now those seven http_options sub-fields are excluded from the dump. base_url
and the rest of http_options are still traced, and the headers are still sent
to the model API unchanged; only the span omits them.

This combines two upstream fixes that edit the same expression, one excluding
the live client objects and one excluding the credential-bearing fields. The
intermediate state has no value on its own, so it is written here in its final
form.

Behaviour change: anyone reading traces loses the headers, extra_body,
client_args and async_client_args sub-fields of http_options from the
gcp.vertex.agent.llm_request attribute.
Serializing a content part in JSON mode base64-encodes its inline_data, so the
model response span and the trace_send_data span carried the bytes themselves.
A live session's audio chunks and any image or document a user uploaded were
copied wholesale onto an exported span attribute, which sent the payload to the
trace backend and grew the span with it.

Now a new private helper replaces every part that has inline_data with a text
part reading "<inline_data: {mime}, {n} bytes>", and both call sites route
their content through it. The request side already dropped inline parts and is
unchanged.

Behaviour change: anyone who was reading audio or image bytes back out of a
span now gets that description string instead. The model still receives the
real bytes; only the span is summarized.
At DEBUG level the Gemini model wrote the request config to the log with only
the system instruction and tools excluded, and on the live path it wrote the
whole LlmRequest and the whole LiveConnectConfig. Credentials a caller put in
GenerateContentConfig.http_options or LiveConnectConfig.http_options, most
often an Authorization header, landed in the google_adk log on both paths.

Now http_options is excluded from the request log and from the repr() used
when the dump fails, and the live path logs the model, the content count and
the response modalities instead of the whole request, with the live connect
config copied without its http_options.

Behaviour change: someone debugging at DEBUG level no longer gets the full
llm_request dump on the live path. The headers are still sent to the model API
and to the live API; only the log omits them.
…g to v1

Starting a live session wrote the entire LlmRequest into the debug log. That
object holds the whole user conversation and config.http_options.headers, which
is where a caller puts an Authorization token, so both ended up in the
google_adk log at DEBUG level.

Now the line logs the agent name, the model, the number of contents and the
response modalities. The request itself is no longer interpolated.

The regression test injects its sentinel credential through
LlmAgent.generate_content_config, which the basic request processor deep-copies
onto llm_request.config, and asserts the header did reach the request the flow
connected with while staying out of the log.

Behaviour change: debug-level output only. The replacement line keeps the
fields anyone was realistically reading.
@GWeale GWeale changed the title fix: Port credential and payload redaction fixes for logs and spans to v1 fix: Port credential and inline-data field exclusions in logs, reprs and spans to v1 Aug 19, 2026
@GWeale
GWeale merged commit 7c2075c into v1 Aug 19, 2026
13 of 14 checks passed
@GWeale
GWeale deleted the backport-v1-pr14 branch August 20, 2026 00:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants