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

# Auto-reply agent

> An agent that reads inbound email and replies in thread.

A minimal support agent: when an email arrives, an LLM drafts a reply and SentFromAI sends it back
in the same thread. The pattern is **webhook → generate → reply**.

## 1. Register a webhook

```bash theme={null}
curl -X POST https://api.sentfrom.ai/v1/webhooks \
  -H "Authorization: Bearer sf_live_…" -H "Content-Type: application/json" \
  -d '{ "url": "https://your-app.com/sentfromai", "events": ["message.received"] }'
```

Store the returned signing `secret`.

## 2. Handle inbound and reply

<CodeGroup>
  ```ts TypeScript theme={null}
  import crypto from "node:crypto";

  const KEY = process.env.SENTFROMAI_API_KEY!;
  const SECRET = process.env.SENTFROMAI_WEBHOOK_SECRET!;
  const API = "https://api.sentfrom.ai/v1";

  // Express-style handler. Use the RAW body for signature verification.
  export async function handler(req, res) {
    const sig = req.headers["x-sentfromai-signature"];
    const expected = "sha256=" + crypto.createHmac("sha256", SECRET).update(req.rawBody).digest("hex");
    if (sig !== expected) return res.status(401).end();

    const { event, message } = JSON.parse(req.rawBody);
    if (event !== "message.received") return res.status(200).end();

    // 1. draft a reply with your LLM of choice
    const reply = await draftReply(message.subject, message.body_text);

    // 2. send it in-thread
    await fetch(`${API}/messages/${message.id}/reply`, {
      method: "POST",
      headers: { Authorization: `Bearer ${KEY}`, "Content-Type": "application/json" },
      body: JSON.stringify({ text: reply }),
    });

    res.status(200).end();   // respond fast; do heavy work async
  }
  ```

  ```python Python theme={null}
  import hmac, hashlib, os, requests
  from flask import Flask, request

  KEY = os.environ["SENTFROMAI_API_KEY"]
  SECRET = os.environ["SENTFROMAI_WEBHOOK_SECRET"].encode()
  API = "https://api.sentfrom.ai/v1"
  app = Flask(__name__)

  @app.post("/sentfromai")
  def inbound():
      raw = request.get_data()
      expected = "sha256=" + hmac.new(SECRET, raw, hashlib.sha256).hexdigest()
      if request.headers.get("x-sentfromai-signature") != expected:
          return "", 401

      body = request.get_json()
      if body["event"] != "message.received":
          return "", 200
      msg = body["message"]

      reply = draft_reply(msg["subject"], msg.get("body_text", ""))   # your LLM
      requests.post(
          f"{API}/messages/{msg['id']}/reply",
          headers={"Authorization": f"Bearer {KEY}"},
          json={"text": reply},
      )
      return "", 200
  ```
</CodeGroup>

<Note>
  Replies thread automatically — SentFromAI sets `In-Reply-To`/`References` and prefixes the subject
  with `Re:`. No need to track headers yourself.
</Note>

## Going further

* Add a [block list](/guides/allow-block-lists) rule so the agent ignores known spammers.
* Use the [realtime WebSocket](/guides/realtime) instead of (or alongside) webhooks for a live view.
* Want native tools instead of REST? Connect via [MCP](/guides/mcp).
