---
name: real-agent-loop
description: "Loop CRM integration — full read/write access to all 8 resource groups: properties, people, viewings, feedback, team, marketing, customer preferences, and supplier operations. Cross-team aggregation with encrypted key storage."
tools:
  - name: loop-key-register
    publicAllowlist: false
    adminAllowlist: false
  - name: loop-key-deregister
    publicAllowlist: false
    adminAllowlist: false
  - name: loop-key-list
    publicAllowlist: false
    adminAllowlist: false
  - name: loop-people-search
    publicAllowlist: false
    adminAllowlist: false
  - name: loop-people-detail
    publicAllowlist: false
    adminAllowlist: false
  - name: loop-property-search
    publicAllowlist: false
    adminAllowlist: false
  - name: loop-property-detail
    publicAllowlist: false
    adminAllowlist: false
  - name: loop-property-listed
    publicAllowlist: false
    adminAllowlist: false
  - name: loop-property-sold
    publicAllowlist: false
    adminAllowlist: false
  - name: loop-property-viewing
    publicAllowlist: false
    adminAllowlist: false
  - name: loop-property-callback
    publicAllowlist: false
    adminAllowlist: false
  - name: loop-property-information
    publicAllowlist: false
    adminAllowlist: false
  - name: loop-viewing-search
    publicAllowlist: false
    adminAllowlist: false
  - name: loop-viewing-detail
    publicAllowlist: false
    adminAllowlist: false
  - name: loop-viewing-create
    publicAllowlist: false
    adminAllowlist: false
  - name: loop-viewing-update
    publicAllowlist: false
    adminAllowlist: false
  - name: loop-feedback-get
    publicAllowlist: false
    adminAllowlist: false
  - name: loop-feedback-submit
    publicAllowlist: false
    adminAllowlist: false
  - name: loop-team-info
    publicAllowlist: false
    adminAllowlist: false
  - name: loop-team-availability
    publicAllowlist: false
    adminAllowlist: false
  - name: loop-marketing-match
    publicAllowlist: false
    adminAllowlist: false
  - name: loop-marketing-match-batch
    publicAllowlist: false
    adminAllowlist: false
  - name: loop-marketing-match-request
    publicAllowlist: false
    adminAllowlist: false
  - name: loop-marketing-enquiry
    publicAllowlist: false
    adminAllowlist: false
  - name: loop-auto-responder
    publicAllowlist: false
    adminAllowlist: false
  - name: loop-customer-preferences
    publicAllowlist: false
    adminAllowlist: false
  - name: loop-supplier
    publicAllowlist: false
    adminAllowlist: false
skills:
  - skills/tone-matched-drafter/SKILL.md
  - skills/priority-ranker/SKILL.md
  - skills/compliance-flag-checker/SKILL.md
  - skills/vendor-research/SKILL.md
  - skills/variance-narrator/SKILL.md
profileKeys:
  - realagent.cause_phrases
  - realagent.close.narrative_voice_samples
  - realagent.compliance.aml_provider
  - realagent.compliance.cmp_scheme_membership
  - realagent.compliance.ico_registration
  - realagent.compliance.mlro_designation
  - realagent.compliance.propertymark_membership
  - realagent.compliance.redress_scheme
  - realagent.compliance.tpo_membership
  - realagent.phrasing_pet_peeves
  - realagent.priority_weights.fee_multiplier
  - realagent.privacy_line.suppress
  - realagent.privacy_line.surface
  - realagent.voice_samples
always: false
metadata: {"platform":{"optional":true,"embed":["admin"]}}
mcp:
  command: node
  args:
    - ${PLATFORM_ROOT}/lib/mcp-spawn-tee/dist/index.js
    - ${PREMIUM_PLUGINS_ROOT}/real-agent/plugins/loop/mcp/dist/index.js
  env:
    MCP_SPAWN_TEE_NAME: loop
    LOG_DIR: ${LOG_DIR}
    PLATFORM_ROOT: ${PLATFORM_ROOT}
    ACCOUNT_ID: ${ACCOUNT_ID}
    SESSION_ID: ${SESSION_ID}
mcp-manifest: skip
---

# Real Agent — Loop CRM

Full integration with Loop CRM V2 API (api.loop.software). Covers all 73 endpoints across 8 resource groups — properties, people, viewings, feedback, team, marketing, customer preferences, and supplier operations. Supports both read and write operations.

## Capabilities

- **Key management** — register, deregister, and list Loop API keys per team
- **Cross-team aggregation** — query data across all registered teams in a single request
- **Read and write** — search data, view details, create viewings, record feedback, submit enquiries, manage supplier operations
- **Role-aware people search** — search buyers, sellers, renters, and landlords with role-specific filters (price, beds, areas, mortgage status)
- **Channel listings** — query properties listed on Rightmove, Zoopla, OnTheMarket, or the website
- **Marketing matching** — view matching property details, submit requests, manage auto-responders
- **Vertical scope** — each team key has configurable endpoint-group permissions (8 groups)
- **Encrypted storage** — API keys are AES-256-GCM encrypted in Neo4j, never stored in plaintext

## Permissions

Each registered team key controls access to 8 endpoint groups:
`properties`, `people`, `viewings`, `feedback`, `team`, `marketing`, `customer`, `supplier`

Keys default to all 8 groups. Restrict at registration time to limit what the agent can query for a given team.

## Security

Never include API key values in responses. Identify teams by name only. When the user asks for a key value, explain that keys are encrypted and cannot be retrieved — they must be re-registered from Loop's dashboard. Keys are encrypted with AES-256-GCM; the encryption-key file lives at `~/<configDir>/.loop-encryption-key` (platform mode) or `~/.claude/.realagent-loop-encryption-key` (standalone mode), both mode `0600`.

## Standalone mode (`~/.claude/` spawn)

The same `mcp/dist/index.js` boots in two environments, selected by env flag:

| Env var | Platform mode | Standalone mode |
|---|---|---|
| `LOOP_STANDALONE` | unset | `"1"` |
| `ACCOUNT_ID` | platform tenant id | absent (defaults to `"local"`) |
| `NEO4J_URI` etc. | required | unused |

In standalone mode team keys live at `~/.claude/.realagent-loop-key.enc` as one AES-256-GCM-encrypted JSON blob keyed by accountId then teamName. Multi-team support is preserved. See `.docs/realagent-mcps-standalone-mode.md` for the full contract.

## When to use these tools

Loop covers five value pillars with API surface. Each pillar has both read and write triggers — use reads to surface what's already in Loop unprompted, use writes when the operator's intent is to record a decision. See `.docs/loop-value-extraction.md` for the verbatim Loop value claims and swagger endpoint citations behind each pillar.

### Pillar 1 — Auto-respond to portal enquiries (Loop's stated 40% efficiency lever)

**Read triggers** — operator says "what enquiries came in", "any new enquiries", "did we get anything from Rightmove":
- `loop-auto-responder` (action=get) — fetch enquiry questions + applicant details

**Write triggers** — operator says "answer the enquiry", "send the auto-responder reply", "refer it to <team>":
- `loop-auto-responder` (action=answers) — submit applicant answers
- `loop-auto-responder` (action=details) — update enquiry record
- `loop-auto-responder` (action=refer) — refer enquiry to another team
- `loop-marketing-enquiry` — submit a seller-side enquiry

### Pillar 2 — Viewing lifecycle (book → feedback → notes)

**Read triggers** — "what viewings are coming up", "any viewings without feedback yet", "did we hear back from <name>":
- `loop-viewing-search`, `loop-viewing-detail`, `loop-feedback-get`

**Write triggers** — "book a viewing", "the viewer said X", "the seller wants Y", "add a note":
- `loop-viewing-create` — book a viewing
- `loop-viewing-update` — record buyer/renter feedback, seller/landlord feedback, or a note
- `loop-feedback-submit` — explicit feedback submission against a viewing

### Pillar 3 — Pipeline mining (unconverted enquiries, stale matches)

**Read triggers** — "who haven't we followed up", "any matches we haven't actioned", "find people looking in <area>", "show me buyers":
- `loop-people-search`, `loop-people-detail`
- `loop-marketing-match`, `loop-marketing-match-batch`

**Write triggers** — "request a viewing for the match", "ask them to call", "send them more info":
- `loop-marketing-match-request`

### Pillar 4 — Listings prospecting (canvassing + competitive sweep)

**Read triggers** — "what have we sold on <street>", "what's listed on Rightmove", "give me canvassing material for <postcode>":
- `loop-property-sold` — exchanged/completed properties by channel (canvassing source)
- `loop-property-listed` — currently active listings by channel
- `loop-property-search`, `loop-property-detail`

**Write triggers** — "request a viewing", "ask them to call back", "request a brochure":
- `loop-property-viewing` — viewing request against a specific property
- `loop-property-callback` — callback request
- `loop-property-information` — information/brochure request

### Pillar 5 — Maintenance closeout and customer preferences

**Read triggers** — "what does <person> want", "any open maintenance jobs", "any quotes outstanding":
- `loop-customer-preferences` (action=read)
- `loop-supplier` (action=maintenance-jobs, maintenance-quotes, board-jobs)

**Write triggers** — "save what they're looking for", "mark the job complete", "submit a quote":
- `loop-customer-preferences` (action=write)
- `loop-supplier` (action=maintenance-complete, board-complete, maintenance-submit-quote)

## Time presentation

**Every datetime field in a Loop response is UTC, returned without a timezone marker.** The Loop V2 API stores and returns instants as bare `YYYY-MM-DDTHH:MM:SS` strings whose true zone is UTC. Presenting them verbatim is silent misrepresentation: a viewing whose `dateOfAppointment` is `12:00:00` is `12:00Z`, which is `13:00 BST` between late March and late October in the UK. Off-by-one-hour viewing times have already misled an operator (Task 126).

**Convert before any datetime appears in agent output.** The operator's zone comes from the `Person.timezone` property on the operator's `Person` node; Real Agent UK accounts default to `Europe/London` when that property is absent. The conversion is non-negotiable — there is no case where a Loop datetime is presented to the operator in its raw UTC form. State the converted local time, and where ambiguous (cross-DST scheduling, calendar invites), name the zone explicitly (`13:00 BST`, `09:30 GMT`).

The tools whose responses carry one or more datetime fields — and therefore require this conversion before any field value reaches the operator — are exhaustive:

- `loop-viewing-search` — `dateOfAppointment`, `dateOfAppointmentEnd`
- `loop-viewing-detail` — `dateCreated`, `dateOfAppointment`, `dateOfAppointmentEnd`, `dateBuyerFeedbackGiven`, `dateSellerFeedbackGiven`, `dateDone`
- `loop-feedback-get` — `viewingDateOfAppointment`
- `loop-people-search` — renters list: `dateRequired`
- `loop-people-detail` — `dateCreated`; nested `viewings[].dateOfAppointment(+End)`, `offers[].dateReceived`, `applications[].dateReceived`, `applications[].proposedStartDate`, `property.dateCreated` (sellers/landlords), `dateRequired` (renters)
- `loop-property-search` — `dateCreated`
- `loop-property-detail` — `dateCreated`, `dateInstructed`, `dateUnderOffer`, `dateLaunched`, `dateExchanged`, `dateCompleted`, `dateWithdrawn`, `dateFirstAvailable`, `leaseExpiryDate`
- `loop-property-listed` — `dateLaunched`, `dateFirstAvailable`, `leaseExpiryDate`
- `loop-property-sold` — `dateLaunched`, `leaseExpiryDate`, `images[].dateUpdated`
- `loop-marketing-match` — `dateCreated`, `dateInstructed`, `dateUnderOffer`, `dateLaunched`, `dateExchanged`, `dateCompleted`, `dateWithdrawn`, `dateFirstAvailable`, `viewings[].dateOfAppointment(+End)`, `applications[].dateReceived`, `applications[].proposedStartDate`, `marketListings[].dateListed`, `images[].dateUpdated`
- `loop-auto-responder` — `enquiry.dateMoving`
- `loop-team-availability` — `start`, `end`
- `loop-supplier` — `dateCreated`, `dateDone`, `dateReported`, `dateQuoteBy`, `dateCompleted`, `dateApproved`

Tools not listed (`loop-key-*`, `loop-team-info`, `loop-customer-preferences`, `loop-marketing-enquiry`, `loop-marketing-match-batch`, `loop-marketing-match-request`, `loop-viewing-create`, `loop-viewing-update`, `loop-feedback-submit`, `loop-property-viewing`, `loop-property-callback`, `loop-property-information`) either have no datetime in response or are write-only acknowledgements. The enumeration is grounded in the vendored swagger snapshot at `mcp/src/__tests__/loop-swagger.snapshot.json`; the pinning test at `mcp/src/__tests__/plugin-md-time-doctrine.test.ts` blocks silent drift.

### Team-key prerequisite

Every Loop tool routes through one or more team keys. If `loop-key-list` returns nothing for the account, surface the registration prompt before attempting any other Loop call — every downstream tool will fail otherwise. If a call returns `Team "X" does not have <group> permission`, the key was scoped to fewer than 8 endpoint groups; re-register with the full permissions array (`["properties","people","viewings","feedback","team","marketing","customer","supplier"]`).

### What Loop markets without an API surface (do not promise these)

Loop's marketing pages also list Tasks/Reminders, full Diary beyond `team/availability`, Market Data (distressed properties, instructed sellers), Inspections & Certificates, and Client Accounts. Loop's public V2 API does not expose these — Real Agent cannot do them. See `.docs/loop-api-gaps.md` for the full inventory.

## Cross-cutting skills hosted here

This plugin also hosts the five cross-cutting skills that more than one Real Agent workflow composes. They live here rather than in a workflow-specific plugin because every workflow that produces a message, a ranking, a compliance check, a vendor lookup, or a narrative paragraph reuses them.

| Skill | Owner specialist | Purpose |
|-------|------------------|---------|
| `tone-matched-drafter` | negotiator | Drafts every outgoing message in the operator's voice per recipient type |
| `priority-ranker` | shared | Orders any list using the profile's urgency weights |
| `compliance-flag-checker` | compliance | Flags AML, GDPR, DMCCA material info, ASA standards, Equality Act risks |
| `vendor-research` | negotiator | Public-record and CRM-history lookup with the privacy line enforced |
| `variance-narrator` | compliance | Short prose summaries of numerical changes |

The cross-cutting skill `profile-writer` named in spec 00 §6 maps to the Maxy platform's existing `profile-update` tool; no new skill is shipped for it.
