July 21, 2026 · 6 min read
CrewAIClaw Messenger
Public PyPI package · v0.1.0 · Python 3.10+

Give your CrewAI agent an iMessage thread it can prove.

Install one CrewAI tool, let it check connection readiness, and finish only when the matching reply reaches the active invocation.

01Open the listener

The tool starts a bounded WebSocket reply consumer.

02Check, then send

Nothing leaves until authenticated readiness passes.

03Return on reply

The same tool call receives the matching inbound message.

Start with one controlled thread

Start the 7-day trial, copy your API key, then return here to install the Python package and run the reply-backed proof.

Start your 7-day trial

One invocation, one proof boundary

The tool handles

One controlled exchange

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

Your app handles

Persistent inbound work

The listener closes when the tool returns. Use your own long-running WebSocket consumer or webhook for production conversations.

The package is a bounded proof tool, not a delivery guarantee, group messaging tool, webhook server, or conversation store.

1. Install the public Python package

Install the current release from PyPI in the environment where your CrewAI agent runs.

python3 -m pip install crewai-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, prompts, screenshots, and logs.

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

3. Let the tool connect and check readiness

The tool opens its reply listener first. It then calls the authenticated readiness endpoint before sending. The API key stays in the authorization header, never in the readiness URL.

open listenerGET /api/agent/readinesssend
Ready to send{"ready":true,"action":"send_controlled_test"}

If readiness fails, the tool returns configuration_errorwith a connect action and sends nothing. Keep the invocation 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 crewai_claw_messenger import ClawMessengerTool

tool = ClawMessengerTool()
result = json.loads(
    tool.run(
        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 CrewAI tool invocation")

In async Python, call await tool.arun(...). 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 CrewAI 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.

Add the tool to a CrewAI agent

ClawMessengerTool is a CrewAI BaseTool. Add it to the agent responsible for the controlled thread, then tell the task to treat only reply_received as proof.

from crewai import Agent, Crew, Task
from crewai_claw_messenger import ClawMessengerTool

messenger = ClawMessengerTool()
agent = Agent(
    role="Controlled thread tester",
    goal="Prove one matching reply reaches this active tool call",
    backstory="You test only registered recipients.",
    tools=[messenger],
)
task = Task(
    description=(
        "Message {controlled_phone}, wait for its matching reply, "
        "and succeed only when proof_status is reply_received."
    ),
    expected_output="A reply_received proof result",
    agent=agent,
)
crew = Crew(agents=[agent], tasks=[task])
crew.kickoff(inputs={"controlled_phone": "+14155550101"})

Keep the actual recipient in your application's controlled input and allow only registered numbers. Do not place a live key or customer phone number in the task text.

If the proof stops halfway

The tool returns configuration_error

Confirm the API key is current, the recipient uses E.164 format, and the listener can connect. A failed readiness check sends nothing.

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.

CrewAI iMessage questions

Does one CrewAI tool call keep listening for later replies?

One CrewAI tool call listens for one matching reply only while that invocation stays open. Ongoing inbound replies require a separate long-running WebSocket consumer or webhook.

Can a CrewAI agent call this tool?

Yes. It is a CrewAI BaseTool and can join an agent's existing tools list or run directly for a controlled proof.

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 daysiMessage API for AI agents. No Mac required.