allanlotta
~/blog/agent-first-on-a-prayer-app

Agent-first product work on a prayer app

The product is guided prayer. Two or three minutes for a real situation: anxiety, grief, money, family. Delivered on WhatsApp first, with an app on the side. I worked on bringing it to Brazil.

The product is content, so making content was the job. The interesting part is that I did not write the content. I built the loop that produces it and the checks that keep it honest, and I signed what came out.

The loop

 ┌──────────┐   ┌──────────┐   ┌──────────┐   ┌──────────┐
 │  source  │──▶│  parse   │──▶│   tag    │──▶│  judge   │
 │  text    │   │ passages │   │ by need  │   │ (agent)  │
 └──────────┘   └──────────┘   └──────────┘   └────┬─────┘
       ▲                                           │
       │                                           ▼
 ┌─────┴────┐   ┌──────────┐   ┌──────────┐   ┌──────────┐
 │ improve  │◀──│  record  │◀──│   fix    │◀──│  sample  │
 │ pipeline │   │ decision │   │ pipeline │   │ by hand  │
 └──────────┘   └──────────┘   └──────────┘   └──────────┘

An agent produces. A second agent judges. A person samples. Every miss goes back into the pipeline, never into the data by hand, so the next run cannot repeat it. Then the decision that came out of it gets a file, and the loop runs again.

The layers

              ┌──────────────────────────────┐
              │  me: priorities, sign-off    │
              └──────────────┬───────────────┘
                             │
              ┌──────────────▼───────────────┐
              │  content and research agents │
              └───────┬──────────────┬───────┘
                      │              │
        ┌─────────────▼────┐   ┌─────▼──────────────┐
        │      memory      │   │       tools        │
        │                  │   │                    │
        │ handoff file     │   │ parser, assembler  │
        │ one file/decision│   │ tagger, judges     │
        │ daily journal    │   │ episode generator  │
        │ runbooks         │   │ stager, publisher  │
        └─────────────┬────┘   └─────┬──────────────┘
                      │              │
              ┌───────▼──────────────▼───────┐
              │          evaluation          │
              │                              │
              │  register judge              │
              │  pastoral safety judge       │
              │  mechanical audit (scripts)  │
              │  human sample                │
              │  conversation harness        │
              └──────────────────────────────┘

The memory layer is plain markdown. A handoff file that any new session reads first, one file per decision, a journal per day, and a runbook for anything done twice. It is what let me switch between chats, and between night and morning, without losing state.

Source and parse

Brazil needed a Catholic translation. The source was a printed edition, so the first job was turning it into passages: two to five verses that stand on their own.

The first assembler cut 10.4% of passages mid-sentence, on a comma or a semicolon. The fix was a look-ahead in the assembler, not an edit of the output. The rate dropped to 0.58% on the probe and 2.0% on the full run of 12,774 passages, with every verse covered.

Tag and judge

Each passage gets the situations it serves: anxiety and fear, grief, loneliness, guilt and forgiveness, work and money, family, gratitude, discernment. The tags are what retrieval runs on, so a wrong tag is a wrong answer to someone in a bad moment.

Three judges ran over the tagged corpus, each a separate agent with one question.

 tagged passages (12,774)
        │
        ├─ register judge ─── narrative | mixed | offering
        │       5,949 insert-ready · 657 held back
        │
        ├─ imprecatory scan ─ 291 hits · 101 held from
        │       sensitive situations
        │
        └─ pastoral safety ── only the 969 passages serving
                affliction: "would a person in that state
                feel worse reading this now?"
                safe | risk | doubt

The pastoral judge exists because of the human sample. Twenty psalms read by hand found five real problems, one of them a verse about sinners being treated as dross, served to anxiety, with no word from the anxiety lexicon in it. A word list cannot see meaning. So the judge only runs where a bad match causes harm, 19% of the corpus, and its prompt says explicitly that lament is not risk. Without that line it would have cut the best material. It cost about twenty cents.

What went to production: 5,105 passages.

Retrieval you can test

 "estou com medo de perder o emprego"
        │
        ▼
 situation: anxiety + work ──▶ faith scope: catholic
        │
        ▼
 Philippians 4:4-7   (grief → Psalm 142, guilt → Psalm 37)

Ten realistic messages in Portuguese, ten on-topic passages back. To keep it that way there is a harness that runs whole conversations against the real model and the real corpus without sending anything to anyone. When a change to the conversational agent broke retrieval, the harness showed the cause was not where the symptom was. That change was reverted on purpose, and the reason is in a file.

Daily episodes

The launch content was a 46-day devotional series, one audio episode per day, tied to the calendar. Day one says "today begins" and names the feast. Publishing late would make the content lie, so the date was the contract.

 brief ──▶ script (3 revisions) ──▶ voice (ElevenLabs,
                                     regional casting)
                                          │
   ┌──────────────────────────────────────┘
   ▼
 mechanical audit, by script not by reading
   fixed prayer text byte-for-byte      15/15
   psalm verses verbatim vs source      16/16
   text / audio / alignment hashes       5/5
   dates vs weekday, day 1 and day 46    ok
                │
                ▼
 agent audit ──▶ human sign-off ──▶ stage ──▶ dry run
                                              │
                                              ▼
                              publish ──▶ daily slot ──▶ 5:30 cron

The agent audit is not the pastoral verdict. It is the input to it. A person signs; the pipeline records who and when. The first ten episodes went out on time. Ten more were ready before their dates. The generator and the runbook were written so the remaining ones could be produced by anyone with the brief.

Decisions, measured

The company runs on data over narrative. Every product question started with what users actually did, pulled from analytics, and ended with something we could measure fast.

The same rule applied to me. Instead of "this will work" I learned to say "I can tell you in an hour whether it works", and then build the harness that could.

The working style

Agents on this project do not wait for tasks. The pattern is decision announced, not permission asked.

 night                              morning
 ───────────────────────            ───────────────────────
 agent runs the queue               I read the report
   hard rules: no commit,           one commit at a time:
   no database, no push               understand
   decide, document, continue         bring the files
   list every file touched            see the diff
 writes decisions/ and a report       verify (command + "green")
                                      commit

An overnight run gets a plan with hard rules and a queue. In the morning I get a report and a delivery file with five boxes per commit. Nothing goes up that I have not read and verified. Autonomy is not the agent doing whatever it wants. It is the agent doing the work and leaving a trail a person can check faster than they could have done it.

Why this is not about prayer

 prayer app                    any content business
 ─────────────────────────     ─────────────────────────────
 source translation            your raw material
 passages tagged by need       units tagged by what they are for
 register + safety judges      agents that check the agents
 twenty psalms by hand         the human sample, always
 fix the assembler             fix the pipeline, never the data
 decisions/ + handoff          memory that survives the chat
 mechanical audit              checks a script can run
 date as the contract          the deadline the content encodes

The hard part was not generating text. It was knowing which text was wrong, at scale, before a person in a bad moment read it. That took a second agent with one question, a human sample small enough to actually do, and a rule that every miss changes the tool.

What I did

I did not write the passages or the episodes. I built the parser and assembler, designed the judges and their prompts, ran the human samples, wrote the runbooks and the delivery process, and signed what shipped. Every lesson ended in a file the next session would read first.