AivoClaw obsidian-ontology-sync
Bidirectional sync between Obsidian PKM (human-friendly notes) and structured ontology (machine-queryable graph). Automatically extracts entities and relationships from markdown, maintains ontology graph, and provides feedback to improve note structure. Run sync every few hours via cron.
git clone https://github.com/yuanyuekejiJN/AivoClaw
T=$(mktemp -d) && git clone --depth=1 https://github.com/yuanyuekejiJN/AivoClaw "$T" && mkdir -p ~/.claude/skills && cp -r "$T/extraSkills/obsidian-ontology-sync-1.0.1" ~/.claude/skills/yuanyuekejijn-aivoclaw-obsidian-ontology-sync && rm -rf "$T"
extraSkills/obsidian-ontology-sync-1.0.1/SKILL.mdObsidian-Ontology Sync
Philosophy: Obsidian is PRIMARY (human writes natural notes) → Ontology is DERIVED (machine extracts structure) → Feedback loop improves both
Core Concept
Obsidian Notes (Markdown) ↓ Extract (every 3 hours) Ontology Graph (Structured) ↓ Query & Analyze Insights & Suggestions ↓ Feedback Improved Note Templates
When to Use
| Situation | Action |
|---|---|
| After creating/updating contacts | Run sync to extract entities |
| Before business queries | Sync then query ontology |
| Weekly review | Sync + analyze + get suggestions |
| New project setup | Extract entities + suggest structure |
| Team status tracking | Sync daily-status → ontology → analytics |
What Gets Extracted
From Contact Notes (references/contacts/*.md
)
references/contacts/*.mdExtracts:
entity (name, email, phone)Person
→works_atOrganization
→met_atEvent
→assigned_to
(if mentioned)Project
→ (prospect, warm_lead, client, etc.)status
Example:
# Alice Johnson **Email:** alice@company.com **Company:** Acme Corp **Met At:** Tech Conference 2026 **Projects:** Project Alpha ## Notes Great developer, responsive communication.
Becomes:
{ "entity": { "id": "person_alice_johnson", "type": "Person", "properties": { "name": "Alice Johnson", "email": "alice@company.com", "notes": "Great developer, responsive communication" } }, "relations": [ {"from": "person_alice_johnson", "rel": "works_at", "to": "org_acme"}, {"from": "person_alice_johnson", "rel": "met_at", "to": "event_tech_conference_2026"}, {"from": "person_alice_johnson", "rel": "assigned_to", "to": "project_alpha"} ] }
From Client Notes (references/clients/*.md
)
references/clients/*.mdExtracts:
entityOrganization
→ numberhas_contract_value
→projects
entitiesProject
→primary_contactPerson
From Team Notes (references/team/*.md
)
references/team/*.mdExtracts:
entityPerson
→works_forOrganization
→assigned_toProject[]
→reports_toPerson
→ (proactive, reactive, non-responsive)response_pattern
From Daily Status (daily-status/YYYY-MM-DD/*.md
)
daily-status/YYYY-MM-DD/*.mdExtracts:
property on Personresponse_time
→status_updateEvent
→blockers
entitiesIssue
trackingbehavioral_pattern
From Project Notes (projects/*.md
)
projects/*.mdExtracts:
entityProject
→for_clientOrganization
→teamPerson[]
,status
,valuedeadline
Sync Process
1. Extract Phase (Markdown → Ontology)
# Run extraction python3 skills/obsidian-ontology-sync/scripts/sync.py extract # What it does: # 1. Scan configured Obsidian directories # 2. Parse markdown frontmatter + content # 3. Extract entities (Person, Project, Organization, etc.) # 4. Extract relationships (works_at, assigned_to, etc.) # 5. Write to ontology using append-only operations
Detection Rules:
# Contact files if file.startswith("references/contacts/"): entity_type = "Person" extract_email_from_content() extract_company_from_property("Company:") extract_projects_from_links([[Project]]) # Client files if file.startswith("references/clients/"): entity_type = "Organization" extract_contract_value() extract_projects() # Team files if file.startswith("references/team/"): entity_type = "Person" role = "team_member" extract_assignments() extract_response_patterns()
2. Analysis Phase (Ontology → Insights)
# Run analytics python3 skills/obsidian-ontology-sync/scripts/sync.py analyze # Generates insights like: # - "3 team members have no assigned projects" # - "Contact 'John Doe' missing email address" # - "Project 'X' has 5 people but no client linked" # - "10 contacts from AI Summit not linked to follow-up tasks"
3. Feedback Phase (Insights → Improve PKM)
# Get suggestions python3 skills/obsidian-ontology-sync/scripts/sync.py feedback # Creates: # - Missing property suggestions # - Broken link reports # - Relationship suggestions # - Template improvements
Example Feedback:
# Sync Feedback - 2026-02-27 ## Missing Information (10 items) - [ ] `Alice Johnson` missing phone number - [ ] `Bob` missing email in team file - [ ] Project `Project Alpha` missing deadline ## Suggested Links (5 items) - [ ] Link `Jane Doe` (TechHub) to organization `TechHub` - [ ] Link `Eve` to project (found in daily-status but not in team file) ## Relationship Insights - `Project Alpha` team: Alice, Carol, David (extracted from daily-status) - Suggest updating project file with team assignments ## Template Suggestions - Add `Projects: [[]]` field to contact template - Add `Response Pattern:` field to team template
Configuration
config.yaml
# /root/life/pkm/ontology-sync/config.yaml obsidian: vault_path: /root/life/pkm # What to sync sources: contacts: path: references/contacts entity_type: Person extract: - email_from_content - company_from_property - projects_from_links clients: path: references/clients entity_type: Organization extract: - contract_value - projects - contacts team: path: references/team entity_type: Person role: team_member extract: - assignments - response_patterns - reports_to daily_status: path: daily-status extract: - response_times - behavioral_patterns - blockers ontology: storage_path: /root/life/pkm/memory/ontology format: jsonl # or sqlite for scale # Entity types to track entities: - Person - Organization - Project - Event - Task # Relationships to extract relationships: - works_at - assigned_to - met_at - for_client - reports_to - has_task - blocks feedback: output_path: /root/life/pkm/ontology-sync/feedback generate_reports: true suggest_templates: true highlight_missing: true schedule: # Run via cron every 3 hours sync_interval: "0 */3 * * *" analyze_daily: "0 9 * * *" # 9 AM daily feedback_weekly: "0 10 * * MON" # Monday 10 AM
Scheduled Sync (Cron Integration)
Setup Automatic Sync
# Add to OpenClaw cron python3 skills/obsidian-ontology-sync/scripts/setup-cron.py # Or manually via cron tool cron add \ --schedule "0 */3 * * *" \ --task "python3 skills/obsidian-ontology-sync/scripts/sync.py extract" \ --label "Obsidian → Ontology Sync"
Cron Jobs Created:
- Every 3 hours: Extract entities from Obsidian → Update ontology
- Daily 9 AM: Run analytics and generate insights
- Weekly Monday 10 AM: Generate feedback report + template suggestions
Queries (Using Ontology)
Once synced, you can query:
# All team members on high-value projects python3 skills/ontology/scripts/ontology.py query \ --type Person \ --where '{"role":"team_member"}' \ --related assigned_to \ --filter '{"type":"Project","value__gt":400000}' # Contacts from specific event not yet followed up python3 skills/ontology/scripts/ontology.py query \ --type Person \ --where '{"met_at":"event_tech_conference_2026"}' \ --missing has_task # Team response patterns python3 skills/ontology/scripts/ontology.py query \ --type Person \ --where '{"role":"team_member"}' \ --aggregate response_pattern # Projects by client python3 skills/ontology/scripts/ontology.py query \ --type Project \ --group-by for_client \ --count
Feedback Loop Examples
Example 1: Missing Email Detection
Ontology finds: Person entity with no email property
Feedback generated:
## Missing Contact Information The following team members are missing email addresses: - [ ] Bob (`references/team/Bob.md`) - [ ] Lucky (`references/team/Lucky.md`) **Suggestion:** Add email field to team member template: \`\`\`markdown **Email:** \`\`\`
Example 2: Broken Project Links
Ontology finds: Person assigned_to Project that doesn't exist
Feedback generated:
## Broken Project References Found references to projects that don't have dedicated files: - [ ] "Project Epsilon" mentioned in team files but no `projects/Project Epsilon.md` - [ ] "Project Delta Tata DT" assigned but no project file **Suggestion:** Create project files with template
Example 3: Relationship Discovery
Ontology finds: Multiple people working at same company
Feedback generated:
## Suggested Company Grouping Found 3 contacts at "TechHub": - Jane Doe - [2 others from daily-status mentions] **Suggestion:** Create `references/clients/TechHub.md` and link contacts
Integration with Daily Workflow
Morning Routine (9 AM)
# Cron runs analysis # Generates daily-insights.md with: - Response rate from yesterday's status requests - Projects needing attention (blockers mentioned) - Contacts to follow up (met > 3 days ago, no task)
Weekly Review (Monday 10 AM)
# Cron generates weekly feedback # Creates suggestions for: - Missing information to fill in - Broken links to fix - New templates to adopt - Relationship insights
On-Demand Queries
# Before a meeting "Show me all interactions with Client X" # Resource planning "Which team members are on <3 projects?" # Sales pipeline "Contacts met at conferences in last 30 days without follow-up"
Benefits
✅ For You
- Zero Extra Work: Just keep writing normal Obsidian notes
- Automatic Structure: Ontology extracted automatically
- Powerful Queries: Find patterns across all your data
- Quality Improvement: Feedback loop catches missing info
- No Double Entry: Single source of truth (Obsidian)
✅ For Team Management
- Track who's on which project (auto-extracted)
- Monitor response patterns (from daily-status)
- Identify unbalanced workloads
- Find blockers across projects
✅ For Sales/BD
- Track contact network (who you met, where, when)
- Follow-up reminders (contacted >7 days ago)
- Relationship mapping (who knows who)
- Pipeline insights (prospects → warm → clients)
✅ For Finance
- Project valuations (extracted from client notes)
- Team cost allocation (people → projects → revenue)
- Revenue forecasting (active projects × value)
File Structure After Sync
/root/life/pkm/ ├── references/ │ ├── contacts/ # Source notes (you write these) │ ├── clients/ # Source notes │ └── team/ # Source notes ├── daily-status/ # Source notes ├── projects/ # Source notes │ ├── memory/ontology/ # Generated ontology │ ├── graph.jsonl # Entity/relation storage │ └── schema.yaml # Type definitions │ └── ontology-sync/ # Sync outputs ├── config.yaml # Your config ├── feedback/ │ ├── daily-insights.md │ ├── weekly-feedback.md │ └── suggestions.md └── logs/ └── sync-YYYY-MM-DD.log
Advanced: Bidirectional Sync
Future capability:
Update Obsidian notes FROM ontology insights:
# Automatically add missing fields python3 skills/obsidian-ontology-sync/scripts/sync.py apply-feedback # What it does: # - Adds missing email field to contact notes # - Creates suggested project files # - Links related entities # - Updates frontmatter
Safety: Always creates backup before modifying files.
Comparison with Alternatives
| Approach | Pros | Cons |
|---|---|---|
| Manual ontology | Full control | Too much work, falls behind |
| Obsidian only | Simple | No structured queries |
| Ontology only | Powerful queries | Not human-friendly |
| This skill | Best of both | Initial setup needed |
Getting Started
1. Install Dependencies
# Already have ontology skill installed clawhub install obsidian # If not already installed
2. Create Config
python3 skills/obsidian-ontology-sync/scripts/init.py # Creates: # - config.yaml with your vault path # - ontology directory structure # - cron jobs
3. Run First Sync
# Manual first sync to test python3 skills/obsidian-ontology-sync/scripts/sync.py extract --dry-run # See what would be extracted # Review, then run for real: python3 skills/obsidian-ontology-sync/scripts/sync.py extract
4. Enable Automatic Sync
python3 skills/obsidian-ontology-sync/scripts/setup-cron.py # Confirms cron jobs: # ✓ Sync every 3 hours # ✓ Daily analysis at 9 AM # ✓ Weekly feedback Monday 10 AM
5. Query Your Data
# Try some queries python3 skills/obsidian-ontology-sync/scripts/query.py "team members on high value projects"
Troubleshooting
Extraction Issues
# Dry run to see what would be extracted python3 skills/obsidian-ontology-sync/scripts/sync.py extract --dry-run --verbose # Check specific file python3 skills/obsidian-ontology-sync/scripts/debug.py \ --file references/contacts/Alice.md
Query Not Finding Data
# Check what's in ontology python3 skills/ontology/scripts/ontology.py query --type Person # Verify sync ran cat /root/life/pkm/ontology-sync/logs/sync-latest.log
Feedback Not Generated
# Manually run analysis python3 skills/obsidian-ontology-sync/scripts/sync.py analyze python3 skills/obsidian-ontology-sync/scripts/sync.py feedback
Version History
- 1.0.0 (2026-02-27) - Initial version with extraction, analysis, feedback loop
Author: Built for team management, contact tracking, and business intelligence at scale License: MIT Tags: obsidian, ontology, knowledge-graph, pkm, automation, sync