Skip to content

Agent Access Patterns for Consumer Knowledge Graph

Agent Access Patterns for Consumer Knowledge Graph

Section titled “Agent Access Patterns for Consumer Knowledge Graph”

This document defines access patterns, query templates, and safety constraints for AI agents (LLMs) interacting with the consumer knowledge graph. These patterns enable agentic shopping assistants to provide personalized recommendations, answer product questions, and predict user needs while maintaining security and performance.


Level 1: Read-Only Basic (Shopping Assistant)

Section titled “Level 1: Read-Only Basic (Shopping Assistant)”

Use Case: Customer-facing chatbots, recommendation widgets

Allowed Operations:

  • ✅ Retrieve user purchase history (scoped to requesting user)
  • ✅ Get product details and attributes
  • ✅ Query product similarities
  • ✅ Check active offers for user
  • ✅ Get repurchase predictions
  • ✅ Search products by category/brand

Forbidden Operations:

  • ❌ Write/update any data
  • ❌ Access other users’ data
  • ❌ Traverse graph beyond 3 hops
  • ❌ Execute unbounded queries
  • ❌ Access system metadata

Rate Limits:

  • 100 queries/minute per agent instance
  • Max 10 concurrent queries
  • 500ms timeout per query

Level 2: Read-Write Contextual (Learning Agent)

Section titled “Level 2: Read-Write Contextual (Learning Agent)”

Use Case: Agents that learn from interactions, update preferences

Allowed Operations:

  • ✅ All Level 1 operations
  • ✅ Update user preferences (tags, interests)
  • ✅ Create INTERESTED_IN relationships
  • ✅ Add product ratings/feedback
  • ✅ Create shopping lists
  • ✅ Log agent interactions

Forbidden Operations:

  • ❌ Modify purchase history
  • ❌ Delete relationships
  • ❌ Create/modify products or offers
  • ❌ Access billing data
  • ❌ Modify other users’ data

Rate Limits:

  • 50 writes/minute per agent
  • Read limits same as Level 1

Use Case: Agents performing analysis, generating insights

Allowed Operations:

  • ✅ All Level 2 operations
  • ✅ Aggregate queries across users (anonymized)
  • ✅ Compute similarity scores
  • ✅ Generate vector embeddings
  • ✅ Create derived relationships (e.g., FREQUENTLY_BOUGHT_WITH)
  • ✅ Access historical trends

Forbidden Operations:

  • ❌ Modify source data (purchases, products)
  • ❌ Access PII without anonymization
  • ❌ Delete nodes or relationships
  • ❌ Bypass rate limits

Rate Limits:

  • Batch operations allowed (with approval)
  • 5-minute timeout for analytical queries
  • Must use read replicas

Agent Intent: “What has this user bought recently?”

MATCH (u:User {user_id: $user_id})-[p:PURCHASED]->(prod:Product)
WHERE p.last >= datetime() - duration({days: $lookback_days})
RETURN prod.product_id, prod.name, prod.category, prod.brand,
p.last AS last_purchase, p.times AS purchase_count
ORDER BY p.last DESC
LIMIT 50

Safety:

  • ✅ User-scoped (can’t leak other users’ data)
  • ✅ Time-bounded (lookback window)
  • ✅ Result-limited (max 50)
  • ✅ No graph expansion

Use Case:

  • “Show me what User123 bought in the last 90 days”
  • “What are this customer’s favorite products?”

Agent Intent: “Find products similar to what user likes”

MATCH (u:User {user_id: $user_id})-[:PURCHASED]->(liked:Product)
WHERE liked.category = $category // optional filter
MATCH (liked)-[s:SIMILAR_TO]->(similar:Product)
WHERE s.score >= $min_similarity
OPTIONAL MATCH (u)-[p:PURCHASED]->(similar)
WITH similar, s.score AS similarity, p
WHERE p IS NULL // exclude already purchased
RETURN similar.product_id, similar.name, similar.category,
avg(similarity) AS avg_similarity
ORDER BY avg_similarity DESC
LIMIT 20

Safety:

  • ✅ User-scoped (starts with user’s purchases)
  • ✅ Bounded expansion (1 hop to similar products)
  • ✅ Excludes already purchased (reduces noise)
  • ✅ Limited results

Use Case:

  • “Recommend products similar to what I’ve bought”
  • “Show me alternatives in the Coffee category”

Agent Intent: “What deals is this user eligible for?”

MATCH (u:User {user_id: $user_id})-[e:ELIGIBLE]->(o:Offer)
WHERE o.start <= datetime() AND datetime() <= o.end
AND e.start <= datetime()
OPTIONAL MATCH (o)-[:APPLIES_TO]->(p:Product)
RETURN o.offer_id, o.title, o.description, o.points,
o.start, o.end,
collect(p.product_id) AS applicable_products
ORDER BY o.points DESC, o.end ASC
LIMIT 20

Safety:

  • ✅ User-scoped
  • ✅ Time-bounded (active offers only)
  • ✅ Limited results
  • ✅ No traversal beyond 2 hops

Use Case:

  • “What rewards can I earn today?”
  • “Show me current offers for User456”

Agent Intent: “When will user need to buy this again?”

MATCH (u:User {user_id: $user_id})-[bp:PURCHASED]->(p:Product)
WHERE bp.times >= 2
AND bp.avg_interval_days > 0
WITH p, bp,
bp.last + duration({days: toInteger(bp.avg_interval_days)}) AS next_expected
WHERE next_expected <= datetime() + duration({days: $prediction_window})
RETURN p.product_id, p.name, p.category,
bp.last AS last_purchase,
bp.avg_interval_days,
next_expected,
duration.inDays(datetime(), next_expected).days AS days_until
ORDER BY days_until ASC
LIMIT 20

Safety:

  • ✅ User-scoped
  • ✅ Uses pre-computed intervals (fast)
  • ✅ Prediction window bounded
  • ✅ Limited results

Use Case:

  • “Remind me when to buy coffee again”
  • “What products will I need this week?”

Agent Intent: “Create a shopping list based on predictions + current offers”

// Step 1: Get repurchase predictions
MATCH (u:User {user_id: $user_id})-[bp:PURCHASED]->(p:Product)
WHERE bp.times >= 2
AND bp.avg_interval_days > 0
WITH u, p, bp,
bp.last + duration({days: toInteger(bp.avg_interval_days)}) AS next_expected
WHERE next_expected <= datetime() + duration({days: 7})
// Step 2: Check for applicable offers
OPTIONAL MATCH (u)-[:ELIGIBLE]->(o:Offer)-[:APPLIES_TO]->(p)
WHERE o.start <= datetime() AND datetime() <= o.end
RETURN p.product_id, p.name,
next_expected,
CASE WHEN o IS NOT NULL THEN o.title ELSE null END AS offer_title,
CASE WHEN o IS NOT NULL THEN o.points ELSE 0 END AS points
ORDER BY next_expected ASC, points DESC
LIMIT 30

Safety:

  • ✅ User-scoped
  • ✅ 7-day prediction window
  • ✅ Limited results
  • ✅ Combines multiple patterns safely

Use Case:

  • “Generate my weekly shopping list”
  • “What should I buy this week to maximize rewards?”

Agent Intent: “What’s in this category?”

MATCH (p:Product)
WHERE p.category = $category
AND ($brand IS NULL OR p.brand = $brand)
OPTIONAL MATCH (u:User {user_id: $user_id})-[purchased:PURCHASED]->(p)
RETURN p.product_id, p.name, p.brand,
CASE WHEN purchased IS NOT NULL THEN true ELSE false END AS previously_purchased,
CASE WHEN purchased IS NOT NULL THEN purchased.times ELSE 0 END AS purchase_count
ORDER BY purchase_count DESC, p.name ASC
LIMIT 50

Safety:

  • ✅ User-scoped (optional filter)
  • ✅ Category-bounded
  • ✅ Limited results
  • ✅ No graph expansion

Use Case:

  • “Show me all coffee products”
  • “What brands of yogurt are available?”

Agent Intent: “Tell me everything about this product for this user”

MATCH (p:Product {product_id: $product_id})
// User's relationship to this product
OPTIONAL MATCH (u:User {user_id: $user_id})-[purchased:PURCHASED]->(p)
// Similar products
OPTIONAL MATCH (p)-[s:SIMILAR_TO]->(similar:Product)
WHERE s.score >= 0.7
// Applicable offers
OPTIONAL MATCH (u)-[:ELIGIBLE]->(o:Offer)-[:APPLIES_TO]->(p)
WHERE o.start <= datetime() AND datetime() <= o.end
RETURN p.product_id, p.name, p.category, p.brand,
purchased.times AS times_purchased,
purchased.last AS last_purchased,
purchased.avg_interval_days,
collect(DISTINCT {pid: similar.product_id, name: similar.name, score: s.score}) AS similar_products,
collect(DISTINCT {offer_id: o.offer_id, title: o.title, points: o.points}) AS offers

Safety:

  • ✅ User-scoped
  • ✅ Product-scoped (single product lookup)
  • ✅ Limited similar products (similarity threshold)
  • ✅ Active offers only

Use Case:

  • “Tell me about this coffee”
  • “Should I buy this product now?”

Agent Intent: “What products are trending?”

MATCH (p:Product)<-[purchased:PURCHASED]-(u:User)
WHERE purchased.last >= datetime() - duration({days: 30})
WITH p, count(DISTINCT u) AS recent_buyers,
avg(purchased.times) AS avg_repeat_purchases
WHERE recent_buyers >= $min_users
RETURN p.product_id, p.name, p.category, p.brand,
recent_buyers,
avg_repeat_purchases,
recent_buyers * avg_repeat_purchases AS trend_score
ORDER BY trend_score DESC
LIMIT 50

Safety:

  • ⚠️ Cross-user query (anonymized)
  • ✅ Time-bounded (30 days)
  • ✅ Minimum user threshold (privacy)
  • ✅ Limited results
  • ⚠️ Requires Level 3 access

Use Case:

  • “What products are popular this month?”
  • “Show trending items in Snacks category”

Agent Intent: “Find products matching natural language query”

// Requires vector index on Product.embedding
CALL db.index.vector.queryNodes('product_embeddings', 5, $query_embedding)
YIELD node AS p, score
OPTIONAL MATCH (u:User {user_id: $user_id})-[purchased:PURCHASED]->(p)
RETURN p.product_id, p.name, p.category, p.brand,
score AS semantic_similarity,
CASE WHEN purchased IS NOT NULL THEN true ELSE false END AS previously_purchased
ORDER BY score DESC
LIMIT 20

Safety:

  • ✅ Result-limited
  • ✅ User context (optional)
  • ⚠️ Requires vector index
  • ⚠️ Query embedding must be validated (no prompt injection)

Use Case:

  • “Find products for ‘quick healthy breakfast’”
  • “Show me ‘sustainable cleaning supplies‘“

Agent Intent: “Find products from image or description”

// Requires image embeddings on Product.image_embedding
CALL db.index.vector.queryNodes('product_image_embeddings', 10, $image_embedding)
YIELD node AS p, score
MATCH (p)-[:IN_CATEGORY]->(c:Category)
OPTIONAL MATCH (u:User {user_id: $user_id})-[:PURCHASED]->(p)
RETURN p.product_id, p.name, c.name AS category,
score AS visual_similarity,
CASE WHEN purchased IS NOT NULL THEN true ELSE false END AS previously_purchased
ORDER BY score DESC
LIMIT 20

Safety:

  • ✅ Result-limited
  • ⚠️ Image embedding validation required
  • ⚠️ Requires multimodal embeddings

Use Case:

  • “Find products that look like this image”
  • “Match this receipt photo to products”

Agent Intent: “Record this conversation for learning”

MATCH (u:User {user_id: $user_id})
CREATE (i:Interaction {
interaction_id: randomUUID(),
user_id: $user_id,
agent_id: $agent_id,
timestamp: datetime(),
intent: $intent,
query: $query,
response: $response,
satisfaction: $satisfaction
})
CREATE (u)-[:HAD_INTERACTION]->(i)
RETURN i.interaction_id

Safety:

  • ✅ User-scoped
  • ✅ Creates new node only (no modifications)
  • ✅ Timestamped
  • ⚠️ Should be rate-limited (max 1/second)

Use Case:

  • “Log this recommendation for feedback”
  • “Track agent performance”

Agent Intent: “User said they like/dislike this”

MATCH (u:User {user_id: $user_id})
MATCH (p:Product {product_id: $product_id})
MERGE (u)-[pref:PREFERENCE]->(p)
SET pref.score = $score, // -1 to 1
pref.updated = datetime(),
pref.source = 'agent_interaction'
RETURN pref.score

Safety:

  • ✅ User-scoped
  • ✅ MERGE prevents duplicates
  • ✅ Timestamped
  • ✅ Source tracked
  • ⚠️ Rate limited (max 10/minute)

Use Case:

  • “User said they love this coffee brand”
  • “User wants to avoid this category”

Agent Intent: “Save this shopping list for user”

MATCH (u:User {user_id: $user_id})
CREATE (list:ShoppingList {
list_id: randomUUID(),
user_id: $user_id,
created: datetime(),
name: $name
})
CREATE (u)-[:HAS_LIST]->(list)
WITH list
UNWIND $product_ids AS product_id
MATCH (p:Product {product_id: product_id})
CREATE (list)-[:CONTAINS {added: datetime()}]->(p)
RETURN list.list_id, count(*) AS item_count

Safety:

  • ✅ User-scoped
  • ✅ Creates new nodes only
  • ✅ Timestamped
  • ⚠️ Product IDs must be validated
  • ⚠️ Max 100 items per list

Use Case:

  • “Save my weekly shopping list”
  • “Create a list from my repurchase predictions”

Max Graph Traversal Depth: 3 hops

MATCH (u:User)-[r1]->(n1)-[r2]->(n2)-[r3]->(n3) // ✅ OK
MATCH (u:User)-[r1]->(n1)-[r2]->(n2)-[r3]->(n3)-[r4]->(n4) // ❌ TOO DEEP

Max Result Set: 1000 nodes/relationships per query

RETURN ... LIMIT 1000 // ✅ OK
RETURN ... LIMIT 10000 // ❌ TOO MANY

Query Timeout: 5 seconds for read, 10 seconds for write

CALL apoc.cypher.runTimeboxed(
$query,
{user_id: $user_id},
5000 // 5 second timeout
)

Always scope to requesting user:

// ✅ GOOD - user-scoped
MATCH (u:User {user_id: $user_id})-[:PURCHASED]->(p:Product)
// ❌ BAD - can access all users
MATCH (u:User)-[:PURCHASED]->(p:Product)

Exception: Level 3 analytical queries with aggregation

// ✅ OK for Level 3 - aggregated, no PII
MATCH (u:User)-[:PURCHASED]->(p:Product {category: $category})
RETURN p.product_id, count(DISTINCT u) AS buyer_count

Never allow:

// ❌ Delete operations
DELETE u, p, r
// ❌ Detach delete
DETACH DELETE u
// ❌ Remove relationships
MATCH (u)-[r:PURCHASED]->(p)
DELETE r
// ❌ Modify purchase history
MATCH (u)-[p:PURCHASED]->(prod)
SET p.last = datetime() // ❌ Can't change history
// ❌ Access system nodes
MATCH (s:System) // ❌ System metadata off-limits
// ❌ Drop indexes/constraints
DROP INDEX product_id_unique // ❌ Schema changes forbidden

Validate all agent inputs:

def validate_agent_query(user_id: str, query: str, params: dict):
# User ID validation
if not re.match(r'^[A-Za-z0-9_-]+$', user_id):
raise ValueError("Invalid user_id format")
# Query allowlist check
forbidden = ['DELETE', 'DROP', 'DETACH', 'REMOVE', 'CREATE INDEX']
if any(kw in query.upper() for kw in forbidden):
raise SecurityError(f"Forbidden operation in query")
# Parameter injection check
if any(isinstance(v, str) and ('MATCH' in v or 'RETURN' in v) for v in params.values()):
raise SecurityError("Possible Cypher injection in parameters")
# Result limit enforcement
if 'LIMIT' not in query.upper():
query += " LIMIT 1000"
return query, params

Per-agent instance:

RATE_LIMITS = {
'Level1': {
'read_queries_per_minute': 100,
'max_concurrent': 10,
'timeout_ms': 500
},
'Level2': {
'read_queries_per_minute': 100,
'write_queries_per_minute': 50,
'max_concurrent': 10,
'timeout_ms': 1000
},
'Level3': {
'read_queries_per_minute': 50, # Analytical queries are expensive
'write_queries_per_minute': 10,
'max_concurrent': 5,
'timeout_ms': 5000
}
}

Instead of allowing arbitrary Cypher, provide parameterized templates:

AGENT_QUERY_TEMPLATES = {
'get_purchase_history': {
'level': 1,
'cypher': '''
MATCH (u:User {user_id: $user_id})-[p:PURCHASED]->(prod:Product)
WHERE p.last >= datetime() - duration({days: $lookback_days})
RETURN prod.product_id, prod.name, p.last, p.times
ORDER BY p.last DESC
LIMIT $limit
''',
'params': {
'user_id': 'required',
'lookback_days': {'default': 90, 'max': 365},
'limit': {'default': 50, 'max': 100}
}
},
'get_repurchase_predictions': {
'level': 1,
'cypher': '''
MATCH (u:User {user_id: $user_id})-[bp:PURCHASED]->(p:Product)
WHERE bp.times >= $min_intervals
AND bp.avg_interval_days > 0
WITH p, bp,
bp.last + duration({days: toInteger(bp.avg_interval_days)}) AS next_expected
WHERE next_expected <= datetime() + duration({days: $prediction_window})
RETURN p.product_id, p.name, next_expected,
duration.inDays(datetime(), next_expected).days AS days_until
ORDER BY days_until ASC
LIMIT $limit
''',
'params': {
'user_id': 'required',
'min_intervals': {'default': 2, 'max': 10},
'prediction_window': {'default': 14, 'max': 90},
'limit': {'default': 20, 'max': 50}
}
},
'find_similar_products': {
'level': 1,
'cypher': '''
MATCH (p:Product {product_id: $product_id})-[s:SIMILAR_TO]->(similar:Product)
WHERE s.score >= $min_similarity
OPTIONAL MATCH (u:User {user_id: $user_id})-[purchased:PURCHASED]->(similar)
WITH similar, s.score, purchased
WHERE purchased IS NULL
RETURN similar.product_id, similar.name, s.score AS similarity
ORDER BY similarity DESC
LIMIT $limit
''',
'params': {
'product_id': 'required',
'user_id': 'required',
'min_similarity': {'default': 0.7, 'max': 1.0},
'limit': {'default': 10, 'max': 50}
}
}
}

Agent calls templates by name:

# Agent code
response = graph.execute_template(
template_name='get_repurchase_predictions',
user_id='USER123',
prediction_window=7
)

You are a shopping assistant with access to a knowledge graph about users, products, and offers.
You have the following capabilities:
1. get_purchase_history(user_id, lookback_days=90) - See what user bought
2. get_repurchase_predictions(user_id, prediction_window=14) - Predict when they'll need to rebuy
3. find_similar_products(product_id, user_id, min_similarity=0.7) - Find alternatives
4. get_active_offers(user_id) - Check eligible rewards
5. search_products(category, brand=None) - Browse catalog
6. get_product_details(product_id, user_id) - Deep dive on one product
7. create_shopping_list(user_id, product_ids, name) - Save a list
IMPORTANT RULES:
- You can ONLY query data for the user you're helping ($user_id)
- You CANNOT see other users' purchase history
- You CANNOT modify purchase history or product data
- You CANNOT execute arbitrary database queries
- If unsure, ask the user for clarification
RESPONSE GUIDELINES:
- Be helpful and conversational
- Explain WHY you're recommending something
- Reference specific purchase patterns when relevant
- Mention applicable offers proactively
- Ask follow-up questions to refine recommendations
Example interaction:
User: "What should I buy this week?"
Assistant: "Based on your purchase history, you typically buy coffee every 28 days, and it's been 26 days since your last purchase. I'd recommend adding coffee to your list. You also have an active offer for 500 points on coffee purchases this week! Would you like me to create a shopping list?"

FEW_SHOT_EXAMPLES = [
{
'user_query': "What have I bought recently?",
'agent_action': "get_purchase_history(user_id='USER123', lookback_days=30)",
'agent_response': "In the last 30 days, you purchased: Colombian Coffee (3 times), Organic Yogurt (2 times), and Wheat Bread (4 times). Your most frequent purchase is Wheat Bread - looks like you really like it!"
},
{
'user_query': "What's running low?",
'agent_action': "get_repurchase_predictions(user_id='USER123', prediction_window=7)",
'agent_response': "Based on your buying patterns, you'll likely need: Coffee (expected in 2 days), Yogurt (in 5 days), and Bread (in 6 days). Would you like me to create a shopping list?"
},
{
'user_query': "I don't like that coffee anymore, any alternatives?",
'agent_action': "find_similar_products(product_id='COFFEE123', user_id='USER123', min_similarity=0.8)",
'agent_response': "I found 3 highly similar coffees you haven't tried: Ethiopian Medium Roast (88% similar), Sumatra Dark Roast (85% similar), and House Blend (82% similar). All are in the same price range as your usual coffee."
}
]

Track these metrics per agent instance:

AGENT_METRICS = {
'queries_executed': Counter('agent_queries_total', ['agent_id', 'template', 'status']),
'query_latency': Histogram('agent_query_duration_ms', ['agent_id', 'template']),
'results_returned': Histogram('agent_results_count', ['agent_id', 'template']),
'errors': Counter('agent_errors_total', ['agent_id', 'error_type']),
'rate_limit_hits': Counter('agent_rate_limits_hit', ['agent_id', 'limit_type']),
'cache_hits': Counter('agent_cache_hits', ['agent_id', 'template'])
}

Log all agent queries for compliance:

AUDIT_LOG_SCHEMA = {
'timestamp': datetime,
'agent_id': str,
'agent_level': int,
'user_id': str, # User being queried
'template_name': str,
'parameters': dict,
'query_hash': str, # Hash of executed Cypher
'execution_time_ms': int,
'results_count': int,
'status': str, # 'success', 'error', 'rate_limited', 'forbidden'
'error_message': str,
'session_id': str # Link to conversation
}

Example audit entry:

{
"timestamp": "2025-01-07T10:30:45Z",
"agent_id": "shopping-assistant-prod-01",
"agent_level": 1,
"user_id": "USER123",
"template_name": "get_repurchase_predictions",
"parameters": {
"user_id": "USER123",
"prediction_window": 7,
"min_intervals": 2
},
"query_hash": "sha256:abc123...",
"execution_time_ms": 45,
"results_count": 5,
"status": "success",
"session_id": "conv-456"
}

Frequently accessed data should be cached:

CACHE_POLICIES = {
'get_purchase_history': {
'ttl_seconds': 300, # 5 minutes
'key_pattern': 'purchase_history:{user_id}:{lookback_days}'
},
'get_repurchase_predictions': {
'ttl_seconds': 900, # 15 minutes
'key_pattern': 'repurchase:{user_id}:{prediction_window}'
},
'get_active_offers': {
'ttl_seconds': 3600, # 1 hour
'key_pattern': 'offers:{user_id}'
},
'get_product_details': {
'ttl_seconds': 7200, # 2 hours
'key_pattern': 'product:{product_id}'
}
}

Cache invalidation triggers:

  • User makes new purchase → invalidate purchase_history, repurchase_predictions
  • New offer created → invalidate active_offers for eligible users
  • Product updated → invalidate product_details

Pattern 14: Recipe Recommendations (Requires Recipe Graph)

Section titled “Pattern 14: Recipe Recommendations (Requires Recipe Graph)”
MATCH (u:User {user_id: $user_id})-[:PURCHASED]->(p:Product)-[:INGREDIENT_IN]->(r:Recipe)
WHERE NOT (u)-[:MADE]->(r) // Haven't made this recipe yet
WITH r, count(DISTINCT p) AS ingredients_owned
MATCH (r)-[:REQUIRES]->(all_ingredients:Product)
WITH r, ingredients_owned, count(DISTINCT all_ingredients) AS total_ingredients
WHERE toFloat(ingredients_owned) / total_ingredients >= 0.7 // Own 70%+ of ingredients
RETURN r.recipe_id, r.name, ingredients_owned, total_ingredients,
toFloat(ingredients_owned) / total_ingredients AS completion_ratio
ORDER BY completion_ratio DESC
LIMIT 10

Pattern 15: Personalized Nutrition (Requires Nutrition Graph)

Section titled “Pattern 15: Personalized Nutrition (Requires Nutrition Graph)”
MATCH (u:User {user_id: $user_id})-[:HAS_GOAL]->(g:NutritionGoal)
MATCH (p:Product)-[:HAS_NUTRITION]->(n:Nutrition)
WHERE n.protein >= g.min_protein
AND n.sugar <= g.max_sugar
AND n.calories <= g.max_calories
OPTIONAL MATCH (u)-[:PURCHASED]->(p)
WITH p, n, g, purchased
WHERE purchased IS NULL // New products only
RETURN p.product_id, p.name,
n.protein, n.sugar, n.calories,
abs(n.protein - g.target_protein) AS protein_diff
ORDER BY protein_diff ASC
LIMIT 20

Pattern 16: Social Recommendations (Requires Social Graph)

Section titled “Pattern 16: Social Recommendations (Requires Social Graph)”
MATCH (u:User {user_id: $user_id})-[:SIMILAR_TASTES]->(friend:User)-[:PURCHASED]->(p:Product)
WHERE NOT (u)-[:PURCHASED]->(p)
WITH p, count(DISTINCT friend) AS friend_count,
collect(DISTINCT friend.name) AS recommenders
WHERE friend_count >= 2 // At least 2 similar users bought it
RETURN p.product_id, p.name, p.category,
friend_count AS popularity_score,
recommenders[0..3] AS sample_recommenders
ORDER BY friend_count DESC
LIMIT 20

  • Implement query template system
  • Create Level 1 access control middleware
  • Add rate limiting per agent instance
  • Implement user data isolation checks
  • Create audit logging pipeline
  • Add query timeout enforcement
  • Write agent system prompt
  • Test with 5 core query templates
  • Add input validation for all parameters
  • Implement result set size limits
  • Add graph traversal depth limits
  • Create monitoring dashboard for agent queries
  • Set up alerting for suspicious patterns
  • Implement caching layer (Redis)
  • Add cache invalidation logic
  • Load test agent query patterns

Phase 3: Advanced Capabilities (Weeks 5-8)

Section titled “Phase 3: Advanced Capabilities (Weeks 5-8)”
  • Implement Level 2 write operations
  • Add interaction logging
  • Create preference update mechanism
  • Implement shopping list creation
  • Add Level 3 analytical queries
  • Create aggregation safety checks
  • Add PII anonymization for cross-user queries
  • Implement vector search templates (future)

Threats to mitigate:

  1. Prompt Injection Attacks

    • Agent tricks system into executing unauthorized queries
    • Mitigation: Template-based queries only, parameter validation
  2. Data Leakage

    • Agent accesses other users’ data
    • Mitigation: Always scope queries to $user_id, enforce in middleware
  3. Denial of Service

    • Agent executes expensive unbounded queries
    • Mitigation: Timeouts, result limits, rate limiting, traversal depth limits
  4. Parameter Injection

    • Malicious Cypher in parameter values
    • Mitigation: Parameterized queries only, input validation
  5. Privilege Escalation

    • Level 1 agent tries to execute Level 3 queries
    • Mitigation: Access level enforcement, template-level restrictions

class AgentQueryMiddleware:
def __init__(self, agent_level: int, user_id: str):
self.agent_level = agent_level
self.user_id = user_id
self.rate_limiter = RateLimiter()
def execute_template(self, template_name: str, **params):
# 1. Check template exists and access level
template = AGENT_QUERY_TEMPLATES.get(template_name)
if not template:
raise TemplateNotFoundError(template_name)
if template['level'] > self.agent_level:
raise InsufficientPermissionsError(
f"Template requires level {template['level']}, agent has {self.agent_level}"
)
# 2. Enforce user_id scoping
if 'user_id' in template['params']:
if params.get('user_id') != self.user_id:
raise SecurityError("Cannot query data for different user")
params['user_id'] = self.user_id # Force to session user
# 3. Validate and normalize parameters
validated_params = self._validate_params(template['params'], params)
# 4. Rate limiting
if not self.rate_limiter.allow(self.user_id, template_name):
raise RateLimitExceededError()
# 5. Check cache
cache_key = self._get_cache_key(template_name, validated_params)
cached = cache.get(cache_key)
if cached:
metrics.agent_cache_hits.inc(template_name)
return cached
# 6. Execute with timeout
try:
result = self._execute_with_timeout(
template['cypher'],
validated_params,
timeout_ms=RATE_LIMITS[f'Level{self.agent_level}']['timeout_ms']
)
except TimeoutError:
metrics.agent_errors.inc('timeout')
raise
# 7. Cache result
cache.set(cache_key, result, ttl=CACHE_POLICIES[template_name]['ttl_seconds'])
# 8. Audit log
audit_logger.log({
'template': template_name,
'user_id': self.user_id,
'params': validated_params,
'results_count': len(result),
'status': 'success'
})
return result

For MVP shopping assistant (Level 1):

  1. Implement 6 core templates:

    • get_purchase_history
    • get_repurchase_predictions
    • find_similar_products
    • get_active_offers
    • search_products
    • get_product_details
  2. Add basic safety:

    • User ID scoping
    • Rate limiting (100 qpm)
    • Query timeouts (500ms)
    • Result limits (50 max)
  3. Monitoring:

    • Query latency metrics
    • Error rates
    • Audit logging

Estimated effort: 2-3 weeks for 2 engineers


  1. Vector search integration (Phase 2)

    • Semantic product discovery
    • Natural language queries
  2. Write capabilities (Phase 2)

    • Interaction logging
    • Preference updates
    • Shopping lists
  3. Advanced analytics (Phase 3)

    • Trend analysis
    • Cross-user insights (anonymized)
    • Predictive modeling
  4. Agentic workflows (Phase 3+)

    • Multi-step reasoning
    • Tool composition
    • Self-improving recommendations