Google Cloud Integration
Neo4j Agent Memory provides comprehensive Google Cloud integration, including Vertex AI embeddings, Google Agent Development Kit (ADK) support, and an MCP server for Cloud API Registry.
Overview
| Feature | Description | Status |
|---|---|---|
Vertex AI Embeddings |
Generate embeddings using Google’s |
Production Ready |
Google ADK |
Native MemoryService implementation for ADK agents |
Production Ready |
MCP Server |
Model Context Protocol server — 6 core / 16 extended memory tools |
Production Ready |
Cloud Run |
Production deployment templates |
Production Ready |
Installation
# Vertex AI embeddings
pip install neo4j-agent-memory[vertex-ai]
# Google ADK integration
pip install neo4j-agent-memory[google-adk]
# MCP server
pip install neo4j-agent-memory[mcp]
# All Google Cloud features ([google] is Vertex AI only)
pip install "neo4j-agent-memory[google,google-adk,mcp]"
Pass-through your Google ADK / Gemini model
llm_provider_from_google_adk accepts a Gemini model string or a configured client. Bare strings short-circuit to from_provider with the vertex_ai/ prefix added:
from neo4j_agent_memory import MemoryClient, MemorySettings
from neo4j_agent_memory.integrations.google_adk import (
llm_provider_from_google_adk,
)
provider = llm_provider_from_google_adk("gemini-2.5-flash")
settings = MemorySettings(
neo4j={"password": "p"},
llm=provider,
embedding="vertex_ai/gemini-embedding-001", # Vertex AI embeddings
)
This is equivalent to MemorySettings(llm="vertex_ai/gemini-2.5-flash"). Both Vertex AI models route through LiteLLM (no native LLM adapter); Vertex AI embeddings have a native adapter. See Configure Embedding Provider for the Vertex AI specifics.
Prerequisites
Google Cloud Authentication
# Authenticate with Application Default Credentials
gcloud auth application-default login
# Set your project
export GOOGLE_CLOUD_PROJECT=your-project-id
Neo4j Database
You need a running Neo4j instance. Options:
-
Neo4j Aura: Managed cloud service (recommended for production)
-
Docker: Local development
-
Self-hosted: On-premises or cloud VM
# Local Docker for development (matches what CI runs)
docker run -d \
--name neo4j \
-p 7474:7474 -p 7687:7687 \
-e NEO4J_AUTH=neo4j/password \
-e NEO4J_PLUGINS='["apoc"]' \
neo4j:5.26-community
Vertex AI Embeddings
Generate high-quality text embeddings using Google’s Vertex AI models.
Basic Usage
from neo4j_agent_memory.embeddings.vertex_ai import VertexAIEmbedder
# Create embedder (gemini-embedding-001 is the default model)
embedder = VertexAIEmbedder(
project_id="your-gcp-project", # or set GOOGLE_CLOUD_PROJECT
location="us-central1",
)
# Generate embeddings
embedding = await embedder.embed("Hello, world!")
print(f"Dimensions: {len(embedding)}") # 768
# Batch embedding. gemini-embedding-001 accepts one text per request, so the
# embedder issues one call per text; text-embedding-005 and
# text-multilingual-embedding-002 batch up to 250 per request.
embeddings = await embedder.embed_batch([
"First text",
"Second text",
"Third text",
])
Output dimensionality
gemini-embedding-001 emits 3072 dimensions natively and supports Matryoshka
truncation to 1536 or 768. The embedder defaults to output_dimensionality=768:
# Default: 768 dimensions, compatible with indexes created for the
# retired text-embedding-004 model.
embedder = VertexAIEmbedder()
# Native 3072 dimensions -- best retrieval quality, but the Neo4j vector
# indexes must be created at 3072 (they cannot be resized afterwards).
embedder = VertexAIEmbedder(output_dimensionality=None)
# Middle ground
embedder = VertexAIEmbedder(output_dimensionality=1536)
The trade-off: Neo4j vector index dimensionality is fixed when the index is
created, and MemoryClient sizes its indexes from embedder.dimensions.
Keeping the default 768 means an existing database keeps working after the
model change with no re-embedding. Raising it on an existing database means
dropping the Message, Entity, Preference and ReasoningTrace vector
indexes, recreating them at the new size, and re-embedding every node, so
choose 1536 or 3072 at the start of a new project rather than later.
Supported Models
| Model | Native dimensions | Notes |
|---|---|---|
|
3072 |
Default. Truncatable to 1536 or 768; one text per request |
|
768 |
English and code, task-specific; up to 250 texts per request |
|
768 |
Multilingual; up to 250 texts per request |
|
|
Task Types
Vertex AI supports different task types for optimized embeddings:
# For indexing documents
doc_embedder = VertexAIEmbedder(
model="gemini-embedding-001",
task_type="RETRIEVAL_DOCUMENT",
)
# For search queries
query_embedder = VertexAIEmbedder(
model="gemini-embedding-001",
task_type="RETRIEVAL_QUERY",
)
Available task types:
-
RETRIEVAL_DOCUMENT- For indexing documents to be searched -
RETRIEVAL_QUERY- For search queries -
SEMANTIC_SIMILARITY- For comparing text similarity -
CLASSIFICATION- For text classification tasks -
CLUSTERING- For clustering similar texts
With MemoryClient
from neo4j_agent_memory import MemoryClient, MemorySettings
from neo4j_agent_memory.config.settings import Neo4jConfig
from neo4j_agent_memory.llm.adapters.vertex_ai import VertexAIEmbeddingProvider
from pydantic import SecretStr
settings = MemorySettings(
neo4j=Neo4jConfig(
uri="bolt://localhost:7687",
password=SecretStr("password"),
),
embedding=VertexAIEmbeddingProvider(
"vertex_ai/gemini-embedding-001",
project_id="your-gcp-project",
location="us-central1",
dimensions=768,
),
)
async with MemoryClient(settings) as client:
# All memory operations now use Vertex AI embeddings
await client.short_term.add_message(
session_id="user-123",
role="user",
content="Hello!",
)
Google ADK Integration
The Neo4jMemoryService implements the Google ADK MemoryService interface for seamless integration with ADK agents.
Basic Usage
from neo4j_agent_memory import MemoryClient, MemorySettings
from neo4j_agent_memory.integrations.google_adk import Neo4jMemoryService
async with MemoryClient(settings) as client:
# Create memory service
memory_service = Neo4jMemoryService(
memory_client=client,
user_id="user-123",
include_entities=True,
include_preferences=True,
)
# Store a conversation session
session = {
"id": "session-1",
"messages": [
{"role": "user", "content": "I prefer dark mode"},
{"role": "assistant", "content": "Noted!"},
]
}
await memory_service.add_session_to_memory(session)
# Search across all memory types. search_memory() returns an ADK
# SearchMemoryResponse — iterate response.memories, not the response.
response = await memory_service.search_memory(
query="user preferences",
limit=10,
)
for entry in response.memories:
# entry.content is a google.genai.types.Content (a list of parts),
# and the memory type lives in custom_metadata.
text = "".join(part.text or "" for part in entry.content.parts)
kind = (entry.custom_metadata or {}).get("memory_type")
print(f"[{kind}/{entry.author}] {text}")
The runnable version of this wiring — a real Runner, ADK’s load_memory
tool, and two turns across two sessions — is
examples/google_adk_demo/.
It runs without Google credentials by driving the same loop with a scripted
model.
|
API Reference
add_session_to_memory
Store a conversation session with automatic entity and preference extraction.
await memory_service.add_session_to_memory(
session={
"id": "session-id",
"messages": [
{"role": "user", "content": "..."},
{"role": "assistant", "content": "..."},
]
}
)
search_memory
Semantic search across all memory types. Returns an ADK SearchMemoryResponse.
response = await memory_service.search_memory(
query="search query",
app_name="my-app", # Accepted for ADK contract parity
user_id="user-id", # Accepted for ADK contract parity
session_id="session-1", # Scopes message search (required on hosted NAMS)
limit=10,
)
for entry in response.memories:
text = "".join(part.text or "" for part in entry.content.parts)
metadata = entry.custom_metadata or {}
print(entry.author, metadata.get("memory_type"), metadata.get("score"), text)
Entity and preference recall is workspace-wide; only message search is scoped by
session_id.
get_memories_for_session
Retrieve all memories for a specific session.
memories = await memory_service.get_memories_for_session(
session_id="session-id",
limit=100,
)
Integration with ADK Agents
Memory is a Runner-level service in Google ADK 2.x: pass it as
Runner(memory_service=…). LlmAgent has no memory= parameter, and there is
no @agent.tool decorator — give the agent ADK’s built-in load_memory tool
(or preload_memory) and it reads from Neo4j.
import os
from google.adk.agents import LlmAgent
from google.adk.runners import Runner
from google.adk.sessions import InMemorySessionService
from google.adk.tools import load_memory
from google.genai import types
from neo4j_agent_memory import MemoryClient, MemorySettings
from neo4j_agent_memory.integrations.google_adk import Neo4jMemoryService
APP, USER, SID = "my-app", "user-123", "session-1"
settings = MemorySettings()
async with MemoryClient(settings) as client:
session_service = InMemorySessionService()
memory_service = Neo4jMemoryService(memory_client=client, user_id=USER)
runner = Runner(
app_name=APP,
agent=LlmAgent(
name="my-agent",
model=os.environ.get("ADK_MODEL", "gemini-2.5-flash"),
instruction="Call load_memory to recall anything the user told you before.",
tools=[load_memory],
),
session_service=session_service,
memory_service=memory_service,
)
await session_service.create_session(app_name=APP, user_id=USER, session_id=SID)
# run_async() is an async generator — iterate it, never await it.
async for event in runner.run_async(
user_id=USER,
session_id=SID,
new_message=types.Content(
role="user", parts=[types.Part(text="I work on Project Alpha")]
),
):
pass
# Commit the finished ADK session to Neo4j so later sessions can recall it.
await memory_service.add_session_to_memory(
await session_service.get_session(app_name=APP, user_id=USER, session_id=SID)
)
await runner.close()
To persist only the latest turn instead of re-ingesting the whole session, use
the ADK 2.x delta API, add_events_to_memory(app_name=…, user_id=…,
events=[…], session_id=…).
Domain Data Access via MemoryClient.graph
For applications that store domain-specific data (customers, transactions, products) in the same Neo4j database, use MemoryClient.graph to run custom Cypher queries alongside memory operations — sharing a single database connection.
from neo4j_agent_memory import MemoryClient, MemorySettings
async with MemoryClient(settings) as client:
# Memory operations use the built-in APIs
await client.short_term.add_message(
session_id="user-123",
role="user",
content="Show me high-risk customers",
)
# Domain queries use the graph client directly
customers = await client.graph.execute_read(
"""
MATCH (c:Customer)
WHERE c.risk_level = 'HIGH'
RETURN c {.*} AS customer
ORDER BY c.name
""",
)
This pattern is used in the Financial Advisor example (examples/financial-services-advisor/google-cloud-financial-advisor/), where a Neo4jDomainService wraps client.graph to provide typed query methods for customers, transactions, alerts, sanctions screening, and network analysis.
See MemoryClient.graph reference for details.
MCP Server
The Model Context Protocol (MCP) server exposes memory capabilities as tools for AI platforms like Claude Desktop.
Available Tools
The MCP server supports two tool profiles: core (6 tools) and extended (16 tools, default).
Core Profile:
| Tool | Description |
|---|---|
|
Hybrid vector + graph search across all memory types |
|
Assembled context for a session |
|
Store message with auto entity extraction |
|
Create/update entity with POLE+O typing |
|
Record user preference |
|
Store subject-predicate-object triple |
The extended profile adds 10 more tools for conversation history, session listing, entity details, graph export, relationship creation, reasoning traces, observations, and read-only Cypher queries. See the MCP Tools Reference for the complete list.
Starting the Server
# stdio transport (for local MCP clients like Claude Desktop)
neo4j-agent-memory mcp serve
# Streamable HTTP transport (for Cloud Run/HTTP deployment).
# Serves the MCP endpoint at POST/GET /mcp/.
neo4j-agent-memory mcp serve --transport http --host 0.0.0.0 --port 8080
# With custom Neo4j connection
neo4j-agent-memory mcp serve \
--uri bolt://localhost:7687 \
--password secret
Claude Desktop Configuration
Add to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"neo4j-agent-memory": {
"command": "neo4j-agent-memory",
"args": ["mcp", "serve"],
"env": {
"NEO4J_URI": "bolt://localhost:7687",
"NEO4J_PASSWORD": "your-password"
}
}
}
}
Programmatic Usage
from neo4j_agent_memory import MemoryClient, MemorySettings
from neo4j_agent_memory.mcp.server import Neo4jMemoryMCPServer
async with MemoryClient(settings) as client:
server = Neo4jMemoryMCPServer(client)
# stdio transport
await server.run()
# Or Streamable HTTP
await server.run_http(host="0.0.0.0", port=8080)
Tool Schemas
Each tool has a defined JSON schema. Example for memory_search:
{
"name": "memory_search",
"description": "Search across all memory types using hybrid vector + graph search",
"inputSchema": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "Search query"
},
"limit": {
"type": "integer",
"default": 10,
"description": "Maximum results"
},
"memory_types": {
"type": "array",
"items": {"type": "string"},
"description": "Filter by memory types: message, entity, preference"
}
},
"required": ["query"]
}
}
Cloud Run Deployment
Deploy the MCP server to Google Cloud Run for production use.
Quick Deploy
cd deploy/cloudrun
# Deploy with gcloud
gcloud run deploy neo4j-memory-mcp \
--source . \
--region us-central1 \
--set-secrets NEO4J_URI=neo4j-uri:latest \
--set-secrets NEO4J_PASSWORD=neo4j-password:latest
Dockerfile
The deployment includes a production-ready Dockerfile:
FROM python:3.11-slim
WORKDIR /app
COPY . .
RUN pip install neo4j-agent-memory[google,mcp]
EXPOSE 8080
CMD ["neo4j-agent-memory", "mcp", "serve", \
"--transport", "http", "--host", "0.0.0.0", "--port", "8080"]
Secret Manager Integration
Store sensitive credentials in Secret Manager:
# Create secrets
echo -n "neo4j+s://xxx.databases.neo4j.io" | \
gcloud secrets create neo4j-uri --data-file=-
echo -n "your-password" | \
gcloud secrets create neo4j-password --data-file=-
# Grant access to Cloud Run service account
gcloud secrets add-iam-policy-binding neo4j-uri \
--member="serviceAccount:[email protected]" \
--role="roles/secretmanager.secretAccessor"
Environment Variables
| Variable | Description | Default |
|---|---|---|
|
GCP project ID for Vertex AI |
Required for Vertex AI |
|
GCP region for Vertex AI |
|
|
Neo4j connection URI |
|
|
Neo4j password |
Required |
Examples
Quick Start Scripts
Comprehensive examples are available in examples/google_cloud_integration/:
-
vertex_ai_embeddings.py- Vertex AI embedding generation and multi-tenant writes -
adk_memory_service.py- entity-extraction and preference narratives through the ADK adapter -
mcp_server_demo.py- MCP server tool profiles and live tool calls -
full_pipeline.py- end-to-end demo: Vertex AI, ADK, MCP, a reasoning-trace audit query, buffered writes, consolidation
The smaller ADK on-ramp — a real Runner loop with load_memory — is
examples/google_adk_demo/.
cd examples/google_cloud_integration
python full_pipeline.py
Financial Advisor (Full Application)
A complete multi-agent compliance investigation app in examples/financial-services-advisor/google-cloud-financial-advisor/:
-
Multi-agent architecture: Supervisor + 4 specialist agents (KYC, AML, Relationship, Compliance)
-
Neo4j domain data: All customer, transaction, organization, sanctions, and PEP data stored and queried from Neo4j via
MemoryClient.graph -
Agent memory: Conversation history and investigation findings via neo4j-agent-memory ADK integration
-
Full-stack: FastAPI backend + React/TypeScript frontend
cd examples/financial-services-advisor/google-cloud-financial-advisor
cp .env.example .env # Set GOOGLE_API_KEY, NEO4J_URI, NEO4J_PASSWORD
make install && make load-data && make dev
See the example’s README.md for the full getting started guide.