<!-- AUTO-GENERATED by export-skills.py — DO NOT EDIT -->
---
name: core-insurance-integration
description: Core insurance system integration patterns for AI agents connecting to Guidewire InsuranceSuite and Duck Creek Technologies. Use when building agents that interact with policy admin, claims, billing, or underwriting APIs.
---

> **Platform Note:** This skill was designed for multi-agent execution. In Codex, treat sub-agent instructions as sequential steps to complete thoroughly within a single agent context.

# Core Insurance System Integration

Connect AI agents to core insurance platforms (Guidewire InsuranceSuite, Duck Creek Technologies) for policy administration, claims processing, billing, and underwriting workflows.

## When to Use

- Building AI agents that query or manage insurance policies, claims, and billing
- Integrating with Guidewire Cloud (PolicyCenter, ClaimCenter, BillingCenter) via REST APIs
- Integrating with Duck Creek OnDemand (Policy, Claims, Billing) via REST APIs
- Automating underwriting, FNOL intake, or claims adjudication with AI-assisted decisioning

## Platform Comparison

| Platform | Architecture | API Style | Strength |
|---|---|---|---|
| **Guidewire InsuranceSuite** | Cloud-native (Guidewire Cloud) | REST + Cloud API | Market leader (P&C), 500+ insurers |
| **Duck Creek Technologies** | SaaS (OnDemand) | REST | Configurable, multi-line support |
| **Majesco** | Cloud-native | REST | Mid-market, speed to market |
| **Socotra** | API-first cloud-native | REST/GraphQL | Modern, developer-friendly |

## Patterns

### 1. Guidewire Cloud API (PolicyCenter)

```python
import requests

class GuidewireClient:
    def __init__(self, base_url: str, token: str):
        self.base_url = base_url.rstrip("/")
        self.headers = {
            "Authorization": f"Bearer {token}",
            "Content-Type": "application/json",
            "GW-Specification": "composite",
        }

    # --- PolicyCenter ---
    def search_policies(self, policy_number: str = "", insured_name: str = "") -> list[dict]:
        """Search policies by number or insured name."""
        params = {}
        if policy_number:
            params["filter"] = f"policyNumber eq '{policy_number}'"
        elif insured_name:
            params["filter"] = f"insuredName sw '{insured_name}'"
        resp = requests.get(
            f"{self.base_url}/pc/rest/composite/v1/policies",
            headers=self.headers,
            params=params,
        )
        resp.raise_for_status()
        return resp.json().get("data", [])

    def get_policy(self, policy_id: str) -> dict:
        """Get full policy details."""
        resp = requests.get(
            f"{self.base_url}/pc/rest/composite/v1/policies/{policy_id}",
            headers=self.headers,
        )
        resp.raise_for_status()
        return resp.json().get("data", {})

    # --- ClaimCenter ---
    def create_claim(self, policy_id: str, loss_date: str, description: str) -> dict:
        """Create a new claim (FNOL)."""
        payload = {
            "data": {
                "attributes": {
                    "policyNumber": policy_id,
                    "lossDate": loss_date,
                    "description": description,
                    "lossCause": "auto_collision",
                }
            }
        }
        resp = requests.post(
            f"{self.base_url}/cc/rest/composite/v1/claims",
            headers=self.headers,
            json=payload,
        )
        resp.raise_for_status()
        return resp.json().get("data", {})

    def get_claim(self, claim_id: str) -> dict:
        """Get claim details with activities."""
        resp = requests.get(
            f"{self.base_url}/cc/rest/composite/v1/claims/{claim_id}",
            headers=self.headers,
        )
        resp.raise_for_status()
        return resp.json().get("data", {})

    def search_claims(self, policy_number: str = "", status: str = "") -> list[dict]:
        """Search claims by policy or status."""
        params = {}
        filters = []
        if policy_number:
            filters.append(f"policyNumber eq '{policy_number}'")
        if status:
            filters.append(f"state eq '{status}'")
        if filters:
            params["filter"] = " and ".join(filters)
        resp = requests.get(
            f"{self.base_url}/cc/rest/composite/v1/claims",
            headers=self.headers,
            params=params,
        )
        resp.raise_for_status()
        return resp.json().get("data", [])

    # --- BillingCenter ---
    def get_account_billing(self, account_id: str) -> dict:
        """Get billing summary for an account."""
        resp = requests.get(
            f"{self.base_url}/bc/rest/composite/v1/accounts/{account_id}",
            headers=self.headers,
        )
        resp.raise_for_status()
        return resp.json().get("data", {})
```

### 2. Duck Creek OnDemand API

```python
import requests

class DuckCreekClient:
    def __init__(self, base_url: str, token: str):
        self.base_url = base_url.rstrip("/")
        self.headers = {
            "Authorization": f"Bearer {token}",
            "Content-Type": "application/json",
        }

    def get_policy(self, policy_id: str) -> dict:
        """Get policy from Duck Creek Policy."""
        resp = requests.get(
            f"{self.base_url}/api/policies/{policy_id}",
            headers=self.headers,
        )
        resp.raise_for_status()
        return resp.json()

    def get_claim(self, claim_id: str) -> dict:
        """Get claim from Duck Creek Claims."""
        resp = requests.get(
            f"{self.base_url}/api/claims/{claim_id}",
            headers=self.headers,
        )
        resp.raise_for_status()
        return resp.json()

    def submit_fnol(self, policy_id: str, loss_date: str, description: str, claimant_name: str) -> dict:
        """Submit First Notice of Loss."""
        payload = {
            "policyId": policy_id,
            "lossDate": loss_date,
            "lossDescription": description,
            "claimantName": claimant_name,
        }
        resp = requests.post(
            f"{self.base_url}/api/claims/fnol",
            headers=self.headers,
            json=payload,
        )
        resp.raise_for_status()
        return resp.json()

    def get_billing_account(self, account_id: str) -> dict:
        """Get billing account details."""
        resp = requests.get(
            f"{self.base_url}/api/billing/accounts/{account_id}",
            headers=self.headers,
        )
        resp.raise_for_status()
        return resp.json()
```

### 3. Agent Tool Pattern for Insurance

```python
def lookup_policy(policy_number: str) -> str:
    """Look up an insurance policy by its number.

    Args:
        policy_number: The policy number (e.g., 'POL-2024-001234')
    """
    client = GuidewireClient(base_url=GW_URL, token=GW_TOKEN)
    policies = client.search_policies(policy_number=policy_number)
    if not policies:
        return f"No policy found with number {policy_number}"
    policy = policies[0]
    attrs = policy.get("attributes", {})
    return (
        f"Policy: {attrs.get('policyNumber')}\n"
        f"Product: {attrs.get('productName')}\n"
        f"Status: {attrs.get('status')}\n"
        f"Effective: {attrs.get('effectiveDate')} - {attrs.get('expirationDate')}\n"
        f"Premium: ${attrs.get('totalPremium', 0):,.2f}"
    )

def file_claim(policy_number: str, loss_date: str, description: str) -> str:
    """File a new insurance claim (FNOL).

    Args:
        policy_number: The policy number to file against
        loss_date: Date of loss (YYYY-MM-DD)
        description: Description of the loss/incident
    """
    client = GuidewireClient(base_url=GW_URL, token=GW_TOKEN)
    claim = client.create_claim(policy_number, loss_date, description)
    claim_num = claim.get("attributes", {}).get("claimNumber", "unknown")
    return f"Claim {claim_num} created successfully for policy {policy_number}."
```

## Anti-Patterns

- Allowing AI agents to auto-approve claims above threshold -- always require human review for high-value claims
- Exposing PII (SSN, DOB, health data) to LLMs -- mask before passing to model, log access for compliance
- Skipping idempotency on FNOL submission -- duplicate claims create operational overhead
- Direct database access bypassing core system APIs -- violates data integrity and audit trail
- Not respecting policy lifecycle states -- check policy status before allowing operations (e.g., no claims on expired policies)

## References

- [Guidewire Cloud API](https://docs.guidewire.com/cloud/)
- [Duck Creek Technologies](https://www.duckcreek.com/products/)
- [Socotra API](https://docs.socotra.com/)
- [Majesco Platform](https://www.majesco.com/)

<!-- Source: .faos/custom/skills/integrations/core-insurance-integration/SKILL.md -->
