Skip to main content
By the end of this page you will be able to add a person as a contact, link their Slack and WhatsApp identities to one record, find and tag contacts, approve or block someone, and decide whether Ravi creates contacts on its own.

What a contact is

A contact is a person or an organization. Groups, channels, threads and sessions are not contacts; they are chats (see Instances and routing). Each contact has:
  • an id, 12 hex characters, for example 37d471eab289;
  • one or more identities: a phone number, a WhatsApp LID, a Slack member id (U...), a Telegram id, an email;
  • a status: allowed, pending, blocked or discovered;
  • tags, and properties such as name, email, notes and opt-out.
Contacts matter because a message is tied to a person only when the sender’s identity is linked to a contact. A sender without a contact gets no tools in that turn, and a contact can hold permission tags and grants. See Permissions.

Add a contact

--instance is the name of your Slack instance. Without --channel slack, Ravi refuses a Slack id and tells you to add the flags.
The command prints the new id:
add creates the contact with status allowed. Other options: --kind person|org, --agent <ids> (see Restricting to agents), and --channel telegram|email|whatsapp|phone. Telegram ids also need --instance.
contacts add --instance does not check that the instance exists. A typo leaves the identity attached to an instance that never receives messages, and the person is not recognized. Check the name with ravi instances list first.
Link every identity a person uses to the same contact, so their tags and grants follow them across channels:
--channel whatsapp with a number stores a phone identity; a WhatsApp LID is passed as lid:<digits>. contacts info lists every identity, and contacts check is the same command. To detach an identity, or to fold a duplicate record into another:

Find and inspect

Every command that takes <contact> accepts the contact id or any of its identities. list ends with a count by status, for example Total: 2 (2 returned, limit 50, offset 0; 2 allowed, 0 pending, 0 blocked, 0 discovered).

Tags, notes and properties

set accepts name, email, tags, notes, opt-out, source, allowed-agents and mode. Use - to clear name, email, source or allowed-agents. note appends an entry to the contact’s timeline. Tags are labels, except permission tags. permission-admin, permission-owner and permission-superadmin give admin:system:* while the contact is allowed, and a profile created with ravi permissions allow (a permission-<profile> tag) gives its capabilities the same way. They apply immediately, with no dry-run, so tag carefully. See Make yourself the owner.

Status

All status changes apply immediately:
These commands refuse group and chat ids. Approve a chat with ravi instances pending approve or add a route instead.
Blocking does not keep someone out on its own. Under an open policy a blocked contact’s messages still start turns, and native Slack never looks at contact status. In a chat that is not governed, a blocked contact who reaches the agent still gets the agent’s full ceiling. To keep people out, use entry policies and explicit routes (Instances and routing); on Slack, keep DMs on pairing and route only the people you trust.

Pending approvals

People land in review in two ways: contact intake creates them as pending, or a pairing policy holds their DM. Groups held by an allowlist policy show up in the same list as pending chats; approve those as described in Instances and routing.
instances pending approve marks the sender allowed, which releases WhatsApp DMs under pairing. reject is a dry-run (exit 3) until you pass --execute.
On native Slack, approving a held DM sender does not release their DMs: the pairing gate there needs an explicit route. See Connect Slack.

Contact intake

By default Ravi does not create contacts from incoming messages: an instance’s contactIntakeMode is off. Turn it on per instance:
With intake on, a new sender becomes a contact with status discovered or pending and their identity is linked. On WhatsApp this covers DMs, and group senders whose phone number the provider resolves. Default tags apply only when intake creates the contact.
Intake makes strangers resolvable. In a chat that is not governed, any sender who resolves to a contact gets the agent’s full ceiling, whatever their status. With intake off, unknown senders get no tools. Turn intake on only where entry policies already keep strangers out, or where the agent’s ceiling is narrow.
To create contacts for DMs that arrived before intake was on, run a backfill. It previews by default:
Backfill never creates contacts for groups, and never changes the status of allowed or blocked contacts.

Restricting to agents

--agent on add or approve, or set allowed-agents, stores a list of agents for the contact:
Only DMs that arrive through Omni, such as WhatsApp, check this list: a message from an allowed contact routed to an agent that is not on the list is dropped. Native Slack ignores it. To choose which agent answers whom, use routes (Instances and routing).

Reply mode

approve <contact> mention and set <contact> mode mention store a reply mode, shown as Mode in contacts info. No channel enforces it today: the agent does not filter replies by mention. In groups, whether the agent speaks up is left to its instructions, and on Slack every human message in a routed channel starts a turn.

Removing a contact