
4 Pitfalls Encountered When Migrating from vertexai.rag to agentplatform
This page has been translated by machine translation. View original
Introduction
One day, while doing local development on a Google Chat bot, I got this warning:
UserWarning: The `vertexai.rag` module is deprecated and will be removed in a future version.
Please migrate to the `agentplatform` client.
vertexai.rag is deprecated? The official documentation doesn't mention anything. But the warning was added in google-cloud-aiplatform >= 1.160.0. Since I wanted to avoid ignoring it and having things suddenly break, I decided to migrate.
To get straight to the point, the API rewrite itself was simple, but there were 3 traps not documented anywhere. In this article, I'll share the actual problems I ran into and how I handled them.
Prerequisites & Environment
google-cloud-aiplatform: 1.156.0 → upgraded to 1.158.0 or higher- Python 3.14 (Cloud Functions 2nd gen)
- APIs targeted for migration:
rag.retrieval_query(),rag.import_files(),rag.list_files(),rag.delete_file()
Investigating the Deprecation
The first thing I wanted to know was: "Is it really deprecated?"
Google Cloud's official deprecation list (Deprecated products/features) has no mention of vertexai.rag. However, when I checked the source code, I found that warnings.warn() had been explicitly added to vertexai/rag/__init__.py in google-cloud-aiplatform v1.160.0.
There's a time lag between the official documentation and the implementation. Since the warning is being raised, I decided it was best to migrate early, as long as the destination agentplatform module was stable.
Note that agentplatform is not a separate package — it's a module within the google-cloud-aiplatform package. No additional installation is needed; you can use it with import agentplatform.
The API Rewrite Itself Is Simple
Here's the mapping of the major methods:
Old (vertexai.rag) |
New (agentplatform.Client.rag) |
|---|---|
aiplatform.init(project=, location=) |
agentplatform.Client(project=, location=) |
rag.retrieval_query() |
client.rag.retrieve_contexts() |
rag.import_files() |
client.rag.import_files() |
rag.list_files() |
client.rag.list_files() |
rag.delete_file() |
client.rag.delete_file() |
rag.create_corpus() |
client.rag.create_corpus() |
The biggest change is the shift from module-level functions to client instance methods. The global initialization via aiplatform.init() is no longer needed; instead, you reuse an instance of agentplatform.Client.
from google.cloud import aiplatform
from vertexai import rag
aiplatform.init(project="my-project", location="asia-northeast1")
response = rag.retrieval_query(
text=query,
rag_resources=[rag.RagResource(rag_corpus=corpus_name)],
rag_retrieval_config=rag.RagRetrievalConfig(
top_k=5,
filter=rag.Filter(vector_distance_threshold=0.6),
),
)
import agentplatform
from agentplatform import types as ap_types
from google.genai import types
client = agentplatform.Client(project="my-project", location="asia-northeast1")
response = client.rag.retrieve_contexts(
vertex_rag_store=types.VertexRagStore(
rag_resources=[
types.VertexRagStoreRagResource(rag_corpus=corpus_name),
],
),
query=ap_types.RagQuery(
text=query,
rag_retrieval_config=types.RagRetrievalConfig(
top_k=5,
filter=types.RagRetrievalConfigFilter(
vector_distance_threshold=0.6,
),
),
),
)
The response structure (like response.contexts.contexts[].text) remains unchanged, so only the call site needs to be updated.
Things went smoothly up to this point. The problems came after this.
Trap 1: Type Ownership Is Split Across Two Modules
This was the biggest headache during migration.
agentplatform types are scattered across two modules:
| Module | Types |
|---|---|
google.genai.types |
VertexRagStore, VertexRagStoreRagResource, RagRetrievalConfig, RagRetrievalConfigFilter, GcsSource |
agentplatform.types |
RagQuery, RagCorpus, ImportRagFilesConfig, GoogleDriveSource, GoogleDriveSourceResourceId |
The tricky part is that importing from either module raises no error locally. Because agentplatform.types appears to re-export google.genai.types internally, even hasattr() checks pass.
But when I deployed to the production environment (Cloud Functions), this happened:
AttributeError: module 'agentplatform._genai.types' has no attribute 'VertexRagStore'
Apparently due to subtle differences in module resolution order between local and Cloud Functions, agentplatform.types.VertexRagStore can't be found in production.
Fix: I confirmed the correct owning module for each type, and clearly separated which types to import from google.genai.types and which from agentplatform.types.
# Types to take from google.genai.types
from google.genai import types
# types.VertexRagStore, types.RagRetrievalConfig, etc.
# Types to take from agentplatform.types
from agentplatform import types as ap_types
# ap_types.RagQuery, ap_types.ImportRagFilesConfig, etc.
Trap 2: pandas Is a Hidden Required Dependency
Right after deploying, another error appeared:
ModuleNotFoundError: No module named 'pandas'
Tracing the cause, the agentplatform._genai.rag module imports _gcs_utils at the module level, and that _gcs_utils does import pandas at the top level.
In other words, pandas is an implicit required dependency when using the RAG features of agentplatform. In google-cloud-aiplatform's pyproject.toml, pandas is listed as an optional dependency, but it's not optional in the RAG module's import path.
Fix: I added pandas>=1.0.0 to pyproject.toml.
dependencies = [
"google-cloud-aiplatform>=1.158.0",
"pandas>=1.0.0", # Required by module-level import in agentplatform.rag
]
Since the old API's vertexai.rag worked without pandas, this issue only surfaces during migration.
Trap 3: RAG Methods in agentplatform Are Added Incrementally by Version
The methods of agentplatform.Client.rag were not all added at once — they were added incrementally across versions:
| Version | Methods Added |
|---|---|
| 1.156.0 | create_corpus |
| 1.157.0 | delete_file, delete_corpus |
| 1.158.0 | import_files |
If you need import_files, >=1.156.0 is not enough — >=1.158.0 is the minimum requirement. Since the official documentation doesn't mention this incremental addition, you may find yourself puzzled by an AttributeError even after upgrading the version.
Fix: I explicitly specified >=1.158.0 in pyproject.toml to pin to a version where all the needed methods are available.
Trap 4: import_files Has an Added Bucket Ownership Check
agentplatform's import_files includes a client-side bucket ownership check that didn't exist in the old vertexai.rag:
# Internal validation code (from agentplatform._genai.rag)
for uri in import_config.gcs_source.uris:
if not _gcs_utils.GcsUtils(self._api_client)._verify_bucket_ownership(
bucket_name=uri.split("/")[2],
expected_project=self._api_client.project,
):
raise ValueError(
f"Bucket {uri} does not belong to project {self._api_client.project}."
)
This verification internally uses the Cloud Resource Manager API (cloudresourcemanager.googleapis.com) to retrieve and compare the bucket's project number. If the API is disabled, the exception is caught and False is returned, causing a ValueError even if the bucket is correctly in the right project.
ValueError: Bucket gs://my-bucket/prefix/ does not belong to project my-project.
The tricky part is that this error never occurred with the old API and only surfaces after migration. Moreover, since it only appears when import_files is actually executed (e.g., only when files change), it's easy to miss in post-migration testing.
Fix: Enable the Cloud Resource Manager API:
gcloud services enable cloudresourcemanager.googleapis.com --project=YOUR_PROJECT_ID
No additional permissions are needed for the service account. The default Compute Engine service account already has the permissions required to retrieve project numbers.
Note on Changes to list_files Return Value
It's not quite a trap, but the return value of list_files has changed and is worth noting:
# Old: iterable
for rf in rag.list_files(corpus_name=corpus):
print(rf.display_name)
# New: ListRagFilesResponse object
response = client.rag.list_files(name=corpus)
for rf in response.rag_files or []:
print(rf.display_name)
The old API returned a generator, but the new API returns a ListRagFilesResponse object. The .rag_files property holds the list of files (which may be None), so guarding with or [] is the safe approach.
Summary
Here's a summary of what I learned migrating from vertexai.rag to agentplatform.Client.rag:
| Item | Key Point |
|---|---|
| Type ownership | Split between google.genai.types and agentplatform.types. Something that works locally may fail in production |
| Hidden dependency | pandas is required by module-level import. Must be explicitly added as a dependency |
| Version requirements | import_files requires >=1.158.0. Methods are added incrementally |
| Return value changes | list_files changed from an iterable to a response object |
The API mapping itself is straightforward, so if you know about these traps, the migration should take less than half a day. I hope this is helpful for anyone considering the same migration.