Live in production302 shadow decisions · 94% ok

Your own Claude, working the support queue like a team.

Pilata is the control room around it. Plain code claims chats, enforces every guardrail and keeps the journal. Claude does only the judgment — investigating, deciding, writing. Anything it shouldn’t handle goes to a person.

  • runs on your Claude login
  • guardrails in code, not prompt
  • people steer, people decide
pilata · live map app inbox · live
Claude Agent SDK Chatwoot Telegram Postgres MCP Your data API Docker systemd Claude Agent SDK Chatwoot Telegram Postgres MCP Your data API Docker systemd Claude Agent SDK Chatwoot Telegram Postgres MCP Your data API Docker systemd
  1. 01

    A customer writes.

    Pilata watches every inbox you connect. Each conversation gets a row in Postgres and a line in the journal. Inboxes you keep for people — WhatsApp, say — stay off-limits in code.

  2. 02

    It waits for the burst to end.

    Customers type in bursts. A turn becomes claimable 45 seconds after the last message, so three messages become one job — and one answer.

  3. 03

    The first free slot takes it.

    One row update with SKIP LOCKED. The lease lives only while the turn is worked; a crashed runner simply stops renewing and the turn goes back to the queue.

  4. 04

    Claude looks things up.

    A fresh context scoped to this one customer. Tools resolve the customer from the conversation — no tool can even name another chat, so nothing leaks between customers.

  5. 05

    Code checks the reply.

    Before anything leaves, the outbox re-checks: did a person reply since the claim? Quiet hours, reply cap, near-duplicates, card and phone numbers, the inbox’s mode.

  6. 06

    Sent — or handed to a person.

    In live mode the reply goes out. In approve mode it waits for a tap. If the customer is upset, money is stuck or tools can’t fix it, Claude hands the chat to a manager with findings and the next step.

Ingest
Settle
Claim
Investigate
Guard
Deliver
А
Айгерим
app inbox · #29871
Здравствуйте
Заказ 48213 так и не пришёл
Уже неделя прошла 😕
journal · conversation.opened · 14:02:11
45ssince last message
Здравствуйте
Заказ 48213 так и не пришёл
Уже неделя прошла 😕
turn · #298713 messages → 1 job
#29880 settling
#29871 Айгерим · заказ не пришёл
#29884 settling
slot-1
working
slot-2
claimed #29871
lease 5:00
slot-3
working
UPDATE jobs SET state = 'claimed', slot_id = $1
WHERE id = (… FOR UPDATE SKIP LOCKED)
context: customer of #29871 only
  • get_conversation3 messages · app inbox0.2s
  • case/orders#48213 · in transit · CDEK0.6s
  • carrier-statusAlmaty sorting centre · 2 days1.1s
  • get_journalno earlier promises0.1s
decision Parcel is moving normally — explain, give the timeline, no escalation.
draft · reply
Айгерим, посылка уже в Алматы на сортировке CDEK — обычно это 1–2 дня…
  • No person replied since claim
  • Outside quiet hours
  • Reply cap · 1 of 4
  • Not a near-duplicate
  • No card or phone numbers
  • Inbox mode · live
Уже неделя прошла 😕
Айгерим, посылка уже в Алматы на сортировке CDEK — обычно это 1–2 дня. Как только курьер её заберёт, придёт уведомление в приложении 🙌Claude · 1m 52s after the last message
live · sent through the outbox
approve · waits for a tap in Pilata or Telegram
upset, fraud, money stuck → private note + handed to a manager

Your Claude stays on your machine.

Agents run in an open-source runner on your server, under your own Claude Code login or an API key. The Pilata server does the plumbing and holds the inbox tokens. Neither side ever holds the other’s keys.

  1. A

    Sources

    Chatwoot inboxes and Telegram team groups. Each source has its own mode — off, shadow, approve or live — enforced by the server.

  2. B

    Pilata server

    Queue, dispatcher, timers, outbox guard and an append-only journal on Postgres. It performs every write to a customer — Claude never holds a Chatwoot token.

  3. C

    Your runner

    pilata-runner connect on any box. It dials out over one websocket — jobs come down, tool calls go up. No open ports, works behind NAT.

A team, not a chatbot.

Pilata replaces one fragile long-running session with a small crew of short, scoped jobs — and a lot of boring, reliable code around them.

Plain code for plumbing. Claude only for judgment.

Anything with a right answer is a rule you can read. Claude is called when a person would have to think.

code
  • Settle delay · 45 s
  • Claims & leases
  • Reply guard
  • Caps & duplicates
  • Waits & deadlines
  • Quiet hours
claude
  • Read the whole chat
  • Look up orders & payments
  • Decide what’s wrong
  • Write in your team’s tone
  • Ask the team when unsure
  • Hand off with findings

Fresh context per job

Every turn starts clean, scoped to one customer. No compaction drift, no cross-customer leaks — by construction.

Everything is journaled

Every tool call, draft, send and hand-off — append-only, and live in the UI.

Idle costs nothing

No agent polls. Slots sleep until a turn is ready, and the playbook prefix is prompt-cached.

Hand-off is a normal outcome

No mode blocks escalation. The person gets the homework already done.

private note · Chatwoot

Возврат 12 400 ₸ по заказу #48190 отклонён банком 2 раза. Карта клиента заблокирована. Дальше: запросить новую карту и повторить возврат.

The prompt asks. The code enforces.

Every outgoing message — to a customer, to the other side of an order, to a team group — passes the outbox guard. Rules that matter don’t live in a prompt that can be talked around.

claude · draft
#29871

Посылка уже в Алматы на сортировке CDEK — обычно это 1–2 дня.

outbox guard
  • Reply guardno person replied since the claim
  • Quiet hoursno outbound at night
  • Reply cap4 replies without a fix → hand off
  • Duplicatesnever the same answer twice
  • Card & phone numbersnever in an outgoing message
  • Inbox modeoff · shadow · approve · live
sent 0 blocked 0
  • waiting for the first draft…

Four modes per inbox. Trust is earned.

Each source has its own mode, switched in one place. New Telegram groups start in shadow.

nothing written to ChatwootClaudeinvestigates · draftsOutbox guardevery send checkedNeeds youapprove or editCustomervia ChatwootJournalproposal recorded
mode · shadow

Watch it think. Nothing is sent.

Claude works every chat for real, but proposals live only in Pilata’s journal — nothing is written to Chatwoot. Grade them against what your team actually sent.

good for The first week on a new inbox.

Managers steer in plain words.
Pilata turns them into work.

01 · Tasks

Give it work in a sentence.

“Get the full address”, “write to the seller”, “wait until it’s delivered”. The composer turns a sentence into a task with a goal, required fields, waits and a deadline. Plain code watches the waits; Claude wakes only when one fires.

  • Required fields the server validates — no premature “done”
  • Waits on a reply, a time or a data check
  • Opens chats and posts to team groups, through the same guard
new task

TASK 41#29871by Danahigh
goal
Get the customer’s full delivery address
done when
citystreethouseapartmentphonechecked by the server, not by Claude
waits
customer reply · 24 h → remind once · then needs you, ping Dana
status
open · 0 of 5
openclaimedwaitingresumeddone
02 · Ask the team

One question, many chats.

When knowledge is missing, an agent asks your team’s Telegram group — but first it checks for an open question that already covers it, and joins instead of re-asking. One answer resumes every waiting chat, with per-chat exceptions in the same line.

  • The agent is free immediately; the chat is parked on the question
  • Answered chats jump to the front of the queue
  • A timeout hands the chat to a manager instead
#29871ask_team · Q-12
#29880same question → joined Q-12
#29881same question → joined Q-12
#29884same question → joined Q-12
П
Поддержкаteam group · 6 members
Q-12 1 chats waiting

Можно вернуть бонусы за отменённый заказ, если он был оплачен бонусами?

ДанаДа, 2000 бонусами всем, кроме #29881 — там оформите возврат.
policy answer → lesson draft L7
03 · Lessons

Teach it like a new hire.

Feedback on a chat, a note in the Teach box or /teach in Telegram becomes one short rule. Claude drafts it, merges it with lessons on the same situation and flags contradictions; a person approves it. From then on it is in every prompt — in full.

  • Verbatim feedback, author and source chats kept with every lesson
  • Never summarised, so nothing is lost to context squeeze
  • Approve in Pilata or with ✅ in Telegram
every agent prompt
SUPPORT.mdtone, guardrails, escalation
Lessons L1 … L9verbatim, in full
KNOWLEDGE.mdFAQ, order lifecycle
this chat onlyfresh context

Shadow first. Live when the grades say so.

Our first customer, a second-hand marketplace, ran Pilata in shadow on its main inbox: Claude worked every chat, nothing was sent, and every proposal was graded against what the human team actually replied.

0shadow decisions graded against real replies
0%graded OK — the rest were playbook gaps, not plumbing
0messages written to customers during shadow
live in production since Oct 2026

Bring your own Claude.
Keep your own box.

The runner is a small open-source CLI. Log in to Claude Code on your server — or set an API key — and connect. Add slots for more parallel chats, add runners for more machines. Each slot runs one short job at a time on the Claude Agent SDK.

  • Your Claude credentials never leave your machine
  • Subscription or API key is one setting
  • Usage per runner, pause or watch any slot live
ops@hetzner-1 — pilata-runner
$
plan window
41%
this week
63%

Give your support queue
a control room.

Start in shadow on one inbox. Go live when the grades say so.

See how it works

Request access

Pilata is in early access. Write to us about your support queue — where customers reach you, roughly how many chats a day, and where your team talks.

or open your mail app