fix: Port credential and inline-data field exclusions in logs, reprs and spans to v1 - #6797
Merged
Conversation
…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.
wukath
approved these changes
Aug 19, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR ports six field-exclusion changes to the
v1branch:beb66ee1)repr()andstr()of the credential models render the secret field names with no values;model_dump()andmodel_dump_json()keep the values.ValidationErrorreports the field name and error type only.McpToolauth-schemeValueErrorandRestApiTool.__repr__omit the credential.59868ea8,761f1ac7)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.fbf5bd5f)<inline_data: audio/pcm, 9 bytes>. The model still receives the bytes.d63a2558)http_options; live connect logs the model, content count and response modalities.base_llm_flow(6fb5e04f)The File Content Compliance check fails here for a pre-existing reason; this PR adds no endpoint URL.