MCP App Store
by KeenEthics
Productivity
toflow.ai icon

toflow.ai

by Toflow Labs Pvt Ltd

Overview

Connect to toflow.ai to prospect, enrich, and run multi-channel outreach, all through ChatGPT. Search for people and companies using filters like title, seniority, industry, company size, and location. Enrich contacts to find verified emails, phone numbers, and LinkedIn profiles. Build and manage lists, then add contacts to outreach sequences via email, LinkedIn, and WhatsApp. Create deals, log calls, create tasks, and track email opens without leaving the chat.

Tools

add_companies_to_list

ChatGPT
Add companies to a list using LinkedIn URL or website as the unique identifier. Each entry in companies must include at least one of: - linkedin_url — primary deduplication key - website — fallback deduplication key Optional fields used when creating a new record: - name (required if no existing match is found — used to create the company) - description - employee_range ("1", "1-10", "11-50", "51-200", "201-500", "501-1,000", "1,001-5,000", "5,001-10,000", "10,001+") Behaviour: - Dedup order: linkedin_url first, then website (case-insensitive match). - If a matching company exists → reuse, no duplicate created. - If new and name is provided → create a minimal record, then add to list. - If new and name is missing → skip with error. - If already in the list → silently skipped. Returns a summary: total processed, added, already in list, newly created, errors. After any follow-up bulk action on this list's members (attribute update), proactively suggest creating a focused filtered view — see the LISTS section of the server instructions for details.

add_people_to_list

ChatGPT
Add people to a list using LinkedIn URL as the unique identifier. Each entry in people must include: - linkedin_url (required) — unique identifier for deduplication Optional fields used when creating a new record: - first_name - last_name - email - job_title - description Behaviour: - If a person with the same LinkedIn URL already exists → reuse, no duplicate created. - If the person is new → a minimal record is created, then added to the list. - If the person is already in the list → silently skipped (no duplicate list entry). Returns a summary: total processed, added, already in list, newly created, errors. After any follow-up bulk action on this list's members (email enrichment, phone enrichment, attribute update), proactively suggest creating a focused filtered view — see the LISTS section of the server instructions for details.

add_person_to_deal

ChatGPT
Associate a person (contact) with a deal. Links an existing person record to an existing deal. A deal can have multiple people associated with it.

add_records_to_list

ChatGPT
Add existing records to a list by their IDs. Use this when you already have record IDs and want to add them to a list directly — no deduplication or record creation is performed. Typical use case: bulk_create succeeded but the automatic list add failed — pass the returned IDs here to retry adding them to the list. resource_type: "person" | "company" | "deal" — must match the list's resource type. resource_ids: list of record IDs to add. Already-present IDs are silently skipped (no duplicates created).

bulk_create

ChatGPT
Bulk create records (companies, people, or deals). Call get_resource_schema first to get attribute IDs, then pass records as a list of dicts where each key is an attribute_id (string) and value is the field value. resource_type: "company" | "person" | "deal"

bulk_enrich_emails

ChatGPT
Find email addresses for multiple people at once. Accepts a list of person_ids (max 50). For each person: - If email already exists → skipped (no credit charge) - If LinkedIn URL available → enqueues enrichment task - If no LinkedIn URL → failed with error message Returns task_ids for queued enrichments. Enrichment runs asynchronously. IMPORTANT — do NOT call get_bulk_enrichment_status immediately. After this tool returns, tell the user: "Enrichment has been queued for N people. Please check back in at least [N × 30] seconds before asking for the status." Do not call get_bulk_enrichment_status until the user explicitly asks for the results after waiting the recommended time. Credit cost: 1 credit per person actually enriched (skipped = free).

bulk_enrich_list

ChatGPT
Enrich all people in a list for a given enrichment type. enrichment_type must be one of: - "email" — find email addresses (1 credit per person enriched) - "phone" — find phone numbers (10 credits per person enriched) - "profile" — fill job_title and description from LinkedIn (0.2 credits per person enriched) For each person in the list: - Already has the requested data → skipped (no credit charge) - No LinkedIn URL stored → failed (cannot enrich without it) - Otherwise → queued for async enrichment Credits are only charged when data is actually found (not on enqueue). Use get_bulk_enrichment_status(task_ids) to check results after waiting at least [N × 30] seconds, where N is the number of queued people. MANDATORY — you MUST call estimate_bulk_enrich_list(list_id, enrichment_type) before calling this tool. Show the credit estimate to the user and get their explicit confirmation before proceeding. Never call this tool without first completing that step. IMPORTANT — do NOT call get_bulk_enrichment_status immediately after this tool returns. Tell the user enrichment has been queued and ask them to check back after the recommended wait time.

bulk_enrich_phones

ChatGPT
Find phone numbers for multiple people at once. Accepts a list of person_ids (max 50). For each person: - If phone already exists → skipped (no credit charge) - If LinkedIn URL available → enqueues enrichment task - If no LinkedIn URL → failed with error message Returns task_ids for queued enrichments. Enrichment runs asynchronously. IMPORTANT — do NOT call get_bulk_enrichment_status immediately. After this tool returns, tell the user: "Enrichment has been queued for N people. Please check back in at least [N × 30] seconds before asking for the status." Do not call get_bulk_enrichment_status until the user explicitly asks for the results after waiting the recommended time. Credit cost: 10 credits per person actually enriched (skipped = free).

check_linkedin_connection

ChatGPT
Check LinkedIn connection status with a CRM person. Use this before deciding the outreach channel: - "connected" → use send_linkedin_message in an existing thread - "no_invitation" → use send_connection_request for cold outreach - "pending" → connection request already sent; wait for acceptance - "ignored" → request was ignored; consider InMail if premium account Parameters - person_id: CRM person to check (must have a LinkedIn URL). - message_account_id: Your LinkedIn message account to check from.

comment_on_linkedin_post

ChatGPT
Post a comment on a LinkedIn post. Supports all LinkedIn post URL formats (same as get_linkedin_post). Rate limits — enforced server-side - 30s ± 15s gap between comments (jitter). - Max 10 comments per 15-minute window; 15-minute cooldown once exhausted. - Max 50 comments per 24 hours per account. - If rate limited: STOP, read the retry time from the error, tell the user. Parameters - message_account_id: ID of a connected LinkedIn account (from list_message_accounts). - post_url: Full LinkedIn post URL. - comment_text: The comment text (max 1250 characters). Writing the comment - If the user hasn't given you the post's content or a comment to post, call get_linkedin_post first to fetch it — never guess at what the post says from the URL alone. - Sound like a real person, not generated copy: short, casual, no filler. - No em dashes. Use a comma, period, or just start a new sentence. - Avoid AI tells: "delve", "seamless", "robust", "unlock", "game-changer", overly polished parallel structure, or generic enthusiasm with no specific detail from the post. Workflow 1. Call list_message_accounts(provider_type="linkedin") to get a connected account. 2. If needed, call get_linkedin_post to read the post before composing a comment. 3. Compose the comment and show it to the user for approval. 4. Only call this tool once the user explicitly approves.

create_ai_enrichment

ChatGPT
Create a new AI enrichment configuration. MANDATORY: call get_ai_enrichment_guide first for model options, template variables, and approval steps. resource_type: "person" | "company" | "deal". base_prompt is REQUIRED — provide a non-empty system-level prompt. field_mappings: [{"output_field": "<col>", "target_attribute_id": <int>, "attribute_prompt": "<required>", "is_enabled": true}]

create_attribute

ChatGPT
Create a new custom attribute (field) for a CRM resource type. resource_type: "person" | "company" | "deal" attribute_type: text | number | currency | date | datetime | boolean | email | phone | url | select | multiselect | record_reference CONFIG — required for certain types: select / multiselect: config={"options": [{"value": "1", "label": "Low"}, {"value": "2", "label": "High"}]} currency: config={"currency_code": "USD"} record_reference: config={"reference_resource": "person" | "company" | "deal", "is_multiselect": false} WORKFLOW: 1. Call list_attributes(resource_type=...) to confirm the field does not already exist. 2. Confirm title, type, and config with the user. 3. Show "Create '{title}' ({attribute_type}) field for {resource_type}?" and wait for explicit user approval before calling this tool.

create_dashboard

ChatGPT
Create a new dashboard. Call this when list_dashboards returns an empty list or when the user explicitly asks to create a new dashboard for their report. BEFORE CALLING: confirm the dashboard name with the user — do not invent one. AFTER CALLING: use the returned id as dashboard_id in create_report. Share the url with the user so they can open the new dashboard. name: Display name for the dashboard — must be unique in the workspace description: Optional description of what this dashboard is for

create_list

ChatGPT
Create a new list for people, companies, or deals. resource_type: "person" | "company" | "deal" Returns the created list ID — use it with add_people_to_list or add_companies_to_list.

create_note

ChatGPT
Create a new note. WORKFLOW — follow these steps before calling: 1. Confirm the person / company / deal context with the user if relevant. 2. Show the user a summary: "Create note '{title}' on [context]?" and wait for explicit approval before calling this tool. The note is attributed to the current user (owner_id = actor_id).

create_record

ChatGPT
Create a new record (person, company, or deal). resource_type: "person" | "company" | "deal" Call record_schema(resource_type=<resource_type>) first to see all available fields, which are required, and allowed values for select fields. Workflow: 1. Read the schema to find required fields. 2. ALWAYS ask the user for any required field they did NOT provide — never auto-resolve or assume a value. Wait for the user's reply before proceeding. 3. Once the user provides a value: - If the field is a record_reference, use the appropriate lookup tool to resolve the name the user gave into a numeric ID: reference_resource=pipeline → list_pipelines reference_resource=stage → list_pipelines first, then list_stages(pipeline_id) reference_resource=workspace_member → list_workspace_members reference_resource=person → list_records(resource_type="person", search=<name>) * reference_resource=company → list_records(resource_type="company", search=<name>) - For "Categories" field (company only): call list_company_categories to get existing category IDs, or get_or_create_category(name=<name>) to resolve a name to an ID. Pass the resolved IDs as a list: {"title": "Categories", "value": [12, 34]} - For other types (text, select, etc.), use the value directly. 4. For optional fields the user did NOT mention, omit them entirely — do NOT ask, assume, or look them up. IMPORTANT: attributes must be a JSON object, NOT a string. Example: { "resource_type": "person", "attributes": { "items": [ {"title": "First Name", "value": "John"}, {"title": "Last Name", "value": "Smith"}, {"title": "Email Addresses", "value": "john@acme.com"} ] } }

create_report

ChatGPT
Save a report permanently to a dashboard. PREREQUISITES — do not call this unless ALL of the following are true: 1. validate_and_preview_report returned valid=true. 2. You showed the preview_rows to the user. 3. The user explicitly confirmed they want to save (e.g. "yes", "save it", "looks good"). If dashboard_id is unknown, call list_dashboards first and ask the user which dashboard they want the report placed on. If no dashboards exist, call create_dashboard to create one before calling this tool. AFTER CALLING: share the url from the response so the user can open the dashboard. dashboard_id: ID from list_dashboards name: Unique name within the dashboard — ask the user if they have not provided one dataset_id: ID from list_datasets query / chart / filters / timezone: use the exact same values as the validated preview

create_sequence

ChatGPT
Create a sequence with any mix of node types. MANDATORY: call get_sequence_creation_guide first and follow all steps before calling this tool. Do not call this tool until all guide steps are complete and the user has approved the final plan. nodes: list of node dicts — required. edges: list of edge dicts connecting the nodes — required. scheduling_config: optional dict with timezone_id, send_window_start, send_window_end, send_on_weekends, thread_emails, email_verification, open_tracking, holiday_ranges.

create_task

ChatGPT
Create a new task. due_date must be an ISO 8601 string, e.g. "2026-03-15" or "2026-03-15T09:00:00Z". Dates without time are treated as midnight UTC. WORKFLOW — follow these steps before calling: 1. Confirm person / company / deal context with the user if relevant. 2. Confirm the due date. 3. Show the user: "Create task '{title}' due {due_date}?" and wait for explicit approval before calling this tool. assignee_id defaults to the current user when not provided.

create_view

ChatGPT
Create a new saved view for a specific list. MANDATORY: call get_view_creation_guide first for the required workflow and parameter reference.

delete_attribute

ChatGPT
Permanently delete a custom attribute and all its stored values across all records. System attributes (is_system=true) cannot be deleted. To hide a field without losing data, use update_attribute with is_archived=true instead. Ask the user to confirm before calling this tool: "Are you sure you want to permanently delete attribute {attribute_id}? This will remove all stored values for this field across all records." Only call once the user explicitly approves.

delete_call

ChatGPT
Delete a call record permanently. Ask the user to confirm before calling this tool: "Are you sure you want to delete call {call_id}?" Only call once the user explicitly approves.

delete_company

ChatGPT
Soft-delete a company from the workspace. The company is removed from all lists and marked as deleted. This action cannot be undone from the MCP interface — always confirm with the user before calling this tool.

delete_deal

ChatGPT
Soft-delete a deal from the workspace. The deal is removed from all lists and marked as deleted. This action cannot be undone from the MCP interface — always confirm with the user before calling this tool.

delete_draft

ChatGPT
Delete a draft email permanently. Only draft emails can be deleted via this tool. This action cannot be undone — always confirm with the user before calling.

delete_list

ChatGPT
Delete a list (soft delete). This action cannot be undone via MCP.

delete_message_draft

ChatGPT
Delete a draft LinkedIn or WhatsApp message permanently. Only draft messages (status="draft") can be deleted via this tool. This action cannot be undone — always confirm with the user before calling. Parameters - message_id: ID of the draft message to delete (from send_linkedin_message or send_whatsapp_message with draft=True).

delete_note

ChatGPT
Delete a note permanently. Ask the user to confirm before calling this tool: "Are you sure you want to delete note {note_id}?" Only call once the user explicitly approves.

delete_person

ChatGPT
Soft-delete a person from the workspace. The person is removed from all lists and marked as deleted. This action cannot be undone from the MCP interface — always confirm with the user before calling this tool.

delete_task

ChatGPT
Delete a task permanently. Ask the user to confirm before calling this tool: "Are you sure you want to delete task {task_id}?" Only call once the user explicitly approves.

draft_email

ChatGPT
Draft an email in the workspace. MANDATORY: call get_draft_email_guide first and follow every step exactly. Optionally link the draft to a CRM person by passing person_id. Returns the draft email ID and a url — share the url with the user after drafting.

enrich_person_by_linkedin

ChatGPT
Get or enrich a person's profile using their LinkedIn URL. Searches for an existing person in the workspace with that LinkedIn URL. - If found and already has job_title + description: returns the existing data immediately with status "already_enriched" — no Bitscale call made. - If found but missing job_title or description: enriches and updates the existing record. - If not found: runs enrichment and automatically creates a new person record from the returned data. Enriched fields include: job_title, description, location, linkedin_url, company_name, company_website, company_linkedin_url, company_description. Works with both regular LinkedIn profile URLs and Sales Navigator URLs. Providing first_name / last_name is optional but improves match accuracy. Waits up to 60 seconds for Bitscale to respond. If it times out, call get_person_enrichment_status(task_id) to check the result — but at most 3 times (waiting ~3 s between calls). Stop after 3 attempts and tell the user to retry manually later. IMPORTANT — after this tool returns: - Always show the enriched data to the user in a readable format. - If created_new_person is true, explicitly tell the user: "A new person record has been created in toflow with this data." - If status is "already_enriched", tell the user the person already exists and show their current profile data. - Otherwise confirm the existing record was updated with fresh data.

enrich_person_email

ChatGPT
Find an email address for a person. Identifies the person using person_id, linkedin_url, or name (checked in that order). At least one must be provided. - person_id: uses the existing record directly. - linkedin_url: looks up the person in the workspace; if not found, automatically enriches their profile and creates the record first, then finds the email address. - first_name / last_name only: searches the workspace. If exactly one match is found the email lookup proceeds. If none are found, the tool asks for a LinkedIn URL. If multiple are found, it returns the candidates and asks for person_id. IMPORTANT — after this tool returns: - Always show the email address (or not-found result) to the user. - If the person did not previously exist and was created automatically (profile_task_id is present in the response), explicitly tell the user: "A new person record was created in toflow before finding the email." - Always confirm with the user that the record and contact data look correct. - If enriching emails for multiple people in a list, after finishing ALL calls suggest a focused filtered view — see the LISTS section of the server instructions for details. A LinkedIn URL must be resolvable (stored or provided) before email enrichment can run — it is required by the enrichment provider. Waits up to 80 s total (40 s per phase). If it times out, call get_person_enrichment_status(task_id) to check the result — but at most 3 times (waiting ~3 s between calls). Stop after 3 attempts and tell the user to retry manually later.

enrich_person_phone

ChatGPT
Find a phone number for a person. Identifies the person using person_id, linkedin_url, or name (checked in that order). At least one must be provided. - person_id: uses the existing record directly. - linkedin_url: looks up the person in the workspace; if not found, automatically enriches their profile and creates the record first, then finds the phone number. - first_name / last_name only: searches the workspace. If exactly one match is found the phone lookup proceeds. If none are found, the tool asks for a LinkedIn URL. If multiple are found, it returns the candidates and asks for person_id. A LinkedIn URL must be resolvable (stored or provided) before phone enrichment can run — it is required by the enrichment provider. Waits up to 80 s total (40 s per phase). If it times out, call get_person_enrichment_status(task_id) to check the result — but at most 3 times (waiting ~3 s between calls). Stop after 3 attempts and tell the user to retry manually later. IMPORTANT — after this tool returns: - Always show the phone number (or not-found result) to the user. - If the person did not previously exist and was created automatically (profile_task_id is present in the response), explicitly tell the user: "A new person record was created in toflow before finding the phone." - Always confirm with the user that the record and contact data look correct. - If enriching phones for multiple people in a list, after finishing ALL calls suggest a focused filtered view — see the LISTS section of the server instructions for details.

enroll_in_sequence

ChatGPT
Enroll a person in a sequence. MANDATORY: call get_enroll_in_sequence_guide first and follow every step exactly. Do not call this tool until all guide steps are complete.

estimate_bulk_enrich_list

ChatGPT
Show the credit cost of bulk_enrich_list before it runs. MANDATORY — call this before bulk_enrich_list. Show the result to the user and get explicit confirmation before proceeding. enrichment_type: "email" (2 cr), "phone" (20 cr), or "profile" (1 cr).

filter_guide

ChatGPT
Filter, sort, and list_id reference for all list_* tools. Call this before calling list_records when you need to filter, sort, or scope results to a list.

forward_email

ChatGPT
Forward an email to new recipients. Forwards the original email as-is — no additional message or signature is added. The subject is prefixed with "Fwd:" automatically. Non-inline attachments from the original email are carried over. Call list_connected_accounts first to get available sending accounts if you don't know which from_email to use. Only call this tool once the user explicitly confirms they want to forward. After forwarding, share the url with the user as a clickable link.

get_account_load_stats

ChatGPT
Get current load stats for sending accounts. Extract the IDs from the list_connected_accounts response and pass them here: - email_account_ids: [a.id for a in list_connected_accounts_result.email] - linkedin_account_ids: [a.id for a in list_connected_accounts_result.linkedin] - whatsapp_account_ids: [a.id for a in list_connected_accounts_result.whatsapp] Pass an empty list [] for channels with no accounts. Do NOT omit the parameters or pass None — omitting them returns no stats for that channel. For each account it returns: - active_enrollments: how many people are currently active/queued in sequences that use this account at this channel's current step - today: enrollments whose next step for this account is scheduled today - tomorrow: enrollments scheduled tomorrow - this_week: enrollments scheduled within the next 7 days Use these stats to recommend less-loaded accounts to the user. An account with high active_enrollments or today count is already carrying significant load — prefer accounts with lower values when the user has not expressed a preference. When presenting to the user, look up the label or identifier from your list_connected_accounts results using account_id — never show a raw account_id.

get_ai_enrichment

ChatGPT
Get a single AI enrichment configuration by provider_id. Use this before update_ai_enrichment to fetch the full current config — especially the complete field_mappings list — so you can pass all mappings back with only the desired ones modified.

get_ai_enrichment_guide

ChatGPT
Get the guide for creating an AI enrichment — model options, template variables, and approval steps. Call this BEFORE create_ai_enrichment and follow every step exactly.

get_all_lists

ChatGPT
List all accessible lists in the workspace. Optionally filter by resource_type: "person" | "company" | "deal" Returns list IDs, names, resource types, and item counts.

get_attribute

ChatGPT
Retrieve a single attribute by its ID.

get_bulk_enrichment_status

ChatGPT
Check status of multiple enrichment tasks at once. Pass the task_ids returned by bulk_enrich_emails or bulk_enrich_phones. Returns current status for each task (pending / completed / failed). IMPORTANT — do NOT call this immediately after bulk_enrich_emails or bulk_enrich_phones. Only call this tool when the user explicitly asks for the results, and only after they have waited at least [N × 30] seconds where N is the number of people in the original batch.

get_call

ChatGPT
Retrieve a single call by its ID. Returns full call details including linked person, company, deal, phone number, outcome, duration, notes, and assignee.

get_company

ChatGPT
Get a single company by ID with full profile. IMPORTANT: Use this tool for a SINGLE company only. If you need data for multiple companies, do NOT call this tool in a loop. Instead, call list_records(resource_type="company", ids=[id1, id2, ...]) once to fetch all of them in a single request.

get_deal

ChatGPT
Get a single deal by ID with full profile. IMPORTANT: Use this tool for a SINGLE deal only. If you need data for multiple deals, do NOT call this tool in a loop. Instead, call list_records(resource_type="deal", ids=[id1, id2, ...]) once to fetch all of them in a single request.

get_draft_email_guide

ChatGPT
Get the mandatory step-by-step guide for drafting an email. Call this BEFORE draft_email and follow every step exactly.

get_email

ChatGPT
Get a single email by ID — returns subject, body, recipients, status, and thread info.

get_email_tracking

ChatGPT
Get open tracking statistics for a sent email. Returns whether it was opened, total opens, and first/last open timestamps. Timestamps are returned in the member's configured timezone (UTC if not set). Use this to answer "did they open my email?" before deciding on follow-up.

get_enroll_in_sequence_guide

ChatGPT
Get the mandatory step-by-step guide for enrolling a person in a sequence. Call this BEFORE enroll_in_sequence and follow every step in the response exactly.

get_enrollment

ChatGPT
Get details of a specific sequence enrollment. Returns status, current node, next execution time, and per-node personalizations. Use the enrollment_id returned from enroll_in_sequence.

get_linkedin_person_posts

ChatGPT
Fetch one page of LinkedIn posts written by a CRM person. Always fetches 20 posts per page — enforced server-side. Pass the returned cursor on the next call to paginate. Workflow 1. Call list_message_accounts(provider_type="linkedin") to get a connected account. 2. Pass the returned cursor back on the next call to paginate. Rate limits — enforced server-side - 30s ± 15s gap between pages (jitter). - Max 10 pages per 15-minute window; 15-minute cooldown once exhausted. - Max 50 pages per 24 hours per account. - If rate limited: STOP, read the retry time from the error, tell the user. Parameters - message_account_id: ID of a connected LinkedIn account. - person_id: CRM person ID — must have a LinkedIn URL set. - cursor: Pagination cursor from the previous response. Omit for page 1. Notes Each post includes social_id which can be passed to get_linkedin_post_comments or get_linkedin_post_reactions.

get_linkedin_post

ChatGPT
Fetch details of a LinkedIn post from its URL. Supports all LinkedIn post URL formats: - https://www.linkedin.com/feed/update/urn:li:activity:{id}/ - https://www.linkedin.com/posts/...-ugcPost-{id}-... - https://www.linkedin.com/posts/...-share-{id}-... Rate limits — enforced server-side - 30s ± 15s gap between fetches (jitter). - Max 10 fetches per 15-minute window; 15-minute cooldown once exhausted. - Max 50 fetches per 24 hours per account. - If rate limited: STOP, read the retry time from the error, tell the user. Parameters - message_account_id: ID of a connected LinkedIn account (from list_message_accounts). - post_url: Full LinkedIn post URL. Response Returns post details including author, text, comment/reaction counts, and the canonical social_id (urn:li:activity:{id}).

get_linkedin_post_comments

ChatGPT
Fetch one page of comments on a LinkedIn post. Always fetches 50 comments per page — enforced server-side. Pass the returned cursor on the next call to paginate. Workflow 1. Call list_message_accounts(provider_type="linkedin") to get a connected account. 2. Pass the returned cursor back on the next call to paginate. Rate limits — enforced server-side - 30s ± 15s gap between pages (jitter). - Max 10 pages per 15-minute window; 15-minute cooldown once exhausted. - Max 50 pages per 24 hours per account. - If rate limited: STOP, read the retry time from the error, tell the user. Parameters - message_account_id: ID of a connected LinkedIn account. - post_url: Full LinkedIn post URL (any supported format). - cursor: Pagination cursor from the previous response. Omit for page 1. Importing commenters Use author_details.id to look up the commenter's profile. Skip entries where author_details is null.

get_linkedin_post_reactions

ChatGPT
Fetch one page of reactions on a LinkedIn post. Always fetches 50 reactions per page — enforced server-side. Pass the returned paging.cursor on the next call to paginate. Workflow 1. Call list_message_accounts(provider_type="linkedin") to get a connected account. 2. Pass paging.cursor back on the next call to paginate. Rate limits — enforced server-side - 30s ± 15s gap between pages (jitter). - Max 10 pages per 15-minute window; 15-minute cooldown once exhausted. - Max 50 pages per 24 hours per account. - If rate limited: STOP, read the retry time from the error, tell the user. Parameters - message_account_id: ID of a connected LinkedIn account. - post_url: Full LinkedIn post URL (any supported format). - cursor: Pagination cursor from paging.cursor of the previous response. Omit for page 1. Importing reactors Use author.id to look up the reactor's LinkedIn profile. author.type is "INDIVIDUAL" or "COMPANY".

get_linkedin_search_guide

ChatGPT
Get the guide for using search_linkedin — workflow, rate limits, and full filter reference. Call this BEFORE search_linkedin for filter syntax and rate-limit rules.

get_list_items

ChatGPT
Get items in a list with pagination. Returns the list metadata, resource IDs for the current page, and pagination info. Use get_person / get_company with those IDs to fetch full details, or use list_records for bulk retrieval with filters. page: page number (default 1) page_size: items per page (default 100)

get_message_thread

ChatGPT
Get a message thread with its full conversation history. Parameters - thread_id: The ID of the thread to retrieve. - message_limit: Max messages to return (default 50, max 100). Messages are ordered oldest-first so the conversation reads naturally.

get_note

ChatGPT
Retrieve a single note by its ID.

get_or_create_category

ChatGPT
Get an existing category by name or create it if it doesn't exist. Returns the category with its id. Use this before create_record or update_record when you have a category name but need the id. Name matching is case-insensitive.

get_person

ChatGPT
Get a single person (contact) by ID with full profile including all attributes. IMPORTANT: Use this tool for a SINGLE person only. If you need data for multiple people, do NOT call this tool in a loop. Instead, call list_records(resource_type="person", ids=[id1, id2, ...]) once to fetch all of them in a single request. Call record_schema(resource_type='person') to understand the fields returned. If you are about to draft an email to this person and their Company has a website, you MUST fetch that website before composing — use it to personalise the email.

get_person_enrichment_status

ChatGPT
Check the status of an enrichment task started by enrich_person_by_linkedin, enrich_person_phone, or enrich_person_email. Use this when any enrichment tool returned status='still_processing'. Returns the current status and enriched data if ready. Possible status values: - pending: enrichment not yet complete - success: enrichment completed, enriched_data contains the result - not_found: Bitscale found no data for the provided LinkedIn URL - failed / error: enrichment encountered an error IMPORTANT — polling limit: - Call this tool at most 3 times per task_id, waiting ~3 seconds between calls. - If status is still 'pending' after 3 attempts, stop polling and inform the user: "Enrichment is taking longer than expected. Please try again in a minute by calling get_person_enrichment_status with task_id='{task_id}'." - Never poll indefinitely — 3 calls is the hard limit.

get_report_guide

ChatGPT
Get the guide for validate_and_preview_report — prerequisites, query/chart/filter syntax, and post-call steps. Call this BEFORE validate_and_preview_report.

get_resource_schema

ChatGPT
Get the attribute schema for a resource type (company, person, deal). Returns attribute IDs and metadata needed to fill in records for bulk_create. Always call this before bulk_create so you know which attribute IDs to use.

get_sequence

ChatGPT
Get full details of a sequence including all nodes and edges. Use this before enrolling to understand the sequence structure: channel order, timing (wait_value, wait_unit), account config per node, and the intended tone and purpose of each step. The subject/body/message fields serve as a reference for intent — generate fresh content per person at enrollment time. The node_ids returned here are what you pass in node_personalizations when enrolling. For email nodes, check whether the config has from_account_ids (pool) or from_account_id (legacy). Pool nodes: omit from_account_id in personalizations — server assigns it.

get_sequence_analytics

ChatGPT
Get detailed analytics and conversion funnel for a sequence. Returns: - Top-level KPIs: enrolled, active, completed, open_rate, reply_rate - Per-step node breakdown: success, failed, pending, skipped, opened, accepted counts for every step (email, LinkedIn, WhatsApp, create_task, etc.) Field semantics per node type: email: opened = unique email opens linkedin_message / whatsapp_message: opened = read receipts or reply-inferred reads linkedin_connection_request / send_linkedin_connection: accepted = connections accepted by recipient (opened = 0) other node types: opened = 0, accepted = 0 - node_order: step IDs in logical display order (trigger excluded) - funnel: conversion funnel with enrolled → active → completed → contacted → sent → opened → replied counts Use this to answer questions like: - "How is my sequence performing?" - "What's the open rate / reply rate for this sequence?" - "Which step has the most failures?" - "How many people have completed the sequence?" Call list_sequences first to get a sequence_id if you don't have one.

get_sequence_creation_guide

ChatGPT
Get the mandatory step-by-step guide for creating a sequence. Call this BEFORE create_sequence and follow every step in the response exactly. Do not call create_sequence until all steps are complete and the user has approved the plan.

get_sequence_schema

ChatGPT
Get all available sequence node types, config fields, template variables, and scheduling config options. Always call this before create_sequence.

get_sequence_update_guide

ChatGPT
Get the mandatory step-by-step guide for updating a sequence. Call this BEFORE update_sequence whenever updating nodes, edges, or scheduling config. Follow every step in the response exactly before calling update_sequence.

get_signal_agent_guide

ChatGPT
Return a setup guide for a specific signal agent type. MANDATORY: call this before setup_signal_agent to understand prerequisites, ICP fields, and allowed values for the signal type you are configuring. - signal_type: the signal type to get the guide for. Currently supported: linkedin_profile_viewers, linkedin_connections, linkedin_hiring, linkedin_job_change, linkedin_post_keywords

get_task

ChatGPT
Retrieve a single task by its ID.

get_update_enrollment_guide

ChatGPT
Get the guide for updating a sequence enrollment's status or node content. Call this BEFORE update_enrollment when changing node content or account configuration.

get_view

ChatGPT
Get full details of a saved view by its ID. Returns the complete view configuration including name, layout, visible_fields, column_order, and the full saved filters. Use list_views first if you only know the view name and need its ID.

get_view_creation_guide

ChatGPT
Get the step-by-step guide for creating a saved view. Call this BEFORE create_view and follow every step exactly.

get_workspace

ChatGPT
Get the current workspace details and authenticated user info. Returns workspace name, slug, avatar URL, creation date, the authenticated member's identity (name, email, role), and the workspace credit balance. Use this tool to discover the workspace context at the start of a session or whenever you need the current member's role or credit balance.

linkedin_search_parameters

ChatGPT
Resolve LinkedIn filter IDs for a given filter type and keyword. LinkedIn search does not accept raw text for filter values — IDs must be resolved first via this tool before calling search_linkedin. Workflow 1. Call list_message_accounts(provider_type="linkedin") to get a connected LinkedIn account and its id — pass that as message_account_id. 2. Call this tool for each filter dimension you want to apply (e.g. LOCATION for "Mumbai", INDUSTRY for "SaaS"). For classic: use LOCATION, INDUSTRY, COMPANY. For sales_navigator: use REGION (not LOCATION), SALES_INDUSTRY (not INDUSTRY), COMPANY. 3. Use the returned id values as filter values in search_linkedin. Parameters - message_account_id: ID of a connected LinkedIn message account. - filter_type: The dimension to resolve. Classic options: LOCATION, COMPANY, INDUSTRY, JOB_TITLE, JOB_FUNCTION, SKILL, SCHOOL, CONNECTIONS, EMPLOYMENT_TYPE, SERVICE. Sales Navigator adds: REGION, SALES_INDUSTRY, DEPARTMENT, TECHNOLOGIES, GROUPS, PERSONA, ACCOUNT_LISTS, LEAD_LISTS, POSTAL_CODE. - keywords: Text to search within the filter type (e.g. "Mumbai"). - service: "classic" (default), "sales_navigator", or "recruiter". Case-insensitive. - limit: Number of suggestions to return (1–100, default 50).

list_ai_enrichments

ChatGPT
List all AI enrichment configurations for the workspace. Call this before run_ai_enrichment to get the provider_id of the config you want to run. Shows name, is_enabled, model, and field mappings for each.

list_attributes

ChatGPT
List workspace attributes (custom fields) with optional filters. Use resource_type to scope results to a specific CRM resource: - "person" → fields defined on contacts - "company" → fields defined on companies - "deal" → fields defined on deals Omit resource_type to retrieve attributes across all resource types. attribute_type values: text, number, currency, date, datetime, boolean, email, phone, url, select, multiselect, record_reference. Only active (non-archived) attributes are returned.

list_calls

ChatGPT
List calls with optional filters. Use call_group to answer time-horizon questions: - "What calls do I have today / are overdue?" → call_group="today" - "What calls do I have coming up?" → call_group="upcoming" - "Show all open calls" → call_group="inbox" - "Show past completed calls" → call_group="archive" call_outcome values: completed, cancelled, no_answer, voicemail call_type values: discovery, demo, follow_up, qualification, other call_direction values: inbound, outbound call_group values: today, overdue, upcoming, inbox, archive Filter by person_id, company_id, or deal_id to see calls linked to a specific record.

list_company_categories

ChatGPT
List all company categories available in the workspace. Returns each category's id and name. Use the id when setting categories on create_record or update_record.

list_connected_accounts

ChatGPT
List all connected sending accounts for the current user. Returns email accounts, LinkedIn accounts, and WhatsApp accounts with their IDs. Use the account ID as from_account_ids in node configs when creating sequences. LinkedIn accounts include a premium_type field: - null: basic LinkedIn account — cannot send InMail, use linkedin_message, send_linkedin_connection, or is_in_linkedin_network - "sales_navigator": Sales Navigator account — can send InMail - "recruiter": LinkedIn Recruiter account — can send InMail - "premium": LinkedIn Premium Business account — can send InMail Only use linkedin_inmail nodes with accounts that have a non-null premium_type.

list_dashboards

ChatGPT
Call this when you need a dashboard_id and the user has not specified one. AFTER CALLING: - If dashboards exist: present the list and ask which one to use. - If the list is empty: tell the user no dashboards exist yet and ask whether to create one — then call create_dashboard before create_report. - If only one dashboard exists, still confirm with the user before assuming.

list_datasets

ChatGPT
STEP 1 of report building — always call this before validate_and_preview_report. Returns every dataset with its exact field names, data types, and capabilities. Use the field names verbatim in query.group_by, query.metrics[].field, and filters[].field. Never guess or invent field names — only use what this returns. AFTER CALLING: - If the user has not specified which dataset they want, show them the list and ask before proceeding. - Note which fields have is_aggregatable=true (usable in query.metrics) and is_groupable=true (usable in query.group_by) for the chosen dataset.

list_email_events

ChatGPT
Get workspace-level email open analytics. Returns total emails sent, total opened, open rate, and total open events. Optionally filter by date range (ISO 8601 datetimes). Date range boundaries are interpreted in the member's configured timezone. Use this to monitor outreach performance across all sent emails.

list_emails

ChatGPT
List emails in the workspace with optional filters. Filters - status: "draft" | "sent" | "received" | "failed" — omit to return all. - person_id / company_id / deal_id: Scope to a CRM record. - thread_id: Return all emails in a specific thread — use this to fetch the full conversation context before replying. Available on each email returned by list_emails or get_email. - resource_type / resource_id: Generic CRM scoping — resource_type is one of "person", "company", "deal". Use together with resource_id. - owner_id: Filter by the workspace member who owns the email. - email_account_id: Filter emails sent/received from a specific connected account. - search: Free-text search on subject. Sorting - sort_by: "email_date" (default) | "sent_at" | "received_at" | "created_at" | "updated_at" | "subject" | "status" - sort_order: "desc" (default) | "asc"

list_enrollments

ChatGPT
List sequence enrollments filtered by sequence or person, with optional status filter. At least one of sequence_id or person_id must be provided. status: optional comma-separated filter, e.g. "active,queued" Valid values: active | queued | paused | completed | cancelled | failed | replied | invalid Use sequence_id to see all people enrolled in a sequence. Use person_id to see all sequences a person is enrolled in.

list_linkedin_connections

ChatGPT
Fetch one page of 1st-degree LinkedIn connections for a connected account. Always fetches exactly 25 connections per page — enforced server-side. Pass the returned cursor on the next call to paginate through further pages. Workflow 1. Call list_message_accounts(provider_type="linkedin") to get connected accounts. 2. Pass the returned cursor back on the next call to paginate. Rate limits — enforced server-side - 30s ± 15s gap between pages (jitter). - Max 10 pages per 15-minute window; 15-minute cooldown once exhausted. - Max 50 pages per 24 hours per account. - If rate limited: STOP, read the retry time from the error, tell the user. Parameters - message_account_id: ID of a connected LinkedIn message account. - cursor: Pagination cursor from the previous response. Omit for page 1.

list_message_accounts

ChatGPT
List all message accounts accessible to the current user (owned + shared). Parameters - provider_type: Optional filter — "linkedin" or "whatsapp". Omit to return accounts for all providers. Response fields (per account) - id: Account ID — pass this as message_account_id to sending tools. - provider_type: "linkedin" or "whatsapp". - account_identifier: LinkedIn profile URL or WhatsApp number. - account_label: Human-readable nickname (may be None). - status: Connection status — "connected" means ready to send. - is_primary: Whether this is the caller's current primary account for this provider. Sending tools require a primary account; if all accounts show is_primary=False, call set_primary_account first. - is_owner: True if this member owns the account; False if shared. - shared_by_member_id: ID of the owner who shared it (shared accounts only). Workflow hint If no account has is_primary=True for a provider, sending tools will fail with a validation error. Call set_primary_account to promote one account, then retry the send.

list_message_threads

ChatGPT
List LinkedIn (or WhatsApp) message threads with optional filters. Parameters - provider_type: Filter by provider — "linkedin" or "whatsapp". Omit to return threads from all connected accounts. - person_id: Filter threads for a specific CRM person. - page / page_size: Pagination (default: page=1, page_size=20). Notes The response includes message_account_id on each thread — use this when calling send_linkedin_message, send_connection_request, or send_inmail.

list_notes

ChatGPT
List notes for the workspace, with optional filters. Use person_id, company_id, or deal_id to scope notes to a specific CRM record. Use search to do a free-text search across note titles and content. Use person_id, company_id, or deal_id to scope notes to a specific CRM record — when scoped, all workspace notes for that record are returned. Without a scope filter, members only see their own notes.

list_pipelines

ChatGPT
List all sales pipelines in the workspace. Returns each pipeline's id, name, and description. Use the pipeline id when creating or filtering deals by pipeline.

list_records

ChatGPT
List records for any resource type. resource_type: "person" | "company" | "deal" BATCH FETCH BY ID — use ids instead of repeated get_* calls When you already have a list of record IDs (e.g. from a previous tool call, a task's input_data, or an enrichment result), pass them all at once via ids instead of calling get_person / get_company / get_deal once per ID. Example — fetch 10 people in one call: list_records(resource_type="person", ids=[101, 102, 103, 104, 105, 106, 107, 108, 109, 110]) ids stacks with all other parameters: you can combine it with filters, search, list_id, sort, and pagination just like any other filter. --- Call record_schema(resource_type=<resource_type>) for available field titles and allowed values. filters: list of filter condition dicts. Each condition must use one of these exact operators: "is", "is_not", "contains", "not_contains", "is_empty", "is_not_empty", "gt", "lt", "gte", "lte", "in" Do NOT use "eq", "equals", "neq" — use "is" and "is_not" instead. Example: [{"field": "Pipeline", "operator": "is", "value": "2"}] IMPORTANT: You MUST call filter_guide() before calling this tool for full filter/sort syntax, operators, and list_id usage. view_id: Apply a saved view's filters automatically. If you only know the view name, call list_views first to get its ID. Any filters passed alongside view_id are merged with the view's saved filters (view filters run first, then user filters are appended).

list_sequence_templates

ChatGPT
List all available sequence templates. Templates are pre-built sequence structures (nodes + edges + scheduling config) that can be used as a starting point when creating a new sequence. Each template includes a unique id, name, description, category, channels, and step count. Categories: email, linkedin, multi_channel Channels: email, linkedin, whatsapp Use the template id with create_sequence (pass nodes/edges from the template) or direct the user to the web app to import the template via the sequence creation dialog. Call get_sequence_schema first if you need to understand node config fields.

list_sequences

ChatGPT
List sequences in the workspace with pagination.

list_stages

ChatGPT
List all stages for a given pipeline. Call this after list_pipelines to get the stage IDs for a specific pipeline. Use the stage id when creating or updating a deal's Stage field.

list_tasks

ChatGPT
List tasks for the workspace, with optional filters. By default returns tasks assigned to the current user. Pass assignee_id to filter by a different workspace member. FOLLOW-UP QUERIES — use task_group to answer time-horizon questions: - "What do I need to follow up on today?" → task_group="today" (due today + overdue incomplete tasks) - "What's coming up this week / what should I work on next?" → task_group="upcoming" (due after today, incomplete only) - "Show me all my open tasks" → task_group="inbox" (all incomplete tasks regardless of date) - "Show me what I've completed" → task_group="archive" (completed tasks) task_group and status can be combined, e.g. task_group="today" + status="IN_PROGRESS" to see only in-progress tasks due today. status values: OPEN, IN_PROGRESS, COMPLETED, CANCELLED.

list_views

ChatGPT
List all saved views for a resource type or a specific list. WHEN TO CALL THIS TOOL Call this whenever the user mentions a view by name (e.g. "show me the Wednesday Outreach view", "fetch records from the Q1 view", "use the Active Leads view"). You must resolve the view name → view_id before calling list_records. REQUIRED WORKFLOW when a view is mentioned STEP 1 — If you don't already know the list_id, ask the user: "Which list does the '[view name]' view belong to?" Use get_all_lists to show available lists if needed. STEP 2 — Call list_views(list_id=<id>) to get all views for that list. Match the user's view name to find the view_id. STEP 3 — Call list_records(list_id=<id>, view_id=<view_id>) to fetch records with that view's saved filters applied. Parameters Provide exactly one of: resource_type : "person" | "company" | "deal" — global resource views list_id : ID of a specific list — list-scoped views Returns id, name, layout, is_default, and has_filters for each view. Match by name to find the view_id you need.

list_workspace_members

ChatGPT
List all active workspace members in the workspace. Use the member id when setting a workspace_member record_reference field (e.g. Owner) in create_record or update_record. Never guess member IDs — always call this tool first to resolve a name to an ID.

log_call

ChatGPT
Log a call or schedule a future call. To log a completed call: provide call_outcome="completed" and optionally duration_seconds. Leave scheduled_at blank or set it to a past time. To schedule a future call: provide scheduled_at as an ISO 8601 string (e.g. "2026-04-10T14:00:00Z"). The call will be marked as scheduled. call_type values: discovery, demo, follow_up, qualification, other call_direction values: inbound, outbound call_outcome values: completed, cancelled, no_answer, voicemail scheduled_at must be ISO 8601 when provided, e.g. "2026-04-10T14:00:00Z". WORKFLOW — confirm with the user before calling: "Log call '{title}' with {phone_number}?" and wait for approval. assignee_id defaults to the current user when not provided.

react_to_linkedin_post

ChatGPT
Add a reaction to a LinkedIn post. Supports all LinkedIn post URL formats (same as get_linkedin_post). Workflow 1. Call list_message_accounts(provider_type="linkedin") to get a connected account. 2. Ask the user which reaction to use (like, celebrate, support, love, insightful, funny) unless they've already specified one. 3. Only call this tool once the reaction type is confirmed. Rate limits — enforced server-side - 30s ± 15s gap between reactions (jitter). - Max 10 reactions per 15-minute window; 15-minute cooldown once exhausted. - Max 50 reactions per 24 hours per account. - If rate limited: STOP, read the retry time from the error, tell the user. Parameters - message_account_id: ID of a connected LinkedIn account (from list_message_accounts). - post_url: Full LinkedIn post URL. - reaction_type: One of "like", "celebrate", "support", "love", "insightful", "funny". Defaults to "like".

record_schema

ChatGPT
Attribute schema for a resource type. Call this BEFORE calling create_record or update_record to discover: - All available field titles (pass these as keys in the attributes dict) - Which fields are required - Allowed values for select / multiselect fields - Whether a field can be updated resource_type: "person" | "company" | "deal" This schema is workspace-specific — custom attributes vary per workspace.

remove_from_list

ChatGPT
Remove one or more resources from a list by their IDs. resource_ids: list of person/company/deal IDs to remove from the list. Returns the count of items removed.

remove_person_from_deal

ChatGPT
Remove a person's association with a deal. Unlinks the person from the deal without deleting either record.

reply_to_email

ChatGPT
Reply to or follow up on an existing email thread. INTENT — determine what to write based on the parent email status: - Parent status is "sent" or "scheduled" → write a FOLLOW-UP email. The recipient has not yet responded; your goal is to follow up on the previous message (e.g. check in, add value, prompt a response). - Parent status is "received" → write a REPLY to the sender. You are responding to an inbound message they sent you. from_email and to_emails are resolved automatically from the parent email: - Sent/scheduled email (follow-up): replies FROM the same account we sent with, TO the original recipients. - Received email (reply): replies FROM the account that received it, TO the original sender. If the original sending account is no longer connected, a ToolError is returned listing available connected accounts — use draft_email to send a fresh email from one of them instead. WORKFLOW — follow these steps in order: 1. Call get_email(parent_email_id) to read the original email before composing. 2. SIGNATURE CHECK — if the resolved account has no signature, this tool returns a ToolError. See the error message for instructions. 3. Compose the html_body. 4. SIGNATURE RULE — do NOT add any closing line, sign-off, or signature to html_body. The sender's signature is appended automatically by the server. 5. Display the full reply to the user (subject, and rendered body) and ask: "Does this look good, or would you like any changes?" 6. Iterate on the content based on user feedback until they approve. 7. Only call this tool once the user explicitly approves the reply. Once sent, share the url with the user as a clickable link. html_body must be valid HTML — use <p> tags with inline style 'margin: 0; margin-bottom: 12px; font-size: 14px;'.

resolve_invalid_enrollments

ChatGPT
Get the step-by-step resolution guide for fixing invalid leads in a sequence. Call this first whenever the user asks to resolve, fix, or retry invalid leads. Follow the instructions returned in the response exactly.

retry_enrollment

ChatGPT
Retry a failed, invalid, or skipped sequence enrollment. - Failed enrollments: resumed from the same node they failed on, no re-validation. - Invalid enrollments: re-runs the full validation pipeline (contact data, template variables) and resumes execution from the beginning if validation passes. Returns a ToolError if validation still fails (exit_reason explains what is missing). - Skipped enrollments (email verification failed or email missing): Re-checks the person's current email status. - If email is now valid (is_email_valid=true): moves to active immediately. - If email status is unknown (e.g. email address was updated): re-triggers async verification; enrollment moves to "verifying" status and resolves automatically. Inform the user verification is in progress. - If email is still invalid or missing: remains skipped (returns ToolError). Do NOT call this on "verifying" enrollments — they resolve themselves automatically.

run_ai_enrichment

ChatGPT
Run an AI enrichment configuration against a list or specific records. MANDATORY — call list_ai_enrichments first to get provider_id and confirm the correct configuration with the user before proceeding. Provide exactly one of: - list_id: run enrichment for all records in that list - record_ids: run enrichment for specific record IDs The resource type (person or company) is determined by the enrichment provider configuration — no need to specify it separately. Enrichment runs asynchronously. After this tool returns, tell the user: "AI enrichment has been queued for N records. Results will be written to their record attributes. Please check back in at least [N × 30] seconds." Do NOT poll for status immediately.

run_report

ChatGPT
Execute a saved report and return its data rows. Use this to run or refresh a report that already exists (report_id required). Set preview=true to limit results to 100 rows for a quick check. Full execution (preview=false) is capped at 200 rows. AFTER CALLING: present the rows to the user in a readable format (table or summary). Do not call this tool repeatedly without user instruction.

search_linkedin

ChatGPT
Execute a LinkedIn people or company search and return one page of results. Always fetches exactly 25 results per page — enforced server-side. MANDATORY: call get_linkedin_search_guide first for workflow, rate limits, and filter reference. Parameters: - message_account_id: ID of a connected LinkedIn message account. - api: "classic" or "sales_navigator". - category: "people", "companies" (both apis), or "posts"/"jobs" (classic only). - filters: Dict of search filters. See get_linkedin_search_guide for all keys and types. - cursor: Pagination cursor from the previous response. Omit for page 1.

send_connection_request

ChatGPT
Send a LinkedIn connection request to a prospect. Use this for cold outreach when you are not yet connected. Call check_linkedin_connection first to confirm the status is "no_invitation". Parameters - person_id: CRM person to send the request to (must have a LinkedIn URL). - message_account_id: Your LinkedIn message account ID (find via list_message_threads). - message: Optional personalised note. Must not exceed 300 characters. When included, a pending-connection thread is created in the CRM. Workflow 1. Call check_linkedin_connection to confirm status is "no_invitation". 2. Compose a short, personalised note (optional but recommended). 3. Present the note to the user for approval. 4. Only call this tool once the user explicitly approves.

send_draft_message

ChatGPT
Promote a saved draft message to sent, dispatching it via the provider. Use this after the user approves a draft that was saved via send_linkedin_message(draft=True) or send_whatsapp_message(draft=True). Parameters - message_id: ID of the draft message to send (from the draft=True response). Notes - Only draft messages (status="draft") can be sent via this tool. - For new-conversation drafts (no Unipile thread yet), this tool starts the conversation on the fly and converts the placeholder thread to a real one. - Always confirm with the user before calling this tool.

send_email

ChatGPT
Send a drafted email by its ID. Use the email_id returned from draft_email. Only call this tool when the user explicitly confirms they want to send.

send_inmail

ChatGPT
Send a LinkedIn InMail to a prospect you are not connected with. InMail requires a premium LinkedIn account (Sales Navigator, Recruiter, or Premium). Use this when you cannot send a connection request or need to bypass the connection step entirely. Parameters - person_id: CRM person to message (must have a LinkedIn URL). - message_account_id: Your LinkedIn message account ID. - subject: InMail subject line. - message: InMail body text. - premium_type: One of "premium", "sales_navigator", "recruiter". Workflow 1. Confirm account has the required premium_type features. 2. Compose subject + message and show to user for approval. 3. Only call this tool once the user explicitly approves.

send_linkedin_message

ChatGPT
Send (or draft) a LinkedIn message in an existing thread or start a new conversation. Provide either thread_id (existing thread) or both person_id + message_account_id (new conversation). thread_id takes priority when both are given. Workflow 1. Call list_message_threads — if a thread exists for this person, pass its thread_id. 2. If no thread exists, call check_linkedin_connection first: - "connected" → pass person_id + message_account_id to this tool - "no_invitation" → use send_connection_request instead - "pending" → wait for acceptance - "ignored" → use send_inmail (premium only) 3. Only call when the user explicitly approves the message text. Pass draft=True to save for review without sending. Notes - Blocked on pending-connection threads — wait for acceptance first. - Validates daily send limits before sending (skipped for drafts).

send_whatsapp_message

ChatGPT
Send (or draft) a WhatsApp message in an existing thread or start a new conversation. Provide either thread_id (existing thread) or both person_id + message_account_id (new conversation). thread_id takes priority when both are given. Workflow 1. Call list_message_threads(provider_type="whatsapp") — if a thread exists, pass its thread_id. 2. If no thread exists, pass person_id + message_account_id (person must have a phone number). 3. Compose the message and show it to the user for approval. Pass draft=True to save for review without sending. Notes - WhatsApp has no connection-request state — messages can be sent to any contact. - Daily send limits are not enforced for WhatsApp.

set_email_signature

ChatGPT
Set or update the email signature for a connected email account. Call this tool when: - The user explicitly wants to set or change their email signature. - You are about to draft an email, reply, or create/update a sequence, and list_connected_accounts shows has_signature=false for the chosen account. In that case: set the signature FIRST with this tool, then proceed with the original task. Do NOT skip this step — emails cannot be drafted from an account with no signature. Use account_id from list_connected_accounts. html_signature must be valid HTML. Plain text is also accepted, but HTML is recommended (use <p> tags with inline styles for best email client compatibility). After setting the signature, show a preview to the user and confirm: "Your signature has been saved. Shall I continue with [original task]?"

set_enrollment_node_content

ChatGPT
Save AI-generated outreach content for a specific node in a sequence enrollment. Call this tool once you have finished composing content for a node. The tool validates content rules (required fields, character limits) and saves it. If validation fails, the tool returns an error — revise your content and call again. Args: enrollment_id: ID of the enrollment being generated node_id: The node_id of the sequence node (e.g. "email-1", "linkedin-2") subject: Email subject line — required for EMAIL nodes only body: Email HTML body — required for EMAIL nodes only. Do NOT include any signature, sign-off, closing line ("Best regards", "Thanks", etc.), or the {{email_account.signature}} placeholder. The server appends the sender's signature automatically. Adding it yourself — in any form — will produce a duplicate or a literal {{email_account.signature}} tag in the sent email. message: Message text — required for LINKEDIN_* and WHATSAPP_MESSAGE nodes

set_primary_account

ChatGPT
Set a message account as the primary account for the current user. IMPORTANT — always confirm with the user before calling This tool has side effects: 1. The previously primary account for this provider loses its primary flag for the current user. 2. If the account is shared (owned by another team member) and they also held it as their primary, they will silently lose their primary — another team member's settings are affected. Required confirmation flow Before calling this tool, you MUST: 1. Call list_message_accounts to show the user their accounts. 2. Tell the user: which account will become primary, what the current primary is (if any), and — if the account is shared — that the owner may lose their own primary setting. 3. Ask for explicit approval. 4. Only call this tool after the user confirms. Parameters - account_id: ID of the account to promote (from list_message_accounts). Workflow list_message_accounts → user picks account → confirm side effects → call this tool → retry the blocked send tool.

update_ai_enrichment

ChatGPT
Update an existing AI enrichment configuration. Only the fields you provide will be changed — omitted fields are left as-is. Use list_ai_enrichments to get the provider_id first. If field_mappings is provided, it REPLACES all existing mappings entirely — any mapping omitted from the list will be permanently deleted. To update only one mapping, fetch the current config first (get_ai_enrichment), then pass ALL existing mappings with the desired one(s) modified. Each mapping dict must include: - output_field (str): the provider output field name - resource_type (str): "person" or "company" - target_attribute_id (int, optional): attribute to write into - attribute_prompt (str, REQUIRED): AI prompt for this field — cannot be empty - is_enabled (bool, optional): defaults to true If updating model, you MUST pick from the supported list (same models shown in create_ai_enrichment). Unsupported models will be rejected. base_prompt cannot be set to an empty string — omit it to leave unchanged. MANDATORY — before calling this tool, you MUST show the user a full summary of every field that will change and wait for explicit approval. Do NOT call this tool until the user confirms with a clear "yes", "looks good", or equivalent. If they request changes, update the draft and show it again.

update_attribute

ChatGPT
Update an existing custom attribute. Only provided (non-null) fields are changed. System attributes (is_system=true) cannot be modified — only custom attributes created by workspace members can be updated. To add options to a select/multiselect attribute, pass the full updated list in config: config={"options": [{"value": "1", "label": "Low"}, {"value": "2", "label": "High"}, {"value": "3", "label": "Critical"}]} To archive an attribute (hide without deleting its data): is_archived=true

update_call

ChatGPT
Update an existing call. Only fields you provide are changed — omit a field to leave it unchanged. Key use case: mark a scheduled call as completed after it happens by setting call_outcome="completed" and optionally duration_seconds. call_type values: discovery, demo, follow_up, qualification, other call_direction values: inbound, outbound call_outcome values: completed, cancelled, no_answer, voicemail scheduled_at must be ISO 8601 when provided, e.g. "2026-04-10T14:00:00Z".

update_draft

ChatGPT
Update fields on an existing draft email — only provided fields are changed. Only works on emails with status "draft". Use send_email to send after updating. html_body must be valid HTML when provided.

update_enrollment

ChatGPT
Update a sequence enrollment's status or node content. Call get_update_enrollment_guide first when updating node content or account configuration. node_updates: list of {"node_id": "...", "node_config": {...}} dicts. Provide only the nodes you want to change; for each, include the full config (account + content). All nodes of the same channel (LinkedIn/email/WhatsApp) must end up on the same account. If unchanged nodes conflict, the error names exactly which ones to add to node_updates. At least one of status or node_updates must be provided.

update_list

ChatGPT
Update a list's name, description, icon, or color. Only fields you provide are updated — omit a field to leave it unchanged.

update_note

ChatGPT
Update an existing note. Only fields that are provided (non-null) will be changed.

update_record

ChatGPT
Update fields on an existing record — PATCH, only provided fields are changed. resource_type: "person" | "company" | "deal" Call record_schema(resource_type=<resource_type>) to see available attribute titles and allowed values. Pass only the fields you want to update. For workspace_member record_reference fields (e.g. Owner): call list_workspace_members first to resolve the member name to an ID. For "Categories" field (company only): call list_company_categories to get existing category IDs, or get_or_create_category(name=<name>) to resolve a name to an ID. Pass the resolved IDs as a list: {"title": "Categories", "value": [12, 34]} IMPORTANT: attributes must be a JSON object, NOT a string. Example: { "resource_type": "person", "record_id": 42, "attributes": {"items": [{"title": "Job Title", "value": "VP of Sales"}]} } IMPORTANT — deal people: Do NOT use this tool to add or remove people on a deal. Use add_person_to_deal / remove_person_from_deal instead. If updating an attribute across multiple records in a list, after finishing ALL calls suggest a focused filtered view — see the LISTS section of the server instructions for details.

update_sequence

ChatGPT
Update a sequence's name, scheduling config, or full structure (nodes + edges). MANDATORY: call get_sequence_update_guide first when updating nodes, edges, or scheduling config. Do not call this tool until all guide steps are complete and the user has approved the changes.

update_task

ChatGPT
Update an existing task. Only fields that are provided (non-null) will be changed. due_date must be an ISO 8601 string when provided. status values: OPEN, IN_PROGRESS, COMPLETED, CANCELLED.

update_view

ChatGPT
Update an existing view's configuration. REQUIRED WORKFLOW — follow these steps in order: STEP 1 — Know the current view: Use view context from a previous call. If changing columns or filters, also call record_schema(resource_type=<resource_type>) to get valid attribute titles. STEP 2 — Present current state and ask what to change: "Currently the view shows [all fields / these specific fields: ...]. To show all fields, pass an empty visible_fields list. To show only specific columns, tell me which ones. You can also update or clear the view's filters." STEP 3 — Call this tool with only the fields the user wants to change. Fields omitted (None) are left unchanged on the server. Parameters view_id : ID of the view to update (required). name : New display name. column_order : New ordered list of attribute titles for column sequence. visible_fields : Attribute titles to show as visible columns. * IMPORTANT: pass an empty list [] to make ALL fields visible. Omit (None) to leave the current visible_fields unchanged. filters : Updated filter conditions using attribute titles as field names — the same format as list_records filters. Call filter_guide() for the full syntax. Pass an empty list [] to clear all filters. Omit (None) to leave the current filters unchanged. layout : "grid" | "kanban" ONLY valid for deal views. * Do not change layout for person or company views.

validate_and_preview_report

ChatGPT
Validate a report configuration and return a 100-row data preview. MANDATORY: call get_report_guide first for prerequisites, query/chart/filter syntax, and post-call steps. Always show preview_rows to the user and get confirmation before calling create_report.

Capabilities

Writes

App Stats

131

Tools

ChatGPT

Platforms

Works with

ChatGPT

Data refreshed daily