# AGS Ontology & Data Layer Best Practices Guide
*A concise workflow for creating robust knowledge graphs from auto-ingested data sources*

## 🎯 Overview
This guide provides proven techniques for building ontologies and transformation layers in AGS (Anzo Graphmart Server) based on automatically ingested data sources (JSON, databases, Snowflake, etc.). Follow this workflow to rapidly create cross-domain linking ontologies with validated relationships.

---

## 🔄 Core Workflow

### Phase 1: Data Discovery & Analysis
**Goal**: Understand your data structure before creating ontologies

#### 1.1 Explore Available Data
```sparql
# Discover entity types and counts
SELECT ?type (COUNT(*) as ?count)
WHERE {
    ?entity a ?type .
    FILTER(STRSTARTS(STR(?type), "http://your-domain/ontologies/"))
}
GROUP BY ?type ORDER BY DESC(?count)
```

#### 1.2 Analyze Entity Properties
```sparql
# Find all properties for a specific class
SELECT DISTINCT ?property
WHERE {
    ?entity a domain:YourClass .
    ?entity ?property ?value .
    FILTER(STRSTARTS(STR(?property), "http://your-domain/ontologies/"))
}
ORDER BY ?property
```

#### 1.3 Sample Data Patterns
```sparql
# Examine actual data values to understand linking opportunities
SELECT ?entity ?property ?value
WHERE {
    ?entity a domain:YourClass .
    ?entity ?property ?value .
}
LIMIT 10
```

---

### Phase 2: Validate Potential Relationships
**Goal**: Test relationship feasibility before creating properties

#### 2.1 Test Cross-Domain Links with SELECT Queries
```sparql
# ALWAYS test linking logic first with SELECT
PREFIX domain1: <http://your-domain/ontologies/Domain1#>
PREFIX domain2: <http://your-domain/ontologies/Domain2#>

SELECT ?entity1 ?linkingValue ?entity2
WHERE {
    ?entity1 a domain1:SourceClass ;
        domain1:linkingProperty ?linkingValue .
    
    ?entity2 a domain2:TargetClass ;
        domain2:matchingProperty ?linkingValue .
}
LIMIT 10
```

**✅ Key Rule**: If your SELECT query returns 0 results, fix the linking logic before creating properties.

#### 2.2 Validate Domain/Range Classes
```sparql
# Verify classes exist in ontologies before using as domain/range
SELECT (COUNT(*) as ?instanceCount)
WHERE {
    ?entity a targetOntology:YourTargetClass .
}
```

---

### Phase 3: Create Minimal Linking Ontologies
**Goal**: Start small with focused, cross-domain linking ontologies

#### 3.1 Create Linking Ontology
```bash
# Use descriptive names like: DomainADomainB + "Linking"
mcp_ags-sparql-ag_create_ontology
- ontology_uri: "http://your-domain/ontologies/ERPLinking"
- ontology_label: "ERP Cross-Domain Linking"
- description: "Links ERP entities to other domain entities"
```

#### 3.2 **CRITICAL**: Register the Ontology
```bash
# ALWAYS register after creation - frequently forgotten step!
mcp_ags-sparql-ag_register_ontology
- ontology_uri: "http://your-domain/ontologies/ERPLinking"
- explanation: "Register ontology for discoverability"
```

#### 3.3 Add Object Properties Only
**Best Practice**: Start with object properties linking existing classes
```bash
mcp_ags-sparql-ag_add_ontology_property
- ontology_uri: "http://your-domain/ontologies/ERPLinking"
- property_uri: "http://your-domain/ontologies/ERPLinking#linksDomainAToB"
- property_type: "object"
- domain_uri: "http://your-domain/ontologies/DomainA#SourceClass"
- range_uri: "http://your-domain/ontologies/DomainB#TargetClass"
```

**⚠️ Avoid**: Creating new classes in linking ontologies - use existing ones

---

### Phase 4: Create Transformation Layers
**Goal**: Implement the validated relationships as transformation steps

#### 4.1 Create Transformation Layer
```bash
mcp_ags-sparql-ag_create_transformation_layer
- layer_name: "Domain Linking"
- layer_description: "Cross-domain relationship linking"
- order_after: "Domain Data"  # Put after data loading layers
```

#### 4.2 Add Transformation Steps
**Critical Pattern**: Use exact AGS template syntax
```sparql
PREFIX domain1: <http://your-domain/ontologies/Domain1#>
PREFIX domain2: <http://your-domain/ontologies/Domain2#>
PREFIX linking: <http://your-domain/ontologies/ERPLinking#>

INSERT {
    GRAPH ${targetGraph} {
        ?source linking:yourProperty ?target .
    }
}
${usingSources}
WHERE {
    # Use the exact WHERE clause from your validated SELECT query
    ?source a domain1:SourceClass ;
        domain1:linkingProperty ?linkingValue .
    
    ?target a domain2:TargetClass ;
        domain2:matchingProperty ?linkingValue .
}
```

**✅ Template Requirements**:
- `${targetGraph}` (single $, not $$)
- `${usingSources}` (single $, not $$)
- Use `\n` for line breaks (not `\\n`)

---

### Phase 5: Test & Iterate
**Goal**: Validate transformation results and expand incrementally

#### 5.1 Test Transformation Results
```sparql
# After layer execution, verify new relationships exist
SELECT (COUNT(*) as ?newLinks)
WHERE {
    ?source linking:yourProperty ?target .
}
```

#### 5.2 Incremental Expansion
- **Start**: 1-2 properties per linking ontology
- **Test**: Each property individually 
- **Expand**: Add more properties once working
- **Scale**: Multiple transformation steps per layer

---

## 🛠️ Advanced Patterns

### Multi-Hop Relationships
Build chains of relationships across domains:
```
Customer --[hasSalesOrder]--> SalesOrder 
    --[becomesInstalledEquipment]--> InstalledEquipment 
        --[implementsPLMSystem]--> PLM System
```

### Hierarchical BOM Linking
For complex product structures:
```sparql
# Level → Direct Components
?level plml:hasDirectComponent ?part .

# Level → Child Assemblies  
?parentLevel plml:hasChildAssembly ?childLevel .

# Inverse: Component → Parent Assembly
?part plml:isComponentOfAssembly ?level .
```

### Bridge Orphaned Classes
Connect isolated classes to main hierarchy:
```sparql
# Link alternative representations to primary structure
?subassembly plml:correspondsToBOMLevel ?bomLevel .
?subassembly plml:containsPart ?part .
```

---

## 🚨 Common Pitfalls & Solutions

| Problem | Solution |
|---------|----------|
| **0 results from linking queries** | Fix SELECT query logic before creating properties |
| **"Class not found" errors** | Verify domain/range classes exist with COUNT queries |
| **Orphaned ontologies** | Always register ontologies after creation |
| **Template syntax errors** | Use single `$`, `\n` line breaks, exact AGS format |
| **Complex queries fail** | Break into smaller, simpler transformation steps |
| **Mixed up domains/ranges** | Double-check which direction the relationship flows |

---

## 📊 Success Metrics

**Validation Checkpoints**:
- ✅ SELECT queries return expected results
- ✅ Domain/range classes have >0 instances  
- ✅ Properties appear in ontology structure lists
- ✅ Transformation steps execute without errors
- ✅ New relationships appear in result queries
- ✅ No orphaned classes in ontology viewer

**Performance Indicators**:
- **Rapid prototyping**: Validate relationships in minutes
- **Reliable execution**: Transformation steps run consistently  
- **Cross-domain navigation**: Multi-hop queries return results
- **Business value**: Enable impact analysis and traceability

---

## 🎯 Quick Reference Commands

```bash
# Discovery
mcp_ags-sparql-ag_list_available_ontologies
mcp_ags-sparql-ag_execute_sparql_query

# Creation
mcp_ags-sparql-ag_create_ontology
mcp_ags-sparql-ag_register_ontology  # DON'T FORGET!
mcp_ags-sparql-ag_add_ontology_property

# Layers
mcp_ags-sparql-ag_create_transformation_layer
mcp_ags-sparql-ag_add_transformation_step

# Validation  
mcp_ags-sparql-ag_list_transformation_steps
mcp_ags-sparql-ag_list_ontology_structure_properties
```

**Remember**: Always test with SELECT before implementing with INSERT! 🎯