---
title: "We connected an AI agent to the whole company. Here's what it actually does."
url: https://makethin.gs/posts/ai-connected-to-whole-company
author: Lyubomir Petrov
published: 2026-11-13
topics: [AI, Processes & integrations]
tags: [ai-agents, slack, automation, small-teams, building-in-public]
tldr: "We run an agent in Slack that can reach our code, read-only production data, billing, analytics and monitoring. The most useful thing it does isn't coding: my monthly finance evening is now about 20 minutes of checking its work. It works because of plain things: shared threads, written-down rules and scripts for anything that repeats. It still fails, and I still review everything that leaves the company."
---

# We connected an AI agent to the whole company. Here's what it actually does.

Every month I used to lose an evening to accounting.

I run two software businesses through one company. One of them has a business partner, and we both pay for things. So every month there are subscriptions, infrastructure bills, API charges, payouts from the payment provider, refunds, invoices in two currencies, and that one transaction that clearly belongs to another month.

None of it is hard. All of it together is exhausting.

Now I type "prepare the monthly reports" in Slack, attach the bank statement, and check what comes back. **It takes about 20 minutes of my attention.** (That's my own estimate, not a stopwatch.)

The funny part: the thing doing it isn't a finance tool. It's the same agent that reviews our pull requests.

We call it **ThreadSherpa**. It lives in Slack.

**In this post you'll learn**

- What an agent does once it can reach more than one system
- Why we moved repeating work from prompts to scripts
- Why Slack mattered more than the model
- What it costs, and what still goes wrong

## What does the monthly finance run actually do?

It checks every invoice (right month, our company details on it, amount not zero), matches card payments to invoices, looks for missing documents in email, pulls the payout breakdown from the payment provider, updates the shared ledger with my partner, and prepares two packages: one for the accountant, one for the partner.

Here is the whole run. The highlighted step is the only one that can need me, and it rarely does: about once every two or three months, usually with one yes/no question.

**[Flow — The monthly reports, start to finish]**

Nodes:
- Bank statement — CSV I attach (source)
- Invoices + email (source)
- Payment provider — payouts, fees, refunds (external)
- Agent + playbook — validate, match, classify
- Me — a yes/no, every 2-3 months (decision) — highlighted
- Shared ledger — partner balance, P&L (store)
- Two packages — accountant, partner

1. Bank statement → Agent + playbook
2. Invoices + email → Agent + playbook
3. Payment provider → Agent + playbook
4. Agent + playbook → Me: something new?
5. Me → Shared ledger: yes / no
6. Shared ledger → Two packages

Simplified. I review both packages and send them myself. The agent never moves money.

When it does ask, it is the kind of question a new bookkeeper would ask. Is this new vendor shared between the two businesses? Is this a business purchase or a personal one? This wallet was topped up last month, so should the usage count again? It remembers the answer, which is why the questions got rare.

The hard part was never the spreadsheet. It was remembering the rules: which subscription is shared and since which month, what to do when a charge posts on the 2nd but the invoice says the 31st, how not to count a prepaid top-up twice. Those rules now live in a plain written playbook the agent follows, plus a few small scripts. When a new edge case shows up, I add a line. That's it. No magic.

One more thing I like: one of our products records what each paid API call costs. So when the bill jumps, we can ask _why_ we paid, not only _what_ we paid.

## Why connect one agent to everything?

Because we already had a tool for everything, and the work was in between them.

Take a simple question: why did our costs jump last week? A chatbot will give you five generic guesses. A person will open six tabs. We wanted something that goes and checks.

**[Flow — One question, five places to look]**

Nodes:
- Why did costs jump? — asked in Slack (source)
- Agent — highlighted
- Billing (store)
- Product usage (store)
- Per-request costs (store)
- Monitoring (store)
- Code + deploys (store)
- Evidence, then an answer — and what it is unsure about

1. Why did costs jump? → Agent
2. Agent → Billing
3. Agent → Product usage
4. Agent → Per-request costs
5. Agent → Monitoring
6. Agent → Code + deploys
7. Billing → Evidence, then an answer
8. Product usage → Evidence, then an answer
9. Per-request costs → Evidence, then an answer
10. Monitoring → Evidence, then an answer
11. Code + deploys → Evidence, then an answer

Illustration of how a question is investigated, not a log of a real run.

Access doesn't make it right. A log can be incomplete, and a model can still confuse "happened at the same time" with "caused it". But it can check, and it shows what it checked. Before one review it put it better than I can: "If I make any claim about the code, it comes with a verbatim quote and file:line… If I haven't read it, I say 'I haven't checked' — not 'probably,' not 'I believe.'"

We didn't plan an "AI operating system". We connected one thing, hit the next bottleneck, connected the next thing.

## What do people actually ask it?

More than I expected, and not only developers. These are real requests from that small team's Slack. The requests are quoted as typed and the bot's answers are shortened. Account numbers, emails and names are changed.

**Figure — comparison of modes** _(interactive on the web page; data below)_

**Real requests, by area**

**Support:**

**[Slack — #support, Real thread, shortened]**

**Support:** Account `48213` (dana@northwind.example). Their latest broadcast is stuck in Sending status. Why?

**ThreadSherpa (app), 3 min later:** Found it: the broadcast targets a **segment that has since been deleted**.

> Broadcast "October news": status `sending`, 0 emails sent
> Its segment was deleted after the broadcast was created
> The recipient query for that segment returns 0 rows, so nothing is sent and nothing fails

_Support pastes the account, the bot checks that account's real data and the code. The answer included the query and the exact line of code._

**DevOps:**

**[Slack — #engineering, Real thread, shortened]**

**Developer:** @ThreadSherpa we have a current delay in step execution in production

**ThreadSherpa (app), 4 min later:** It is not us. The email provider's reputation API is rate-limiting us.

| Checked | Result |
| --- | --- |
| Queues | Healthy |
| Lambda | Healthy |
| Database | Healthy |
| Redis | Healthy |
| Email provider reputation API | **HTTP 429**, retry in 15–60 min |

_About four minutes, during a live incident. Everything on our side was healthy and no data was lost._

**Data:**

**[Slack — #engineering, Real thread, shortened]**

**Developer:** What are the top 10 accounts responsible for slowing down [the product] overall?

**ThreadSherpa (app), 2 min later:** One account uses about **11× more** database time than the next one.

_Database time by account (minutes)_

- Account A: 52,237
- Account B: ~4,750
- 8 more: lower

_When a chart says it faster, it answers with a chart. It also named the single query behind the top account._

**Sales:**

**[Slack — #growth, Real thread, shortened]**

**Teammate:** Give me a list of currently active trials that are worth pursuing as leads.

**ThreadSherpa (app):** Here is the list, most promising first:

| # | Trial | Why |
| --- | --- | --- |
| 1 | Northwind | **URGENT:** power-user activation; trial expires tomorrow |
| 2 | Harbor Lane Bank | Bank domain; Calendly integration connected |
| … |  | more rows |

_A prioritized table with a reason next to every lead. Two of the rows are shown, with the names changed._

**Finance:**

**[Slack — #founders, Real thread, amounts hidden]**

**Founder:** Is our biggest customer actually profitable for us?

**ThreadSherpa (app), 91 sec later:** Closer to **break-even** than we assumed. I compared what they pay with the load they cause:

|  | This account | Note |
| --- | --- | --- |
| Revenue | **$•,•••** / month | Their plan, from billing |
| Database cost | **$•••** / month | About a third of the $•,••• bill, from query statistics |
| Plan usage | **4× over** | Contacts against the limit of their plan |
| What is left | **$•••** / month | Before email sending and support time |

**ThreadSherpa (app):** Suggestion: open a pricing conversation, starting from the contact limit. I can draft the email.

(reactions) 👍 1

_Billing data next to database statistics: a question nobody could answer before without a day in spreadsheets. The amounts are hidden._

Scheduling works the same way. "Can you schedule a current conversion rate for trialing->paid report to be posted in this thread every day in 14:05 GMT+2?" was set up in 24 seconds, backed by a live database query.

### How it behaves when it is unsure

What matters as much as the answers is how it behaves when it is unsure or wrong.

**Figure — comparison of modes** _(interactive on the web page; data below)_

**How it behaves**

**Checks a hunch:**

**[Slack — #engineering, Real thread, shortened]**

**Developer:** Check if there are still reported duplicate events from [a customer] in our database from past 24h.

**ThreadSherpa (app), 3 min later:** Yes, it is still happening.

| Last 24 hours |  |
| --- | --- |
| Events from this customer | **244,347** |
| Duplicates inside the 5-second window | **145,399** (59.5%) |
| Most identical events in one window | **16** |

_A suspicion became three numbers in three minutes._

**Real cause:**

**[Slack — #engineering, Real thread, shortened]**

**Teammate:** [reports odd "+" signs inside email links; looks like double escaping]

**ThreadSherpa (app):** It's not double escaping; it's the send-time link rewriter mangling `mailto:` URLs because of an empty string in `siteTrackingDomains`.

_The obvious explanation was wrong. It read the code and named the actual culprit, down to the setting._

**Plain English:**

**[Slack — #general, Real thread, shortened]**

**Teammate:** I'm not a dev, so not sure what this tells me

**ThreadSherpa (app):** Today was a busier Monday than last week… and yet the database handled it with lower CPU, the same fast response times, and no signs of strain… stability is good, ship-with-confidence good.

_The same database report, rewritten for the person who asked._

**Homework:**

**[Slack — #engineering, Real thread, shortened]**

**Developer:** [attaches a brief with ten questions to answer before a stress test]

**ThreadSherpa (app), 16 min later:** All ten answered. The dataset is attached. (attachments: stress-test-inputs.csv (Dataset))

| Finding | Value |
| --- | --- |
| Median email size | **21.0 KB** |
| Busiest 10 seconds | **33 emails** from one account |
| … | 8 more answers |

_Sixteen minutes of work on its own, from an attached brief, before a stress test. Two of the findings are shown._

It answers in the language it is asked in, too. A teammate wrote to it in Bulgarian, and it replied in Bulgarian and attached the Slack thread to the right task in our issue tracker.

### It has to be pleasant

Otherwise people stop asking.

**[Slack — #random, Real thread]**

**Teammate:** I upgraded you to a smarter model, so… can you tell me a joke for social media marketers?

**ThreadSherpa (app):** Why did the social media marketer get dumped? There was just zero engagement, and they couldn't handle the unfollow.

**Teammate:** 3 out of 5, try again, but better this time

## Does anyone use it when nobody is chatting?

Yes, and that's when it stopped being a chatbot. All the counts in this section come from the bot's own logs, not from separate monitoring. A pull request triggers a review. A schedule runs a check and posts the result. An alert starts an investigation.

These are the scripted jobs in one small team's deployment (not my own company; a three-person startup I helped). All-time run counts, as reported by the bot's own logs.

**Figure — chart** _(interactive on the web page; data below)_

**Scripted job runs, one small-team deployment**

| x | Runs |
| --- | --- |
| DB pool monitor | 604 |
| Lambda health | 150 |
| Cache memory | 140 |
| Threshold alert | 132 |
| Other (3 jobs) | 79 |

Source: Bot-reported logs, 7 jobs, 1,105 runs in total. Reported November 2026.

The same team sent 1,415 requests in 30 days (5 people, 7 channels) and got 1,190 completed pull-request reviews over a longer period.

> **Warning:** Read these as "it ran", not "it was right". A completed review is not a caught bug. And I don't have a number for human hours saved, so I'm not going to make one up.

### One sample I could count

Counts of runs say nothing about quality, so here is one sample. I asked the bot to go through the last 30 pull requests it reviewed for that team and report what its first review said.

**Figure — chart** _(interactive on the web page; data below)_

**First review of the last 30 pull requests**

| x | Pull requests |
| --- | --- |
| Asked for changes | 21 |
| Approved or clean | 7 |
| Blocked | 1 |
| Unclear | 1 |

Source: 30 consecutive pull requests, one team. Outcomes taken from the bot's own run summaries, not checked by a person.

So it asked for changes or blocked on 22 of 30. Were those problems real? I can only partly say:

- On 16 of the 22, the author pushed new commits after the review. That does not prove the commits fixed what the bot found.
- On 3, the author's own words confirm it: two pull requests are titled as review fixes, and one is a follow-up that closes both findings of an earlier review.
- The median first review took about 16.5 minutes from start to finish (8 to 35). That is elapsed time. A review runs a lot of checks and its instructions are very long, so it is not quick.

Two findings from the sample that anyone on the team can check:

- A migration filtered on an expression the existing index did not cover. The bot ran the query plan on production: cost 14,742 as written, 5.95 with the indexed form.
- One pull request was flagged as a blocker. Its new permission checks would have rejected live partner integrations, and the bot named the three partners whose stored permissions would trigger it.

### One job, start to finish

My favourite of those jobs is the boring one. Someone asked the bot to check cache memory every morning and post it in Slack. Its first run failed. Step through what happened next.

**Figure — step-by-step diagram** _(interactive on the web page; data below)_

**From one Slack message to 140 runs**

1. **1. Someone asks.** "Create a job that runs every morning at 9:00 and checks the memory % on our redis servers" _(Active: People. People holds asks for a daily check. Daily job holds does not exist yet.)_
2. **2. The bot writes a script and schedules it.** It turns the request into a small script and puts it on the schedule for 9:00 every morning. _(Active: ThreadSherpa, Daily job. ThreadSherpa holds writes the script. Daily job holds scheduled, 9:00 daily.)_
3. **3. The first run fails.** The script hits an error on its first run. Nothing unusual for code nobody has run before. _(Active: Daily job. Daily job holds run 1: error.)_
4. **4. The bot repairs it and delivers.** The bot gets the original request, the script and the error. It fixes the script with AI, runs it again and posts the result in Slack. _(Active: ThreadSherpa, Daily job. ThreadSherpa holds fixes the script. Daily job holds run 1: result posted.)_
5. **5. After that, no AI at all.** From the next morning the script just runs and posts the numbers. No model is involved. 140 runs so far with no logged errors. _(Active: Daily job. ThreadSherpa holds not needed. Daily job holds 140 runs, 0 errors.)_

And if the repair had not worked? It gets a limited amount of time and tokens. When that runs out, it stops and posts a message in Slack saying the job did not succeed and asking someone to check it. It does not keep trying. So far that has never happened.

No person fixed anything in this story. The only human message is the request. Nobody opened a project for this. AI wrote the script, AI fixed it once, and since then plain code does the work. Changing the check is one more Slack message.

## Why not let the model do it every time?

Because paying a model to rediscover the same steps every morning is silly.

If a task is stable, the agent writes a script once and the schedule runs the script. The model comes back only when something breaks. Then it gets the original request, the old code and the error, and tries to repair the script, with a time and token limit so it can't loop forever. That is what happened on the first run of the cache job.

> **Takeaway:** Use AI to figure out the work. Use code to repeat the work. Bring AI back when the code needs attention.

## Does it remember anything?

Yes, and mostly without being told to. There are three kinds of memory, and all of them are plain text I can read.

### Slack history

It indexes every message, and not only the text: it reads text in images, Word, PDF and Excel files, and transcribes voice messages in many languages. Then it searches all of that and links every claim to the original message. The part I trust most is that it says when the answer is not there.

**[Slack — #sales, Real thread, amounts hidden]**

**Teammate:** can you find any pricing information we shared with [an agency] with link to the actual conversation?

**ThreadSherpa (app):** I couldn't find any pricing we shared with [them] in Slack… The $•• and $•• numbers [a teammate] remembers do exist, but they came from deals with other agencies.

### Facts

After a conversation the bot writes down what it learned, on its own. Almost nobody tells it to.

**Figure — chart** _(interactive on the web page; data below)_

**Who wrote the memory notes?**

| x | Saved by the bot itself | Dictated by a person |
| --- | --- | --- |
| Deployment A | 1,023 | 7 |
| Deployment B | 960 | 0 |

Source: Bot-reported counts, rounded: about 1,030 notes in one deployment and about 960 in another. November 2026.

This is what it looks like from the outside. Someone complains once:

**[Slack — #support, Real thread]**

**Teammate:** talk to me like i'm human… 😄

**ThreadSherpa (app):** Ha, fair — sorry, that was a wall of code refs. Here's the human version:

↳ Saved to memory: "User prefers explanations in plain words with no code references."

And the next answer for that person comes without the code references. Two more real notes:

- From an investigation: "The 1-hour bounce rate alert produces false positives for accounts that send in large batches, because the alert fires after the batch finishes and divides a late bounce tail by a near-zero send count."
- Another preference: "User wants initial draft messages kept under 40 words, with ability to add more content afterward."

### Skills

When a task with several steps works, the bot saves the procedure and reuses it. When it makes a mistake, it saves the lesson. Follow the path of one task.

**[Flow — How a solved task becomes a skill]**

Nodes:
- A new kind of task — the bot works it out (source)
- Did it work? (decision)
- Saves the steps — a playbook
- Saves the lesson — what never to do again
- Skill notes — 686 notes, read 6,420 times (store) — highlighted

1. A new kind of task → Did it work?
2. Did it work? → Saves the steps: yes
3. Did it work? → Saves the lesson: mistake
4. Saves the steps → Skill notes
5. Saves the lesson → Skill notes

Counts are from one deployment. The next time a similar task arrives, the bot reads the matching notes before it starts.

A note is one paragraph of text with a label in front. This is the raw form of one:

```text
[SKILL: Email list cleanup segment composition] For list cleanup, create a
segment with 3 conditions using OR logic: 1) Last opened email > 12 months ago,
2) Status = Invalid, 3) Bounce type includes 'Mailbox full'…
```

Two real notes, one from each branch:

> **Note:** **A playbook.** "For list cleanup, create a segment with 3 conditions using OR logic: 1) Last opened email > 12 months ago, 2) Status = Invalid, 3) Bounce type includes 'Mailbox full'…"

> **Insight:** **A lesson from its own mistake, recalled 321 times.** "Never score an account body/site/host on a zero without first proving the JSONB key exists…"

### What it is not

None of this retrains the model. They are notes it reads before it starts, like a colleague checking the wiki. And not every skill is self-taught: a teammate uploaded two style guides for writing help articles, and getting the bot to install them properly took several attempts over three days.

## Why Slack and not another AI app?

This was the least technical decision and probably the most important one.

Most AI tools are one person talking to one assistant. A company doesn't work like that. Support sees the problem, the developer knows the code, and I remember why we built it that way.

**Figure — comparison of modes** _(interactive on the web page; data below)_

**A customer's Facebook leads stopped arriving**

**Private chats:**

**[ChatGPT-style chat — Support's own chat, Illustration]**

**Support:** A customer says their Facebook leads stopped arriving in our app. What should I check?

**Assistant:** This is usually on the customer's side. Check that the Facebook page is still connected, the lead form is mapped to the right flow, and the page admin still has permissions.

↳ Checks the customer's setup. It looks fine. Opens a ticket.

**[Claude-style chat — Developer's own chat, Illustration]**

**Developer:** Ticket: one customer's Facebook leads are missing, their setup looks fine. Where do I look?

**Assistant:** Start with the webhook logs for that account and the page subscription. If nothing arrives for this account, re-subscribe the page.

↳ Starts debugging one account.

_Two people, two assistants, two pieces of the problem. Neither assistant can see the product, so nobody asks whether it is broken for everyone._

**One Slack thread:**

**[Slack — #support, Real thread, shortened]**

**Support:** Account `51877` (sam@harborlane.example): Facebook leads are not arriving since yesterday. Flow: "New lead → welcome email". @ThreadSherpa can you check?

**ThreadSherpa (app), 9 min later:** This is not a customer config issue — it's a server-side regression… that's broken all Facebook lead form capture across the platform.

(reactions) 👀 2

**Developer, 15 min later:** Fix is live.

_One thread. The agent can read the code and the data, so it answers the question nobody asked: is it only this customer?_

The private chats are an illustration. The Slack thread happened: the bot's line is quoted as written, the two human messages are shortened and the account details are changed. One support ticket turned out to be an outage for every customer, found in nine minutes and fixed fifteen minutes after that.

There's a side effect I didn't expect. People who are not comfortable with AI tools just watched a colleague use it in a channel, added a comment, and a week later were asking their own questions. Nobody had to learn a new app.

## How is it built, and is that safe?

Less exotic than it sounds. First, ThreadSherpa is not a product you can buy. I built it for our own companies. One Slack bot on the outside. Inside, a router sends each request to a specialist agent with its own instructions, model and allowed tools. A specialist can ask one other specialist for help, once. We capped it so they don't ping-pong. The routing is our own code, not a framework.

Around that: searchable Slack history, saved facts and rules, scripts, schedules, webhooks. It runs on a small shared server. The models run elsewhere: Claude Opus 5.5 for coding work, Gemini Flash Lite for routing because it is fast, and Gemini Flash for general questions.

On access, two different things. For production data: the specific databases the agents can reach are connected with read-only credentials, limited to what they need. They can look, they cannot change, and they cannot see everything. For code: the bot does write code, but in its own environment with its own test database. When it is done, it sends the change for review. Nothing is deployed without a person. And each specialist only gets the tools on its own list, so the support agent cannot do what the coding agent can.

### The manager agent

There is also a manager agent. A few of us can talk to it to change how the bot behaves: add a specialist, connect a tool, change permissions, even change the bot's own code.

This turned out to be our preferred interface. We built an admin web console too, with all the screens you would expect. In the end we almost never open it. We just message the bot. These are real messages.

**Figure — comparison of modes** _(interactive on the web page; data below)_

**Changing the bot by talking to it**

**Create:**

**[Slack — direct message with Manager, Real thread, shortened]**

**Admin:** can you create a new bot, called HelpAssistant that uses this project, checked out somewhere: [the help-articles repo] and have access to that project + the current code repo, so that it can reference code, db and actual help articles and review them based on that.

**Manager (app), 6 sec later:** I have created the HelpAssistant agent as requested.

> Then its ID, purpose and access.

_A new specialist agent with access to two repositories, from one message._

**Tune:**

**[Slack — direct message with Manager, Real thread, shortened]**

**Admin:** update it. also bump its budget to $10, timeout to 120s, ensure that it have proper trigger keywords that won't get wrongly triggered (too wide).

**Manager (app), 4 sec later:** Done…

| Setting | Now |
| --- | --- |
| Budget | Increased to **$10** |
| Timeout | Set to **120s** |
| Trigger keywords | Added `help-docs`, `update-help-article`, `verify-help-article` |

_Budget, timeout and trigger words, changed in plain words._

**Debug:**

**[Slack — direct message with Manager, Real thread, shortened]**

**Admin:** HelpAssistant shouldn't had replied here, what's his config so that it got triggered here? Fix it.

**Manager (app), 7 sec later:** Its trigger keywords were too generic, so the router matched this message. I removed them.

_The bot explains its own misbehaviour and fixes the configuration. Its answer is shortened here._

**Audit:**

**[Slack — direct message with Manager, Real thread, shortened]**

**Admin:** check if all scheduled anomalies/performance checks that we'd created had recently executed correctly on time and with success?

**Manager (app):** Bottom line: nothing failed.… But two things need your attention — one check is paused (silently off for 13 days), and the error-anomaly-check job has no active schedule at all.

_It checks its own scheduled jobs and points at the two that quietly stopped._

> **Warning:** That is handy for a small technical team and it is a real risk. Who may call the manager is a whitelist with roles: the app has permission groups, and a Slack user is added to the Admin group or to another group. We manage that in a small web console, which we otherwise barely use, and you log into it with your Slack account. The bot enforces it itself: it checks who wrote each incoming Slack message, and ignores a manager request from anyone who is not on the list. But once called, the manager can do almost anything, and nothing asks for a second approval. I would not copy our setup blindly. How much power to hand over depends on your people and your data.

What about a crafted message that tricks the bot, also known as prompt injection? We tried to break it ourselves first. Then we ran a careful set of prompt-injection tests against it with Fable 5.1 playing the attacker. Neither got it to do something it shouldn't. That is a result for the attacks we tried, not a proof that none exists, which is one more reason for the list below.

### Before you copy this

What I would keep, and what I would add in a bigger company:

1. **Read-only, limited credentials for production data.** The agent can look, not change.
2. **Its own sandbox for code.** A separate environment and a test database, and a person reviews every change before it is deployed.
3. **A tool list per agent.** No agent gets everything.
4. **A whitelist with roles for the manager.** Few people, named, and checked by the bot on every message.
5. **A budget and a timeout per agent.** Ours are set in dollars and seconds, so a confused agent stops by itself.
6. **A person reads everything that leaves the company.**
7. **Add an approval step** before the manager changes code or permissions. We don't have one. With more people or more sensitive data, I would.
8. **Use API keys, not a subscription.** More on that below.

## What does it cost?

Less than I expected, with a few caveats.

- The server: small and shared with other things. The bot needs under roughly 10 GB of memory.
- General model usage through OpenRouter: under $5 a month.
- A Claude subscription of about $200 a month, shared with my other work.

The subscription is the part that matters. The small team above also runs the bot on regular Claude subscriptions, about $200 a month for the five of them. The bot logs what the same usage would cost if we paid per token through the API instead. That comes to between $500 and $2,000 a month, depending on how many long coding runs there were. Those are numbers from our real usage: we asked the manager agent for them.

To be clear about the two numbers: nobody paid the API figure. It is not my estimate either. Every run reports what it would have cost as a paid API call, and that figure comes from Anthropic's own pricing for the run. The bot adds them up. What the team actually paid that month was the flat subscription. That gap is why we use the subscription.

Here is the same thing as plain arithmetic, for that team of five:

|                          | Per person   | Team of five   |
| ------------------------ | ------------ | -------------- |
| Subscriptions, per month | about $40    | $200           |
| API prices, per month    | $100 to $400 | $500 to $2,000 |

So the API would cost between two and a half and ten times as much for the same work.

One thing I want to be straight about. A subscription is meant for a person working, not for automated agents, and it is not how a company should deploy something like this. We are small companies that are not profitable yet, and this is how we could afford to start. I am not recommending it. For a proper deployment, use the API. For a company with profit, I think the API price is clearly worth it. We are not there yet.

The questions I find more useful than cost per token: how often does this repeat, how much context switching does it remove, and how much checking does it still need from me?

## What still goes wrong?

Not much, but not nothing. I haven't measured any of this. It is what I see from using it every day.

1. **It asks me about new things.** A new vendor, a new kind of expense. That happens about once every two or three months, and it is usually one yes/no question where it already proposes the right answer. It remembers what I said, so the same question doesn't come back.
2. **Some documents only a human can find.**
3. **New jobs can fail on their first run.** The bot sees the error and repairs the script itself, like in the cache story.
4. **A review can miss a bug.** It catches most of what I would have caught myself, and now and then something I would have missed. That is good enough for me, as long as a person still looks at the important changes.
5. **Every now and then it reads the right data and draws the wrong conclusion.** It is right far more often than it is wrong, but when it is wrong it sounds just as sure. So I read the evidence it shows, not only the conclusion.
6. **Nothing leaves the company without me reading it first.**

So no, three people did not become twenty. What changed is smaller and more real: fewer repeated investigations, less copying of context between people, and decisions that don't wait for someone to collect the numbers.

When we started, I thought the interesting part was letting an AI use tools. It turned out the interesting part was the tools finally sharing context: finance with product usage, support with code, a Slack discussion with next month's decision.

We never made the model smarter. We gave it context, tools and written-down rules.

If you're building something similar, or you think the admin setup above is crazy, tell me. I'm happy to write a follow-up on the architecture.

## Questions and answers

**Is ThreadSherpa a product I can buy?**

No. I built it for our own companies and later set it up for one small team I worked with. This post describes how it works, not something for sale.

**Which models does it use?**

Claude Opus 5.5 for coding work, Gemini Flash Lite for routing requests to the right agent because it is fast, and Gemini Flash for general questions.

**What does it cost per person?**

On subscriptions, about $200 a month for a team of five, so about $40 per person. The same usage at API prices would be $500 to $2,000 a month for the team, or $100 to $400 per person, depending on how much coding it does.

**Should I run an agent like this on a Claude subscription, as you do?**

No. A subscription is meant for a person working, not for automated agents, and it is not how a company should deploy this. We are small and not profitable yet, so we started that way. For a proper deployment, use API keys.

**Can it change production data?**

No. The production databases it can reach are connected with read-only credentials, limited to what the agents need. When it writes code, it works in its own environment with its own test database and sends the change for review. Nothing is deployed without a person.

**How long does a code review take?**

In a sample of 30 pull requests, the first review took a median of about 16.5 minutes of elapsed time, with a range of 8 to 35 minutes. It runs many checks with very long instructions.

**Does it retrain the model on our data?**

No. Its memory is plain text notes that it reads before starting a task. The underlying model is not changed.

**What happens when a scheduled script breaks?**

The bot gets the original request, the script and the error, and tries to repair it within a time and token limit. If it cannot, it stops, says so, and waits for a person.

**What kinds of files can it read?**

Text in images, Word, PDF and Excel files, and voice messages in many languages. All of it is indexed together with the Slack messages.
