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?
- Handling Binary Data: Artifacts are designed for large data: files, images, audio, video, and, most importantly, structured documents like PDFs or large CSVs.
- 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.
- 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:
data
: The raw file content, which must be inbytes
format.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.
✅ Best Practices & Summary
- Always use
types.Part
: This is the canonical representation for all data interchange, including Artifacts. - Ensure
bytes
: Data must be converted tobytes
using either string encoding (for TXT/CSV) or a dedicated library function (for PDF) before being passed to theBlob
. - 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 withasync def
and useawait
.
🌐 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