July 20, 2026 · Updated September 17, 2026 · 6 min read
LangChainClaw Messenger
Public PyPI package · v0.1.0 · Python 3.10+

Give your LangChain agent an iMessage thread it can prove.

Install one StructuredTool, check connection readiness, and finish only when the matching reply reaches the active invocation. The same tool fits LangGraph agents.

01Connect your app

Keep a persistent WebSocket consumer running.

02Check, then send

Confirm readiness before invoking the tool.

03Return on reply

The same tool call receives the matching inbound message.

Start with one controlled thread

Start the 7-day trial (card required), copy your API key, then install the Python package and run the reply-backed proof. Compare plans and limits. AI agent texting costs.

Start your 7-day trial

One invocation, one proof boundary

The tool handles

One controlled exchange

It opens a listener, sends one plain-text message, and waits for that recipient's reply in the same chat.

Your app handles

Persistent inbound work

The tool closes its listener when it returns. Keep your own long-running WebSocket consumer connected with the same account API key for ongoing replies.

The package is a bounded proof tool, not a delivery guarantee, group messaging tool, webhook server, or conversation store. It works with LangChain directly and with the LangChain runtime inside LangGraph.

1. Install the public Python package

Install the current release from PyPI in the environment where your LangChain or LangGraph agent runs.

python3 -m pip install langchain-claw-messenger

Current public release: v0.1.0. Inspect the package, Apache 2.0 license, and release metadata on PyPI.

2. Prepare one controlled thread

Use one registered phone in E.164 format that you control. Keep the API key and recipient outside code, notebooks, screenshots, and logs.

export CLAW_API_KEY="cm_live_REDACTED"
export CONTROLLED_TEST_PHONE_E164="+14155550101"

First-send examples

curl --fail-with-body -X POST https://claw-messenger.onrender.com/api/agent/send-message \
  -H "Authorization: Bearer $CLAW_MESSENGER_API_KEY" \
  -H "Content-Type: application/json" \
  --data '{"phone_number":"YOUR_REGISTERED_PHONE","text":"Claw test. Reply yes."}'

Set CLAW_MESSENGER_API_KEY. Replace YOUR_REGISTERED_PHONE with your registered phone. Keep a persistent WebSocket listener running for replies.

3. Connect your app and check readiness

Keep your app's WebSocket consumer connected with the same account API key. Check readiness below before running the tool. Published v0.1.0 opens a listener during each call but does not check readiness automatically.

curl -fsS https://claw-messenger.onrender.com/api/agent/readiness \
  -H "Authorization: Bearer $CLAW_API_KEY"
open listenerGET /api/agent/readinesssend
Ready to send{"ready":true,"action":"send_controlled_test"}

If readiness is false, fix the connection before invoking the tool. Keep both your app listener and the tool call running through the reply step.

4. Run the working code example

The person holding the controlled phone should be ready to reply in the same thread while this call waits.

import json
import os

from langchain_claw_messenger import create_claw_messenger_tool

tool = create_claw_messenger_tool()
result = json.loads(
    tool.invoke(
        {
            "recipient_e164": os.environ["CONTROLLED_TEST_PHONE_E164"],
            "message": "This is my Claw Messenger test. Reply yes.",
            "timeout_seconds": 300,
        }
    )
)

if result["proof_status"] != "reply_received":
    raise RuntimeError(f"Two-way proof failed: {result['proof_status']}")

print("Matching reply reached the LangChain tool invocation")

In an async agent, call await tool.ainvoke(...). The sync path deliberately refuses to nest another event loop.

5. Finish on the matching reply

Reply once from the controlled phone. The package matches the sender and chat, then returns a privacy-safe result to the active tool call.

Matching reply reached the LangChain tool

proof_status: reply_received is the setup finish line.

A result with accepted, delivered, orread describes the outbound message. It does not prove the next inbound message can reach your agent.

Use the same tool in LangGraph

create_claw_messenger_tool() returns a LangChain StructuredTool. Add it to the tool set already bound to your model or agent runtime, then make reply_received the only state that can mark setup complete.

tools = [create_claw_messenger_tool()]

# Bind tools to the model or agent runtime used by your graph.
# Allow only registered recipients.
# Treat only proof_status == "reply_received" as setup complete.

If you want to build the long-running graph loop yourself, use the separate LangGraph WebSocket and REST tutorial. This page stays focused on the installable package and its bounded proof contract.

If the proof stops halfway

The tool returns configuration_error

Use a valid E.164 recipient, nonempty message, and timeout between 1 and 900 seconds. Check the API key and connection if the call raises an error.

The send succeeds, but the tool times out

Reply from the exact registered phone in the same thread before the timeout. A different sender or chat will not satisfy the match.

The result says accepted or delivered

Keep waiting for reply_received. Outbound state is useful diagnostics, but it is below the two-way finish line.

LangChain and LangGraph iMessage questions

Does one LangChain tool call keep listening for later replies?

One LangChain tool call listens for one matching reply only while that invocation stays open. Ongoing inbound replies require a separate long-running WebSocket consumer using the same account API key.

Can a LangGraph agent call this tool?

Yes. It is a LangChain StructuredTool and can join the tool set used by a LangGraph agent runtime.

What counts as a working thread?

One controlled message leaves the tool, then the matching reply reaches that active invocation. Delivery status alone is not the finish.

Try Claw Messenger free for 7 days — iMessage API for AI agents. No Mac required.