> ## Documentation Index
> Fetch the complete documentation index at: https://trytilde.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# WhatsApp tools for AI agents

> Explore 8 WhatsApp tools for AI agents in Tilde, including supported authentication and MCP capabilities.

export const ToolProviderDetail = ({provider: fallbackProvider, ProviderLogo, apiUrl = PUBLIC_CATALOG_URL}) => {
  const [provider, setProvider] = useState(fallbackProvider);
  const [toolQuery, setToolQuery] = useState("");
  useEffect(() => {
    const controller = new AbortController();
    const loadProvider = async () => {
      const url = new URL(apiUrl);
      url.searchParams.set("page_size", "100");
      url.searchParams.set("deployment_alias", "latest");
      const response = await fetch(url, {
        signal: controller.signal,
        credentials: "omit",
        headers: {
          Accept: "application/json"
        }
      });
      if (!response.ok) throw new Error(`Catalog request failed: ${response.status}`);
      const page = await response.json();
      const match = (page.items || []).find(item => item.type_id === fallbackProvider.slug);
      if (match) setProvider(providerFromApi(match));
    };
    loadProvider().catch(error => {
      if (error.name !== "AbortError") console.warn("Using bundled provider details", error);
    });
    return () => controller.abort();
  }, [apiUrl, fallbackProvider.slug]);
  const filteredTools = useMemo(() => {
    const normalized = toolQuery.trim().toLowerCase();
    if (!normalized) return provider.tools;
    return provider.tools.filter(([name, description]) => `${name} ${description}`.toLowerCase().includes(normalized));
  }, [provider, toolQuery]);
  return <div className="tp-browser tp-detail">
      <a className="tp-back" href="/docs/tool-providers/index">
        <span aria-hidden="true">←</span> Providers
      </a>
      <div className="tp-detail-header">
        <div>
          <ProviderLogo provider={provider} detail />
          <div className="tp-detail-copy">
            <h2>{provider.name}</h2>
            <p>{provider.summary}</p>
          </div>
        </div>
        <div className="tp-detail-meta">
          <span>{provider.category}</span>
          <a href="https://api.trytilde.ai/tools/available-tool-providers">Add provider</a>
        </div>
      </div>
      <div className="tp-supported-auth">
        <span>Supported auth</span>
        <div className="tp-badges">
          {provider.auth.map(method => <span className="tp-badge" key={method}>
              <svg viewBox="0 0 24 24" aria-hidden="true">
                <path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10Z" />
                <path d="m9 12 2 2 4-4" />
              </svg>
              {method}
            </span>)}
        </div>
      </div>
      <section className="tp-tools-panel">
        <div className="tp-tools-heading">
          <div>
            <h3>Available tools</h3>
            <p>{filteredTools.length} shown{provider.tools.length < provider.toolCount ? ` · ${provider.toolCount} in Tilde` : ""}</p>
          </div>
          <label className="tp-search">
            <span className="sr-only">Search tools</span>
            <svg viewBox="0 0 24 24" aria-hidden="true">
              <circle cx="11" cy="11" r="7" />
              <path d="m20 20-3.6-3.6" />
            </svg>
            <input type="search" value={toolQuery} onChange={event => setToolQuery(event.target.value)} placeholder="Search tools..." />
          </label>
        </div>
        <div className="tp-tool-table" role="table" aria-label={`${provider.name} tools`}>
          <div className="tp-tool-row tp-tool-row--header" role="row">
            <span role="columnheader">Tool</span>
            <span role="columnheader">Description</span>
          </div>
          {filteredTools.map(([name, description]) => <div className="tp-tool-row" role="row" key={name}>
              <span role="cell">{name}</span>
              <span role="cell">{description}</span>
            </div>)}
        </div>
      </section>
    </div>;
};

export const ProviderLogo = ({provider, detail = false}) => {
  const sources = provider.iconSources || [iconUrl(provider.slug), iconUrl(provider.name)].filter(Boolean);
  const [sourceIndex, setSourceIndex] = useState(0);
  const source = sources[sourceIndex];
  useEffect(() => setSourceIndex(0), [provider.slug]);
  return <span className={detail ? "tp-detail-logo" : "tp-provider-logo"}>
      {source ? <img src={source} alt="" onError={() => setSourceIndex(index => index + 1)} /> : <span className="tp-logo-fallback">{provider.initials}</span>}
    </span>;
};

export const providerFromApi = source => {
  const metadata = source.metadata || ({});
  const auth = [...new Set((source.credential_sources || []).map(credential => credential.display_name || credential.name).filter(Boolean))];
  return {
    name: source.name,
    slug: source.type_id,
    initials: source.name.replace(/[^a-zA-Z0-9]/g, "").slice(0, 2).toUpperCase(),
    category: String(source.categories?.[0] || "Tools").replaceAll("_", " "),
    summary: source.documentation,
    auth,
    iconSources: [metadata.icon_url, iconUrl(metadata.icon_slug), iconUrl(source.type_id), iconUrl(source.name)].filter(Boolean),
    toolCount: (source.tools || []).length,
    tools: (source.tools || []).map(tool => [tool.name, tool.documentation])
  };
};

export const iconUrl = name => {
  const normalized = String(name || "").toLowerCase().replace(/[_./:]+/g, " ").replace(/\s+/g, " ").trim();
  if (!normalized || (/^(tilde|debug|message internal)\b|internal agent$/).test(normalized)) return null;
  const slug = iconAliases[normalized] || normalized.replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
  return slug ? `https://thesvg.org/icons/${slug}/default.svg` : null;
};

export const iconAliases = {
  "amazon s3": "aws-s3",
  "aws s3": "aws-s3",
  "google bigquery": "google-bigquery",
  "google gmail": "gmail",
  "google mail": "gmail",
  "mongo db": "mongodb",
  "open ai": "openai",
  "vercel ai sdk": "vercel"
};

export const PUBLIC_CATALOG_URL = "https://api.trytilde.ai/api/v1/mcp/available-tool-groups";

export const provider = {
  "name": "WhatsApp",
  "slug": "whatsapp",
  "initials": "WH",
  "category": "Chat",
  "summary": "Send WhatsApp text, template, and media messages, mark messages read, fetch media metadata, list approved templates, and inspect the sending number through the Meta Cloud API.",
  "auth": ["WhatsApp Cloud API"],
  "iconSources": [],
  "toolCount": 8,
  "tools": [["Send a WhatsApp text message", "Send free-form text to a WhatsApp user. Only allowed within 24 hours of the user's last message; outside that window Meta returns error 131047 and you must use whatsapp_send_template. Bodies over 4096 characters are rejected; split them first."], ["Send a WhatsApp template message", "Send an approved message template. This is the only way to start a conversation or reach a user whose 24 hour customer service window has closed. Components carry header, body, and button parameters in Meta's format."], ["Send a WhatsApp media message", "Send an image, video, audio, document, or sticker by public link or previously uploaded media id. Subject to the same 24 hour window as text."], ["React to a WhatsApp message", "Add an emoji reaction to a message the user sent, or remove one by passing an empty emoji. Reactions are lightweight acknowledgements and do not open or extend the 24 hour window."], ["Mark a WhatsApp message read", "Mark an inbound message as read (blue ticks) and optionally show a typing indicator while a reply is being prepared."], ["Get WhatsApp media metadata", "Resolve an inbound media id to its download URL, MIME type, and size. The URL is short-lived and must be fetched with the same bearer token."], ["List WhatsApp message templates", "List the WhatsApp Business Account's message templates with status, language, category, and components so template sends can be built correctly."], ["Get the WhatsApp sending number", "Read the sending number's display number, verified name, quality rating, messaging limit tier, and status. Pause outbound traffic when the status is not CONNECTED."]]
};

Send WhatsApp text, template, and media messages, mark messages read, fetch media metadata, list approved templates, and inspect the sending number through the Meta Cloud API.

Tilde exposes **8 WhatsApp tools** for AI agents through MCP. Connect with WhatsApp Cloud API.

<ToolProviderDetail provider={provider} ProviderLogo={ProviderLogo} />

## Popular WhatsApp tools

* **Send a WhatsApp text message** — Send free-form text to a WhatsApp user. Only allowed within 24 hours of the user's last message; outside that window Meta returns error 131047 and you must use whatsapp\_send\_template. Bodies over 4096 characters are rejected; split them first.
* **Send a WhatsApp template message** — Send an approved message template. This is the only way to start a conversation or reach a user whose 24 hour customer service window has closed. Components carry header, body, and button parameters in Meta's format.
* **Send a WhatsApp media message** — Send an image, video, audio, document, or sticker by public link or previously uploaded media id. Subject to the same 24 hour window as text.
* **React to a WhatsApp message** — Add an emoji reaction to a message the user sent, or remove one by passing an empty emoji. Reactions are lightweight acknowledgements and do not open or extend the 24 hour window.
* **Mark a WhatsApp message read** — Mark an inbound message as read (blue ticks) and optionally show a typing indicator while a reply is being prepared.
* **Get WhatsApp media metadata** — Resolve an inbound media id to its download URL, MIME type, and size. The URL is short-lived and must be fetched with the same bearer token.
* **List WhatsApp message templates** — List the WhatsApp Business Account's message templates with status, language, category, and components so template sends can be built correctly.
* **Get the WhatsApp sending number** — Read the sending number's display number, verified name, quality rating, messaging limit tier, and status. Pause outbound traffic when the status is not CONNECTED.

## Connect WhatsApp to an AI agent

Add WhatsApp from the [Tilde dashboard](https://api.trytilde.ai/tools/available-tool-providers), then enable the tools your agent needs on an MCP server. [Learn how tools work in Tilde](/docs/tools).

[Browse every Tilde tool provider](/docs/tool-providers/index) or [compare Tilde-managed and self-managed authentication](/docs/tool-providers/managed-auth).
