AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Chatwoot Contact Operations

skill-fazer-ai-chatwoot-skills-chatwoot-contact-operations · by fazer-ai

Manage Chatwoot contacts — search, filter, create, update, merge duplicates, manage labels, and link contacts to inboxes. Use when working with customer data, contact records, or contact management.

No reviews yet
0 installs
18 views
0.0% view→install

Install

$ agentstack add skill-fazer-ai-chatwoot-skills-chatwoot-contact-operations

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-fazer-ai-chatwoot-skills-chatwoot-contact-operations)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
6mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Chatwoot Contact Operations? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Chatwoot Contact Operations

Complete guide for managing contacts (customers) in Chatwoot using mcp-chatwoot MCP tools.

Contact Data Model

A Chatwoot contact represents a customer or end-user. Key fields:

| Field | Type | Description | | ----------------------- | -------- | ---------------------------------------------- | | id | integer | Unique contact ID | | name | string | Display name | | email | string | Email address | | phone_number | string | Phone (with country code, e.g., +1234567890) | | identifier | string | External system identifier | | custom_attributes | object | Arbitrary key-value pairs | | thumbnail | string | Avatar URL | | additional_attributes | object | System-managed attributes (browser, OS, etc.) | | created_at | datetime | Creation timestamp | | last_activity_at | datetime | Last interaction timestamp |

Creating Contacts

contacts_create(
  account_id: 1,
  name: "Jane Smith",
  email: "jane@company.com",
  phone_number: "+15551234567",
  identifier: "CRM-12345",
  custom_attributes: {
    "plan": "enterprise",
    "company": "Acme Corp"
  }
)

Tips:

  • email and phone_number are used for deduplication — Chatwoot may reject if a contact with the same email/phone exists
  • identifier is useful for linking to external systems (CRM, billing, etc.)
  • custom_attributes are freeform but should match defined attribute keys for consistency

Finding Contacts

Quick text search: contacts_search

Searches across name, email, phone, and identifier fields:

contacts_search(account_id: 1, q: "jane@company.com")
contacts_search(account_id: 1, q: "Acme")
contacts_search(account_id: 1, q: "+1555")

Best for: Quick lookups when you have a partial name, email, or phone.

Structured filtering: contacts_filter

Complex queries with boolean logic and operators:

contacts_filter(
  account_id: 1,
  payload: [
    {
      "attribute_key": "email",
      "filter_operator": "contains",
      "values": ["@acme.com"],
      "query_operator": "AND"
    },
    {
      "attribute_key": "last_activity_at",
      "filter_operator": "days_before",
      "values": [90],
      "query_operator": null
    }
  ]
)

Best for: Finding contacts matching specific criteria (inactive contacts, contacts without email, contacts from a specific domain, etc.)

When to use which

| Scenario | Tool | | ---------------------------- | ---------------------------------------------- | | "Find John's contact" | contacts_search(q: "John") | | "Find all Gmail contacts" | contacts_filter(email contains "@gmail.com") | | "Contacts without phone" | contacts_filter(phone_number is_not_present) | | "Contacts created this week" | contacts_filter(created_at days_before 7) | | "Contact with ID CRM-123" | contacts_search(q: "CRM-123") |

See the mcp-tools-expert skill's SEARCH_GUIDE.md for complete filter syntax.

Updating Contacts

contacts_update(
  account_id: 1,
  id: 42,
  name: "Jane Smith-Jones",
  custom_attributes: {
    "plan": "enterprise-plus",
    "renewal_date": "2026-06-15"
  }
)

Only pass the fields you want to change — other fields are preserved.

Contact Labels

Labels are string tags for categorizing contacts.

List labels

contact_labels_list(account_id: 1, contact_id: 42)
→ ["vip", "enterprise"]

Set labels (replaces all)

contact_labels_set(account_id: 1, contact_id: 42, labels: ["vip", "enterprise", "churning"])

⚠️ Replaces all labels — read first, merge, then set.

Merging Duplicate Contacts

When two contact records represent the same person:

contacts_merge(
  account_id: 1,
  base_contact_id: 42,
  mergee_contact_id: 87
)
  • base_contact_id — The contact that survives (keeps its ID)
  • mergee_contact_id — The contact that gets merged into the base (deleted)
  • Conversations, messages, and attributes from the mergee are transferred to the base

Deduplication workflow

1. contacts_search(q: "jane@company.com")
   → Returns contacts [42, 87] with same email

2. contacts_get(id: 42) → Check which has more data
   contacts_get(id: 87) → Compare

3. contacts_merge(base_contact_id: 42, mergee_contact_id: 87)
   → Contact 87's conversations now belong to contact 42

Contact-Inbox Relationships

List contactable inboxes

Find which inboxes a contact can be reached through:

contacts_contactable_inboxes(account_id: 1, id: 42)
→ [{ inbox: { id: 3, name: "Email" }, source_id: "jane@company.com" }, ...]

Link contact to inbox

Create a contact-inbox association:

contacts_create_contact_inbox(
  account_id: 1,
  id: 42,
  inbox_id: 5
)

This is needed to create conversations for a contact on a specific inbox channel.

Contact's Conversations

Get all conversations for a specific contact:

contacts_conversations(account_id: 1, id: 42)
→ List of conversations with this contact

Useful for getting a customer's full history before responding.

Deleting Contacts

contacts_delete(account_id: 1, id: 42)

⚠️ Destructive: Permanently removes the contact and their data. Consider merging instead if it's a duplicate.

Common Patterns

See FILTER_GUIDE.md for advanced contact filtering examples.

See EXAMPLES.md for real-world scenario walkthroughs.

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.