Skill: agenticio/insurance (version 2.2.0)

--- name: insurance description: Local-first insurance record organizer for tracking policies, renewals, claims logs, and related insurance records. Use when the user wants to store policy details, list recorded policies, track renewal dates, log claim events, or summarize insurance records. NEVER provides insurance advice, recommends coverage amounts, or facilitates policy purchases. --- # Insurance Local-first insurance record manager. Track what is already on file, keep dates organized, and log claim-related events. ## Critical Privacy & Safety ### Data Storage (CRITICAL) - **All insurance records stored locally only** under `memory/insurance/` - **No external APIs** for insurance data - **No connection** to insurance company systems - **No policy purchases** through this skill - User controls all data retention and deletion ### Safety Boundaries (NON-NEGOTIABLE) - ✅ Track recorded policy details - ✅ Log claims and incident records - ✅ Summarize stored premiums, renewals, and policy counts - ✅ Highlight missing or untracked policy categories in the user's stored records - ❌ **NEVER provide insurance advice** - ❌ **NEVER recommend specific coverage amounts** - ❌ **NEVER tell the user what insurance they should buy** - ❌ **NEVER replace** a licensed insurance agent, broker, or attorney - ❌ **NEVER facilitate policy purchases** ### Legal Disclaimer Insurance decisions depend on individual circumstances, jurisdiction, and exact policy language. This skill is only for organizing and reviewing stored insurance records. Missing categories in stored records do not imply the user needs additional insurance. For coverage decisions or legal interpretation, consult a licensed insurance professional. ## Data Files This skill stores local JSON files in: - `memory/insurance/policies.json` - `memory/insurance/claims.json` Additional files may be added later as the skill expands. ## Core Workflows ### Add Policy Record User: "Add my home insurance policy" → Use `scripts/add_policy.py` → Store the policy details locally ### List Recorded Policies User: "Show my insurance policies" → Use `scripts/list_policies.py` → Show all policies already stored in local records ### Check Upcoming Renewals User: "Any insurance renewals coming up?" → Use `scripts/check_renewals.py --days 60` → Show policies in local records renewing soon ### Generate Summary User: "Summarize my insurance records" → Use `scripts/generate_summary.py` → Show totals by type, total annual premium, and upcoming renewals ### Log Claim Event User: "Log a claim for my auto policy" → Use `scripts/log_claim.py` → Store claim-related event details locally ## Scripts Reference | Script | Purpose | |--------|---------| | `add_policy.py` | Add a new policy record | | `list_policies.py` | List all stored policies | | `check_renewals.py` | Find policies renewing soon | | `generate_summary.py` | Summarize stored policy records | | `log_claim.py` | Log a claim or incident record | ## Disclaimer This skill is for local insurance record organization only. It does not provide insurance advice, recommend coverage levels, interpret legal policy obligations, or replace licensed professionals.

path: scripts/add_policy.py
content: #!/usr/bin/env python3
"""Add insurance policy."""
import argparse
import uuid
from datetime import datetime

from lib.output import error, ok
from lib.schema import (
    DEFAULT_POLICIES,
    non_negative_amount,
    normalize_policy_type,
    parse_json_object,
    validate_date,
)
from lib.storage import load_json, save_json


def main() -> None:
    parser = argparse.ArgumentParser(description="Add insurance policy")
    parser.add_argument("--type", required=True, help="Policy type")
    parser.add_argument("--carrier", required=True, help="Insurance company")
    parser.add_argument("--premium", type=float, required=True, help="Annual premium")
    parser.add_argument("--renewal", default="", help="Renewal date (YYYY-MM-DD)")
    parser.add_argument("--effective-date", default="", help="Effective date (YYYY-MM-DD)")
    parser.add_argument("--expiration-date", default="", help="Expiration date (YYYY-MM-DD)")
    parser.add_argument("--policy-number", default="", help="Policy number")
    parser.add_argument("--insured-name", default="", help="Insured person or entity")
    parser.add_argument("--notes", default="", help="Free-form notes")
    parser.add_argument(
        "--coverage-limits",
        default="{}",
        help='JSON object of coverage limits, e.g. {"liability":300000}',
    )
    parser.add_argument(
        "--deductibles",
        default="{}",
        help='JSON object of deductibles, e.g. {"collision":500}',
    )

    args = parser.parse_args()

    try:
        policy_type = normalize_policy_type(args.type)
        carrier = args.carrier.strip()
        if not carrier:
            raise ValueError("carrier is required.")

        premium = non_negative_amount(args.premium, "premium")
        renewal_date = validate_date(args.renewal, "renewal")
        effective_date = validate_date(args.effective_date, "effective-date")
        expiration_date = validate_date(args.expiration_date, "expiration-date")
        coverage_limits = parse_json_object(args.coverage_limits, "coverage-limits")
        deductibles = parse_json_object(args.deductibles, "deductibles")
    except ValueError as exc:
        error(str(exc))
        return

    data = load_json("policies.json", DEFAULT_POLICIES)

    policy_id = f"POL-{str(uuid.uuid4())[:6].upper()}"
    now = datetime.now().isoformat()

    policy = {
        "id": policy_id,
        "type": policy_type,
        "carrier": carrier,
        "policy_number": args.policy_number.strip(),
        "insured_name": args.insured_name.strip(),
        "premium": premium,
        "effective_date": effective_date,
        "renewal_date": renewal_date,
        "expiration_date": expiration_date,
        "coverage_limits": coverage_limits,
        "deductibles": deductibles,
        "notes": args.notes.strip(),
        "added_at": now,
        "updated_at": now,
    }

    data["policies"].append(policy)
    save_json("policies.json", data)

    ok(
        "Policy added successfully.",
        {
            "policy_id": policy_id,
            "type": policy_type,
            "carrier": carrier,
            "premium": premium,
            "renewal_date": renewal_date,
        },
    )


if __name__ == "__main__":
    main()


path: scripts/check_renewals.py
content: #!/usr/bin/env python3
"""Check upcoming policy renewals."""
import argparse
from datetime import datetime, timedelta

from lib.output import ok, error
from lib.schema import DEFAULT_POLICIES
from lib.storage import load_json


def main() -> None:
    parser = argparse.ArgumentParser(description="Check upcoming renewals")
    parser.add_argument("--days", type=int, default=60, help="Look-ahead window in days")
    args = parser.parse_args()

    if args.days < 0:
        error("days must be non-negative.")
        return

    data = load_json("policies.json", DEFAULT_POLICIES)
    policies = data.get("policies", [])

    today = datetime.today().date()
    end_date = today + timedelta(days=args.days)

    upcoming = []
    for policy in policies:
        renewal = policy.get("renewal_date", "")
        if not renewal:
            continue
        try:
            renewal_date = datetime.strptime(renewal, "%Y-%m-%d").date()
        except ValueError:
            continue

        if today <= renewal_date <= end_date:
            upcoming.append(
                {
                    "id": policy.get("id", ""),
                    "type": policy.get("type", ""),
                    "carrier": policy.get("carrier", ""),
                    "renewal_date": renewal,
                    "days_until": (renewal_date - today).days,
                }
            )

    ok(
        "Renewal check completed.",
        {
            "days_checked": args.days,
            "count": len(upcoming),
            "renewals": sorted(upcoming, key=lambda x: x["renewal_date"]),
        },
    )


if __name__ == "__main__":
    main()


path: scripts/generate_summary.py
content: #!/usr/bin/env python3
"""Generate insurance portfolio summary."""
from collections import Counter

from lib.output import ok
from lib.schema import DEFAULT_POLICIES
from lib.storage import load_json


def main() -> None:
    data = load_json("policies.json", DEFAULT_POLICIES)
    policies = data.get("policies", [])

    total_annual_premium = sum(float(p.get("premium", 0) or 0) for p in policies)
    by_type = Counter(p.get("type", "unknown") for p in policies)

    ok(
        "Insurance summary generated.",
        {
            "total_policies": len(policies),
            "total_annual_premium": round(total_annual_premium, 2),
            "policies_by_type": dict(by_type),
        },
    )


if __name__ == "__main__":
    main()


path: scripts/lib/__init__.py
content: """Shared helpers for the insurance skill."""


path: scripts/lib/output.py
content: #!/usr/bin/env python3
"""Standardized output helpers for the insurance skill."""
import json
from datetime import datetime
from typing import Optional


def ok(message: str, data: Optional[dict] = None) -> None:
    payload = {
        "status": "ok",
        "message": message,
        "timestamp": datetime.now().isoformat(),
        "data": data or {},
    }
    print(json.dumps(payload, ensure_ascii=False, indent=2))


def error(message: str, data: Optional[dict] = None) -> None:
    payload = {
        "status": "error",
        "message": message,
        "timestamp": datetime.now().isoformat(),
        "data": data or {},
    }
    print(json.dumps(payload, ensure_ascii=False, indent=2))


path: scripts/lib/schema.py
content: #!/usr/bin/env python3
"""Schema and validation helpers for the insurance skill."""
import json
from datetime import datetime

ALLOWED_POLICY_TYPES = {
    "health",
    "home",
    "renters",
    "auto",
    "life",
    "umbrella",
    "business",
}

DEFAULT_POLICIES = {"policies": []}
DEFAULT_CLAIMS = {"claims": []}


def parse_json_object(raw: str, field_name: str) -> dict:
    try:
        value = json.loads(raw)
    except json.JSONDecodeError as exc:
        raise ValueError(f"{field_name} must be valid JSON.") from exc

    if not isinstance(value, dict):
        raise ValueError(f"{field_name} must be a JSON object.")
    return value


def validate_date(date_str: str, field_name: str) -> str:
    if not date_str:
        return date_str
    try:
        datetime.strptime(date_str, "%Y-%m-%d")
    except ValueError as exc:
        raise ValueError(f"{field_name} must be in YYYY-MM-DD format.") from exc
    return date_str


def normalize_policy_type(policy_type: str) -> str:
    value = policy_type.strip().lower()
    if value not in ALLOWED_POLICY_TYPES:
        allowed = ", ".join(sorted(ALLOWED_POLICY_TYPES))
        raise ValueError(f"Invalid policy type '{policy_type}'. Allowed: {allowed}")
    return value


def non_negative_amount(value: float, field_name: str) -> float:
    if value < 0:
        raise ValueError(f"{field_name} must be non-negative.")
    return value


path: scripts/lib/storage.py
content: #!/usr/bin/env python3
"""Storage helpers for the insurance skill."""
import json
import os
import shutil
from datetime import datetime

WORKSPACE_ROOT = os.environ.get(
    "WORKSPACE_ROOT",
    os.path.expanduser("~/.openclaw/workspace"),
)
INSURANCE_DIR = os.path.join(WORKSPACE_ROOT, "memory", "insurance")


def ensure_dir() -> None:
    os.makedirs(INSURANCE_DIR, exist_ok=True)


def _path(filename: str) -> str:
    return os.path.join(INSURANCE_DIR, filename)


def load_json(filename: str, default: dict) -> dict:
    ensure_dir()
    filepath = _path(filename)

    if not os.path.exists(filepath):
        return default

    try:
        with open(filepath, "r", encoding="utf-8") as f:
            return json.load(f)
    except json.JSONDecodeError:
        timestamp = datetime.now().strftime("%Y%m%dT%H%M%S")
        corrupt_backup = f"{filepath}.corrupt.{timestamp}.bak"
        shutil.copy(filepath, corrupt_backup)
        return default


def save_json(filename: str, data: dict) -> None:
    ensure_dir()
    filepath = _path(filename)
    with open(filepath, "w", encoding="utf-8") as f:
        json.dump(data, f, indent=2, ensure_ascii=False)


path: scripts/list_policies.py
content: #!/usr/bin/env python3
"""List stored insurance policies."""
from lib.output import ok
from lib.schema import DEFAULT_POLICIES
from lib.storage import load_json


def main() -> None:
    data = load_json("policies.json", DEFAULT_POLICIES)
    policies = data.get("policies", [])

    simplified = [
        {
            "id": p.get("id", ""),
            "type": p.get("type", ""),
            "carrier": p.get("carrier", ""),
            "premium": p.get("premium", 0),
            "renewal_date": p.get("renewal_date", ""),
        }
        for p in policies
    ]

    ok(
        "Policies loaded.",
        {
            "count": len(simplified),
            "policies": simplified,
        },
    )


if __name__ == "__main__":
    main()


path: scripts/log_claim.py
content: #!/usr/bin/env python3
"""Log an insurance claim or incident record."""
import argparse
import uuid
from datetime import datetime

from lib.output import error, ok
from lib.schema import DEFAULT_CLAIMS, validate_date
from lib.storage import load_json, save_json


def main() -> None:
    parser = argparse.ArgumentParser(description="Log claim or incident")
    parser.add_argument("--policy-id", required=True, help="Policy ID related to the claim")
    parser.add_argument("--incident", required=True, help="Incident type or short description")
    parser.add_argument("--date", required=True, help="Incident date (YYYY-MM-DD)")
    parser.add_argument("--status", default="logged", help="Claim status")
    parser.add_argument("--notes", default="", help="Additional notes")

    args = parser.parse_args()

    try:
        incident_date = validate_date(args.date, "date")
    except ValueError as exc:
        error(str(exc))
        return

    data = load_json("claims.json", DEFAULT_CLAIMS)
    claim_id = f"CLM-{str(uuid.uuid4())[:6].upper()}"

    claim = {
        "id": claim_id,
        "policy_id": args.policy_id.strip(),
        "incident": args.incident.strip(),
        "incident_date": incident_date,
        "status": args.status.strip() or "logged",
        "notes": args.notes.strip(),
        "logged_at": datetime.now().isoformat(),
    }

    data["claims"].append(claim)
    save_json("claims.json", data)

    ok(
        "Claim event logged successfully.",
        {
            "claim_id": claim_id,
            "policy_id": claim["policy_id"],
            "incident_date": incident_date,
            "status": claim["status"],
        },
    )


if __name__ == "__main__":
    main()


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)