Tool reference
Chatway exposes 21 MCP tools. This page documents every one: its parameters, what it returns, the permission it needs, and when it asks for confirmation.
You do not normally call these yourself — your assistant does. Use this page when you are building an integration, debugging a failed call, or writing instructions that steer an assistant toward the right tool.
Tool index
| Tool | Permission | Confirmation |
|---|---|---|
list-conversations |
read_conversations |
— |
get-conversation |
read_conversations |
— |
list-conversation-messages |
read_conversation_messages |
— |
search-conversations |
read_conversations |
— |
get-visitor |
read_visitor_details |
— |
search-contacts |
search_contacts |
— |
search-knowledge-base |
search_knowledge_base |
— |
view-tags |
view_tags |
— |
view-custom-fields |
view_custom_fields |
— |
list-agents |
assign_conversations |
— |
send-message |
send_replies |
— |
resolve-conversation |
resolve_conversations |
Bulk |
unresolve-conversation |
unresolve_conversations |
Bulk |
assign-conversation |
assign_conversations |
Bulk |
add-note |
add_notes |
— |
add-tag |
add_tags |
— |
remove-tag |
remove_tags |
Always |
add-custom-data |
add_custom_data |
— |
update-custom-data |
update_custom_data |
— |
remove-custom-data |
remove_custom_data |
Always |
handoff-to-human |
request_human_handoff |
— |
Conventions
These rules apply to every tool.
| Identifiers | Every *_id is a UUID. |
| Scope | Results are always limited to the widgets and channels the connection was granted. A conversation outside that set behaves as if it does not exist. |
| Permissions | A tool is only published to the assistant if its permission was granted. Calling one without permission returns an error. |
| Rate limit | 120 requests per minute per connection, then 429. |
| Visibility | Inbox tools only appear once a live connection exists. A disconnected connection publishes none. The MCP server may still expose internal diagnostic tools to assistants only — these are not configurable in Chatway. |
Read tools are marked read-only, and resolve-conversation, remove-tag, and
remove-custom-data are marked destructive, so clients that surface those hints can warn you
before running them. No tool is marked idempotent — calling one twice does the work twice.
The confirmation flow
Five tools refuse to act until you approve. Instead of doing the work they return
confirmation_required: true with a confirmation_token, an affected_count, a plain-language
message, and expires_in_seconds. The assistant shows you the message, then repeats the call
with the token to proceed.
Tokens last 300 seconds and are bound to the exact arguments they were issued for, so an approval cannot be replayed against a different call.
| Tool | Asks when |
|---|---|
resolve-conversation |
Always — show the user the message, then retry with confirmation_token |
unresolve-conversation |
Always |
assign-conversation |
Always |
remove-tag |
Always |
remove-custom-data |
Always |
Read tools
list-conversations
Lists conversations newest first, with a preview of the last message. Call this before reading messages so newly created conversations are picked up.
Permission: read_conversations
| Parameter | Type | Required | Notes |
|---|---|---|---|
status |
string | No | all, unresolved, or resolved. Defaults to all. |
page |
integer | No | 1–10000. Defaults to 1. |
per_page |
integer | No | 1–100. Defaults to 25. |
Returns conversations and pagination.
Each conversation carries id, contact (id, name, email), last_message (id,
content, type, origin, sender_type, created_at), widget_id, origin, origin_url,
email_subject, is_resolved, resolved_at, ended_at, created_at, and updated_at.
pagination carries page, per_page, has_more, and next_page.
get-conversation
Gets one conversation with contact and assigned-agent detail.
Permission: read_conversations
| Parameter | Type | Required | Notes |
|---|---|---|---|
conversation_id |
string | Yes | UUID. |
Returns a single conversation object with everything list-conversations provides plus
contact.phone, contact.country, contact.language, contact.timezone, assigned_agents
(each id, name, email), message_count, social_account_identifier,
external_identifier, resolved_by, and reopened_at.
Errors: no permission; Conversation not found for the configured team.
list-conversation-messages
Lists the messages in one conversation, newest first, using cursor pagination.
Permission: read_conversation_messages
| Parameter | Type | Required | Notes |
|---|---|---|---|
conversation_id |
string | Yes | UUID. |
limit |
integer | No | 1–100. Defaults to 50. |
before_sort_number |
string | No | Cursor. Pass next_before_sort_number from the previous response. |
include_system_messages |
boolean | No | Defaults to false. |
include_internal_messages |
boolean | No | Defaults to false. |
Returns conversation_id, messages, and pagination.
Each message carries id, conversation_id, sort_number, sender (type, id, name,
email), origin, type, content, urls, parent_id, is_system_message, edited_at,
created_at, and updated_at. pagination carries limit, has_more, and
next_before_sort_number.
Note that system and internal notes are hidden unless you ask for them, so an assistant summarising a thread sees what the visitor saw by default.
search-conversations
Permission: read_conversations
| Parameter | Type | Required | Notes |
|---|---|---|---|
query |
string | Yes | 1–255 characters. |
limit |
integer | No | 1–50. Defaults to 20. |
Returns conversations, each with id, email_subject, origin, is_resolved, and
contact (id, name, email). This is a lighter shape than list-conversations — follow up
with get-conversation for full detail.
get-visitor
Permission: read_visitor_details
| Parameter | Type | Required | Notes |
|---|---|---|---|
visitor_id |
string | Yes | UUID. |
Returns visitor with id, name, email, phone, country, language, timezone,
widget_id, and created_at.
Errors: no permission; Visitor not found for the authorized sources.
search-contacts
Permission: search_contacts
| Parameter | Type | Required | Notes |
|---|---|---|---|
query |
string | Yes | 1–255 characters. |
limit |
integer | No | 1–50. Defaults to 20. |
Returns contacts, each with id, name, email, phone, and widget_id.
search-knowledge-base
Searches your FAQ and Help Center content — useful for grounding a reply in your own material instead of letting the model improvise.
Permission: search_knowledge_base
| Parameter | Type | Required | Notes |
|---|---|---|---|
query |
string | Yes | 1–255 characters. |
limit |
integer | No | 1–50. Defaults to 20. |
Returns results, each with id, question, and answer.
view-tags
Permission: view_tags
Takes no parameters. Returns tags, each with id, name, and color.
view-custom-fields
Permission: view_custom_fields
Takes no parameters. Returns custom_fields, each with id and name.
list-agents
Lists teammates so the assistant can resolve a name like "Nibir" to an agent UUID before assigning. Deactivated agents are omitted.
Permission: assign_conversations
| Parameter | Type | Required | Notes |
|---|---|---|---|
query |
string | No | Filter by name or email (partial match). |
limit |
integer | No | Max results (default 50, max 100). |
Returns agents, each with id, name, email, status, and online_status.
Write tools
send-message
Sends a reply into a conversation. The message is posted as the connection's Send Replies as agent, so it appears to the visitor like any other agent reply.
Permission: send_replies
| Parameter | Type | Required | Notes |
|---|---|---|---|
conversation_id |
string | Yes | UUID. |
content |
string | Yes | 1–10,000 characters. |
Returns message with id, conversation_id, content, type, and created_at.
Errors: no permission; conversation not found; No agent is configured for this connection.;
human handoff already requested for this conversation. Chatway also rejects sends that are not
allowed for the conversation's current state, passing through its own explanation.
After handoff-to-human (or Chatway AI's own handoff) has been requested, External AI cannot
send further replies on that conversation until the handoff is cleared.
resolve-conversation
Permission: resolve_conversations · Confirmation: always · Bulk queue: when more than one conversation
| Parameter | Type | Required | Notes |
|---|---|---|---|
conversation_ids |
array of string | Yes | 1–100 UUIDs. Pass all targets in one call — do not loop single resolves. |
confirmation_token |
string | No | Required on the second call after the user approves the challenge. |
Returns resolved_conversation_ids for a single conversation. For two or more, returns
queued: true, queued_conversation_ids, and skipped_conversation_ids — each conversation is
processed in its own background job.
The first call always returns confirmation_required: true with a plain-language message, for
example:
This action will resolve 100 conversations. Are you sure?
Show that message to the user. After they approve, call again with the same arguments plus
confirmation_token.
unresolve-conversation
Permission: unresolve_conversations · Confirmation: always · Bulk queue: when more than one conversation
| Parameter | Type | Required | Notes |
|---|---|---|---|
conversation_ids |
array of string | Yes | 1–100 UUIDs. |
confirmation_token |
string | No | Required on the second call after the user approves the challenge. |
Returns unresolved_conversation_ids for a single conversation. For two or more, returns
queued: true with queued_conversation_ids and skipped_conversation_ids (one background job
per conversation).
assign-conversation
Assigns or unassigns a teammate. Prefer agent_query when the user names someone ("assign
Nibir"); use list-agents first if you need to browse the roster or the match is ambiguous.
Permission: assign_conversations · Confirmation: always · Bulk queue: when more than one conversation
| Parameter | Type | Required | Notes |
|---|---|---|---|
conversation_ids |
array of string | Yes | 1–100 UUIDs. |
agent_id |
string | One of | UUID of an agent on your team. Required unless agent_query is set. |
agent_query |
string | One of | Name or email to resolve (e.g. Nibir). Required unless agent_id is set. |
confirmation_token |
string | No | Required on the second call after the user approves the challenge. |
Returns agent_id, agent (id, name, email), and assigned_conversation_ids for a
single conversation. For two or more, returns queued: true with queued_conversation_ids and
skipped_conversation_ids (one background job per conversation).
When several teammates match agent_query, the tool returns ambiguous: true with a
candidates list instead of assigning — call again with the chosen agent_id.
Errors: no permission; Agent not found for this team.; no match for agent_query.
add-note
Adds a private internal note. Notes are never shown to the visitor.
Permission: add_notes
| Parameter | Type | Required | Notes |
|---|---|---|---|
conversation_id |
string | Yes | UUID. |
content |
string | Yes | 1–10,000 characters. |
Returns note with id, conversation_id, content, and created_at.
Errors: no permission; conversation not found; The authenticated user does not have an agent profile.
add-tag
Tags the visitor on a conversation. Creates the tag if it does not exist yet.
Permission: add_tags
| Parameter | Type | Required | Notes |
|---|---|---|---|
conversation_id |
string | Yes | UUID. |
name |
string | Yes | Up to 100 characters. |
color |
string | No | Up to 50 characters. |
Returns conversation_id, chat_contact_id, and tag.
Errors: no permission; conversation not found; This conversation has no visitor/contact to tag.
remove-tag
Permission: remove_tags · Confirmation: always
| Parameter | Type | Required | Notes |
|---|---|---|---|
conversation_id |
string | Yes | UUID. |
name |
string | Yes | Up to 100 characters. |
confirmation_token |
string | No | Required on the second call. |
Returns conversation_id, chat_contact_id, and removed_tag.
Every call is confirmed, even for a single tag:
This action will remove the tag "refund". Are you sure?
add-custom-data
Sets a custom field value on a visitor. Note this targets a visitor, not a conversation.
Permission: add_custom_data
| Parameter | Type | Required | Notes |
|---|---|---|---|
visitor_id |
string | Yes | UUID. |
name |
string | Yes | Up to 100 characters. |
value |
string | Yes | Up to 1,000 characters. |
Returns visitor_id, name, and value.
update-custom-data
Same parameters and return shape as add-custom-data, for changing a value that already exists.
Permission: update_custom_data
| Parameter | Type | Required | Notes |
|---|---|---|---|
visitor_id |
string | Yes | UUID. |
name |
string | Yes | Up to 100 characters. |
value |
string | Yes | Up to 1,000 characters. |
Returns visitor_id, name, and value.
remove-custom-data
Permission: remove_custom_data · Confirmation: always
| Parameter | Type | Required | Notes |
|---|---|---|---|
visitor_id |
string | Yes | UUID. |
name |
string | Yes | Up to 100 characters. |
confirmation_token |
string | No | Required on the second call. |
Returns visitor_id and removed_field.
handoff-to-human
Escalates a conversation to a human using the same handover flow as Chatway's built-in AI agent, so your team gets the notifications and inbox state they already expect.
Permission: request_human_handoff
| Parameter | Type | Required | Notes |
|---|---|---|---|
conversation_id |
string | Yes | UUID. |
Returns conversation_id and status, where status is handoff_requested.
Common workflows
Triage the unresolved queue. list-conversations with status: unresolved, then
list-conversation-messages on each interesting one, then add-tag or assign-conversation
(use list-agents or agent_query when assigning by name).
Answer from your own docs. list-conversation-messages to read the question,
search-knowledge-base to find the answer, send-message to reply.
Find a customer's history. search-contacts to get the visitor, get-visitor for their
profile, search-conversations for their past threads.
Close out a batch. search-conversations to gather candidates, resolve-conversation with
all the IDs, then confirm when asked.
Related pages
- Permissions & access — which permission unlocks which tool.
- MCP overview — how MCP compares to webhooks and the REST API.