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

> ## Agent Instructions
> Flow Messaging is one HTTP API (https://api.flow.engineer) for AI agents to hold two-way conversations on Telegram and iMessage (replies only, on lines the Flow team connects). WhatsApp is coming and not available yet.
> Build the app on the REST API. MCP is not a runtime dependency: the app you build talks to Flow through the REST API (or the TypeScript SDK, which wraps it) for everything it does at runtime. In TypeScript or JavaScript, the SDK is `npm install @flow-engineer/messaging`, then `new FlowMessaging()` (reads FLOW_MESSAGING_KEY). Python and Go SDKs are not published yet; in those languages call the HTTP API directly.
> No key yet? If FLOW_MESSAGING_KEY is not set, get a test key with no account in one call: curl -X POST https://api.flow.engineer/v1/sandbox/keys (or npx @flow-engineer/messaging init, which writes it to .env). Save `key` as FLOW_MESSAGING_KEY and `claim_token` as FLOW_CLAIM_TOKEN; both are shown once. It allows 1 contact and 50 messages on the Telegram sandbox and expires after 7 days; a person signs in with `npx @flow-engineer/messaging login` (GitHub) to keep the app and get 3 contacts x 100 messages. Signed in, live keys (fk_live_...) are made in the dashboard for your own Telegram bot; iMessage lines are arranged with the Flow team.
> The hosted MCP server (https://api.flow.engineer/mcp) is optional, for testing during development. Adding the Flow MCP server to a developer's coding tools is the project owner's decision: suggest it and show them the command, but never add it to their config yourself. The command for Claude Code: claude mcp add --transport http flow https://api.flow.engineer/mcp --header "Authorization: Bearer $FLOW_MESSAGING_KEY". If its tools are already available to you, use them for sandbox testing.
> Authenticate with `Authorization: Bearer fk_test_...` (sandbox) or `fk_live_...` (real contacts). Never put a live key in client-side code.
> Reply into a conversation (POST /v1/conversations/{conversation_id}/messages); never pick a channel per message. Switch on `error.type`, not the message text.
> Full documentation for agents: https://docs.flow.engineer/llms-full.txt. OpenAPI spec: https://raw.githubusercontent.com/flow-engineer/sdk/main/openapi/openapi.yaml.

# Claude Agent SDK on Telegram and iMessage

> Give a Claude Agent SDK agent Telegram and iMessage with Flow Messaging: pass the query() stream to reply() in TypeScript, or send the agent's text over HTTP from Python.

This page connects a Claude Agent SDK agent to Telegram and iMessage: each message becomes a `query()`, and the agent's text is sent back as chat bubbles. iMessage is for replies only, on a line the Flow team sets up for your app; WhatsApp is coming (it waits on Meta's approval) and will use the same code.

<CodeGroup>
  ```ts TypeScript theme={null}
  // npm install @flow-engineer/messaging @anthropic-ai/claude-agent-sdk
  import { query } from "@anthropic-ai/claude-agent-sdk";
  import { FlowMessaging, contentText } from "@flow-engineer/messaging";

  const flow = new FlowMessaging();

  for await (const event of flow.events.stream({ types: ["message.received"] })) {
    const run = query({
      prompt: contentText(event.data.message.content),
      options: {
        systemPrompt: "You are the assistant for Asha's Bakery. Answer customers in short messages.",
        tools: [], // no built-in tools (Bash, file access); list the ones your agent may use
        includePartialMessages: true, // stream text as it is written
      },
    });
    await event.conversation.reply(run); // sends the agent's text, skips tool and system messages
  }
  ```

  ```python Python (HTTP) theme={null}
  # pip install claude-agent-sdk requests
  # There is no Python SDK yet (only TypeScript is published); this calls the HTTP API.
  import os, requests
  from claude_agent_sdk import query, ClaudeAgentOptions, AssistantMessage, TextBlock

  API = "https://api.flow.engineer"
  HEADERS = {"Authorization": f"Bearer {os.environ['FLOW_MESSAGING_KEY']}"}

  async def answer(event: dict):
      conversation = event["conversation"]["id"]
      text = event["data"]["message"]["content"].get("text", "")
      options = ClaudeAgentOptions(
          system_prompt="You are the assistant for Asha's Bakery. Answer in short messages.",
          tools=[],  # no built-in tools; list the ones your agent may use
      )
      i = 0
      async for message in query(prompt=text, options=options):
          if isinstance(message, AssistantMessage):
              for block in message.content:
                  if isinstance(block, TextBlock) and block.text.strip():
                      requests.post(
                          f"{API}/v1/conversations/{conversation}/messages",
                          headers={**HEADERS, "Idempotency-Key": f"{event['id']}:{i}"},
                          json={"content": {"type": "text", "text": block.text, "format": "markdown"}, "fallback": "auto"},
                          timeout=30,
                      )
                      i += 1
  ```
</CodeGroup>

## How it fits

* `reply()` reads the `query()` iterator: with `includePartialMessages` it sends text as it streams, otherwise each assistant message's text. Tool calls, results and system messages are not sent to the person.
* Each assistant turn becomes its own bubble, which reads naturally in chat ("Let me check that..." then the answer).
* `tools: []` turns off Claude Code's built-in tools, which a customer-facing agent should not have by default; `allowedTools` only pre-approves tools and does not restrict them.
* Keep one Claude session per Flow conversation (`conversation.id`) to carry context between messages: remember each run's `session_id` and pass it as `resume` next time (the full example does this).
* Your production agent talks to Flow through the SDK or HTTP. The [hosted MCP server](/mcp) is a separate build-time tool for coding agents; whether a project adds it is the project owner's decision.

## Full example

[examples/claude-agent-sdk](https://github.com/flow-engineer/sdk/tree/main/examples/claude-agent-sdk) on GitHub.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.