tensquads — What we build

· Moe Ghashim

Read this page from the top. Each part uses the ideas of the parts before it.

Contents

  1. How tensquads works. What the product is, with one picture and one example.

  2. Words we use. The meaning of each important word.

  3. The bots and the persons. The five bots of the MVP, and the role of each person.

  4. How Petra works. How Petra makes decisions and reads the business.

  5. How the owner speaks to Petra. The chat, email and WhatsApp.

  6. How a bot does a task. The bot, the image, the sandbox and the state.

  7. Credits and prices. The packages, the price of each task, and the cost.

  8. What the squad remembers and learns. The memory, the trails and the learning.

  9. How we build it. The rules for the code and the tools.

  10. Feature list. All the features of the MVP, with the priority and the person who added each one.

  11. Decisions. The questions that have an answer.

  12. Test cases. The success cases for each bot.

  13. Research and sources. What each reference says.

  14. Open questions. The questions that have no answer.

1. How tensquads works #

tensquads gives a small business a squad of bots. The bots do the work for the business. The owner speaks to one bot only. Its name is Petra. Petra gives the tasks to the other bots, and the owner sees the result.

A company can launch with us: research the competition, build the website, and add support when there is a need for it.

The owner talks only to Petra; Petra directs the botsBusiness ownerasks and approves,sees the resultPetrathe masterpicks the bot for each taskreports back to the ownerMachuresearches the competitionAngkorbuilds the website and the menuKyotohandles customer supportGreenwichlooks after Google MapsrequestanswertaskFor every task: credits are checked first, risky actions wait for the owner, and each step is recorded

Each bot completes its task and gives the result to Petra. Only Petra sends messages to the owner.

One request, in sequence

  1. The owner makes a request. Example: "Build my website."

  2. Petra selects the bot. In this example, Petra selects Angkor. For an automatic event, such as a new Google review, a fixed rule selects the bot.

  3. The system does a check of the credit balance. If the balance is not sufficient, the system tells the owner to pay or to upgrade.

  4. The bot does the task on Cloudflare. It uses an isolated sandbox only for a tool that needs a real computer. The bot cannot send a message to the owner. The bot cannot give the task to a different bot.

  5. An action with a risk does not start without approval. If an action publishes, pays or refunds above the limits of the owner, the owner must approve it first.

  6. Petra gives a report. Petra shows the result, for example a preview link. Petra also tells the owner which work remains.

  7. The squad keeps a record. The system records each step. The squad keeps the knowledge for the next task.

2. Words we use #

Read these words first. All the parts below use them.

WordMeaning
OwnerThe person who has the business and the account
CustomerA person who buys from the business of the owner. A customer speaks to Kyoto, not to Petra
BotOne member of the squad, with one job. Also called a squadmate
PetraThe master bot. The only one that talks to the owner
TaskOne piece of work given to one bot
CreditThe unit an account spends to run a task
ApprovalThe owner's yes to an action outside their limits
TrailThe full record of one task
Fixed ruleAn instruction that sends one kind of automatic event to one bot
PriceThe credits that the owner pays for one task. The price is fixed for each type of task
CostThe money that one task costs us
Price listThe list of the prices for all the types of task
SandboxAn isolated space where the tools of one bot run for one task. It starts from the image of the bot when a tool needs it, and it stops when the task is complete
LoopThe code that runs a bot for one task. It asks the model, runs the tools, and repeats until the task is complete. It runs outside the sandbox and keeps no state
SessionThe full record of one task, in the database. The loop reads it to continue a task. It is the same record as the trail

3. The bots and the persons #

Each bot is a character. The name of each character comes from a famous place. Refer to 10squads.com/design/#mascots.

The five MVP mascots: Petra, Machu, Angkor, Kyoto and Greenwich

From left to right: Petra, Machu, Angkor, Kyoto and Greenwich.

BotRoleDoesDoes not doSpeaks toExample
PetraMasterSelects the bot for each task. Asks the owner for approval. Gives the report. Reads the signals and suggests changesThe work of a different botThe owner"Your website preview is ready. Do you want to publish it?"
MachuResearcherFinds the competitors, reads their pages, and compares their offers and pricesA change to something that the public seesPetra only"Five restaurants are near you. Three have a lower price at lunch."
AngkorWebsite and menu builderMakes one landing page. A restaurant gets a menu. A grocer gets a list of items. Does the audit of the websitePublish without approvalPetra onlyA preview link in the chat
KyotoSupportAnswers the messages of the customers of the business. Makes refunds that are in the limits of the ownerAnswer a review on Google MapsThe customers of the business, and PetraA customer asks for a refund of $15
GreenwichGoogle MapsKeeps the Google Maps listing correct. Answers the reviews. Reports the numbers of the listingAnswer a direct message from a customerThe public on Google Maps, and Petra"A 2-star review came. Here is a draft reply."

The MVP has these five bots. The roadmap bots (Analytics, Accounting, Finance) and the future squads come after the MVP. The success cases of each bot are in Part 12.

Roles #

Each bot has one role. The role tells you what the bot does, what it does not do, and to whom it speaks. The roles of the bots are in the table of the bots above. The persons also have roles:

PersonRoleCan do
OwnerThe person who has the business and the accountSpeaks to Petra. Sets the rules. Approves actions. Reads and corrects the memory
Customer of the businessA person who buys from the businessWrites to the business. Kyoto answers
Super adminA person of the tensquads teamSees all the accounts, the trails, and the price and cost dashboard. Changes the prices

4. How Petra works #

Petra receives each request and each event. This part shows how she decides what to do, how she reads the performance of the business, and how a fast model helps her.

How Petra decides #

Petra makes a decision for each request and each event. She does it in a fixed sequence of questions. Three parts of the system give the answers, and the owner gives the answer when the three parts cannot.

Every owner message goes to Petra; a task starts only when credits cover itOwner messagealways goes to PetraPetraspeaks to the ownerpicks a bot, logs whyEnough creditsfor the task?Specialist botno delegationno owner chatQueue and retryno silent fallback;then Petra asks ownerOther eventswebhooks, schedulesA binding rulematches?finished work returns to Petrayesno: prompt to payor upgradenoyesbot downEvery account can use every bot. A task starts only when the credit balance covers it.When several binding rules match, the most specific one wins. An undelivered task is dead-lettered after a set age.One Durable Object and one set of queues per account. Bots reach each other only over the bus.

Routing sends each task to the correct bot. A message from the owner always goes to Petra, and Petra selects the bot. An automatic event, such as a new Google review, obeys a fixed rule if one applies. If no fixed rule applies, the event goes to Petra. The system does not give a task to a different bot without a report. If the bot is not available, the system tries again. If the task still fails, Petra tells the owner.

Who answersWhat it answersExample
The codeA question that has a number or a ruleIs $60 above the limit of $20? Are the credits sufficient? Are there three complaints in one week?
JevA small question about the meaning of a textIs this a refund request? Is this complaint about the same problem?
The large modelA plan, or a textWhich bots, and in which sequence? What does Petra say to the owner?
The ownerA question about the limits, the preferences, or a thing that Petra is not sure aboutDo you approve this refund? Which instruction is correct?

The sequence of questions

StepQuestionIf the answer is noTest case
1Is the request clear?Petra asks the owner one question. No bot startsP2
2Can a bot in the squad do this?Petra tells the owner that no bot can do it. No task startsJ3
3Does the request agree with the preferences of the owner?Petra tells the owner about the disagreement and asks which is correctJ4
4Does a fixed rule select the bot?Petra selects the bot and gives the reason. If the task needs two bots, she tells the owner the sequence firstJ1, J2
5Are the credits sufficient?The task does not start. Petra shows a payment cardD5
6Is the action in the limits of the owner?Petra shows an approval card. The action does not start until the owner approves itD3
7Is Petra sure?Petra asks the owner. She does not guessJ6
8Is this a signal, and not one event?Petra records the event and makes no suggestionJ8

If all the answers are yes, the bot does the task, and Petra gives the report.

The rules for each decision

  1. Petra records each decision in the trail, with its reason.

  2. When the owner asks "Why?", Petra gives the reason in simple words. The reason agrees with the trail.

  3. Petra cannot increase her own limits. If the owner asks for more freedom for Petra, that is a change to a rule, and the owner must confirm it.

  4. When a number or a rule can give the answer, the code decides, not the model.

Rules and approvals. The owner sets the limits. Example: "Refund without my approval below $20." In the limits, the bot does the action. Out of the limits, Petra asks the owner, and the action does not start until the owner approves it. The system cannot increase its own limits. It can only recommend a change.

For the builders. These rules make the routing safe:

  1. A message from the owner always goes to Petra. For each other event, a table of fixed rules in the database gives the bot. The most specific rule applies.

  2. If no fixed rule applies, Petra selects the bot from a list of what each bot can do. The system records the selection and its reason.

  3. The system does not change the bot silently. If no bot is correct, or the bot is not available, the task waits and the system tries again. Then the task goes back to Petra, and Petra asks the owner.

  4. A bot does not give its task to a different bot, and it does not send a message to the owner.

  5. Two bots can send messages to each other only if a list permits that pair.

  6. Each account is isolated. Each query has the id of the account. Each bot has its own memory area and its own list of permitted tools.

The loop of Petra

Petra is always on, and she does not work in a sandbox. She uses the same loop design. For Petra, each bot is a tool: she starts a bot and gets only its last result, not all its turns. Thus the context of Petra stays small. For each message or event, she does this sequence:

  1. She reads the state of the account from the database.

  2. She makes the decision, with the sequence of questions in Part 4.

  3. She answers the owner, starts a bot, or asks the owner for an approval.

  4. She writes the state to the database, and she waits for the next message or event.

Performance review and suggestions by Petra #

Petra reads the performance of the business at regular intervals. She then suggests changes that can improve it. A change can be to the website, to the Google Maps listing, to the support answers, or to a different area of the business. Petra does not make a change without the approval of the owner.

Signals, not single events. Petra does not react to each piece of information. One complaint is an event. A bot answers it, and Petra records it. Petra makes a suggestion to the owner only when the event becomes a signal. An event becomes a signal in one of two ways:

  1. A measurement confirms it. If a problem can be measured, Petra starts an audit. She makes a suggestion only if the audit finds the problem.

  2. It occurs again. If a problem cannot be measured, Petra counts the events of the same type. Three events or more in one week are a signal.

One complaint is an event. Petra makes a suggestion only for a signalOne complaintA bot answers it.Petra records it.Can we measurethe problem?Measure itPetra starts an audit.It is a signal if theaudit finds the problem.Count itPetra counts the eventsof the same type.Three or more in oneweek are a signal.A signalPetra makes asuggestion to theowner.yesno

The picture shows the two ways.

ExampleThe eventWhat the bot doesWhat Petra does
The websiteA customer says that the website does not respondKyoto answers the customerPetra starts an audit of the website. If the audit finds that the website is slow, Petra suggests changes to the owner. If the website is not slow, Petra makes no suggestion
A bad reviewA customer writes on Google Maps that the food came after more than 45 minutesGreenwich answers the reviewPetra records the complaint. After three complaints or more of the same type in one week, Petra tells the owner and suggests a change

Jev helps here also. For each new complaint, the code asks Jev: "Is this complaint about the same problem as these earlier complaints?"

How Angkor does the audit of the website. This is a proposal.

  1. Petra gives Angkor the task "audit the website".

  2. The loop of Angkor asks for a browser. The system starts a sandbox, and the sandbox opens the website in a real browser, as a customer does.

  3. Angkor measures the website five times: on a computer and on a phone. It records the time to load, the size of the page, and each error.

  4. Angkor compares the numbers with the limits. Example of a limit: the page loads in less than 3 seconds.

  5. Angkor gives Petra a report: the numbers, the cause of the problem if it found one, and the change that it recommends.

  6. If all the numbers are in the limits, the report says "no problem found", and Petra makes no suggestion.

Where the data comes from

SourceDataBot
The websiteVisits, and what the visitors selectAngkor
Google MapsViews, calls, requests for directions, reviewsGreenwich
SupportThe questions and the complaints of the customersKyoto
CompetitorsTheir prices and their offersMachu

Sales and orders are not in the MVP, because no bot reads them. The roadmap bots (Analytics, Accounting, Finance) can add them later.

The sequence

  1. Each week, Petra collects the data from the four sources.

  2. Petra finds what changed. Example: "Calls from Google Maps decreased by 30%."

  3. The large model writes possible suggestions. Example: "Add the lunch menu to the Google Maps listing."

  4. Jev gives an answer to small questions about each suggestion.

  5. The code uses the answers of Jev to remove the weak suggestions and to put the others in sequence.

  6. Petra shows the owner a maximum of three suggestions. Each one shows the evidence and the price in credits.

  7. The owner approves or rejects each suggestion. An approved suggestion becomes a task for a bot.

  8. After some weeks, Petra measures the result and records it in the memory.

How we use Jev here

Jev does not write suggestions. It answers many small questions quickly and at a low cost. This feature has many such questions, so it is a good use of Jev.

Question for JevType of answer
Is this change in the data important, or is it usual?Yes or no
Does the evidence support this suggestion?Yes or no
Does this suggestion disagree with a preference of the owner?Yes or no
How large is the possible effect?A score
How much work is it for the owner?A score
Which bot does this task?One of the bots
Did the owner reject a similar suggestion before?Yes or no

The rules

Fast decision model (Jev) #

Jev is a small, fast model with a low cost. It answers only two types of question: "yes or no?" and "which one?". The bots make many such decisions each day. We use Jev. We can test Sage, a model from a different company, later. The plan has three steps:

  1. Build with the large model.

  2. Record each decision.

  3. Test Jev with those records, and change one use at a time.

The problem that Jev solves. Each task has small decisions. Which bot gets this task? Is this refund in the rules of the owner? Is this reply safe to send? Without Jev, the large model answers each of these questions. That takes seconds and costs more for each call.

An example. Sara has a grocery shop and uses tensquads. She has this rule: "Refund without my approval below $20, if the item was damaged or missing."

A customer writes to the shop: "My eggs arrived broken. I want my $15 back."

Kyoto must find if this message obeys the rule of Sara. This needs three small decisions. Jev reads the message and answers three questions:

QuestionJev's answerHow sure
Is this person asking for a refund?Yes97%
Is the reason "damaged or missing"?Yes94%
Is the message abusive?No99%

Jev does not know the limit of Sara, and Jev does not make the decision. Our code makes the decision from the rule of Sara and the answers of Jev:

If the customer asks for $60, the answer is always "ask Sara", because $60 is above her limit. Our code does this check with a simple calculation.

Why we divide the work this way. A model is good at reading a message and finding its meaning. Code applies a money limit exactly, and we can test it. Thus the model reads, and the code applies the rule. The percentages in this example are not real. Moe sets the level at which Jev is "sure".

Where we use Jev

UseThe questionIf it is wrong
RoutingWhich bot should take this task?Low harm. Petra sends it again
Checking workDoes this result do what the task asked?Medium. Poor work reaches the owner
GuardrailsIs this message safe to send?Medium to high. A bad reply goes out
Autonomy gateMay the bot do this without asking the owner?High. Money moves or something is published

5. How the owner speaks to Petra #

The owner speaks to Petra in three places: the chat in the app, email and WhatsApp. This part shows what the owner sees in each place.

Cards in the chat with Petra #

This is an important use case. The owner speaks to Petra in the chat, and Petra shows cards in the chat. A card is a small part of a screen in a message. The owner reads the card or selects a button on it, and does not go to a different screen.

Petra shows cards in the chat, and the owner stays in the chatWho are my competitors?PetraI found the restaurants near you. Here are two of them.CompetitorWhat Machu foundZaatar HouseLunch menu at $11Cedar GrillOnline menu with photosPetraKyoto wants to refund $60. This is above your limit of $20.Refund $60 to a customerYour limit is $20ApproveRejectTable cardThe owner reads the result in the chat.Approval cardThe owner selects a button.Our code makes the approval.

This picture shows how the chat looks. The names and the numbers are examples.

The chat with Petra uses OpenUI. This is a decision, and it is a part of the MVP. We make our own components with the tensquads design.

CardWhen Petra shows itWhat the owner can do
TableA result with rows, such as the list of competitorsRead it
Website previewAngkor made or changed the pageSee the page before it is public
ApprovalAn action is above a limit of the ownerApprove or reject
PaymentThe credits are not sufficient for a taskBuy a credit pack, upgrade, or stop
SuggestionsThe weekly review, or a signalAccept or reject each suggestion

The rules for the cards:

  1. Each card also has a text form. Email and WhatsApp show the text form, because they cannot show a card.

  2. Our code makes each approval. The model can only show an approval that the system made. A click goes to our code.

  3. After the owner selects a button, the card shows the selection, and the buttons go away.

  4. Petra can show only the cards in this table.

Email and WhatsApp for Petra #

When an owner signs up, the system gives Petra two addresses for that business. Only the owner writes to these addresses. The customers of the business do not use them.

  1. An email address. The service is AgentMail. The system makes one inbox for each owner. The Petra of that owner is responsible for the inbox.

  2. A phone number for WhatsApp. The service is AgentPhone. A number costs $3 for each month. Only a business in the United States or Canada gets a number. Each business has its own WhatsApp Business account.

A message that comes to one of these addresses is an event. It goes to Petra, the same as a message in the chat. The routing rules in the section above apply.

6. How a bot does a task #

Petra gives each task to one bot. This part shows how the bot starts, does the task and gives the result to Petra.

In simple words: bot, image, sandbox and state #

Read this section first. A bot does not run in a sandbox. A bot thinks in one place and works with its hands in a different place.

The bot thinks on Cloudflare, works on boat.dev, and remembers in the databaseCloudflare: the thinkingPetra: always onThe loop of a botasks the model:what is the next step?boat.dev: the handsImagea saved computer with a browserSandboxa running copy, for one task.It keeps nothing.Neon database: the stateMessages, tasks, approvals, memory, and the record of each task. Nothing is lost when a sandbox stops.gives the taskstarts a copyonly for a tool thatneeds a real computerrun thisthe resultreads and writes each step
WordWhat it isWhere it is
BotA job description: the instructions, the skills and the list of permitted tools. It is not a machineIn our code
ImageA saved copy of a computer with the programs of that bot, such as a browser. It does nothing until the system starts itStored, ready to use
SandboxA running copy of the image, for one task. One image can make many sandboxesboat.dev
StateAll that must not be lost: the messages, the tasks, the approvals, the memory, and the record of each taskThe Neon database

The image is the template, and the sandbox is one computer made from the template. The system deletes the sandbox after the task. Nothing is lost, because the state was never in the sandbox.

When a sandbox starts

A sandbox starts only when the model asks for a tool that needs a real computer. A sandbox does not start for thinking, for writing an answer, or for reading the memory.

Example 1: no sandbox

A customer asks Kyoto: "Are you open on Sunday?"

  1. The loop of Kyoto, on Cloudflare, reads the opening hours from the database.

  2. The model writes the answer.

  3. The answer goes to the check, and then to the customer.

boat.dev is not used. Thus the answer is quick.

Example 2: with a sandbox

The owner asks Petra: "Who are my competitors?"

  1. Petra, on Cloudflare, gives the task to the loop of Machu, also on Cloudflare.

  2. The model says: "I must read these five websites."

  3. A browser is necessary to read a website. The system starts a sandbox on boat.dev from the image of Machu.

  4. The sandbox reads the pages and gives the text to the loop. The same sandbox does all the reading for this task.

  5. The model writes the result. The result goes to the check, and then to Petra.

  6. The sandbox stops, and the system deletes it.

The system writes each step to the database. If the sandbox breaks at step 4, the system starts a new sandbox, and the task continues.

A sandbox cannot see the data of a different account or of a different task. A sandbox keeps no data after it stops, and it has no keys. If a sandbox breaks, the loop gets a failed tool result, and the system starts a new sandbox. The session, the memory and the trails are in the database, not in the sandbox.

Only Petra is always on. The loop of each other bot runs only while it has a task. A simple task, such as one answer by Kyoto, needs no sandbox, so it is quick. The repository has a boat.dev adapter now.

Inside a bot #

This section is a proposal. The design of the loop follows the agent loop of the Claude Agent SDK. The section shows what a bot contains and how its loop runs. The detail for the builders is in Part 9, "The loop in detail".

What a bot contains

PartWhat it is
InstructionsThe role of the bot: what it does, what it does not do, and to whom it speaks
SkillsThe method for each type of task. Example: how Machu does competitor research
ToolsThe list of the tools that the bot can use. Example: the page reader for Machu
The loopThe code that runs the turns. It is the same for all the bots
The checkHow the bot knows that the task is complete. Each type of task has its own check
The imageThe programs that the tools need in a sandbox, such as a browser. The loop is not in the image

The model is not in the image. The bot calls the large model through a port. Each model is a plug-in behind this port, so we can replace the model and change no bot. For this reason, we write our own loop with the design of the reference, and we do not use the Agent SDK as the engine, because it runs only Claude models.

What the loop gets when a task starts

The loop

The loop repeats turns until the model makes no tool requestTask from Petrainstructions, tools,memory core, rules1. EvaluateThe model answers withtext, tool requests,or bothToolrequests?2. ExecuteOur code checkseach request andruns the toolsA limit stops the loopmaximum turns, or maximum budget3. ResultThe result goes to the checkyesnoOne turn: evaluate, then execute. The results go back to the model.
  1. Receive. The loop gets the task from Petra, the instructions of the bot, the definitions of its tools, the core of the memory and the rules.

  2. Evaluate. The model reads all of this and answers. The answer has text, one or more tool requests, or both.

  3. Execute. Our code does a check of each tool request against the rules, and then it runs the tool. A tool that needs a browser or code runs in the sandbox. Tools that only read can run at the same time. Tools that change something run one after the other. The results go back to the model.

  4. Repeat. Steps 2 and 3 are one turn. The turns continue until the model answers with no tool request.

  5. Result. The last answer is the result. A checker that is not the maker tests the result. Then the bot gives the result and the evidence to Petra.

A simple task, such as one answer by Kyoto, needs two or three turns. A research task by Machu can need many turns.

How the loop stops

The loop stops in one of these ways. Each way has a name, and Petra reads the name to know what to do.

How the loop stopsMeaningWhat Petra does
SuccessThe model made no more tool requests. This is a claim, not a proofSends the result to the check. If the check passes, Petra gives the report to the owner
Maximum turnsThe loop reached its limit of turnsTells the owner. The system gives the credits back
Maximum budgetThe task reached its limit of costTells the owner. The system gives the credits back
ErrorAn error stopped the loopStarts the task again one time. Then tells the owner

Each result has the cost, the number of turns and the id of the session, also when the task fails. The super admin dashboard uses these numbers.

What a bot cannot do

How a result is checked #

A loop that runs alone also makes mistakes alone. Thus "done" must be a result that is tested, not a statement by the bot. The rule: the model that did the task never decides that the task is complete. In this section, the maker is the bot that did the task, and the checker is the part that tests the result.

The model that did the task does not decide that the task is completeThe resultwith the evidence,from the maker1. Tests by codelinks open, limits,rules of the memory2. The checkera different model,reads only the task,conditions and resultAll conditionscorrect?The maker tries againone time, with the reasonA second no: failurecredits back, triage listPetra gives the reportto the owneryesno

The five layers

  1. A written check for each type of task. The definition of the bot has a list of conditions that can be tested. Example for Machu: five competitors, each with a source that opens.

  2. Evidence with each result. The maker gives evidence for each condition: a link, a screenshot or a measured number.

  3. Tests by code. Our code tests what it can with no model: the links open, the page loads, the price is in the limits, and the text does not break a rule in the core of the memory.

  4. The checker. A different model tests each condition that code cannot test.

  5. The owner and the team. An action with money, or an action that the public sees, needs the approval of the owner. Each week, the team examines a sample of the tasks. A result that the owner rejects or changes becomes a test case.

The checker

PointDesign
Where it runsIn the stop hook of the loop plug-in. The checker is a separate plug-in, so we can replace it
What it getsOnly the task, the conditions, the result and the evidence. It does not get the turns of the maker, so the maker cannot persuade it
Which modelA different model plug-in from the maker, or Jev, with different instructions
What it answersFor each condition: yes or no, and how sure it is
What it can doIt can only read. It can open a link to test the evidence. It cannot change anything
If an answer is noThe result goes back to the maker with the reason, for one more try. After a second no, the task fails. Petra tells the owner, the system gives the credits back, and the task goes to the triage list of the super admin
The costIt is a part of the price of the task

How we know that the checker is good

The numbers in this section are a start: one more try, and a sample each week.

7. Credits and prices #

Each account can use all the bots. Before a task starts, the system does a check of the credit balance of the account. If the balance is not sufficient, the task does not start. The system then tells the owner to pay or to upgrade. There are three subscription packages, as in the design: Starter $49, Growth $149 and Scale $399 for each month. Each package includes a number of credits. The owner can also buy credit packs. The credits come in increments of 1,000. Starter includes 1,000 credits, Growth 3,000 and Scale 8,000. A credit pack is 1,000 credits for $50.

The system takes the credits before the task, and gives them back if the task failsThe owner asksfor a taskThe system readsthe price listCreditssufficient?The system takesthe creditsThe bot doesthe taskPetra shows thepayment cardThe system givesthe credits backPetra givesthe reportyesnothe task failscompleteBuy a credit pack, upgrade, or stop

The picture shows the check of the credits for one task.

The pricing structure #

This structure is a proposal. Moe decided five points: one credit is 5 cents, the credits in each package, the credit pack, the system takes the credits before a task starts, and a failed task costs nothing. The other numbers are a start. We change them by trial and error, with the data from the super admin dashboard.

1. The value of a credit

1,000 credits cost $50. One credit is 5 cents.

2. The subscription packages

PackagePrice for each monthCredits for each month
Starter$491,000
Growth$1494,000
Scale$39910,000

3. The credit packs

PackPrice
1,000 credits$50

An owner buys a pack when the credits of the month are not sufficient. Start with one pack size. Add larger packs only if owners ask for them.

4. The price of each type of task

These prices are a first estimate. We do not know the real costs at this time.

BotType of taskPrice in creditsPrice in money
PetraA chat message0$0
MachuCompetitor research200$10
AngkorBuild a website or a menu page400$20
AngkorChange one thing on the page40$2
KyotoAnswer one customer message4$0.20
GreenwichExamine the Google Maps listing100$5
GreenwichWrite a draft reply to one review10$0.50
GreenwichWeekly report40$2
PetraWeekly performance review0$0. A part of each package
AngkorAudit of the website0$0. A part of each package

With these prices, a Starter owner can do one research task, one website, five changes and 50 customer answers in one month.

5. The rules

  1. The system takes the credits before the task starts.

  2. If the task fails, the system gives the credits back.

  3. The system uses the credits of the subscription first, and then the credits of a pack.

  4. The credits of the subscription stop at the end of the month. The credits of a pack stay for 12 months.

  5. A chat with Petra costs no credits, so the owner can always ask a question. The weekly performance review by Petra and the audit of the website by Angkor are a part of each package and also cost no credits. Petra tells the owner the price of a task only when the credits are not sufficient for it.

  6. The 14-day trial gives 600 credits. This is sufficient for one research task and one website.

6. How we adjust the prices

  1. Each week, the team reads the super admin dashboard.

  2. The target: the real cost of a task is 30% of its price or less.

  3. If the real cost is above 40% of the price, increase the price.

  4. If the real cost is below 15% of the price, the team can decrease the price.

  5. A new price applies to new tasks only.

Price, cost and the super admin dashboard #

The owner pays a fixed price for each type of task. The price does not change if the task uses more work than usual. Two words are important here:

The owner pays a fixed price; the system records the real costThe loop of the botPrice listfixed price per task typeCredit checkbalance covers the priceCost estimatorgives the expected costPlan a stepDo the stepTaskcomplete?Result to Petraafter the checkRecord the taskthe price and the real costSuper admin dashboardcompare, then change the pricePetra gives the task to the loop of the botno: do the next stepyes

The team uses the dashboard to compare the price with the real cost. If the cost is too near the price, the team changes the price list.

  1. The system reads the price from the price list.

  2. The system does a check of the credit balance.

  3. The cost estimator calculates the cost that we expect for the task.

  4. Petra gives the task to the loop of the bot.

  5. The loop runs until the task is complete. It uses a sandbox only for a tool that needs a real computer.

  6. The result goes to the check, and then to Petra. If a sandbox started, it stops.

  7. The system records the price and the real cost.

  8. The super admin dashboard shows the price and the real cost for each type of task.

  9. The team changes a price when it is necessary. The new price applies to new tasks only.

What the dashboard shows

ColumnMeaning
Type of taskFor example "competitor research" or "build a website"
PriceThe credits that the owner pays
Average real costThe average cost of the tasks of this type
DifferenceThe price minus the real cost
Number of tasksHow many tasks of this type the bots did
Tasks above the priceHow many tasks had a real cost above their price

The repository has a super admin area now, with a Companies screen and a Squad images screen. This dashboard is a new screen. It needs a design before we build it.

8. What the squad remembers and learns #

The squad keeps what it learns about the business. This part shows the memory, the trails and how the system uses them to improve.

Memory #

The squad remembers the business, so the owner does not have to give the same information again. The memory has four layers:

  1. The full record of all messages.

  2. The notes that each bot writes after a task.

  3. One page for each subject, such as the menu, the suppliers and the competitors.

  4. A small core that each task reads.

The memory has four layers, and each task reads only the small coreCore: a small listeach task reads itPages: one page for each subjectby search or a linkNotes: what each bot writes after a taskby searchThe full record of all the messagesby searchHow a task reads the layer

The picture shows the four layers. The core is small, and the record is large.

Each night, a job corrects and combines the notes. A sandbox keeps no memory.

For the builders. The four layers in the database:

LayerContainsWho writes itWhen a task reads it
Record of messagesEach message and each event. Nothing is changed or deletedThe systemOnly by search
NotesWhat a bot learned in a taskThe bot that did the taskOnly by search
PagesOne page for each subject: menu, suppliers, competitors, customersOne bot for each pageBy search, or by a link from the core
CoreA small list with a size limit, and the preferences of the ownerThe night job and the owner onlyEach task reads it, with the limits and the rules

The Memory screen (design proposal). The owner uses this screen to read and correct the memory of the squad. It is a new item in the menu, below Rules.

Design proposal for the Memory screen

The screen has three areas:

  1. Petra always remembers. This is the small core that each bot reads before each task. The owner can add, edit or forget an item. The maximum is 20 items.

  2. Pages. One page for each subject, such as Menu, Competitors and Customers. Each fact shows who found it and its sources. The owner can correct a fact or tell the squad to forget it.

  3. Recent changes. A record of each change to the memory. The owner can undo a change for 30 days.

The rules of the screen:

This is a proposal. The numbers 20 and 30 are a start. The text and the colours use the tensquads design tokens.

Trails #

A trail is the full record of one task. It contains each message, each use of a tool, each decision and each approval, in sequence. The team uses the trail to see what a bot did and why. The system keeps a trail for one month. Only the super admin of tensquads can see a trail. The owner cannot see it. The system keeps the approval records for more than one month, as evidence of each approval.

For the builders. What the trail contains, and what the plan has now:

Part of the trailStatusSource
Messages between botsIn the planThe system puts each event in sequence and writes it to the database
Task results and evidenceIn the planEach task has a check. The bot sends a result with evidence
ApprovalsIn the planEach approval records the rule, the limit and the person who approved
Calls to the modelMissingRecord each input and each reply as an event. This shows why a bot did an action
Uses of a toolMissingThe loop records each use of a tool and its result while it works, not only the last result
DecisionsMissingOne row for each question to the decision model: the question, the answers, how sure, the level and the time

How we store the trail

Learning #

The system uses the trails to improve in two ways. For one business, the squad learns the preferences of that owner, and Petra recommends changes to the rules. For the full product, a task that failed becomes a test case. First, the system removes the customer data. Then the tensquads team examines the test case. A change to a bot must pass these tests before release.

The signals that the trails give

SignalWhat it tells us
The check passed or failed, on the first try or after more triesIf the bot can do the task
The owner approved, rejected or changed an approvalIf the decision of the bot agrees with the decision of the owner
The owner asked for a changeThe result was not what the owner wanted
The task stopped, took too long or was lostWhere the loop breaks
How sure the decision model was, compared with what the person did laterIf the levels are correct
The time and the cost of each taskIf a change made the task slower or more expensive

Loop 1: for one business

  1. After each task, a bot writes a note of what it learned.

  2. Each night, a job compares the notes with the trail, combines them and updates the core of the memory.

  3. A correction from the owner becomes a preference. A preference is stronger than a note of a bot.

  4. Petra recommends changes to the rules from what she sees. Example: "You approved 12 refunds below $20. Do you want to increase the limit?" The owner decides. The system does not increase its own limits.

Loop 2: for the full product

  1. Each task that failed, or that the owner asked to change, can become a test case. First, the system removes the customer data.

  2. The image of each bot has a set of these test cases. A change to a skill or to a prompt must pass the set before release.

  3. A change goes out in three steps: Draft, Beta, Stable. We compare the signals between the steps before we continue.

  4. If a change makes a signal worse, we go back to the old version. The old plug-in is still there.

  5. The failures that occur again and again go to the counts of bugs and requested features on the Squad images screen.

The safety rules

9. How we build it #

This part is for the persons who build the system. It gives the rules for the code, the tools, and the rule for each feature.

Architecture #

Four rules tell us how to build the code. The repository obeys the first two rules in part. The notes tell you what is there now and what to add.

Domain-driven design. We divide the code into business areas, not into technical layers. Each area has its own words, data and rules. Each area is one plug-in. The areas use events to send information to each other. No area reads the tables of a different area. The screens, the code and the documents use the same word for the same thing.

AreaWhat it ownsIn the code today
PlatformAccounts, plans, subscriptionsYes
SquadsBots, skills, sandboxesYes
BusEvents between bots, shared stateYes
PolicyRules, limits, approvalsYes
CatalogBot images, bugs, feature requestsYes
ConversationChat threads and messagesYes
MasterPetra's loop: tasks, checks, routingYes
BillingCredits, packages, top-upsTo add
MemoryNotes, pages, the coreTo add

Anti-corruption layer. Our code does not use the words of an external service. We define a port for each external service in our own words. An adapter behind the port changes our words into the words of the service. The names and the data shapes of the service stop at the adapter.

The words of an outside service stop at the adapterOur codeThe business areasuse only the ports.Port (our words)AdapterOutside serviceMachineProviderchanges the wordsboat.devEventBuschanges the wordsCloudflare queuesDeciderchanges the wordsJev or SageA mailbox portchanges the wordsAgentMail

The picture shows four of the ports. The table below shows all of them.

Outside serviceOur portStatus
boat.dev sandboxesMachineProviderExists
Cloudflare queuesEventBusExists
Neon databaseRepositoriesExists
Jev or SageDeciderPort exists, no adapter yet
Large model providerA model portTo add
Google Maps (Greenwich)A listings portTo add
Payments (credits)A payments portTo add
AgentMail (email for Petra)A mailbox portTo add
AgentPhone (WhatsApp for Petra)A messaging portTo add

The benefit: we can replace Jev with Sage, or replace one payment provider with a different one, and no business rule changes. A test makes sure of this. No file in a business area can import an adapter or an external library.

Keys. The keys of all the outside services are in a vault: the model, Google Maps, AgentMail, AgentPhone and payments. Our code calls each service through a proxy, and the proxy adds the key. The model and the sandbox do not see a key. Thus an attack on a bot cannot get a key.

Adversarial review. The decisions set the architecture. A pull request does not change it. For all other requirements, a reviewer tries to find a fault. The reviewer is not the builder. The reviewer must show evidence for each requirement. A report of "no fault found" without evidence is a fault.

RequirementThe reviewer tries to
SecurityRead another account's data. Hide an instruction in a review or a web page that a bot reads
Money safetyMake a bot refund or pay above the limit, or run a task without credits
ReliabilityStop a sandbox in mid-task. Send the same message twice
PrivacyFind customer data in a test case, a log or another account's memory
PerformanceFind a page or a reply that is too slow
AccessibilityUse every screen with the keyboard only
CostMake one task spend credits without limit

The Reviewer role is in the repository now, for screens. This rule adds the requirements in the table above to that role.

Plug-in framework. Each part of the system is a plug-in, as in the DeepSeek projects. Thus we can replace a part without a restart. The base is there now. We must add four tests that prevent drift:

  1. You can remove a plug-in, and it leaves nothing behind.

  2. A plug-in does not import a different plug-in.

  3. Each piece of state has one writer.

  4. The documents agree with the code.

Where each part runs #

This section shows where each part of the system runs, and which parts are always on. The app and Petra are always on. A bot is not a server. The loop of a bot runs on Cloudflare while the bot has a task. A sandbox runs only the tools that need one.

Petra and the loops run on Cloudflare. A sandbox runs only the tools of a taskThe ownerChatin the appEmailAgentMailWhatsAppAgentPhoneCloudflare: always onThe app and the chatPetraone for each accountThe loop of each botMessages between the botsboat.devA sandbox when a tool needs itA sandbox stops after its task.MachuAngkorKyotoGreenwichNeon databaseAccounts, rules, memory, trails. Only Petra writes.Cloudflare R2Large items of a trailCloudflare PagesThe websites of Angkorreads and writesAngkor publishesOutside services, behind ports. Keys in a vault.OpenAIThe large modelJevFast decisionsClerkSign-inPaymentsNot selectedGoogle MapsNot selected
PartWhere it runsAlways onNotes
The app and the chatCloudflare WorkersYesThe owner uses the app in a browser
PetraCloudflare, one Durable Object for each accountYesShe receives each message and each event. She is the only writer of the state
Messages between the botsCloudflare QueuesYesPetra sends a task to a bot, and the bot sends the result
The tools of a bot that need a sandboxA sandbox on boat.dev, started from the image of the botNo. A sandbox starts when a tool needs itThe sandbox stops after the task and keeps no data
The state: accounts, rules, memory, trailsNeon databaseYesOne database for the MVP, with a second safety layer
Large items of a trailCloudflare R2YesScreenshots, copies of pages and long records
The websites that Angkor makesCloudflare PagesYesAngkor publishes a website only after the owner approves it
Email for PetraAgentMailOutside serviceA message arrives as an event and goes to Petra
WhatsApp for PetraAgentPhoneOutside serviceA message arrives as an event and goes to Petra
Sign-inClerkOutside serviceFor the owners and the super admin
The large modelOpenAIOutside serviceIt makes the plan of a task and writes text
The fast decision modelJevOutside serviceIt answers small questions
PaymentsNot selectedOutside serviceSubscriptions and credit packs
Google MapsNot selectedOutside serviceThe listing and the reviews, for Greenwich
The loop of each botCloudflare WorkersOnly while the bot has a taskThe loop keeps no state. It reads the session from the database, asks the model and runs the tools
The keys of the outside servicesA vault, behind a proxyYesThe proxy adds the key to each call. The model and the sandbox do not see a key

Each outside service is behind a port, as the Architecture section shows. Petra does not run all the time. She starts when a message or an event comes, does her work, writes the state to the database, and then waits. The loop runs on Cloudflare and calls the large model through the model port. A sandbox does not call the model. The keys of all the outside services are in a vault, and each call goes through a proxy that adds the key.

Where the state is #

Keep the state out of Petra. Petra reads and writes the state, but the database keeps it. If Petra stops or gets an update, no data is lost. Petra starts again and reads the state from the database.

StateWhere it isWho writes it
Messages, tasks, approvals, trailsThe databasePetra only
Memory of the businessThe databasePetra only. A bot sends a note to Petra
Rules, limits, credit balanceThe databasePetra only
The sequence of events for one accountPetra keeps a work copyPetra only
Keys and passwordsA key storeThe super admin
Data in a sandboxNothing stays after the sandbox stopsThe bot, during one task

One writer for each account prevents two bots from changing the same data at the same time. The plan agrees with this recommendation: Petra runs on Cloudflare, and the database is Neon.

One database for all the businesses, or one store for each business. One database can hold 10,000 businesses; the quantity is not the problem. The risk is isolation: with one database, one error in the code can show the data of one business to a different business.

OptionHow it operatesGoodBad
A. One database for allEach row has the identity of its business. The plan uses this nowSimple. One update for all. The super admin reads all the data easilyOne error in a filter can show data to the wrong business
B. One database for each businessNeon makes a database for each businessStrong isolation. Easy to delete or restore one businessEach change to the tables runs 10,000 times. Reports for all the businesses are more difficult
C. Petra on her own machine, with the state on the machineOne machine for each business that is always onStrong isolation10,000 machines that are always on. If a machine fails, its data can be lost. Reports must ask 10,000 machines
D. A private store in each Petra, and one central databaseEach Petra keeps the data of her business in her own private store on Cloudflare. A central database keeps only the data that is for all: accounts, subscriptions, credits, prices, costsStrong isolation with no machine that is always on. Cloudflare keeps the copiesA change to the plan. The code that reads Neon now must change

The decision: option A for the MVP, with a second safety layer in the database. The second layer makes the database refuse a row that is not for the business that asks. Then option D, when the number of businesses increases or when a customer asks for isolation. We do not use option C.

The loop in detail #

This section is for the builders. Part 6 shows the loop in simple words. This section gives the controls, the hooks, the context, the session, the plug-ins, and how we add a new bot.

The controls of the loop

ControlWhat it doesHow tensquads uses it
Permitted toolsThe list of the tools that a bot can useEach bot has its own list. A tool that is not on the list is refused
Permission modeWhat occurs when a tool needs an approvalNo person watches the loop. Thus a request that is not permitted is refused, and the bot asks Petra
Maximum turnsThe limit of turnsOne limit for each type of task
Maximum budgetThe limit of costOne limit for each type of task, far above the normal use
EffortHow much the model thinks in each turnLow for a simple answer by Kyoto. High for research by Machu

When our code refuses a tool request, the model gets the refusal as the result. Then the model tries a different method, or it reports that it cannot continue.

The hooks

A hook is our code that runs at a fixed point of the loop. A hook does not use the context of the model.

HookWhen it runsHow tensquads uses it
Before a toolBefore the tool runsApplies the rules and the limits of the owner. It can refuse the request
After a toolAfter the tool gives its resultRecords the step in the trail
StopWhen the loop completesDoes the check of the result. Saves the state of the session
Before the context is made shorterWhen the context is almost fullNothing is lost. The full record is already in the session

The context

The context is all that the model can read in one turn: the instructions, the tool definitions, and the earlier turns with their tool results. It becomes larger with each turn. When it is almost full, the loop makes a summary of the old turns. A summary loses information, and we cannot get that information back from the summary. Thus the full record of the task stays in the session, outside the context. The loop can read an old part of the session again when the model needs it. The permanent rules are in the instructions of the bot, not in the task message.

Stop and continue

Each task is a session with an id. The session is the full record of the task: each message, each tool request and each result, in sequence. The system only adds to it. It is in the database, not in the sandbox and not in the loop. It is the same record as the trail. Because the loop keeps no state, a new loop can read the session and continue from the last event. When a bot needs an approval, the loop and the sandbox stop. After the owner approves, a new loop continues the session. This is a decision.

The loop as a plug-in

The loop is one plug-in, and each bot is one plug-in. No bot contains loop code.

Plug-inWhat it gives
The loop plug-inOne port, "run a task". It takes the definition of a bot and a task, and it returns a result. The engine of the loop is behind this port, so we can replace the engine and change no bot
A bot plug-inThe definition of one bot: instructions, skills, permitted tools, the check, and the limits and the effort for each type of task. Also the price of each type of task
PolicyThe hook before a tool: the rules and the limits of the owner
TrailsThe hook after a tool: the record of each step
MemoryThe core of the memory at the start, and the hook before the context is made shorter
BillingThe credits before the task, and the cost of the result
A model plug-inOne model behind the model port. The loop sends the context to the port and gets the answer with its tool requests. To use a different model, we add a new model plug-in and change the setting. The loop and the bots do not change

The loop plug-in has the hook points. The other plug-ins add their hooks to these points. When we remove a plug-in, its hooks go away with it, and it leaves nothing behind.

When the model changes

A rule in the loop that helps a weak model can make a strong model slower. When we change the model plug-in, we examine the loop again. We run the test cases of each bot, and we remove each rule that does not help.

How we add a new bot

A new bot is one new plug-in. No other plug-in changes.

  1. Make one folder for the bot, with its definition: instructions, skills, permitted tools, the check, the limits, and the price of each type of task.

  2. If the bot needs a new outside service, add a port and an adapter for it.

  3. Add the test cases of the bot.

  4. Add the plug-in to the list of plug-ins. Then Petra finds the bot in the list of what each bot can do, the price list has its prices, and the system builds its image.

The roadmap bots and the future squads come in this way.

Technologies and tools #

This table shows each tool, its use, and its status. "In the repository" means that the code uses the tool now.

AreaToolUseStatus
LanguageTypeScriptAll the codeIn the repository
Web appTanStack Start, React, ViteThe screens and the server functionsIn the repository
HostingCloudflare Workers, Durable Objects, QueuesRuns the app, Petra and the messages between botsIn the repository
DatabaseNeon Postgres, DrizzleStores the accounts, the rules, the memory and the trailsIn the repository
Sign-inClerkSign-in for the owners and the super adminIn the repository
Plug-in corecordisLoads each business area as a plug-inIn the repository
Bot sandboxesboat.devRuns the tools of each bot in an isolated sandboxIn the repository
Service setupStripe Projects (projects.dev)Sets up Cloudflare, Neon and Clerk. Adds new services, provisions them, and manages their costIn the repository
TestsPlaywright, axeTests each screen, records video, examines accessibilityIn the repository
Behaviour modelsTLA+Proves that a state model has no broken ruleIn the repository
Format and lintBiomeKeeps the code in one styleIn the repository
Automatic checksGitHub ActionsRuns the tests on each pull requestIn the repository
Large modelOpenAIPlans tasks and writes text. The model is a plug-in behind a port, and we can replace itIn the plan
Fast decision modelJev, from TypeSafeFast answers to small questionsIn the plan
Page readerScrapling, on boat.devReads the pages of competitors for MachuIn the plan
Website publishingCloudflare PagesPublishes the pages that Angkor makesIn the plan
PaymentsNot selectedSubscriptions and credit packsOpen
Google MapsNot selectedThe listing and the reviews for GreenwichOpen
Email for PetraAgentMailGives each Petra her own email inbox at sign-upSuggested by Moe
WhatsApp for PetraAgentPhoneGives each Petra a phone number that receives WhatsApp messagesSuggested by Moe
Chat with PetraOpenUI (github.com/thesysdev/openui)Shows tables, previews and approvals in the chat while the model writes its answerDecided. A part of the MVP, with our own components. Suggested by Moe

Clear expectation and a video for every feature #

We do not start a feature until its expectation is written. We do not accept a feature until a person sees it operate.

  1. Write the expectation before the work starts. Use simple words. Write what the feature does, who uses it, and what the correct result is. Use the cases in Part 12 as the model: one line for the action of the owner, and one line for the necessary result.

  2. The coding agent builds the feature. It builds only what the expectation says.

  3. The coding agent records a video. The video shows the feature from start to end. It shows the written cases in sequence.

  4. The coding agent attaches the video to the pull request. The person who examines the pull request sees the video and compares it with the expectation.

  5. A difference is a fault. If the video does not show a written case, the pull request goes back. If the video shows something that the expectation does not include, the pull request also goes back.

The repository asks for screenshots and automated tests now. This rule adds a video. The test tool that runs the automated tests can also record the video. Thus the agent records the tests while they run.

10. Feature list #

This is the only list of the features that we build. Add one row for each feature that you want. Write your name in the "Added by" column. Set the priority. Parts 3, 4 and 5 give an explanation of each feature.

#FeatureGroupPriorityStatusAdded byNotes
1Petra, the master and chief of staffMVP botHighProposedMoeTalks to the owner. Directs the other bots
2Machu, the research botMVP botHighProposedMoeResearches the competition
3Angkor, the website and menu builderMVP botHighProposedMoeBuilds the website and the menu
4Kyoto, the support botMVP botMediumProposedMoeHandles support when the business needs it
5Greenwich, the Google Maps botMVP botMediumProposedMoeHandles the business on Google Maps
6Credits and subscriptionsBillingMediumProposedMoeStarter $49, Growth $149 and Scale $399 for each month, each with credits. Credit packs for more credits. A task starts only when the balance is sufficient
7Domain-driven designArchitectureHighProposedMoeThe code is split by business area, in the business's own words
8Anti-corruption layerArchitectureHighProposedMoeOutside services never leak their terms into our code
9Adversarial review of all non-architectural requirementsArchitectureHighProposedMoeA reviewer tries to break each requirement and shows evidence
10Plug-in framework with tests that stop driftArchitectureMediumProposedMoeEverything is a plug-in, as DeepSeek does
11RoutingSystemHighProposedMoeHow a task reaches the right bot
12MemorySystemMediumProposedMoeWhat the squad remembers about the business
13TrailsSystemHighProposedMoeA record of what every bot did and why, kept one month
14LearningSystemLowProposedMoeThe system improves from its trails
15Fast decision model (Jev)SystemLowProposedMoeA small model for quick yes/no judgements. We test it during the MVP
16Clear expectation and a video for every featureProcessHighProposedMoeThe expectation is written before work starts. The coding agent records a video of the feature working, for the person who checks the pull request
17Fixed price for each type of taskBillingMediumProposedMoeA price list gives the credits for each type of task
18Credit ledgerBillingMediumProposedMoeA record of each credit that an account gets or uses
19Real cost record for each taskBillingHighProposedMoeThe system records what each task costs us: model use, sandbox time, external services
20Bot image, sandbox and loopSystemHighProposedMoeThe loop of a bot runs on Cloudflare. It starts an isolated sandbox on boat.dev from the image of the bot only for a tool that needs a real computer. The loop gives the result to Petra
21Cost estimatorBillingLowProposedMoeBefore a task starts, the estimator calculates the cost that we expect
22Super admin dashboard: price and real costSuper adminMediumProposedMoeFor each task, the team sees the price that we charge and the real cost
23Price change by the super adminSuper adminLowProposedMoeThe team changes the price of a type of task. The new price applies to new tasks
24Trail viewer for the super adminSuper adminMediumProposedMoeThe tensquads team sees the trail of each task. The owner does not see it
25Stripe Projects (projects.dev)ArchitectureMediumProposedMoeWe use it to add new services, to provision them, and to manage their cost. The repository uses it now for Cloudflare, Neon and Clerk
26Second safety layer in the databaseArchitectureHighProposedMoeThe database refuses a row that is not for the business that asks. For the MVP
27Private store in each Petra, and one central databaseArchitectureLowProposedMoeAfter the MVP. Each Petra keeps the data of her business. The central database keeps the data for all the businesses
28PI-Starter: rules and checks for coding agentsProcessLowProposedMoeLater. Before we add it, select the web framework: Next.js or TanStack Start
29Email address for PetraChannelsMediumProposedMoeAt sign-up, the system gives Petra her own email address. The service is AgentMail
30WhatsApp number for PetraChannelsMediumProposedMoeAt sign-up, the system gives Petra a phone number that receives WhatsApp messages. The service is AgentPhone
31Performance review and suggestions by PetraSystemMediumProposedMoePetra reads the performance of the business each week and suggests changes to the website or to other areas. Jev gives a score to each suggestion. The review is a part of each package and costs no credits
32Roles of the bots and the personsSystemHighPlannedMoeEach bot has one role: what it does, what it does not do, and to whom it speaks. The persons are the owner, the customer of the business and the super admin
33OpenUI for the chat with PetraArchitectureMediumProposedMoeTo consider. With OpenUI, Petra can show a table, a preview or an approval in the chat, not only text
34Cards in the chat with PetraSystemHighProposedMoePetra shows cards in the chat: a table, a website preview, an approval, a payment message and suggestions. A very important use case. The chat uses OpenUI
35Check of a result by a separate checkerSystemHighProposedMoeThe model that did the task does not decide that the task is complete. Our code tests what it can. A checker with a different model tests each other condition. Refer to Part 6

Roadmap and future squads #

These bots and squads are not in the MVP, and they are not in the feature list above. The roadmap bots come first. The future squads come after them. Moe will add more to the roadmap.

NameRoleWhenAdded by
Analytics botRoadmapMoe
Accounting botRoadmapMoe
Finance botRoadmapMoe
Paid ads managementRuns paid adsFutureMoe
SEO growth specialistGrows organic trafficFutureMoe
Order managementManages ordersFutureMoe
Catalog managementManages the product catalogFutureMoe
Integration / channels managerIntegrates with other marketplacesFutureMoe

11. Decisions #

Each row is one decision that Moe made. The parts above use these decisions. To change a decision, add a question to Part 14.

AreaSubjectDecision
Credits and pricesPrice of a taskEach type of task has a fixed price. A cost estimator calculates the expected cost. The super admin dashboard compares the price with the real cost
Credits and pricesPackagesStarter $49, Growth $149 and Scale $399 for each month, as in the design. The design does not change
Credits and pricesCredits in each packageStarter 1,000 credits, Growth 3,000 and Scale 8,000
Credits and pricesCredit pack1,000 credits for $50
Credits and pricesValue of a credit5 cents. We adjust this value by trial and error
Credits and pricesTime of paymentThe system takes the credits before the task starts
Credits and pricesFailed taskThe owner does not pay. The system gives the credits back
Credits and pricesPrice before the taskPetra tells the owner the price only when the credits are not sufficient
Credits and pricesCost limitEach type of task has a maximum of turns and a maximum budget. These are safety limits only, far above the normal use. When a limit stops a task, the owner gets the credits back. The dashboard shows the tasks that cost more than their price
Credits and pricesWeekly performance reviewA part of each package. It costs no credits. Petra does it each week. The data of the MVP is sufficient for the first version
Credits and pricesWebsite auditA part of each package. It costs no credits
Petra and the botsDecision modelWe use Jev. We do the Jev test during the MVP. We can test Sage later
Petra and the botsSignalThree complaints of the same type in one week. This is a start, and we can change it
Petra and the botsReviews on Google MapsGreenwich answers them
Petra and the botsAlways onOnly Petra is always on. The loop of each other bot runs on Cloudflare while the bot has a task. A sandbox starts only when a tool needs it
Petra and the botsStart time of a sandboxA simple answer by Kyoto needs no sandbox. For a task that needs one, measure the start time first. If a sandbox starts in more than 10 seconds, Kyoto keeps one sandbox ready for each business that has support on
Petra and the botsGreenwich characterThe new repository has the Greenwich file in assets/mascots
Petra and the botsFuture squadsMoe added them. They are in their own section below the feature list
Email and WhatsAppWhatsApp serviceAgentPhone (agentphone.ai)
Email and WhatsAppWho writes to PetraOnly the owners
Email and WhatsAppCost of a number$3 for each number for each month. AgentPhone adds no price for a WhatsApp message. Meta sends its own bill for the WhatsApp conversations
Email and WhatsAppInboxesOne inbox for each owner. The Petra of that owner is responsible for it. Before the first owner, the team must confirm that the AgentMail plan permits this number of inboxes
Email and WhatsAppCountries of the numbersOnly the businesses in the United States and Canada get a number. A business in a different country gets the email address and the chat
Email and WhatsAppWhatsApp Business accountOne account for each business. The team must read the AgentPhone documents to learn how a business connects its account, and what Meta charges
Memory and trailsTrailsOnly the super admin of tensquads sees a trail. The system keeps a trail for one month
Memory and trailsApproval recordsThe system keeps them for more than one month. The time is not defined
Memory and trailsMemory screenThe owner can read and correct the memory. The design proposal is in Part 8
Memory and trailsTest cases from failed tasksA failed task of one business can become a test case for all, after the system removes the customer data. The tensquads team examines each test case
How we build itStateThe database keeps the state. Only Petra writes it
How we build itDatabaseOne database for the MVP, with a second safety layer. Later, a private store in each Petra and one central database
How we build itLimits of the private storeWe confirm the size limit and the price when we have 500 businesses, or when an owner asks for isolation
How we build itprojects.devIt is Stripe Projects. We use it to add new services, to provision them, and to manage their cost
The chatOpenUI for the chatWe use OpenUI for the chat with Petra. It is a part of the MVP. We make our own components with the tensquads design. Each card also has a text form for email and WhatsApp. Our code makes each approval
How we build itThe model and the loopEach model is a plug-in behind a port, and we can replace it easily. We write our own loop with the design of the Claude Agent SDK. We do not use the SDK as the engine, because it runs only Claude models
Petra and the botsApproval in the middle of a taskThe system saves the session, and the loop and the sandbox stop. After the owner approves, a new loop continues the session
How we build itCalls to the modelThe loop runs on Cloudflare and calls the model. A sandbox does not call the model. The system records the cost and the trail of each call
How we build itWhere the loop runsOutside the sandbox, in our code on Cloudflare. The loop keeps no state. A sandbox is only a tool: run this, and give me the result. A task that needs no sandbox starts immediately
Memory and trailsSession recordThe full record of a task is in the session, outside the context of the model. The loop can read an old part again. It is the same record as the trail
How we build itKeysThe keys of all the outside services are in a vault, behind a proxy. The model and the sandbox do not see a key
How we build itWhen the model changesWe examine the loop again. We run the test cases of each bot, and we remove each rule that does not help
Petra and the botsCheck of a resultThe model that did the task does not decide that the task is complete. Our code tests what it can, and a separate checker with a different model tests each other condition. After a second failure, the task fails and the owner gets the credits back

12. Test cases #

These are the success cases for the MVP bots. Select Yes, Later or No in the last column. Each case uses a restaurant or a grocery shop, the two types of business in the plan. In these cases, the owner is the person who has the account, and a customer is a person who buys from the business.

Petra (master / chief of staff) #

Petra is the only bot that speaks to the owner. These cases test her alone.

#CaseWhat the owner doesSuccess looks likeTest it?
P1Picks the right botAsks "Who are my competitors nearby?"Petra sends the task to Machu, not to another bot. The trail shows her choice and reason
P2Asks when unclearSays "Fix my online stuff"Petra asks one clear question before she starts any task. No bot runs until the owner answers
P3Answers aloneAsks "What did the squad do today?"Petra answers from the trail with the correct tasks and results. No bot is started
P4Honest statusAsks "Is my website ready?" while Angkor is still workingPetra says it is in progress and what remains. She does not say it is done
P5Reports a failureA bot's task fails its check twicePetra tells the owner what failed, in plain words, and offers a next step. She does not hide it
P6Stops for approvalA task needs an action above the limit of the ownerPetra puts one approval in the inbox and waits. The action does not run before a yes
P7Only Petra speaksAny task that uses another botEvery message that the owner sees comes from Petra. No other bot writes to the owner

Petra and Machu (research) #

The owner asks Petra. Petra gives Machu the task. Machu returns the findings with their sources. Petra tells the owner.

#CaseWhat the owner doesSuccess looks likeTest it?
M1Finds real competitorsA restaurant owner asks "Who are my competitors?"At least 5 competitors. Each is a real business of the same type in the same area, with a working link
M2Compares pricesAsks "How do my prices compare?"A table of competitor prices for like items. Every price has the page it came from
M3Finds the gapsAsks "What are they missing that I could offer?"At least 3 gaps. Each one names the competitors it is based on
M4Admits what it could not findThe business is in a small town with little onlineMachu returns what it found and says what it could not. It invents no competitor and no price
M5Plain summaryAny research taskPetra's summary fits one screen, uses no jargon, and links to the full findings
M6Research feeds the websiteResearch is done, then the owner asks for a websiteAngkor's page uses at least one finding from Machu, such as a gap or a price point

Petra and Angkor (website and menu builder) #

The owner asks Petra for a website. Angkor builds it. Petra shows a preview link in the chat. Petra publishes the website only after the owner approves it.

#CaseWhat the owner doesSuccess looks likeTest it?
A1Builds a restaurant pageA restaurant owner says "Build my website" and gives name, address, hours and menuA live preview link in the chat. The page shows the correct name, address, hours and every menu item with its price
A2Builds a grocer pageA grocer gives a list of itemsOne page that lists every item given. No item is missing, added or renamed
A3Works on a phoneOpens the preview on a phoneThe page reads well at phone width with no sideways scroll. It loads in under 3 seconds
A4Changes on requestSays "Change the price of the falafel wrap to $9"Only that price changes. The preview updates and nothing else on the page moves
A5Asks for what is missingAsks for a site but gives no menuPetra asks for the menu. Angkor invents no dish and no price
A6Publishes only after a yesReviews the previewThe site goes live at its public address only after the owner approves. Before that, only the preview exists
A7Fits the cultureThe restaurant has a clear cuisine, such as LebaneseThe design reflects it in colour, type or imagery, and the owner rates it acceptable without a redesign

Petra and Kyoto (support) #

Kyoto answers the messages of the customers of the business. Petra tells the owner what occurred and brings the approvals.

#CaseWhat happensSuccess looks likeTest it?
K1Answers a simple questionA customer asks "Are you open on Sunday?"Kyoto replies with the correct hours from the business's own data, within one minute
K2Says when it does not knowA customer asks about something not in the data, such as parkingKyoto says it will check and passes the question to the owner through Petra. It invents no answer
K3Refund under the limitA customer asks for a $15 refund; the owner's limit is $20Kyoto follows the owner's rule without asking. The trail records the rule it matched
K4Refund over the limitA customer asks for a $60 refund; the limit is $20No refund is made. Petra shows the owner one approval with the amount and reason. The refund runs only after a yes
K5Angry customerA customer sends an angry complaintKyoto stays polite, makes no promise it cannot keep, and Petra flags it to the owner the same day
K6Owner's daily summaryThe owner asks Petra "Any support issues today?"Petra gives the correct count of messages, what was resolved and what waits for the owner
K7Support is off until neededA new business has not turned support onKyoto answers nothing. Petra offers to turn it on when the first customer message arrives

Petra and Greenwich (Google Maps) #

Greenwich looks after the business's Google Maps listing. Anything the public will see goes through Petra to the owner for a yes first.

#CaseWhat the owner doesSuccess looks likeTest it?
G1Audits the listingAsks "How does my Google listing look?"Greenwich reports what is missing or wrong: hours, phone, category, photos, website link. Each point matches the live listing
G2Updates the hoursSays "We now close at 10 pm on Fridays"Petra shows the change for approval. After a yes, the live listing shows the new hours and nothing else changed
G3Drafts a reply to a good reviewA 5-star review arrivesGreenwich drafts a short reply that mentions what the reviewer said. It is posted only after the owner approves
G4Handles a bad reviewA 1-star review arrivesPetra tells the owner the same day with a calm draft reply. Nothing is posted without a yes. The draft admits no fault the owner has not confirmed
G5Links the new websiteAngkor publishes the siteGreenwich proposes adding the site and menu link to the listing. After a yes, the listing links to the live site
G6Creates a missing listingThe business has no Google listingGreenwich prepares the listing details and tells the owner the steps only they can do, such as verification. It does not claim the listing is live before it is
G7Weekly reportAsks "How did we do on Google this week?"Petra gives views, calls, direction requests and new reviews. The numbers match Google's own

Petra and the cards in the chat #

The owner speaks to Petra in the chat, and Petra shows cards in the chat. Moe said that this use case is very important.

#CaseWhat the owner doesSuccess looks likeTest it?
D1A table cardAsks "Who are my competitors?"Petra shows one table card in the chat, with one row for each competitor. The answer is not a long text
D2A website preview cardAsks "Build my website" and gives the menuPetra shows a preview card with the name, the hours and each menu item. The card says "preview" until the website is public
D3An approval cardA $60 refund request comes, and the limit is $20Petra shows one approval card with the amount, the reason and two buttons. The refund occurs only after the owner selects "Approve"
D4The card after a selectionSelects a button on an approval cardThe card shows the selection, and the buttons go away. The owner cannot approve the same action two times
D5A payment cardAsks for a task, and the credits are not sufficientPetra shows a payment card with the price of the task and the balance. The task does not start
D6A suggestions cardThe weekly review occursPetra shows one card with three suggestions or fewer. Each one has its evidence and its price in credits
D7The same answer on WhatsAppThe owner asks the same question on WhatsAppPetra sends the same information as text. The text has all the facts of the card

The judgement of Petra #

These cases show how Petra decides. In each case, Petra must make a decision that a fixed rule cannot make, and she must give her reason. Part 4, "How Petra decides", gives the sequence of questions.

#CaseWhat the owner doesSuccess looks likeTest it?
J1A request with no clear botSays "My customers cannot find us"Petra selects Greenwich, because the problem is about Google Maps. She tells the owner her reason in one sentence
J2A request for two botsSays "I want to start a lunch offer"Petra does the research with Machu first, and then asks Angkor to add the offer to the website. She tells the owner the sequence before she starts
J3A request that no bot can doSays "Do my taxes"Petra tells the owner that no bot in the squad can do this. She starts no task and takes no credits
J4A request that disagrees with a preferenceThe owner said before "Never mention delivery". Now the owner says "Add a delivery banner to the website"Petra tells the owner about the disagreement and asks which one is correct. She does not select by herself
J5A request to give Petra more freedomSays "From now on, answer all the bad reviews without me"Petra tells the owner that this changes a rule. She asks the owner to confirm the new rule. She does not increase her own limits
J6Petra is not sureA refund request comes with a reason that is not clearPetra does not guess. She asks the owner, and no refund occurs before the answer
J7The owner asks for the reasonAsks "Why did you ask Machu?"Petra gives the reason in simple words. The reason agrees with the reason in the trail
J8An event, not a signalOne customer complains about a long waitPetra records the complaint and makes no suggestion. She can tell the owner why, if the owner asks

Petra and the signals #

Petra reads signals and confirms them. She does not react to each piece of information. Moe gave the examples for these cases.

#CaseWhat occursSuccess looks likeTest it?
N1One complaint, and the website is slowA customer says that the website does not respondKyoto answers the customer. Petra starts an audit of the website. The audit finds that the website is slow. Petra shows the owner the measurement and a suggested change
N2One complaint, and the website is not slowA customer says that the website does not respondKyoto answers the customer. Petra starts an audit. The audit finds no problem. Petra makes no suggestion to the owner, and she records the complaint
N3One bad reviewOne review on Google Maps says that the food came after more than 45 minutesGreenwich answers the review. Petra records the complaint. Petra makes no suggestion to the owner
N4Three complaints of the same typeIn one week, a third customer says that the food came after more than 45 minutesPetra tells the owner about the signal. She shows the three complaints as evidence and suggests a change
N5Three complaints of different typesThree bad reviews come. Each one is about a different problemPetra does not count them as one signal. She makes no suggestion
N6The same complaint in different wordsOne customer writes "we waited almost an hour". A second writes "the food took 50 minutes"Petra counts the two complaints as the same type
N7The owner rejects the suggestionThe owner rejects a suggestion from PetraPetra does not make the same suggestion again, unless new evidence comes

The whole squad #

These cases test the promise: a company can launch with tensquads.

#CaseWhat the owner doesSuccess looks likeTest it?
S1Launch in one conversationA new restaurant owner says "Help me launch"In one chat: competitor research, a published site with the menu, and a Google listing that links to it. The owner gave at most 3 approvals
S2One change, everywhereSays "We are closed on Mondays now"The site, the Google listing and Kyoto's answers all show the new hours. Petra confirms each one
S3A bot is downThe sandbox of Angkor fails during a buildPetra tells the owner there is a delay. The task continues in a new sandbox and completes. No work is lost and nothing is done twice
S4Nothing sent twiceThe network drops while Kyoto sends a replyThe customer receives the reply exactly once
S5The trail is completeAny finished taskThe team can open the task and see every message, tool call, decision and approval, in order
S6Memory carries overThe owner says once "Never mention delivery; we do not deliver"A week later the site, the review replies and Kyoto's answers still follow it
S7Two businesses stay apartTwo owners use tensquads on the same dayNothing from one business appears in the other's chat, site, memory or trail

How to measure. Run each chosen case 5 times. A case passes when all 5 runs meet "Success looks like". Where a row gives no number, the tensquads team judges it against the written line.

13. Research and sources #

This part contains the research behind the design. It shows what each reference says and what we take from it. The design is in Parts 4 to 9. Moe added all the topics.

Framework: everything is a plugin #

tensquads already has the base: a cordis core, one plug-in per domain area, skill updates as plug-in swaps. What it lacks is the tests that stop drift. DeepSeek's projects get their discipline from tests, not from the plug-in idea alone.

What it means in DeepSeek Harness (DSH). There is no privileged core. The model adapter, tool registry, session log and agent loop are each a plug-in. Each service has one owner and one typed key. Every registration returns a disposer, so unloading a plug-in removes all it added. Composition is data, and one command prints the booted tree.

How they stop drift. A dispose test for every registry. A boot test for each plug-in. Recorded-session snapshots. Config that is validated and fails loudly at load. Tests that check the docs match the code. The rule "what the model sees is logged".

Philosophy (dsh-superagent). Take little human attention and give much value. Act only on request or by a written rule. Ask one question at a time. Stop by impact. Report honestly. Few concepts, few settings. Start narrow.

Borrow, in order

#WhatFromWhat changes in tensquads
1Every registration is an effect with a disposer, plus a dispose test per plug-inDSHProves "a removed plug-in leaves no trace" and the skill swap in decision 18
2Typed service keys with one owner eachDSHReplaces the casts and per-plug-in branches in kernel.ts
3Import-boundary testsdsh-superagentDomain imports no adapter; plug-ins do not import each other
4One writer per state, as a testdsh-superagentEnforces decision 16
5A surface per caller (web, Durable Object, queue)dsh-superagentSplits the one wide Kernel class
6Docs-match-code testdsh-superagentADR 0001 names plugins.ts; the code is plugins/. A test catches this
7Model-visible means logged, plus replay snapshotsDSHEvery input to a Petra prompt is a bus event; replays guard her replies
8Model-surface testdsh-superagentTool schemas and prompts checked against the glossary and a size budget
9Validated config, loud failureDSHNo hidden defaults
10Steward, checkpoint and handoff note for long chatsDS-BotPetra's long chat: condense past 80% of the window, keep the user's messages word for word

Does not fit. DSH and DS-Bot assume one long-lived process with local files and SQLite. A Durable Object hibernates, so plug-ins there must rebuild from stored state. Their hot reload watches files; tensquads swaps by bus message. DSH lets users patch composition; decision 18 forbids customer version pinning.

Not read. The cordis primer on DSH's docs site was blocked, so the cordis plug-in API itself is unverified here.

Bots studied: what to borrow #

The three products confirm the tensquads shape: one master that talks, specialists that work, approvals before risky actions. The ideas worth taking are about reliability, not features.

ProductWhat it isHow it works
RerunSelf-hosted "AI coworkers"A Chief of Staff agent interviews the owner, plans a team and hires coworkers. Each agent is a folder of Markdown files: soul, skills, memory. Coworkers stop and ask before they send, pay or delete
OpenMausBotDesktop group chat for agentsOne local server owns every agent process and logs one event stream per thread. Risky actions become Allow / Deny cards. A cheap decision model routes messages
OpenBotWorkspace for persistent agents, desktop and hostedAn event log with projections. Each agent has a crash-safe queue. Workflows run as trigger, steps, approval

Borrow

#IdeaFromWhy it fitsSize
2A routine skips its run if the last one is still activeOpenMausBotStops queue build-up on always-on machinesS
3Boot reconcilers and a health check per machineRerunAgents heal after a restartS
4Workflows shown as trigger, steps, approvalOpenBotMaps directly onto the approval inboxS
5Job statuses: settled, needs user, failed, stalled, timed outOpenMausBotPetra gives the owner one honest status lineM
6Squad templates install with everything offOpenMausBotRestaurant and grocer templates arrive paused and unapprovedM
7Crash-safe queue per agent with pause, resume, cancelOpenBotA machine restart loses nothingM
8Onboarding interview that plans the squadRerunFits a non-technical owner; Petra already owns the conversationM
9After each run, a curator writes memory the owner can readRerunThe owner can see and correct what the squad learnedM
10Append-only event log with projectionsOpenBot, OpenMausBotAudit and replay of what each agent didL

Do not borrow

OpenMausBot, a closer read. It is the nearest relative of tensquads: it runs bots on boat.dev cloud computers and uses Jev to route messages.

Rerun, a closer read. Its pitch is the tensquads pitch: say what you need in plain words, and a Chief of Staff builds the team.

Not read. The OpenMausBot site redirects to a host this session cannot reach. Its findings come from its GitHub repository.

Memory #

What the references say

Routing #

What OpenClaw does

Decisions: Jev #

Speed and cost. These are the vendor's own numbers; we have not tested them.

JevA large model
Time for one judgement0.114 seconds8.566 seconds
Cost for one judgement$0.000081$0.013880

TypeSafe says this example is "on the higher end of real world gains". It gives no accuracy number.

There are two candidates. Jev is from TypeSafe. Sage is from Levanto and does the same job. The Capacitr case study you sent is about Sage, not Jev. Capacitr put Sage in front of eight money-moving tools and reported under 100 ms per decision and no wrong blocks in 152 audited calls. Sage accepts Jev's request format, so we can test both with the same code.

Notes for builders

Sources #

Framework

Bots

Memory and routing

Decisions

Could not open

Also read: TypeSafe docs (introduction, models, confidence, index), Levanto docs (introduction, pricing, SystemOne API), and the full READMEs of Rerun and OpenMausBot.

14. Open questions #

Each question needs an answer before we build the related feature. When a question has an answer, the answer goes to Part 11, Decisions.

There are no open questions now.