HarborCRM Task Solving Skill
Overview
This skill captures recurring patterns for solving HarborCRM CRM-integration tasks. Tasks involve querying a local HarborCRM API, applying business rules, and producing structured JSON output matching a provided answer template.
Environment Setup
- The HarborCRM API is available after running
env/setup.sh. - Base URL is supplied by the runner; default for local runs is
http://127.0.0.1:8067. - Only query endpoint paths and entity IDs explicitly named in the task prompt. Do not use global list/index endpoints to discover IDs.
Core Workflow
- Read the prompt to identify the task type (event reconciliation, trade-show prospecting, batch import cleanup, etc.).
- Read the answer template (
input/payloads/answer_template.json) to understand the exact required schema, keys, enums, and sort orders. - Query only the explicitly named endpoints from the prompt.
- Apply business rules (qualification, exclusion, CRM action mapping, opportunity sizing, normalization).
- Sort all lists exactly as specified in the template or prompt.
- Produce JSON only — no explanatory prose outside the JSON.
Task-Type Patterns
1. Post-Event Reconciliation (e.g., neuralops_2026, edgeai_field_2026)
Data to fetch:
- Event details, orders, badges, sponsor packages
- Finance invoices (filtered by
event_id) - CRM accounts, contacts, opportunities, campaign members
- Policies (for exclusion/qualification rules)
Key business rules:
- Sponsor statuses use controlled values:
paid_deferred,open_invoice,proposal_only(and sometimesnot_sponsor). - Revenue totals are integer USD. For
open_invoice, report the open balance separately. - Exclude from lead handoff: sponsor attendees, inactive/canceled sponsors, non-business badges, existing disqualified CRM accounts.
- Qualified leads are non-sponsor accounts with business badges that are not already disqualified.
- Opportunity amount comes from the event's configured lead opportunity amount (e.g., 42000, 18000).
- Follow-up due dates are derived from the event date (e.g., leads due 5 business days after event end; sponsor finance due 3 business days after).
- CRM action counts summarize implied account/contact/campaign-member creates and updates.
Sorting conventions:
sponsor_statuses: byaccount_nameascendingqualified_lead_accounts: byaccount_nameascendingexcluded_records: bycompany_nameascending, thencontact_nameascendingbadge_decisions: bybadge_idascendingcampaign_member_actions: bysubject_keyascendingbadge_only_contacts: bycompany_nameascending
Normalization rules:
- Email: lowercase, trimmed; empty string when missing
- Phone: digits only; empty string when missing
2. Trade-Show Prospecting (e.g., aquafarm_robotics_2026, marinesense_2026)
Data to fetch:
- Trade-show details (
/api/tradeshows/{show_id}) - Exhibitors (
/api/tradeshows/{show_id}/exhibitors) - Meeting interest (
/api/tradeshows/{show_id}/meeting_interest) - CRM accounts, policies
Qualification rules:
- Qualified leads are exhibitors that make or OEM-build robotics or underwater-camera platforms covered by the prospecting policy.
- Exclude distributors, service-only providers, sensor-only vendors, research-only entities.
- Existing CRM accounts should be marked for
update_existing; new qualified exhibitors forcreate_account. - Excluded exhibitors remain visible with a controlled
exclusion_reasonandcrm_action: no_import.
Ranking rules (prospecting):
- Demo request first (
requested_demo: truebeforefalse) - Meeting interest score descending
- Broader platform coverage (more platforms = higher rank)
- Company name ascending (tie-breaker)
Opportunity sizing by priority tier:
A: USD 120000 — demo-requested qualified leads with score ≥ 90B: USD 90000 — demo-requested qualified leads with score ≥ 80C: USD 50000 — all other qualified leads
Platform enums: AUV, ROV, Underwater Camera
- Platforms list must be sorted in the order:
AUV,ROV,Underwater Camera
Summary fields:
qualified_lead_count,excluded_countexisting_crm_overlap_countandexisting_crm_overlap_account_ids(sorted ascending)total_estimated_opportunity_usd(sum of lead opportunities)platform_coverage_counts: counts of leads covering each platform
Excluded exhibitor schema:
- Required:
company_id,company_name,relationship_type,exclusion_reason,crm_action relationship_typeenums:distributor,service_provider,sensor_vendor,researchexclusion_reasonenums:distributor_only,service_only,sensor_only,research_only- Sort excluded exhibitors by
company_nameascending
3. Batch Import Cleanup (e.g., fall_webinar_import)
Data to fetch:
- Import batch raw contacts (
/api/import_batches/{batch_id}/raw_contacts) - Suppression list (
/api/import_batches/{batch_id}/suppression) - CRM accounts and contacts (for deduplication and existing record matching)
- Policies
Business rules:
- Remove duplicates by email (keep the latest/most complete record as winner).
- Remove suppressed emails/domains.
- Remove unusable rows (missing contact name, missing email, etc.).
- Match remaining rows to existing CRM accounts by company name/email and to existing contacts by email.
- CRM action per row:
create_account,update_existing,no_import,suppress. - If a row matches an existing account but not an existing contact, action is
update_existingfor account andcreate_contactfor contact.
Output sections:
clean_contacts: import-ready rows withclean_contact_id,source_row_id, company/contact info,crm_action,existing_account_id,existing_contact_idduplicate_summary: count and details of duplicates removed (winner/removed mapping)removal_summary: count and reasons for all removed rows (duplicate,suppressed,missing_contact, etc.)import_action_totals: aggregate counts percrm_actioncampaign_member_import_count: number of clean contacts that will become campaign members
Universal Conventions
JSON Output Rules
- Return JSON only — no markdown, no prose, no comments.
- Match the answer template schema exactly; include all required keys.
- Use
null(not missing keys) for nullable fields unless the template says otherwise. - Currency amounts are always integer USD.
- Dates are ISO 8601 (
YYYY-MM-DD) unless the template specifies otherwise.
Sorting Rules
- Always sort lists as specified in the template or prompt.
- Common sort keys:
account_nameascending,company_nameascending,badge_idascending,subject_keyascending,rankascending (1-based contiguous). - For tie-breakers, fall back to secondary keys (e.g.,
contact_name,company_id).
CRM Actions
Common crm_action values across tasks:
create_account— new account + contactupdate_existing— update matched accountcreate_contact— new contact on existing accountno_import— excluded or suppressedno_action— already correct stateadd_campaign_member/create/update— campaign member actions
Exclusion Reasons
Common exclusion reasons:
sponsor_attendeenon_business_badgeexisting_disqualifiedmissing_contactdistributor_onlyservice_onlysensor_only/sensor_vendor_onlyresearch_only
API Query Discipline
- Only call endpoints explicitly listed in the prompt.
- Do not call global list endpoints (
/api/events,/api/tradeshows, etc.) to discover IDs. - Use query parameters exactly as specified (e.g.,
?event_id=neuralops_2026).
Common Pitfalls
- Missing sort order — Many lists have strict ordering requirements. Check the template.
- Wrong opportunity amounts — Use the event-specific lead opportunity amount, not a hardcoded default.
- Platform list order — In trade-show tasks, platforms must be ordered
AUV,ROV,Underwater Camera. - Duplicate handling — In batch imports, deduplicate by email and report the winner/removed mapping precisely.
- Normalization — Emails must be lowercase and trimmed; phones digits-only.
- Null vs missing key — Use
nullfor fields likecrm_account_idwhen there is no match; do not omit the key. - Contiguous ranks — Ranks must be 1-based and contiguous (no gaps after filtering).
- Open invoice balance — For sponsors with
open_invoice, calculateopen_balance = package_amount - paid_amount.