> For clean Markdown content of this page, append .md to this URL. For the complete documentation index, see https://docs.postnuvia.com/llms.txt.

# LangChain

> PostNuvia's LangChain integration

## Getting started

[LangChain](https://www.langchain.com/) is the most widely used framework for building LLM-powered agents. The [`langchain-postnuvia`](https://github.com/postnuvia-to/langchain-postnuvia) package wraps the PostNuvia SDK as standard LangChain tools, plus a document loader and a retriever — so a LangGraph agent can send, reply, draft, label, and search email through a real inbox without any glue code.

## Use cases

* **Give agents their own inboxes:** Provision a dedicated email address per agent so it can send and receive mail independently.
* **Triage and reply:** Read recent threads, summarize what's new, and reply inside the same thread with the right In-Reply-To headers.
* **Stage and schedule sends:** Use the draft tools to compose iteratively or schedule a delivery time via `send_at`.
* **RAG over email:** Load messages as LangChain `Document`s and index them into a vector store for semantic search across the inbox.

## Prerequisites

1. An [PostNuvia account](https://postnuvia.com/) with an API key from the [PostNuvia Console](https://console.postnuvia.com).
2. Python 3.10+ and a LangChain-compatible model provider (e.g. an `OPENAI_API_KEY` or `ANTHROPIC_API_KEY`).

## Setup

Install the integration package:

```bash
pip install langchain-postnuvia
```

Set your API key:

```bash
export POSTNUVIA_API_KEY="your-api-key"
```

## Quickstart

Build a ReAct agent with the full toolkit in a few lines:

**`Python`**

```python title="Python"
from langchain_openai import ChatOpenAI
from langgraph.prebuilt import create_react_agent

from langchain_postnuvia import PostNuviaToolkit

toolkit = PostNuviaToolkit.from_api_key()
agent = create_react_agent(
    ChatOpenAI(model="gpt-4o-mini"),
    tools=toolkit.get_tools(),
)

result = agent.invoke(
    {"messages": [("user", "Summarize my most recent email thread.")]}
)
print(result["messages"][-1].content)
```

You can also pull a single tool in if you don't need the whole toolkit:

**`Python`**

```python title="Python"
from langchain_postnuvia import PostNuviaClient, PostNuviaSendTool

send = PostNuviaSendTool(client=PostNuviaClient())
send.invoke({
    "inbox_id": "ib_...",
    "to": "alice@example.com",
    "subject": "Ping",
    "text": "Hello from my agent.",
})
```

## Available tools

The toolkit exposes one tool per PostNuvia operation.

### Inbox and thread management

| Tool                     | Description                                            |
| ------------------------ | ------------------------------------------------------ |
| `postnuvia_list_inboxes` | List inboxes the account owns                          |
| `postnuvia_create_inbox` | Create a new inbox (random or custom username)         |
| `postnuvia_list_threads` | List threads across an inbox with label / time filters |
| `postnuvia_get_thread`   | Pull every message in a thread                         |

### Message operations

| Tool                              | Description                                                 |
| --------------------------------- | ----------------------------------------------------------- |
| `postnuvia_list_messages`         | List messages inside an inbox                               |
| `postnuvia_get_message`           | Fetch one message with its full plain-text body             |
| `postnuvia_send_message`          | Send a new email                                            |
| `postnuvia_reply_to_message`      | Reply inside an existing thread (with optional reply-all)   |
| `postnuvia_update_message_labels` | Add or remove labels (archive, follow-up, etc.)             |
| `postnuvia_get_attachment`        | Get a signed HTTPS CDN URL to download a message attachment |

### Draft management

| Tool                     | Description                                                    |
| ------------------------ | -------------------------------------------------------------- |
| `postnuvia_create_draft` | Stage a draft (with optional `send_at` for scheduled delivery) |
| `postnuvia_update_draft` | Revise an existing draft                                       |
| `postnuvia_send_draft`   | Send a previously created draft                                |
| `postnuvia_delete_draft` | Permanently delete a draft                                     |

## RAG over an inbox

`PostNuviaLoader` streams messages as LangChain `Document`s — one per message, plain-text body as `page_content`, sender / subject / labels / thread / attachment metadata on `metadata`. Pair it with any vector store for semantic search:

**`Python`**

```python title="Python"
from langchain_core.vectorstores import InMemoryVectorStore
from langchain_openai import OpenAIEmbeddings

from langchain_postnuvia import PostNuviaLoader

docs = PostNuviaLoader(inbox_id="ib_...", limit=200).load()
store = InMemoryVectorStore.from_documents(docs, OpenAIEmbeddings())
retriever = store.as_retriever(search_kwargs={"k": 5})

retriever.invoke("Q3 invoice from acme")
```

For a quick keyword search without embeddings, use the bundled `PostNuviaRetriever` instead.

## Inbound email via webhooks

The `webhooks` extra ships a FastAPI router with svix-compatible signature verification so a LangGraph agent can react to inbound mail:

```bash
pip install 'langchain-postnuvia[webhooks]'
```

**`Python`**

```python title="Python"
from fastapi import FastAPI
from langchain_postnuvia.webhooks import PostNuviaEvent, create_fastapi_router

async def on_event(event: PostNuviaEvent) -> None:
    if event.event_type == "message.received":
        # drive your LangGraph agent here
        ...

app = FastAPI()
app.include_router(
    create_fastapi_router(on_event),  # reads POSTNUVIA_WEBHOOK_SECRET
    prefix="/postnuvia",
)
```

## Resources

* **Source code:** [github.com/postnuvia-to/langchain-postnuvia](https://github.com/postnuvia-to/langchain-postnuvia)
* **PyPI:** [pypi.org/project/langchain-postnuvia/](https://pypi.org/project/langchain-postnuvia/)