> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.getdial.ai/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.getdial.ai/_mcp/server.

# LangChain integration

> Give a LangChain agent Dial tools for sending messages and placing calls.

`dial-langchain` packages Dial's operations as LangChain tools, so an agent can send messages and place calls as part of its reasoning.

#### [Full API reference](https://sdk.getdial.ai/langchain)

Every class and method for `dial-langchain`, generated from the package source with examples.

## Install

```bash
pip install dial-langchain
```

This pulls in `dial-sdk` and `langchain-core`.

## Available tools

Each tool takes your shared `DialClient` (`client=`):

| Tool                      | Action                                                            |
| ------------------------- | ----------------------------------------------------------------- |
| `ListNumbersTool`         | List your phone numbers                                           |
| `SetNumberPropertiesTool` | Update a number's nickname or inbound instruction                 |
| `SendMessageTool`         | Send an SMS                                                       |
| `ReplyToMessageTool`      | Reply or react to a message                                       |
| `StartTypingTool`         | Show a typing indicator (iMessage numbers; SMS numbers ignore it) |
| `StopTypingTool`          | Clear a typing indicator                                          |
| `MakeCallTool`            | Place an AI voice call                                            |
| `ListMessagesTool`        | List recent messages                                              |
| `ListCallsTool`           | List recent calls                                                 |

## Give the tools to an agent

Build one [`DialClient`](/documentation/sdks/python), hand it to `DialToolkit`, and call `get_tools()` to give the agent the full set, no per-tool imports. Every tool shares that one client (a single connection pool):

```python
from dial_sdk import DialClient, DialConfig
from dial_langchain import DialToolkit
from langchain.chat_models import init_chat_model
from langgraph.prebuilt import create_react_agent

model = init_chat_model("claude-sonnet-4-6", model_provider="anthropic")

dial = DialClient(DialConfig(api_key="sk_live_..."))
toolkit = DialToolkit(client=dial)
agent = create_react_agent(model, toolkit.get_tools())
```

`DialToolkit` is a standard LangChain [`BaseToolkit`](https://python.langchain.com/api_reference/core/tools/langchain_core.tools.base.BaseToolkit.html), so `get_tools()` works anywhere a list of tools is expected.

### Or pick individual tools

When you only want a subset, import the tools directly and pass them the same client:

```python
from dial_sdk import DialClient, DialConfig
from dial_langchain import ListNumbersTool, SendMessageTool, MakeCallTool

dial = DialClient(DialConfig(api_key="sk_live_..."))
tools = [
    ListNumbersTool(client=dial),
    SendMessageTool(client=dial),
    MakeCallTool(client=dial),
]

# Bind to any tool-calling model or agent
llm_with_tools = llm.bind_tools(tools)
```

The tools are async — LangChain calls them via `ainvoke`. `SendMessageTool` expects `to`, a from-number (`from_number` — ID, owned E.164, or nickname — or the legacy `from_number_id`), and `body`; `MakeCallTool` expects `to`, a from-number, `outbound_instruction`, and optionally `language` and `idempotency_key`.

`SendMessageTool` is a write action and isn't idempotent — if your agent re-invokes it after a failure, it can send a duplicate message. `MakeCallTool` accepts an optional `idempotency_key`: a re-invoke with the same key returns the already-placed call instead of placing a duplicate. See [Retries and idempotency](/documentation/reference/errors#retries-and-idempotency).

## Receiving events

Inbound events aren't a tool — they're an ingress stream, not something the agent "calls." To react to inbound SMS or completed calls, use the [Python SDK's](/documentation/sdks/python) `new_events_connection()` directly — a **presence-based** stream (not at-least-once — for durable delivery, register a [webhook](/documentation/platform/webhooks)) — and feed events into your agent however suits your app:

```python
from dial_sdk import DialClient, DialConfig

dial = DialClient(DialConfig(api_key="sk_live_..."))
async with dial.new_events_connection() as conn:
    async for event in conn:
        ...  # route the event into your agent
```