Skip to content

fix: restore .text attribute when loading text artifacts from GCS#5155

Open
Maanik23 wants to merge 1 commit intogoogle:mainfrom
Maanik23:fix/artifact-text-retrieval
Open

fix: restore .text attribute when loading text artifacts from GCS#5155
Maanik23 wants to merge 1 commit intogoogle:mainfrom
Maanik23:fix/artifact-text-retrieval

Conversation

@Maanik23
Copy link
Copy Markdown

@Maanik23 Maanik23 commented Apr 4, 2026

Fixes #3157

Summary

When artifacts are saved via Part.from_text() using GcsArtifactService, the .text attribute is None after loading — the content is present in .inline_data instead. This PR fixes the deserialization to correctly restore text artifacts.

Root Cause

GcsArtifactService._save_artifact() stores text parts with content_type="text/plain", but _load_artifact() always used Part.from_bytes() which populates inline_data regardless of content type.

Before (broken):

artifact = types.Part.from_bytes(data=artifact_bytes, mime_type=blob.content_type)
# artifact.text is None, content is in artifact.inline_data

After (fixed):

if blob.content_type and blob.content_type.startswith("text/plain"):
    return types.Part(text=artifact_bytes.decode("utf-8"))
# artifact.text == "original text"

Why startswith instead of ==

Using startswith("text/plain") handles potential charset suffixes like text/plain; charset=utf-8 that cloud storage providers may append.

Consistency

FileArtifactService already handles this correctly (line 473: return types.Part(text=text)). This fix brings GcsArtifactService in line with that behavior.

Test plan

  • Added test_text_artifact_roundtrip — parametrized across all three service types (InMemory, GCS, File)
  • Asserts loaded.text == original_text after save/load cycle
  • Includes descriptive assertion message showing both .text and .inline_data on failure

GcsArtifactService._load_artifact() always used Part.from_bytes()
which populates inline_data even for text/plain content. This caused
Part.from_text() artifacts to lose their .text attribute after a
save/load cycle.

Now detects text/plain content type and returns Part(text=...) instead,
matching the behavior of FileArtifactService which already handles
this correctly.

Fixes google#3157
@google-cla
Copy link
Copy Markdown

google-cla bot commented Apr 4, 2026

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@adk-bot adk-bot added the services [Component] This issue is related to runtime services, e.g. sessions, memory, artifacts, etc label Apr 4, 2026
@adk-bot
Copy link
Copy Markdown
Collaborator

adk-bot commented Apr 4, 2026

Response from ADK Triaging Agent

Hello @Maanik23, thank you for creating this PR!

It looks like you haven't signed the Contributor License Agreement (CLA) yet. Please sign the CLA so we can proceed with reviewing your contribution. You can find more information in the "checks" section at the bottom of the pull request.

Thanks!

@Maanik23
Copy link
Copy Markdown
Author

Maanik23 commented Apr 4, 2026

I have signed the Google CLA at cla.developers.google.com. Could you please recheck?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

services [Component] This issue is related to runtime services, e.g. sessions, memory, artifacts, etc

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Artifact stored as text is not retrieved as text

2 participants