Skip to main content

Analyze Comp Set

Complete rent analysis for a comp set. Returns ALL data needed to answer
rent, pricing, or competitive positioning questions — with pre-computed
comparisons, so you can respond directly without further calculation.

Response structure:
- subject: flat dict with property info + average metrics + detail breakdown.
- comp_set_summary: aggregated averages across all comps (+ per-group),
including the set's leasing signal (avgListingDays, exposure, occupancy).
- positioning: pre-computed comparisons against comps and market:
- {field}VsComps: % difference vs comp set average (e.g. "+4.7%").
- askingRentRank: subject rank by asking rent (e.g. "2/13", 1=highest).
- effectiveRentRank: subject rank by effective rent after concessions.
- askingRentVsMarket: % diff vs ZIP market average (when zip_code provided).
- effectiveRentVsMarket: same for effective rent.
- comps: CSV with one row per comp (propertyId, name, yearBuilt, askingRent, ...).
Key computed columns:
- concessionSpread: discount depth = (asking - effective) / asking * 100.
Higher values = more aggressive concessions. 0 = no discount.
- exposure: units available / the property's unit count, as a
percentage. Present only when the unit count is known; when it is
absent, so is this — do not substitute unitsSeen for it.
- occupancy: the leased share — exposure's complement, same condition.
- unitsSeen: distinct units seen listed in the window. A sample size,
NOT the building — it typically runs 20-35% of the unit count.
- avgListingDays: days on market, averaged over the period's listings.
LEASING SIGNAL: exposure, days on market and leased % are HERE, for the
subject and every comp. Do NOT reach for get_comp_set_comps_details to
get them; that costs 100K+ tokens for the same numbers.
propertyId is the Keyway property code (e.g. "USNC-007026"). Pass it
straight to get_property_details, get_rent_metrics_for_properties or
get_historical_exposure_summary — do NOT re-resolve comps by name with
get_property_id, several comps in a set can share a name.
The subject also carries reportedOccupancy: KeyComps' own leased share
for the building, independent of this window's listings.
- comps_by_bedroom: CSV with comp propertyId + name + per-bedroom metrics
(when grouping != PROPERTY). ONE ROW PER BEDROOM COUNT PER COMP, labelled
by a `bedrooms` column — read that column before quoting a number, a
12-comp set is ~40 rows. UNIT_MIX names it comps_by_unit_mix and adds
`bathrooms`; FLOOR_PLAN names it comps_by_floor_plan and labels by
`floorPlan`. positioning.byBedroom is keyed the same way, one entry per
bedroom count. These cuts carry no exposure or occupancy: a cut's real
denominator is the units of that bedroom count, which nothing here knows.
- concessions_summary: (when include_concessions=True) dict with:
- propertiesWithActiveConcessions: "X/Y" count.
- subjectHasActiveConcession: bool.
- byProperty: list with per-property concession activity:
- concessionDays: days with active concessions in date range.
- frequency: concessionDays/totalDays as percentage.
- changes: number of distinct concession texts (volatility indicator).
- concessions: CSV with ONLY active concessions (descriptions cleaned of boilerplate).
NOTE: Concessions are property-level (not broken down by unit type). Do NOT
call other tools trying to get per-unit-type concession data, it does not exist.
- historical_rent: CSV of rent trends (when include_historical_rent=True).
- market_benchmarks: ZIP-level metrics pass-through (when zip_code provided).

Inputs​

ParameterRequiredTypeDetails
comp_set_idYesstringThe unique identifier of the comp set
date_fromNoanyOfStart date in YYYY-MM-DD format (default: 90 days ago)
Default: null
date_toNoanyOfEnd date in YYYY-MM-DD format (default: today)
Default: null
groupingNostringLevel of detail for metrics breakdown:
- "PROPERTY": One aggregate row per property
- "BEDROOM": Break down by bedroom count per property (default, recommended)
- "UNIT_MIX": Break down by bedroom/bathroom combination
- "FLOOR_PLAN": Break down by floor plan per property
Default: "BEDROOM"
Allowed: ["PROPERTY","BEDROOM","UNIT_MIX","FLOOR_PLAN"]
include_concessionsNobooleanSet to True when the question involves concessions,
incentives, or move-in specials (default: False)
Default: false
include_historical_rentNobooleanSet to True when the question involves rent trends,
rent history, or how rents have changed over time. Fetches historical
rent data for the subject property (default: False).
Default: false
lease_termNoanyOfOptional filter for lease term in months (e.g., 12)
Default: null
unit_conditionNoanyOfOptional filter for renovation status:
- "RENO": Only renovated units
- "NON_RENO": Only non-renovated units
- None: All units (default)
Default: null
zip_codeNoanyOfOptional ZIP code for market benchmarks. When provided, ZIP-level
market metrics (property + bedrooms) are fetched in parallel and returned
under "market_benchmarks".
Default: null

Annotations​

{
"title": "Analyze Comp Set",
"readOnlyHint": true,
"destructiveHint": false,
"openWorldHint": false
}

Input schema​

{
"type": "object",
"additionalProperties": false,
"properties": {
"comp_set_id": {
"type": "string",
"description": "The unique identifier of the comp set"
},
"date_from": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Start date in YYYY-MM-DD format (default: 90 days ago)"
},
"date_to": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "End date in YYYY-MM-DD format (default: today)"
},
"grouping": {
"default": "BEDROOM",
"enum": [
"PROPERTY",
"BEDROOM",
"UNIT_MIX",
"FLOOR_PLAN"
],
"type": "string",
"description": "Level of detail for metrics breakdown:\n- \"PROPERTY\": One aggregate row per property\n- \"BEDROOM\": Break down by bedroom count per property (default, recommended)\n- \"UNIT_MIX\": Break down by bedroom/bathroom combination\n- \"FLOOR_PLAN\": Break down by floor plan per property"
},
"include_concessions": {
"default": false,
"type": "boolean",
"description": "Set to True when the question involves concessions,\nincentives, or move-in specials (default: False)"
},
"unit_condition": {
"anyOf": [
{
"enum": [
"RENO",
"NON_RENO"
],
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Optional filter for renovation status:\n- \"RENO\": Only renovated units\n- \"NON_RENO\": Only non-renovated units\n- None: All units (default)"
},
"lease_term": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"description": "Optional filter for lease term in months (e.g., 12)"
},
"zip_code": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Optional ZIP code for market benchmarks. When provided, ZIP-level\nmarket metrics (property + bedrooms) are fetched in parallel and returned\nunder \"market_benchmarks\"."
},
"include_historical_rent": {
"default": false,
"type": "boolean",
"description": "Set to True when the question involves rent trends,\nrent history, or how rents have changed over time. Fetches historical\nrent data for the subject property (default: False)."
}
},
"required": [
"comp_set_id"
]
}