Skip to main content

Documentation Index

Fetch the complete documentation index at: https://www.plain.com/docs/llms.txt

Use this file to discover all available pages before exploring further.

Plain is designed to be a great home for agents. You can build your own customer support agent using whatever AI stack you prefer and have it work alongside your team in the same threads, with the same tools, and the same audit trail as everyone else. These docs are about the plumbing of building an agent on Plain: how it gets an identity, how it receives events, how it decides when to act, and how it replies. The AI part (e.g. model choice, prompts, RAG, tool use) is up to you.
If you just want to chat about support data with a local agent, our MCP server is the fastest way to get a model talking to Plain. This guide is about building autonomous agents within Plain.

What an agent looks like in Plain

An agent in Plain is made of three pieces:

A machine user

The agent’s identity in Plain. Has a public name, an avatar, and one or more API keys.

A webhook listener

A public HTTPS endpoint that receives Plain events like new threads, incoming messages, and assignment changes.

A GraphQL client

Makes calls back to Plain to read threads, reply, change assignment, add labels, create notes, and more.
When something happens in Plain (a customer sends an email, a teammate assigns a thread), Plain delivers a webhook to your endpoint. Your code decides whether the agent should act and uses the GraphQL API to do whatever it does: read context, reply, label, summarise, hand off, post a note, anything else. Agents come in many shapes. Some reply to every new thread; some only act when assigned; some never reply at all and just classify, summarise, or post internal notes. The building blocks below are the same regardless of what your agent does.

The journey

1

Create a machine user

A machine user is the agent’s identity in Plain. Give it a public name (what customers see) and create an API key with the right permissions.Set up a machine user →
2

Stand up a webhook endpoint

Plain delivers events as HTTP POST requests. Use the @team-plain/webhooks package to verify and parse them with full type safety.Receive events from Plain →
3

Decide when your agent should act

You can filter events in code, or use Plain’s built-in workflows to assign specific threads to the machine user and only react to those.Route threads to your agent →
4

Read the thread

If your agent needs the conversation context, query the thread and pull its content as LLM-ready text.Read thread content →
5

Act on the thread

Use the @team-plain/graphql SDK to do whatever your agent does: reply, label, change status, create a note, hand off to a human, or anything else.Act on the thread →

A minimal example

Here’s one possible shape: an agent that replies to every new thread. It uses Express, but the same shape works with any HTTP framework. Your own agent will likely do something different in the handler.
import express from "express";
import { verifyPlainWebhook } from "@team-plain/webhooks";
import { PlainClient } from "@team-plain/graphql";

const plain = new PlainClient({ apiKey: process.env.PLAIN_API_KEY! });

const app = express();
app.use(express.text({ type: "*/*" })); // we need the raw body for signature verification

app.post("/webhooks/plain", async (req, res) => {
  const result = verifyPlainWebhook(
    req.body,
    req.header("plain-request-signature")!,
    process.env.PLAIN_WEBHOOK_SECRET!,
  );

  if (result.error) {
    return res.status(400).send(result.error.message);
  }

  const event = result.data;

  if (event.payload.eventType === "thread.thread_created") {
    const reply = await generateReply(event.payload.thread); // your AI goes here

    await plain.mutation.replyToThread({
      input: {
        threadId: event.payload.thread.id,
        textContent: reply,
      },
    });
  }

  res.sendStatus(200);
});

app.listen(3000);
Replace generateReply with whatever AI library you prefer, like the Vercel AI SDK, Anthropic SDK, OpenAI SDK, or your own.

What’s next

Machine users

Create the agent’s identity and API key.

Receiving events

Listen for the events that matter to your agent.

Routing to your agent

Use workflows and assignment to control when the agent acts.

Reading threads

Fetch thread context as LLM-ready text.

Acting on threads

Reply, suggest replies, post notes, add labels, and reassign threads.