Joel Stevick

Story 4 · Running the shop

Teaching my site to run the shop

My site now does the work of running my consulting business on its own. Every five minutes it reads every record it keeps, works out what is due, and does each thing it can with the same tools and the same delivery skills I use: it answers the chat, sends the agreement, bills the milestone, chases the invoice, answers a prospect and my mail. What it cannot do with the site's own hands it lists for me as one line with one button, and it never asks me a question.

Thirty features and one person

I counted, and my site has about thirty features for finding work, doing it and talking to the people it is for. There were the offers on the home page then, and there is the free demo, a chat with each client, a Guide that delivers each project step by step, invoices and care plans, outreach from my own Gmail, a search for companies that may need my services, the Upwork pipeline, and a job-search assistant that answers recruiters for me.

Each feature did its part well, and every one of them waited for me: to open it, to read it, to press its button. I am one person. What I wanted was simple to say: find the business, handle the conversations, and tell me only what needs my hands. Not a list of what is waiting for me to do, but the work done, and a short list of what only I can do.

What it does on its own

Every five minutes a set of rules in code reads the records and says what is due: an inquiry not yet answered, a registration with no agreement sent, a chat whose last message is the client's, an invoice past its due date, an email from a client waiting for an answer, a prospect's reply, companies found and not yet decided on. Nothing stores that list. It is a computed queue: worked out from the records themselves every time, so it can never drift from them. The rules are idempotent: the same records give the same queue, however often it is worked out.

Then the assistant takes each item, one model turn each, in the engagement's own Guide thread, reading the same delivery skills I follow in Claude Code. It is an agent in the plain sense: it decides what the step needs and does it with the site's own tools. It answers the client in their chat, writes the terms and sends the agreement from my Gmail, plans and sends the milestone invoice through Stripe, chases the one that is late, answers a prospect in their thread, accepts or dismisses each company it found and writes the first email to the ones it accepts, and answers my mail when the records say what to say. It writes as me, in my voice and with my signature, and the records say the assistant wrote it.

When the assistant has dealt with an item, it marks it, and the mark holds only while the fact it was put on is unchanged: if the client writes again, the newer message is newer than the mark, and the item is back. I call these re-arming marks: a mark can quiet a fact, never hide a newer one.

Each action is one line in a log on my admin page: what it did, for which project, with a link to the record. I read it when I want to, the way I would read a colleague's notes at the end of a day.

flowchart LR
  R[("The records: engagements, invoices, chat, the inbox, outreach")] --> U["The rules, in code"]
  U --> A["The assistant, with the delivery skills"]
  A --> X["The records change, one line in the log"]
  A --> N["Or Needs you: one line, one button"]
  X -.-> R
From the records to the assistant and back to the records, or to me

What it never does alone

Some things need a person's hands, and the assistant knows which in code, not by asking a model. It never signs anything. It never moves money out of a bank, so a developer's payout is mine to send. It never touches Upwork, which only Claude Code reaches. It never works in a client's own systems, so a care plan's monthly run in their repository is a person's. And it cannot authenticate, so a Google connection that needs signing in again is mine. Each of these is one line under Needs you, with one button that goes to where it is done: Sign, Pay, Open, Reconnect, Open in Claude Code.

When the assistant tries something and finds it needs a person after all, it hands it over the same way, as one imperative and never a question: "Run the eval in their repository", not "Which data source do you want?". If a client asks something the records cannot answer, it replies that they will hear back, and the line it leaves me is the one thing to do. That is the human in the loop, kept for what only a human can do. And there is a Pause switch on the page, the brake: paused, it does nothing at all.

What counts as behind

The rules still say when each item is due and when it is behind, so the work goes in the right order: behind first, then due, money first within each. The lines are figures in one place in the code, and this table is checked against them:

What is waitingOn the listBehind
An inquiry, an agreement to send, an email, an outreach replyat onceafter 2 working days
A client's or a visitor's chat messageat onceafter 24 hours
An invoice sent and unpaidthe day after its due dateat once
An agreement sent and not signedafter 7 daysat once
A payout owed to a developerafter 14 daysat once
A project's due date2 days beforeonce it has passed
A project under way with nothing recordedafter 7 daysnever: it is a question
A care plan's monthafter 30 daysafter 35 days
Companies the search found and nobody decided onafter 3 daysnever: it is upkeep
The Upwork syncafter 24 hoursafter 3 days

My home page promised a reply to every inquiry within two working days, so that rule counts working days, Monday to Friday, in New York. With the assistant answering within five minutes, the line is rarely reached; it is there for the day the assistant is paused.

The guards are code

An assistant that sends mail and invoices as me needs limits I can read, and a prompt is not a limit. Every one of these is a constant in the site's code, checked on every call whatever the model asks, and this table is checked against them. These are guards in code: the model can be talked into anything, the code cannot.

WhatAt most
Tasks one five-minute tick works on10
Tool calls in one turn on one task15
Turns in a day300
Tries at one task, an hour apart, before it is handed to me with the error3
Replies to my inbox in a day20
Outreach emails in a day50

Who it may write to is code too. A reply in the chat goes to the engagement's own client, found from the record, never from an address the model names. A reply to my mail goes only to the person who wrote, once per message, never to an address nobody reads, and never with anything my profile says is never shared. A business marked do not contact is never written to. And everything the assistant reads, a client's message, an email, a web page, is data, never instructions.

My inbox

Clients and colleagues write to my Gmail, and the job assistant already sorted every new message there every five minutes. A message from a person waiting for my answer becomes an item in the queue, and the assistant answers it when the records say what to say: a client asking when the next milestone is, a colleague confirming a time. When they do not, it leaves me the line "Answer them in Gmail", with the thread one click away.

sequenceDiagram
  participant K as A client
  participant G as Gmail
  participant T as The five-minute tick
  participant C as Claude
  participant J as Me
  K->>G: An email
  T->>G: Anything new?
  G-->>T: A message that waits for an answer
  T->>C: The message, the thread, the records
  alt The records answer it
    C->>G: A reply, as me
    T->>G: Anything from me in that thread?
    G-->>T: Yes: it is answered
  else Only I can
    C-->>J: Needs you: answer them in Gmail
  end
An email from a client, answered from the records or handed to me

A developer's version

A developer who delivers projects for me sees the same page over the projects assigned to them: what the assistant did on those projects, and what needs their hands there, like a step in a client's repository. They never see money, my inbox, my job search, outreach or Upwork, and the server checks the role and the assignment on every request, whatever the page asks for.

What it costs

One model call per item that needs one, with the same model and key the Guide already used, and the calls that were already being made: the inbox sorting, the daily search. An item the rules can settle in code, a payout or an Upwork sync, never reaches the model. The status line at the top of the page says when the assistant last ran, what it did and how much needs me, and the log says each thing it did. That is its observability: I can see that it is working, and an empty Needs you means the work is done, not that the assistant is asleep.

This story is about the build, not the results: it went live the day it was built. When there are weeks of it worth reporting, their numbers will come from an export of the records, as every number in these stories does.

What to take from it

The shape is not about my business. An assistant that works a queue computed from the records a business already has, does what the code allows with the tools the business already has, and hands people only what needs their hands, works the same with tickets, orders, claims or contracts in place of my engagements and invoices. The useful part is not a clever model. It is the limits written in code around it, and a short, plain list of what is left for you.

Comments