Empowering Your AI Agent: File Downloads with Google ADK Artifacts

Introduction: The Agent’s Delivery Problem

Your AI Agent is generating complex outputs — be it a comprehensive PDF report, a spreadsheet of financial data, or a detailed log file. Simply printing this content as a long string in the chat is an unsatisfactory experience. The solution lies in using Google ADK Artifacts

This post will detail how to build a flexible ADK tool that can securely generate and deliver files in multiple formats (PDF, CSV, TXT) by correctly utilizing the ADK’s Artifact system.🛠️ Implementing the Multi-Format Download Tool

The core challenge in supporting multiple formats is converting your raw string data (content_to_save) into the correct binary format (bytes) and specifying the correct MIME type.

🚀 Understanding ADK Artifacts

ADK Artifacts the crucial, built-in mechanism within the Agent Development Kit for managing named, versioned binary data associated with a user’s session or profile.

Why Use Artifacts?

  1. Handling Binary Data: Artifacts are designed for large data: files, images, audio, video, and, most importantly, structured documents like PDFs or large CSVs.
  2. Data Persistence & Versioning: They provide a dedicated system for persisting large data chunks that would overwhelm simple session state. Each time you save a file with the same name, a new version is created automatically.
  3. Seamless User Delivery: When your agent saves an artifact, the ADK framework handles the secure storage (via an underlying Artifact Service, like GCS) and provides a secure, temporary download link to the front-end user interface.

The Core Concept: types.Part

The data structure for an Artifact is always the standard Google GenAI google.genai.types.Part object. This object holds the file content as a types.Blob, which requires two things:

  1. data: The raw file content, which must be in bytes format.
  2. mime_type: A string that tells the browser what kind of file it is (e.g., 'application/pdf').

Our goal is to ensure the input content is correctly converted into this bytes and paired with the right MIME type before calling the core saving method.

🛠️ The Multi-Format Implementation

The difference between a downloadable text file (like CSV or TXT) and a complex document (like PDF) lies solely in how the bytes are generated.

1. Generating Binary Content for PDF

A PDF is a highly structured document. You can’t just encode the text; you need a dedicated library (like fpdf2 in this example) to structure the document layout and render it into a valid PDF binary stream.

Python code example

import io
from fpdf import FPDF # Requires: pip install fpdf2
from typing import bytes
def generate_valid_pdf_bytes(text_content: str) -> bytes:
"""
Generates a complete, valid PDF file in memory and returns its binary content.
"""
pdf = FPDF()
pdf.add_page()
pdf.set_font("Arial", size=12)
pdf.multi_cell(0, 10, text_content)
# The 'S' destination returns the document as a raw byte string.
return pdf.output(dest='S')

2. Generating Binary Content for CSV/Text

For simple text formats, the process is trivial: convert the string into bytes using a standard encoding like utf-8.

Python

# For CSV or TXT:
content_bytes = text_content.encode('utf-8')

3. 🔧 The create_download_file Tool

This asynchronous function acts as our tool, selecting the correct byte conversion method based on the desired MIME type and then using the core tool_context.save_artifact method.

Python

from google.generativeai.types import Part, Blob
from google.generativeai.tool.function_tool import FunctionTool
from google.generativeai.tool.function_tool import CallbackContext
from typing import Dict, Any
async def create_download_file(
content_to_save: str,
filename: str,
mime_type: str = "text/plain",
tool_context: CallbackContext = None,
) -> Dict[str, Any]:
"""
Saves the provided content as a downloadable Artifact using the ADK framework.
"""
if tool_context is None:
return {
"status": "error",
"message": "Tool context is missing, cannot save artifact.",
}
# --- STEP 1: Convert Content to Bytes Based on MIME Type ---
if mime_type == "application/pdf":
content_bytes = generate_valid_pdf_bytes(content_to_save)
else:
# Use simple string encoding for text/csv, text/plain, etc.
content_bytes = content_to_save.encode('utf-8')
# --- STEP 2: Create the ADK Artifact (types.Part) ---
artifact_part = Part(
inline_data=Blob(data=content_bytes, mime_type=mime_type)
)
# --- STEP 3: Save the Artifact to the ADK System ---
# save_artifact handles the versioning and makes the file available for download.
version = await tool_context.save_artifact(
filename=filename,
artifact=artifact_part
)
# --- STEP 4: Return the structured response ---
return {
"status": "success",
"message": f"File '{filename}' (version {version}) has been created and is now available for download.",
# The ADK UI will automatically intercept this response and provide a download link.
}
# Wrap the function as an ADK tool
download_tool = FunctionTool(
func=create_download_file,
description="Creates a downloadable file (PDF, CSV, or Text) from content and saves it as an ADK Artifact for the user.",
)

Downloading the Artifact in the ADK Web Interface

When your agent successfully executes the create_download_file tool, the structured response is intercepted by the client, which replaces the plain text message with a dynamic download link.

Link to the PDF generated
Generated PDF

✅ Best Practices & Summary

  • Always use types.Part: This is the canonical representation for all data interchange, including Artifacts.
  • Ensure bytes: Data must be converted to bytes using either string encoding (for TXT/CSV) or a dedicated library function (for PDF) before being passed to the Blob.
  • Specify MIME Type: The correct mime_type is critical for the browser to properly handle the download (e.g., open a PDF viewer or offer a CSV save dialog).
  • Async/Await: The save_artifact operation is an I/O function, so your tool must be defined with async def and use await.

🌐 Beyond the Download: Advanced Use Cases and Persistence

1. Vector Search Integration: Making Artifacts Actionable

The Artifact’s raw binary data (bytes) can be immediately ingested into a Vector Store. This allows a separate RAG agent to perform similarity search and answer questions about the newly created report.

2. Global Tool Definition: Agent Reusability

Define the create_download_file tool once as a Global Tool for the ADK Runner. This allows multiple agents across your ecosystem to use the file-generation capability without redundant code.

3. Persistent Storage with GcsArtifactService

For production needs, configure the ADK Runner with the GcsArtifactService. This automatically writes the Artifact data to a specified Google Cloud Storage (GCS) bucket, ensuring the files are persistent and available for long-term audit or external processing.

✅ Conclusion

  • By implementing this pattern, you leverage the powerful, secure, and scalable Google ADK Artifacts system, transforming your agent into a professional data-delivery platform. 💡

Learn more Empowering Your AI Agent: File Downloads with Google ADK Artifacts

Leave a Reply

Your email address will not be published. Required fields are marked *