Skip to content

Documentation

What runs when nobody is looking

Three things Kicklace can do on its own overnight: read and tag the email that arrives, write one short brief in the morning, and watch for four named situations you would have spotted yourself if you had had the time. All three are off until you switch them on, and none of them can send anything.

Kicklace does three things on its own overnight, and it never sends anything.

  • Triage — every email that arrives is read once and tagged by intent, and the matching reply is drafted on the person's record for somebody to send.
  • The brief — one notice a morning saying what changed: who joined, who went quiet, what is waiting for approval, which drafts are ready, and which of your charts moved.
  • Noticing — four named rules looking for the thing you would have spotted if you had time, each arriving with the work already written down.

All three are off until you switch them on, all three run inside the same worker that already refreshes the paragraphs at the top of your records, and all three obey the one rule everything here obeys: what it wants to send is a draft, and a person decides that it goes.

The direction behind it is docs/ai-centric-direction.md §4 and §10.


1. Triage is a starter, not a new engine

There is no separate triage system. Reply triage is one of the starters in docs/blueprints.md, written in the ordinary automation language, and you read it, edit it and switch it on like any other automation.

Settings → Setup → Starters → Reply triage installs, paused:

  • an Intent field on a person — A question · A complaint · A cancellation · Thanks · Something else;
  • four emails to rewrite in your own words — Answer to a question, Sorry about that, Before you go, Thank you;
  • two automations that read — one for a reply (email_in), one for a message to your own support inbox (support) — each of which has the model set Intent from what the person wrote;
  • four automations that draft — each watching Intent, each drafting the matching email for the owner to send. The cancellation one also puts Call <name> today: they are cancelling on the owner's list, due today.

What it costs. One model call per message that arrives, on your workspace's own allowance under Settings → Billing. The four drafters ask nothing at all: they read a field. A workspace with AI switched off installs the whole starter happily and the two readers are skipped with a sentence in the run's log, which the activation question tells you before you arm one.

What it never does. There is no send_email anywhere in it. Every card says drafts only.

Why it is six automations and not one. Otherwise is one level, on purpose: four outcomes cannot be one sentence without becoming a flowchart. One classifier and four drafters also means each card is a line you can read and switch on by itself, and only the first one spends anything.


2. The morning brief

Switch it on: Settings → General → What Kicklace does on its ownA morning brief. Get it by email: your own profile, one tick box per workspace.

At 08:00 in the workspace's own timezone, once a day, Kicklace works out what changed in the last twenty-four hours and, if there is anything to say, delivers one notice.

What it counts, all from the database:

Line What it means
3 people joined: … People who left an address, whose first touch was in the last day (or, for a record typed in by hand, the day it was made)
2 people have gone quiet after 14 days: … People who left an address, whose last activity crossed the fortnight line in the last day — so a person is named the morning they go quiet, and not every morning after
2 proposals are waiting for you: … Pending approvals (#211) that have not run out
4 emails and 1 broadcast are drafted and waiting to be sent Open tasks an automation left with draft_email, and broadcast drafts
Subscribers this month: 41 — 33 the period before (+24%) Every number tile on the main dashboard that compares itself against the period before and moved

Joined and went quiet name only people who left an address — the same line the People view draws. A browser that read a page and went away again is on the visitors chart, and five Anonymous visitor rows every morning would be noise nobody can act on.

When it actually arrives. The worker runs on Vercel Cron and after a page loads. The worker's cron runs every hour (since 2026-09-09, on the Pro plan), so a brief for this morning's 08:00 lands within the hour — sooner if anyone opens a page, since a page load looks too. The occurrence it covers is the calendar's, not the worker's, so a late brief is still yesterday-to-08:00 and it is never written twice.

Then, only if AI is on, one model call (purpose brief, on the same allowance) writes at most two sentences over the top of those facts. The model is shown the facts and nothing else, and it is told never to state a number or a name it was not given. The facts go out whether or not it answers: a model that is down, a switch that is off, or a day's allowance already spent all mean the brief arrives with no lead sentence and every fact intact.

Where it lands: the bell, for every owner and admin; your Slack channel, because it goes through notifyManagers like every other notice; and, by email, to each manager who ticked the box on their profile.

A workspace with nothing to say gets nothing. "Nothing new" is not news, and a bell that is empty six mornings out of seven is a thing people switch off.

Stopping the email. Every brief carries a Stop the brief link. It is signed the way a reply address is, so one click works straight from the email with no sign-in — and it takes you off that workspace's email and nothing else: the brief stays on for everybody, and it is still in your bell.


3. What Kicklace notices

Switch them on: Settings → General → What Kicklace does on its ownWhat Kicklace notices. Each is one sentence with its own box; none is on by default.

Rule What it looks for
Read your pricing twice People who read a page with "pricing" in its address twice in the last seven days, have an email address, and have never had an email from you
Signed up and never got started People who made an account seven days ago or more and have not been activated since
Cancelled and nobody wrote back People whose subscription was cancelled in the last seven days and who have had no email from you since
A reply nobody answered People who wrote to you more than two days ago and have had nothing back

Each runs once a day, at the same 08:00 the brief lands, and each is plain SQL over your own timeline. Nothing here calls the model.

When a rule finds somebody it writes:

  • one notification — "3 people read your pricing page twice this week and have never heard from you: Ada Lovelace, Grace Hopper and Alan Turing" — with the names capped at five;
  • one task per person (at most ten a day) on that person's record, for the workspace's first owner, due today, written by what Kicklace noticed. It never writes the same task twice: a person already on your list is left there.

Where the workspace has the email for it — the one the Reply triage or SaaS starter installs — the notice names it as the wording to start from, and a rule that found exactly one person links straight to the composer with those words in it.

A rule that finds nobody says nothing at all.


4. Autonomy, granted per sentence

From docs/ai-centric-direction.md §10: autonomy is granted per sentence, never per agent. So every automation and every starter wears one of three words, worked out from what it actually does and whether it is switched on — never written by hand, so it cannot say one thing while the definition does another.

Word When What it means
drafts only Nothing in it emails a person What it writes waits for a person to send it
proposes, you approve It emails people, and it is not switched on Activating it is your approval; until then nothing goes out
runs alone It emails people, and it is on It emails people without asking again

The word is on the automation's own card, in the automations list beside its state, and on every starter in Settings → Setup. send_email is the one act that counts as reaching outside: a Slack line, a signed post to your own server and an email to a member all stay inside the team.


5. What it never does

  • It never sends an email to a customer. Not the brief, not a noticing rule, not any part of Reply triage. The one thing in Kicklace that emails a person because a rule said so is a send_email you switched on yourself.
  • It never deletes anything, and it never changes a setting.
  • It never puts anybody on a list.
  • The model never sees another workspace, another record, or a timeline row's words except the message that started the run — the same rule every AI step keeps (docs/automations-v2.md → The four that ask the model).
  • It never spends without the switch. The brief's lead and Reply triage's classifier both go through askModel: the server's key, the workspace's AI switch, the account's daily allowance, and the meter the console reads. Everything else here asks nothing.

6. Where it lives

Piece File
The brief's facts, and the words they become src/lib/data/brief.ts
The hour, the lead, the delivery, the claim src/lib/automation/brief.ts
The signed "Stop the brief" address src/lib/automation/brief-token.ts, src/app/brief/stop/[token]/
The four rules src/lib/automation/noticing.ts
Both jobs in the worker src/lib/automation/tick.ts
The switches src/components/settings/features-form.tsxAgentForm
The email opt-in src/components/account/brief-email.tsx
The three words src/components/automations/describe.tsautonomyWord
The starter blueprints/reply-triage.json

Both daily jobs are claimed per workspace through a jobs row (brief:<id>, notice:<id>), one update … where last_run_at < … returning, so two checks running at the same moment cannot both write a brief. There is no migration behind any of it: the two new notification kinds and the new features keys are a text column and a jsonb one.

Tests: src/lib/data/__tests__/brief.test.ts, src/lib/data/__tests__/noticing.test.ts, the three words in src/components/automations/describe.test.ts, and the starter in src/lib/data/__tests__/blueprints.test.ts.