DEV Community

Domonique Luchin
Domonique Luchin

Posted on

Building a royalty acquisition pipeline for oil and gas with AI agents

I've spent 6 years designing structural systems for oil and gas facilities. Pipe racks, equipment platforms, compressor stations. You learn to spot patterns in the industry data.

Last year I started Load Bearing Empire to apply that pattern recognition to royalty acquisitions. Instead of building platforms, I'm building pipelines that find undervalued mineral rights.

The problem with traditional royalty hunting

Most investors rely on brokers or cold calling landowners. You're competing with everyone else for the same deals. The good opportunities get bid up fast.

I wanted first access to properties before they hit the market. That meant monitoring public records, permit databases, and production reports across multiple states. Doing this manually would take 40+ hours per week.

My AI agent architecture

I built a system of specialized agents that work together on a single Vultr VPS. Each agent handles one piece of the acquisition process:

  • Scout Agent: Monitors new drilling permits and lease filings
  • Analyst Agent: Evaluates production data and calculates fair market values
  • Outreach Agent: Contacts property owners through voice calls and SMS
  • Deal Agent: Manages negotiations and document review

The agents communicate through a shared Supabase database. LangGraph orchestrates the workflows between them.

Scout Agent implementation

The Scout Agent checks 3 data sources every morning:

import requests
import asyncio
from supabase import create_client

class ScoutAgent:
    def __init__(self):
        self.supabase = create_client(SUPABASE_URL, SUPABASE_KEY)

    async def check_new_permits(self):
        # Texas RRC API
        permits = await self.fetch_rrc_permits()
        # Oklahoma Corporation Commission
        permits.extend(await self.fetch_occ_permits())
        # North Dakota Industrial Commission  
        permits.extend(await self.fetch_ndic_permits())

        for permit in permits:
            if self.meets_criteria(permit):
                await self.save_lead(permit)

    def meets_criteria(self, permit):
        return (permit['operator_tier'] in ['tier_1', 'tier_2'] and
                permit['formation'] in ['Eagle Ford', 'Permian', 'Bakken'] and
                permit['estimated_reserves'] > 100000)
Enter fullscreen mode Exit fullscreen mode

The Scout Agent found 847 new permits last month. 23 met my screening criteria.

Production analysis with the Analyst Agent

When the Scout Agent flags a property, the Analyst Agent pulls historical production data and runs a DCF model:

def calculate_npv(self, well_data):
    monthly_production = well_data['oil_bbls']
    gas_production = well_data['gas_mcf']

    # Apply decline curve analysis
    decline_rate = self.estimate_decline(monthly_production)
    oil_price = 75  # Current WTI assumption
    gas_price = 3.2  # Henry Hub assumption

    cash_flows = []
    for month in range(240):  # 20 year projection
        oil_vol = monthly_production[0] * (1 - decline_rate) ** month
        gas_vol = gas_production[0] * (1 - decline_rate) ** month

        revenue = (oil_vol * oil_price) + (gas_vol * gas_price)
        royalty_payment = revenue * 0.125  # 1/8 royalty
        cash_flows.append(royalty_payment)

    return self.npv(cash_flows, discount_rate=0.10)
Enter fullscreen mode Exit fullscreen mode

The Analyst Agent valued 18 properties last month. Average NPV was $340,000 per mineral acre.

Automated outreach that works

Here's where most people mess up. They send generic emails that get ignored. I use VAPI voice agents running on my self-hosted Asterisk PBX.

The Outreach Agent makes actual phone calls:

class OutreachAgent:
    def __init__(self):
        self.vapi_client = VAPIClient(api_key=VAPI_KEY)
        self.supabase = create_client(SUPABASE_URL, SUPABASE_KEY)

    async def contact_owner(self, property_record):
        call_script = self.generate_script(property_record)

        response = await self.vapi_client.create_call({
            'phone_number': property_record['owner_phone'],
            'assistant_id': 'mineral_rights_assistant',
            'script_variables': {
                'owner_name': property_record['owner_name'],
                'property_description': property_record['legal_description'],
                'offer_range': f"${property_record['min_offer']} to ${property_record['max_offer']}"
            }
        })

        await self.log_interaction(property_record['id'], response)
Enter fullscreen mode Exit fullscreen mode

The voice agent handles initial conversations. If the owner shows interest, it schedules a follow-up call with me.

Response rate: 12% compared to 1-2% for cold emails.

Results after 8 months

Metric Value
Properties analyzed 847
Qualified leads 156
Owner contacts made 156
Interested responses 19
Deals closed 3
Total acquisition cost $2.1M
Projected 20-year NPV $4.8M

The system runs entirely on a $80/month Vultr VPS. No expensive SaaS subscriptions.

What you can build

You don't need oil and gas experience to use this approach. The same pattern works for:

  • Distressed property acquisitions
  • Commercial real estate deals
  • Land development opportunities
  • Tax lien investments

The key is finding public data sources in your market and building agents that monitor them consistently.

Start with one data source and one agent. Add complexity as you prove the concept works.

You can find the code examples and setup guides at loadbearingempire.com. I'm also building out tutorials for different real estate verticals.

What deals are you missing because you're not monitoring the right data sources?

Top comments (0)