# property-assessor Decision-grade residential property assessment skill for OpenClaw, with official public-record enrichment and fixed-template PDF report rendering. ## Overview `property-assessor` is for evaluating a condo, townhouse, house, or similar residential property from an address or listing URL and ending with a practical recommendation such as `buy`, `pass`, or `only below X`. The skill is intended to: - normalize the property across listing sources - review listing photos before making condition claims - incorporate official public-record / appraisal-district context when available - compare the property against comps and carrying costs - produce a fixed-format PDF report, not just ad hoc chat prose ## Standalone helper usage This skill now ships with a small TypeScript helper package for three tasks: - assembling an address-first preliminary assessment payload - locating official public-record jurisdiction from an address - rendering a fixed-template PDF report From `skills/property-assessor/`: ```bash npm install scripts/property-assessor --help ``` The wrapper script uses the skill-local Node dependencies under `node_modules/`. ## Commands ```bash scripts/property-assessor assess --address "4141 Whiteley Dr, Corpus Christi, TX 78418" scripts/property-assessor assess --address "4141 Whiteley Dr, Corpus Christi, TX 78418" --recipient-email "buyer@example.com" scripts/property-assessor assess --address "4141 Whiteley Dr, Corpus Christi, TX 78418" --recipient-email "buyer@example.com" --output /tmp/property-assessment.pdf scripts/property-assessor locate-public-records --address "4141 Whiteley Dr, Corpus Christi, TX 78418" scripts/property-assessor locate-public-records --address "4141 Whiteley Dr, Corpus Christi, TX 78418" --parcel-id "14069438" scripts/property-assessor locate-public-records --address "4141 Whiteley Dr, Corpus Christi, TX 78418" --listing-geo-id "233290" scripts/property-assessor render-report --input examples/report-payload.example.json --output /tmp/property-assessment.pdf ``` ## Core workflow Default operating sequence: 1. Normalize the address and property type. 2. Resolve public-record jurisdiction from the address. 3. Discover accessible listing sources for the same property. 4. Build a baseline fact set. 5. Review listing photos before making condition claims. 6. Pull same-building or nearby comps. 7. Underwrite carry costs and risk factors. 8. Render the final report as a fixed-template PDF. ### `assess` ```bash scripts/property-assessor assess --address "" scripts/property-assessor assess --address "" --recipient-email "" ``` Current behavior: - starts from the address - automatically runs public-record / appraisal-district lookup - returns a structured preliminary report payload - asks for recipient email(s) before PDF generation - renders the fixed-template PDF when recipient email(s) are present Important limitation: - this first implementation wires the address-first assessment spine - it does not yet auto-run listing extraction, photo review, comps, or carry underwriting inside the helper itself - those richer assessment steps are still governed by the skill workflow and the `web-automation` extractors ## Source priority Unless the user says otherwise, preferred listing/source order is: 1. Zillow 2. Redfin 3. Realtor.com 4. HAR / Homes.com / brokerage mirrors 5. county or appraisal pages Public-record / assessor data should be linked in the final result when available. ## Public-record enrichment The skill should not rely on listing-site geo IDs as if they were assessor record identifiers. Correct approach: 1. start from the street address 2. resolve the address to state/county/FIPS/GEOID 3. identify the official public-record jurisdiction 4. use parcel/APN/account identifiers when available 5. link the official jurisdiction page and any direct property page used ### `locate-public-records` ```bash scripts/property-assessor locate-public-records --address "" ``` Current behavior: - uses the official Census geocoder - returns matched address, county/state/FIPS, and block GEOID context - for Texas, returns: - Texas Comptroller county directory page - appraisal district contact/site details - tax assessor/collector contact/site details Important rules: - Zillow/Redfin/HAR geo IDs are hints only - parcel/APN/account IDs are stronger search keys than listing geo IDs - official jurisdiction pages should be linked in the final report - if a direct property detail page is accessible, its data should be labeled as official public-record evidence ### Texas support Texas is the first-class public-record path in this implementation. For Texas addresses, the helper resolves: - the official Census geocoder link - the official Texas Comptroller county directory page - the appraisal district website - the tax assessor/collector website That output should be used by the skill to: - identify the correct CAD - attempt address / parcel / account lookup on the CAD site - capture official assessed values and exemptions when a public detail page is available Recommended fields to capture from official records when accessible: - account number - owner name - land value - improvement value - assessed total - exemptions - official property-detail URL ## Minimum data to capture For the subject property, capture when available: - address - list price or last known list price - property type - beds / baths - square footage - lot size if relevant - year built - HOA fee and included services - taxes - days on market - price history - parking - waterfront / flood clues - subdivision or building name - same-building or nearby active inventory - listing photos and visible condition cues - public-record jurisdiction and linked official source - account / parcel / tax ID if confirmed - official assessed values and exemptions if confirmed ## Photo-review rules Photo review is mandatory when photos are exposed by a listing source. Do not make strong condition claims from structured text alone if photos are available. Preferred photo-access order: 1. Zillow extractor 2. HAR extractor 3. Realtor.com photo page 4. brokerage mirror or other accessible listing mirror Use the dedicated `web-automation` extractors first: ```bash cd ~/.openclaw/workspace/skills/web-automation/scripts node zillow-photos.js "" node har-photos.js "" ``` When those extractors return `imageUrls`, that returned set is the photo-review set. ## Approval-safe command shape For chat-driven runs, prefer file-based commands. Good: - `scripts/property-assessor assess --address "..."` - `node check-install.js` - `node zillow-photos.js ""` - `node har-photos.js ""` - `scripts/property-assessor locate-public-records --address "..."` - `scripts/property-assessor render-report --input ... --output ...` Avoid when possible: - `node -e "..."` - `node --input-type=module -e "..."` ## PDF report template The final deliverable should be a fixed-template PDF, not a one-off layout. Template reference: - `skills/property-assessor/references/report-template.md` Current renderer: ```bash scripts/property-assessor assess --address "" --recipient-email "" scripts/property-assessor render-report --input "" --output "" ``` The fixed template includes: 1. Report header 2. Verdict panel 3. Subject-property summary table 4. Snapshot 5. What I Like 6. What I Do Not Like 7. Comp View 8. Underwriting / Carry View 9. Risks and Diligence Items 10. Photo Review 11. Public Records 12. Source Links 13. Notes page ### Recipient email gate The report must not be rendered or sent unless target recipient email address(es) are known. If the prompt does not include recipient email(s), the skill should: - stop - ask for target recipient email address(es) - not finalize the PDF workflow yet The renderer enforces this. If `recipientEmails` is missing or empty, it fails with: `Missing target email. Stop and ask the user for target email address(es) before generating or sending the property assessment PDF.` ## Example payload Sample payload: - `skills/property-assessor/examples/report-payload.example.json` This is the easiest way to test the renderer without building a report payload from scratch. ## Output contract The assessment itself should remain concise but decision-grade. Recommended narrative structure: 1. Snapshot 2. What I like 3. What I do not like 4. Comp view 5. Underwriting / carry view 6. Risks and diligence items 7. Verdict with fair-value range and offer guidance It must also explicitly include: - `Photo source attempts: ...` - `Photo review: completed via ` or `Photo review: not completed` - public-record / CAD evidence and links when available ## Validation flow ### 1. Install the helper package locally ```bash cd ~/.openclaw/workspace/skills/property-assessor npm install npm test ``` ### 2. Run address-first assess without recipient email ```bash cd ~/.openclaw/workspace/skills/property-assessor scripts/property-assessor assess --address "4141 Whiteley Dr, Corpus Christi, TX 78418" ``` Expected shape: - `needsRecipientEmails: true` - public-record / CAD jurisdiction included in the returned payload - no PDF generated yet - explicit message telling the operator to ask for target recipient email(s) ### 3. Run public-record lookup directly ```bash cd ~/.openclaw/workspace/skills/property-assessor scripts/property-assessor locate-public-records --address "4141 Whiteley Dr, Corpus Christi, TX 78418" ``` Expected shape: - state/county/FIPS/GEOID present - official Census geocoder link present - for Texas: Comptroller county directory link present - for Texas: appraisal district and tax assessor/collector contacts present ### 4. Run assess with recipient email and render the PDF ```bash cd ~/.openclaw/workspace/skills/property-assessor scripts/property-assessor assess --address "4141 Whiteley Dr, Corpus Christi, TX 78418" --recipient-email "buyer@example.com" --output /tmp/property-assessment.pdf ``` Expected result: - `needsRecipientEmails: false` - JSON success payload with `outputPath` - a non-empty PDF written to `/tmp/property-assessment.pdf` ### 5. Run PDF render with the sample payload ```bash cd ~/.openclaw/workspace/skills/property-assessor scripts/property-assessor render-report --input examples/report-payload.example.json --output /tmp/property-assessment.pdf ``` Expected result: - JSON success payload with `outputPath` - a non-empty PDF written to `/tmp/property-assessment.pdf` ### 6. Verify the email gate Run the renderer with a payload that omits `recipientEmails`. Expected result: - non-zero exit - explicit message telling the operator to stop and ask for target recipient email(s) ### 7. Verify the end-to-end skill behavior When testing `property-assessor` itself, confirm the assessment: - starts from the address when available - uses Zillow first for photo extraction, HAR as fallback - uses official public-record jurisdiction links when available - does not treat listing geo IDs as assessor keys - asks for recipient email(s) if they were not provided - renders the final report through the fixed PDF template once recipient email(s) are known ## Related files - skill instructions: - `skills/property-assessor/SKILL.md` - underwriting heuristics: - `skills/property-assessor/references/underwriting-rules.md` - PDF template rules: - `skills/property-assessor/references/report-template.md` - sample report payload: - `skills/property-assessor/examples/report-payload.example.json` - photo extraction docs: - `docs/web-automation.md`