How Our AI Team Runs AthlyticZ
The Jarvis starter: the jobs, the approvals, the models, the daily brief and the guardrails
Michael Czahor · Founder, AthlyticZ · November 2026
Why I built it
AthlyticZ runs on a lot of small jobs. A paid order has to become a login. A new signup has to get the right email at the right time. An application needs a reply, a booking link and a reminder. Job postings need reading every week. None of it is hard. All of it has to happen every day, without fail.
So I'm building a team of small AI agents to run it. Jarvis is our nickname for the whole system. The goal is simple: I hear from it once a day, unless a decision needs me.
This guide is how it's wired. It's honest about where we are: some of it has been running for weeks, and some of it is being built this month. I'll tell you which is which.
The one rule everything follows
Agents propose. A person approves. A separate step acts.
Nothing in our system decides and acts in one command. That single rule is most of the safety. An agent that can only write down what it wants to do can't surprise you, and you can read its homework before anything leaves the building.
1. The jobs
Each agent has one job, its own instructions and its own short list of allowed actions. They don't talk to each other directly. They hand work over through the plan store (section 2).
Running today:
| Agent | Its one job | How often |
|---|---|---|
| Routing | Turns every paid order into an academy enrollment, then sends our welcome email | Every 5 minutes |
| Nurture | Sends each new site signup the next email in their series, when it's due | Every 5 minutes, inside a daytime send window |
| Free masterclass | Sends the free masterclass and the three follow-ups | Every 5 minutes |
| Applications | Reads every Program application, alerts me with every answer, and drafts the reply with a booking link | Every 5 minutes |
| Reviews | Asks each paying customer for a review, and publishes only the ones they consent to | In batches I approve |
| Announcements | Drafts one email from me to everyone who currently has a product | When I ask |
| Jobs | Reads new sports analytics job postings each week, drafts them for our board, and marks the expired ones | Monday mornings |
| Content | Turns session recordings into clips, captions, lesson notes and posts, with every line of code checked against the real materials | Per recording |
Being built this month:
| Agent | Its one job |
|---|---|
| Sales | Booking chase, call reminders, no-show rebooks, and the follow-up after a call |
| Concierge | Answers questions from our knowledge base, and hands anything sensitive to a person |
| Ads | Reads spend and results every day, and proposes what to pause, replace or scale |
| Social | Tracks comments and keyword DMs per video, and proposes what to boost |
| Onboarding | Welcomes new members, and checks in when someone goes quiet |
| Partners | Credits instructor and affiliate sales, and builds monthly statements |
| Brief | Writes the daily text (section 4) |
2. The plan store and approvals
The plan store is a small database, and it's the heart of the system. Every agent writes what it wants to do there, as a record. Each record holds:
- which agent proposed it, and when
- the target (a contact, an order, a product)
- what the target looks like now, and what it will look like after
- the exact requests that will be sent, word for word
- a one-line summary a person can read in five seconds
A record moves through five states, and only these moves are allowed:
proposed → approved → executed (or failed), and proposed or approved → rejected.
Every move is logged with who made it and when. Records are never deleted. The store is the history.
Approving is one command: review.py approve 331 --commit. It also works as a text: reply "approve 331" from my phone. Then a separate step, the executor, picks up only approved records. Before it acts, it re-reads the live system. If the target has changed since the record was proposed, the record fails as stale and nothing is sent. The agent proposes again from the new state, and a person looks again.
Every script runs as a practice run by default. It prints what it would do and does nothing until you add --commit.
Policies: how a job earns the right to run alone
Approving every email by hand doesn't scale. So each kind of message earns its independence:
- The first ones go by hand. Two for application replies. Ten for the nurture emails. I read each one before it goes.
- Then the agent proposes a policy. The policy is itself a record I approve. Once it's on, that one kind of message approves itself.
- Every policy has a ceiling. For example, at most 50 nurture emails a day and at most 20 application replies a day. Follow-up emails only go out inside a daytime window.
- Every policy can trip itself off. One failed send, or two bounces within 24 hours, turns it off. It goes back to approval by hand until I switch it on again.
There's also a plain stop switch. A single file on the server stops the email agent before it reads anything at all.
3. Model choice per agent
Here's the part that surprises people: the agents running today don't call an AI model at all. Routing an order, sending a due email and reading a form are plain code. Plain code is faster, cheaper and does the same thing every time. Our content agent is the exception: it uses models to cut clips and draft notes, and a person checks the output.
A model comes in only where language does: answering a question, drafting a follow-up from call notes, or reading a week of ad results. So we're building the new agents to be model-agnostic from day one:
- One config file names the model for each agent. For example, a fast, inexpensive model for the concierge's first pass, and a stronger model for sales follow-ups and the ads analysis.
- Every agent calls one internal function to talk to a model. Switching provider or model is a one-line change to the config, not a rewrite.
- Every message logs the model that wrote it, so when something reads wrong we can see where it came from.
Pick the model by the job, not the other way round.
4. The daily brief
Every morning at 7:30 Eastern, Jarvis sends me one text, with email as the fallback. It's six lines at most:
Yesterday: [questions answered], [new members], [applications], [calls booked], [sales], [ad spend].
Ad spend per held call this week: [amount].
Needs you ([count]): [each item waiting on me, one line each].
Reply [number] to approve [the plan].
- "Needs you" lists only what's waiting on me: plans to approve, questions the concierge escalated, and anything a guardrail stopped.
- If nothing needs me, the last line says "Nothing needs you."
- I reply with a number to approve that plan. Any other reply is logged and shown on the dashboard.
- Every number is defined in one file, so the text and the dashboard can never disagree.
The first brief goes out this week. It's the piece I'm looking forward to most.
5. The guardrails
These are written into the spec. The agents already running enforce them in code, and every new agent has to as well:
- It never moves money on its own. Refunds, discounts, budget increases and payouts are always plans a person approves.
- Every outbound message is logged: the text, the recipient, the agent, the reason and the policy it went under.
- New kinds of message go by hand first, then earn a policy (section 2).
- Nothing deletes. Not contacts, not student records, not videos. Ads get paused, never deleted.
- Keys and tokens stay in the server's environment file. Never in chat, never in the code repository, never on a screen.
- Stop means stop. A reply, an unsubscribe or a "stop" ends the sequence for that person, for good.
- A person is one message away. Refunds, complaints, legal or privacy questions, anything the concierge isn't sure of, and anyone who asks for a person go to a human.
- Every release ends with a probe. A test applicant goes through apply, book, remind and hold, and has to show up correctly everywhere before we call the release done. Then it's marked as a probe, not deleted.
- Plain language everywhere a person reads it.
Build your own: where I'd start
- Build the plan store first, before any agent. A table of proposed actions, an approve command and an executor that re-checks before it acts.
- Pick the most boring daily job you have, and make it the first agent. Ours was turning paid orders into logins.
- Approve everything by hand at first. Write the policy only after you've read enough of its work to trust it.
- Add a model only where language is the job.
- Ask for one message a day. If you need more than that, something upstream needs fixing.
Want to go further? Reply to the email this came with and tell me the first job you'd hand to an agent. I read every one.