---
title: "Public School Is a Second Job. I Built It an Assistant."
description: "Two working parents, half a dozen school apps, and a first grader who came home upset about a library book. I built a household agent that reads all of it and sends one message the night before. Here is how little I let the model decide, what the evaluation caught, and the two times it sent something it should not have."
url: "https://angstromsys.com/blog/carson-household-agent/"
published: 2026-10-28
author: "Andrew Kaiser"
tags: ["AI Agents","Build in Public","Forge"]
---
# Public School Is a Second Job. I Built It an Assistant.

For two working parents, a public school can feel like another job. Messages come from the district and from the school. There are half a dozen apps, each with its own login. There is a lunch menu, a weekly rotation of gym and library and music, and a steady stream of "don't forget" that arrives at the worst possible time.

We learned this in kindergarten, mostly by getting it wrong. We forgot library books, so our son came home upset because he wasn't allowed to check out new ones. We sent him without a rain jacket because the morning was sunny. We missed spirit days. We didn't pack a lunch on the day the menu was something he would never eat.

None of it is hard. It is scattered across too many places, and it lands on whoever happens to be paying attention that day.

So I built Carson, a household agent. Every evening at 7:00 it sends my partner and me one short message about tomorrow: what our first grader needs, whether there is school at all, what's for lunch, the weather at drop-off and pickup, and anything on the family calendar. It runs on a Mac at home, on [Forge](https://angstromsys.com/products/#forge), the agent runtime I wrote. It went from an empty folder to its first automatic brief in four days, and it cost about thirteen cents in model spend over its first nine days.

This post is about how it is built, and mostly about how little the model is trusted.

---

## One message, and nothing to open

The first decision had nothing to do with models. The problem was six apps, so a seventh was never going to be the answer. Carson has no app, no dashboard and no login. It reads everything, works out what matters for tomorrow, and puts that in front of us on channels we already check: a full email with quotes and links, and a short text for the phone.

I have built this shape before. A restaurant group had reviews coming in across every location, and what I built for them read all of it and delivered a briefing on a schedule. Nobody had to go and look at a dashboard to find out what kind of week it had been. The lesson I took from that work is that a synthesis people have to go and fetch stops being fetched. Push it to them, finished, and ask nothing in return except that they read it.

The brief still tells us to do things. Put the library books in the backpack. Pack a lunch tomorrow. But getting to that point takes no effort from either of us, and that turns out to be the whole difference. I can message Carson now, and my partner will be able to soon, but that stays optional. The brief has to keep working for the parent who never answers it.

## The model proposes; code decides

A school post is informal. A teacher writes a friendly paragraph, and somewhere in it is the one fact you needed. That is a job a language model is good at. It is also a job where being confidently wrong once costs you a child standing in the wrong shirt.

So the model is given the smallest role I could design. It reads each post and lists what is in it, something like "School Colors Day, wear the green shirt, the 14th." Everything after that is ordinary code:

- **The model must quote the post, and the quote must appear in it word for word.** If it doesn't, the item is thrown out.
- **If the quote contains a date, code reads the date itself** and compares it with the model's. If they disagree, the item is held.
- **A relative date is held as a question.** "Due back next Friday," written on a Friday, could mean either of two days. The brief asks "the 6th or the 13th?" instead of picking one.
- **The brief is assembled by code, not written by a model.** Every line is a stored fact or the sender's own words, with a link to the original.

I want to be exact about what this buys. The quote check proves the words are really in the post. It does not prove the model understood them. What covers that gap is the second rule: say what you don't know. A held item shows up as a question. A brief built on stale data says so at the top. A calendar feed that has died fails loudly instead of looking like a quiet month.

There are also two tiers of trust in the sources. The district calendar is authoritative, so it is fetched directly and believed. Teacher and school posts are situational, so they are extracted and checked. When the two disagree on a fact, the calendar wins. The teacher adds what the calendar never says, which is what to wear and what to bring.

## Measured before it was allowed to run

The extractor was evaluated before it ever ran on its own.

The test set has two parts. The first is synthetic posts with known answers, built from the patterns real posts have: a list of dates run together on one line, "tomorrow" sitting next to "on Thursday," a deadline in the fourth paragraph of a newsletter, a welcome letter with nothing dated in it, events meant for other grades. The second is real posts with hand-written answers. The real text never enters the repository.

Every case runs three times, because the model is not deterministic. The bar is zero hard failures: nothing missed, nothing invented, and nothing that should be a question presented as a fact. The result was 141 of 141 expected items, with no failures.

The evaluation also made the model replaceable. Carson started on one provider's model, and eleven days in I moved extraction to another. I changed the configuration and ran the same suite three times before switching it on. The new model disagreed with my answer key exactly once, and it was right, so I changed that answer and got 141 of 141. Without the suite that switch would have been a guess. I wrote about it in more detail in [Keep the Receipts, Swap the Model](https://angstromsys.com/blog/receipts-and-swappable-model/).

That number describes the test set, so here is the other half. In real use the extractor occasionally drops a low-stakes item, such as another family's volunteer slot. In testing it has never dropped one we act on.

The evaluation earned its keep before anyone saw a brief. It caught the model stitching two separate sentences into a single "quote." It caught "were sent home on Wednesday" being read as next Wednesday. And it caught a rule meant to skip other grades' events also dropping our son's own class activity, because that activity happened to involve older students.

## Quiet is a feature

Most of the product decisions were about leaving things out.

- **Weekends only when something is on.** An empty "nothing tomorrow" every Saturday would teach us to skim.
- **One plain weather line.** Something like "41° at drop-off, 58° at pickup, cloudy." A separate rain-jacket line appears only when rain overlaps school hours. Cold is not flagged, because we dress for that the same way every day.
- **Lunch is listed, not judged.** Our son is picky enough that we decide.
- **Each parent gets their own copy.** My anniversary reminder arrives thirty days out and reaches only me. A grandparent is "Dad" in my copy and "Grandpa" in my partner's.

It also changed quickly once we were living with it. It started at 6:00 in the morning. Within a day it was obvious that mornings are too hectic to act on anything, so it moved to the evening before. Then it started reading the family calendar we already keep by hand. Then came the forecast, because my partner kept asking about the weather. Then home upkeep, like the furnace filter with its size so we order the right one, and birthdays with enough warning to do something about them.

## Two times it sent something it shouldn't have

**The model filled in an optional field.** The tool that sends the brief had an optional setting for who receives it, meant for my own testing. The scheduled agent set it anyway, picked the first allowed value, and sent that evening's brief to me alone. A model will fill in every optional field you offer it. Tools that a scheduled agent calls now take no arguments at all. Overrides exist only on the command line, where a person types them.

**Then my fix broke my own previews.** Making the tool ignore its arguments meant my "preview" calls went through the same door, lost their preview flag, and really sent. Twice. The preview path now calls the underlying function directly, and I check the send log after every preview.

Neither mistake was a model being clever or malicious. Both were ordinary tool design.

## What never reaches a model

This system handles a child's school life, so some things are simply out of bounds.

Private messages between a teacher and a parent are never read by a model and never summarised. The brief says one arrived and links to it. The titles on our family calendar never leave the Mac. Login tokens embedded in school email links are stripped before anything is stored.

It is also why Carson is its own deployment, separate from the assistant I run for myself on the same runtime. It holds different data, it writes to someone other than me, and it has a lower tolerance for being wrong. Same runtime, separate blast radius.

## What it costs, and what it can't do yet

Model spend was about thirteen cents in the first nine days, estimated from the run ledger, on the first model. The hourly sync is the cheap part, because the model only sequences tool calls. The weather and lunch-menu sources are free, and the Mac was already on.

The rough edges are real:

- **Carson only half hears.** I can now message it, to put something on the family calendar or the grocery list, but my partner isn't on that channel yet, and it still can't be told that a form went back to school.
- **Undated items are skipped.** "Sharing next week, bring a collection" has no day in it, so it is left out.
- **School platforms change their templates.** A new newsletter layout arrived mid-week and had to be cleaned up.
- **Everything runs on one Mac.** If it is asleep, so is Carson.

Next is bringing my partner into that conversation, then dinner planning: three ideas to choose from and an ingredient list.

---

*Carson runs on Forge, the agent runtime behind the systems I build for clients. If your business has its own version of six logins and a stream of "don't forget," that is the kind of problem [a walkthrough](https://angstromsys.com/walkthrough/) is for.*
