Systems Library / Operations & Admin / How to Automate Contractor Agreement Management
Operations & Admin hr people

How to Automate Contractor Agreement Management

Manage contractor agreements with automated renewals and compliance tracking.

Jay Banlasan

Jay Banlasan

The AI Systems Guy

Contractor agreements expire, terms get forgotten, and compliance gaps appear when nobody tracks the paperwork. I built a system to automate contractor agreement management that monitors every contract, alerts you before renewals, and keeps a compliance checklist current.

This system tracks dates, terms, and status so nothing slips.

What You Need Before Starting

Step 1: Set Up the Agreement Database

import sqlite3

def init_agreements_db(db_path="contractors.db"):
    conn = sqlite3.connect(db_path)
    conn.execute("""
        CREATE TABLE IF NOT EXISTS agreements (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            contractor_name TEXT,
            contractor_email TEXT,
            company TEXT,
            agreement_type TEXT,
            start_date TEXT,
            end_date TEXT,
            auto_renew INTEGER DEFAULT 0,
            notice_days INTEGER DEFAULT 30,
            hourly_rate REAL,
            document_path TEXT,
            status TEXT DEFAULT 'active',
            compliance_status TEXT DEFAULT 'pending'
        )
    """)
    conn.execute("""
        CREATE TABLE IF NOT EXISTS compliance_items (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            agreement_id INTEGER,
            item_name TEXT,
            required INTEGER DEFAULT 1,
            completed INTEGER DEFAULT 0,
            completed_date TEXT,
            FOREIGN KEY (agreement_id) REFERENCES agreements(id)
        )
    """)
    conn.commit()
    return conn

Step 2: Add Agreements with Compliance Checklist

def add_agreement(conn, contractor_data):
    cursor = conn.execute(
        """INSERT INTO agreements
        (contractor_name, contractor_email, company, agreement_type,
         start_date, end_date, auto_renew, notice_days, hourly_rate, document_path)
        VALUES (?,?,?,?,?,?,?,?,?,?)""",
        (contractor_data["name"], contractor_data["email"], contractor_data["company"],
         contractor_data["type"], contractor_data["start"], contractor_data["end"],
         contractor_data.get("auto_renew", 0), contractor_data.get("notice_days", 30),
         contractor_data.get("rate", 0), contractor_data.get("doc_path", ""))
    )

    agreement_id = cursor.lastrowid
    compliance_items = ["NDA signed", "W-9 received", "Insurance verified",
                       "Background check", "IP assignment signed"]

    for item in compliance_items:
        conn.execute(
            "INSERT INTO compliance_items (agreement_id, item_name) VALUES (?,?)",
            (agreement_id, item)
        )
    conn.commit()
    return agreement_id

Step 3: Monitor Expiring Agreements

from datetime import datetime, timedelta

def check_expiring_agreements(conn, days_ahead=60):
    cutoff = (datetime.now() + timedelta(days=days_ahead)).strftime("%Y-%m-%d")
    today = datetime.now().strftime("%Y-%m-%d")

    expiring = conn.execute("""
        SELECT id, contractor_name, contractor_email, end_date, auto_renew, notice_days
        FROM agreements
        WHERE status = 'active' AND end_date BETWEEN ? AND ?
    """, (today, cutoff)).fetchall()

    alerts = []
    for row in expiring:
        end_date = datetime.strptime(row[3], "%Y-%m-%d")
        days_left = (end_date - datetime.now()).days
        notice_deadline = end_date - timedelta(days=row[5])

        alerts.append({
            "contractor": row[1],
            "email": row[2],
            "expires": row[3],
            "days_left": days_left,
            "auto_renew": bool(row[4]),
            "notice_deadline": notice_deadline.strftime("%Y-%m-%d"),
            "action_needed": "none" if row[4] else "renew_or_terminate"
        })

    return alerts

Step 4: Track Compliance Status

def compliance_report(conn):
    rows = conn.execute("""
        SELECT a.contractor_name, a.status,
               COUNT(c.id) as total_items,
               SUM(c.completed) as completed_items
        FROM agreements a
        LEFT JOIN compliance_items c ON a.id = c.agreement_id
        WHERE a.status = 'active'
        GROUP BY a.id
    """).fetchall()

    report = []
    for name, status, total, completed in rows:
        report.append({
            "contractor": name,
            "compliance_rate": round(completed/total*100) if total else 0,
            "missing_items": total - completed,
            "status": "compliant" if completed == total else "incomplete"
        })

    return report

Step 5: Automate Renewal Notifications

def run_daily_check(conn):
    alerts = check_expiring_agreements(conn, days_ahead=60)
    compliance = compliance_report(conn)

    for alert in alerts:
        if alert["days_left"] <= 30:
            print(f"URGENT: {alert['contractor']} expires in {alert['days_left']} days")
        elif alert["days_left"] <= 60:
            print(f"UPCOMING: {alert['contractor']} expires in {alert['days_left']} days")

    for item in compliance:
        if item["status"] == "incomplete":
            print(f"COMPLIANCE GAP: {item['contractor']} missing {item['missing_items']} items")

What to Build Next

Add document generation so renewal agreements pre-populate from the existing terms. Connect to DocuSign or HelloSign for automated signature collection. The tracking is foundation. Automated renewals are the next level.

Related Reading

Want this system built for your business?

Get a free assessment. We will map every system your business needs and show you the ROI.

Get Your Free Assessment

Related Systems