Knowledge Graph Generation
Control how knowledge graphs are created from your memories using auto or manual modes.
📌 API Update: The
graph_generationfield has been replaced withmemory_policy. This guide uses the newmemory_policysyntax. See Migration Guide below for upgrading existing code.
Overview
When you add memories to Papr, the system can automatically build a knowledge graph by:
- Extracting entities from content
- Identifying relationships between entities
- Connecting related memories
- Using custom schemas (if provided) to guide structure
You have two modes for controlling this process: Auto mode (let AI handle it) or Manual mode (specify exactly what you want).
How Graph Generation Works
- Content added - You add memory via document upload, message, or direct API
- Schema selected - System uses custom schema if provided, otherwise system schema
- Entities extracted - Predictive models identify entities in the content
- Relationships mapped - System identifies how entities relate to each other
- Graph built - Entities and relationships are added to knowledge graph
- Predictive connections - Additional connections are made based on patterns
Auto Mode (Recommended)
Auto mode lets the AI analyze content and automatically extract entities and relationships. This is the recommended approach for most use cases.
Basic Auto Mode
from papr_memory import Papr
import os
client = Papr(x_api_key=os.environ.get("PAPR_MEMORY_API_KEY"))
response = client.memory.add(
content="Meeting with Jane Smith from Acme Corp about Q4 project timeline. She mentioned they need delivery by December 15th.",
memory_policy={
"mode": "auto"
}
)The system will automatically:
- Extract entities (Jane Smith, Acme Corp, Q4 project)
- Identify relationships (Jane works for Acme Corp, project has deadline)
- Build appropriate graph structure
Auto Mode with Custom Schema
Provide a schema_id to guide entity extraction for your domain:
response = client.memory.add(
content="Meeting with Jane Smith from Acme Corp about Q4 project timeline",
memory_policy={
"mode": "auto",
"schema_id": "crm_schema" # Your custom CRM schema
}
)The system will use your CRM schema to understand that Jane Smith should be a "Contact", Acme Corp should be a "Company", etc.
Auto Mode with Schema Reference
Reference a schema to guide entity extraction for your domain:
response = client.memory.add(
content="Customer Jane Doe purchased iPhone 15 Pro for $999",
memory_policy={
"mode": "auto",
"schema_id": "ecommerce_schema" # Recommended for domain-specific extraction
}
)This ensures consistent entity types and relationships aligned with your domain model.
Auto Mode with Node Constraints
Use node constraints to control how entities are created and matched:
response = client.memory.add(
content="Jane Smith from Acme Corp mentioned interest in Enterprise plan",
memory_policy={
"mode": "auto",
"schema_id": "crm_schema",
"node_constraints": [
{
"node_type": "Contact",
"create": "auto", # Create if not found
"search": {
"properties": [{"name": "email", "mode": "exact"}]
},
"set": {
"role": {"mode": "exact", "value": "decision_maker"},
"source": {"mode": "exact", "value": "direct_outreach"}
}
},
{
"node_type": "Company",
"create": "auto",
"search": {
"properties": [{"name": "name", "mode": "semantic"}]
},
"set": {
"industry": {"mode": "exact", "value": "technology"},
"size": {"mode": "exact", "value": "enterprise"}
}
}
]
}
)Node constraints ensure that:
- Entities are matched using the right properties (exact vs semantic)
- You can force specific property values on matched entities
- Entity resolution works reliably across documents
- You control when to create new entities vs link to existing ones
Manual Mode (Exact Control)
Manual mode lets you specify exactly what entities and relationships to create. Use this when you have structured data or need precise control.
Basic Manual Mode
response = client.memory.add(
content="Signed service agreement with Acme Corp for $50,000 annually",
memory_policy={
"mode": "manual",
"nodes": [
{
"id": "contract_acme_2024",
"type": "Contract",
"properties": {
"title": "Service Agreement 2024",
"value": 50000,
"term": "annual",
"status": "active",
"signed_date": "2024-03-15"
}
},
{
"id": "company_acme",
"type": "Company",
"properties": {
"name": "Acme Corp",
"industry": "Technology",
"size": "Enterprise"
}
}
],
"relationships": [
{
"source": "company_acme",
"target": "contract_acme_2024",
"type": "HAS_CONTRACT",
"properties": {
"signed_date": "2024-03-15",
"start_date": "2024-04-01"
}
}
]
}
)Manual Mode with Schema Validation
Even in manual mode, specify a schema to ensure your nodes match your domain model:
response = client.memory.add(
content="New product launch: Widget Pro at $299",
memory_policy={
"mode": "manual",
"schema_id": "ecommerce_schema", # Validates against this schema
"nodes": [
{
"id": "product_widget_pro",
"type": "Product", # Must match schema node type
"properties": {
"name": "Widget Pro",
"price": 299.00,
"category": "electronics",
"in_stock": True,
"sku": "SKU-001"
}
}
],
"relationships": []
}
)Agent Memory Example
Agents can document their own workflows, learnings, and reasoning patterns as memories:
# Agent documents its refund workflow
response = client.memory.add(
content="""
Refund Request Workflow:
1. Verify customer account status and history
2. Check purchase date and confirm within return window
3. Review product condition requirements
4. Apply refund policy based on timeframe:
- Within 30 days: Full refund
- 30-60 days: Store credit only
- After 60 days: Case-by-case basis
5. Document reason for refund
6. Process refund through accounting system
""",
metadata={
"role": "assistant", # This is an agent memory
"category": "learning",
"workflow_type": "customer_service",
"topics": ["refunds", "customer_service", "policy"]
},
memory_policy={
"mode": "auto"
}
)
# Agent documents a successful resolution pattern
response = client.memory.add(
content="When customers express frustration about delayed shipping, immediately: 1) Acknowledge their concern, 2) Check tracking details, 3) Offer specific ETA, 4) Provide discount code for inconvenience. This approach has 85% satisfaction rate.",
metadata={
"role": "assistant",
"category": "learning",
"success_metric": 0.85,
"topics": ["customer_service", "shipping", "escalation"]
},
memory_policy={
"mode": "auto"
}
)These agent memories enable the AI to:
- Remember successful workflows and apply them to similar situations
- Learn from past interactions
- Improve responses based on what worked before
- Build institutional knowledge that persists across sessions
Choosing Between Auto and Manual
Use Auto Mode When:
- Processing natural language content (conversations, documents)
- You want the AI to identify entities and relationships
- Content structure is not rigidly defined
- You have a custom schema to guide extraction
- You want the system to make predictive connections
Examples:
- Customer conversations
- Meeting notes
- Email content
- Document analysis
- Social media posts
Use Manual Mode When:
- You have structured data with known entities
- Entity IDs and relationships are critical and must be exact
- Importing from existing databases
- Building specific graph patterns
- Testing schema designs
Examples:
- Database imports
- API integrations
- CRM sync
- Financial transactions
- Audit logs
Hybrid Approach
Start with auto mode and add property overrides for critical entities:
response = client.memory.add(
content="Jane Smith called about upgrading from Basic to Pro plan",
memory_policy={
"mode": "auto",
"schema_id": "saas_schema",
"node_constraints": [
{
"node_type": "Customer",
"search": {
"properties": [{"name": "name", "mode": "semantic"}]
},
"set": {
"current_plan": {"mode": "exact", "value": "basic"},
"account_value": {"mode": "exact", "value": 99},
"contact_method": {"mode": "exact", "value": "phone"}
}
}
]
}
)This gives you AI-powered extraction with manual control over key entities.
TypeScript Examples
Auto Mode
import Papr from '@papr/memory';
const client = new Papr({
xAPIKey: process.env.PAPR_MEMORY_API_KEY
});
const response = await client.memory.add({
content: "Meeting with Jane Smith from Acme Corp about Q4 project",
memory_policy: {
mode: "auto",
schema_id: "crm_schema",
node_constraints: [
{
node_type: "Contact",
search: {
properties: [{ name: "name", mode: "semantic" }]
},
set: {
role: { mode: "exact", value: "decision_maker" }
}
}
]
}
});Manual Mode
const response = await client.memory.add({
content: "New contract signed with Acme Corp",
memory_policy: {
mode: "manual",
nodes: [
{
id: "contract_acme_2024",
type: "Contract",
properties: {
title: "Service Agreement 2024",
value: 50000,
status: "active"
}
}
],
relationships: []
}
});Best Practices
1. Use Simple Schema Mode in Production
memory_policy={
"mode": "auto",
"schema_id": "your_domain_schema" # Consistency across operations
}This ensures consistent entity extraction whether you're uploading documents or adding memories directly.
2. Define Node Constraints for Key Entities
For entities that appear frequently, use node constraints to control matching and property setting:
node_constraints=[
{
"node_type": "Customer",
"search": {
"properties": [{"name": "email", "mode": "exact"}]
},
"set": {
"segment": {"mode": "exact", "value": "enterprise"}
}
}
]3. Start with Auto, Switch to Manual for Critical Data
Use auto mode for general content, manual mode for critical structured data:
# Auto for conversational content
client.memory.add(content=conversation, memory_policy={"mode": "auto"})
# Manual for financial transactions
client.memory.add(content=transaction, memory_policy={"mode": "manual", "nodes": [...]})4. Use Descriptive Node IDs
Create human-readable IDs that make graph debugging easier:
nodes=[
{"id": "customer_jane_smith", ...}, # Good
{"id": "cust_12345", ...} # Less readable
]5. Leverage Custom Schemas
Always provide a custom schema for domain-specific extraction:
memory_policy={
"mode": "auto",
"schema_id": "your_domain_schema" # Critical for accuracy
}6. Document Agent Learnings
Have agents document their successful workflows:
# Good practice: Agent documents what works
client.memory.add(
content="Workflow for handling X: step 1, step 2, step 3. Success rate: 90%",
metadata={"role": "assistant", "category": "learning"}
)Common Patterns
CRM Contact Tracking
response = client.memory.add(
content="Call with John at TechCorp - interested in Enterprise plan upgrade",
memory_policy={
"mode": "auto",
"schema_id": "crm_schema",
"node_constraints": [
{
"node_type": "Contact",
"search": {
"properties": [{"name": "name", "mode": "semantic"}]
},
"set": {
"company": {"mode": "exact", "value": "TechCorp"},
"interest_level": {"mode": "exact", "value": "high"}
}
}
]
}
)E-commerce Order
response = client.memory.add(
content="Order #12345 from Jane Doe: 2x Widget Pro ($299 each)",
memory_policy={
"mode": "manual",
"nodes": [
{
"id": "order_12345",
"type": "Order",
"properties": {"order_id": "12345", "total": 598}
},
{
"id": "customer_jane_doe",
"type": "Customer",
"properties": {"name": "Jane Doe"}
},
{
"id": "product_widget_pro",
"type": "Product",
"properties": {"name": "Widget Pro", "price": 299}
}
],
"relationships": [
{
"source": "customer_jane_doe",
"target": "order_12345",
"type": "PLACED"
},
{
"source": "order_12345",
"target": "product_widget_pro",
"type": "CONTAINS",
"properties": {"quantity": 2}
}
]
}
)Project Management
response = client.memory.add(
content="New task: Implement user authentication. Assigned to: Alex. Due: 2024-04-15",
memory_policy={
"mode": "auto",
"schema_id": "project_schema",
"node_constraints": [
{
"node_type": "Task",
"set": {
"status": {"mode": "exact", "value": "open"},
"priority": {"mode": "exact", "value": "high"},
"project_id": {"mode": "exact", "value": "proj_auth"}
}
}
]
}
)Troubleshooting
Entities Not Being Extracted
- Check if custom schema is properly defined
- Verify property descriptions are clear and LLM-friendly
- Try manual mode to see if schema validation passes
- Review required properties - may be too strict
Duplicate Entities Created
- Use property overrides with consistent IDs
- Check unique_identifiers in schema definition
- Consider using enums for exact matching on key fields
Relationships Not Forming
- Verify relationship types are defined in schema
- Check allowed_source_types and allowed_target_types
- Ensure entities are created before relationships reference them
Graph Structure Inconsistent
- Enable simple_schema_mode for consistency
- Use same schema_id across related operations
- Add property overrides for key entities
Migration from graph_generation
The graph_generation field has been replaced with memory_policy for better clarity and expanded functionality.
Key Changes
Old (deprecated but still supported):
graph_generation={
"mode": "auto",
"auto": {
"schema_id": "my_schema",
"simple_schema_mode": True,
"property_overrides": [...]
}
}New (recommended):
memory_policy={
"mode": "auto",
"schema_id": "my_schema",
"node_constraints": [...] # Replaces property_overrides with more control
}What Changed
- Top-level field:
graph_generation→memory_policy - Flatter structure: Properties moved from
auto/manualsub-objects to top level - Node labels:
label→typein manual mode nodes - Relationships: Simplified field names (
source_node_id→source, etc.) - Property overrides: Replaced with more powerful
node_constraintsandedge_constraints - Simple schema mode: Removed - use
schema_idinstead
Migration Steps
- Replace
graph_generationwithmemory_policy - Move properties from
autoormanualsub-objects to top level - Update
property_overridestonode_constraints(see examples above) - Update node
labeltotypein manual mode - Update relationship field names if using manual mode
Backward Compatibility
The graph_generation field still works but is deprecated. We recommend migrating to memory_policy for:
- Better clarity on what the field controls
- Access to new constraint features
- Future-proofing your code
- Unified policy structure (includes ACL, consent, risk)
Next Steps
- Custom Schemas - Define domain ontologies
- GraphQL Analysis - Query your knowledge graph
- Document Processing - Extract from documents
- API Reference - Complete endpoint documentation