How Mila did it: case studies and news
Content, ads and admin — three Milas in one chat? By default Mila ignores bots: two bots answering each other is the fastest way to burn a subscription. Her own team she hears under strict rules: a bot from your list, addressed by @name or by a reply to her message, at most 20 messages an hour from one bot. Every line below links to the code.
For an owner whose Milas — content, ads, admin — work in one chat.
The session feeder, install/companion-feeder.py, passes incoming Telegram messages into Mila’s session. Messages from people always go through, as before. A message from a bot goes through only under four conditions. team-hearing.md:3-6 companion-feeder.py:274-276 team-hearing.md:10-17 companion-feeder.py:316-339 team-hearing.md:19 companion-feeder.py:320-321
The sender is in the registry of our bots, the file our-bots.json. Foreign bots are never fed.
Her bot’s @name is in the text, in any case, or the message is a reply to one of her messages.
A message from her own bot is not fed back to her.
team-hearing.md:16 companion-feeder.py:325At most 20 messages from one bot per rolling hour. Past that the feeder drops them.
team-hearing.md:30-31 companion-feeder.py:331-339The rule for a Mila is simple: to reach another one, write @their_bot_name or reply to her message. Anything else she will not hear. team-hearing.md:19-21
A role name in plain words, like “@Content”, does not work — only the bot’s username. Who is called how, the team keeps in a table, canon/TEAM-CONTACTS.md: who, what she does, how to call her. The repository ships a template, and updates never touch your own table. TEAM-CONTACTS.example.md:3-4 TEAM-CONTACTS.example.md:12 release.json:50-58 release.json:77
When a Mila replies to a message, the quoted text goes into the session up to 3000 characters, escaped like the rest of the envelope. team-hearing.md:25-26 companion-feeder.py:84-86
@<admin_bot>.@<bot>.@<bot>. TEAM-CONTACTS.example.md:6-10our-bots.json is a JSON array of bot usernames without @, in any case. Copy our-bots.example.json and put your list in. The feeder looks for it at COMPANION_OUR_BOTS, by default ~/.mila-companion/our-bots.json. The file is git-ignored, so the real list never lands in the repository. team-hearing.md:37-41 our-bots.example.json:1 companion-feeder.py:277 team-hearing.md:43-45 .gitignore:5
No file, or a broken one, means an empty registry: Mila hears no bot at all. A failure closes the door rather than opening it. team-hearing.md:45-46 companion-feeder.py:290-294
Her own bot name comes from COMPANION_BOT_USERNAME; if it is not set, from the receiver’s log, receiver.log. team-hearing.md:54 companion-feeder.py:297-313
# ~/.mila-companion/our-bots.json
["acme_content_bot",
"acme_traffic_bot",
"acme_admin_bot"]
The guard counts fed messages from each sending bot over the last 3600 seconds. The twenty-first is not fed, and the feeder writes a line to its log: bot-loop-guard @name and the count for the hour. companion-feeder.py:278-280 companion-feeder.py:331-338 team-hearing.md:30-32 companion-feeder.py:335
A person writing in the same chat does not notice: the limit does not count people. team-hearing.md:32-33 companion-feeder.py:320-321
The threshold is set by COMPANION_BOT_PAIR_MAX. If it is not a number, it stays at 20. companion-feeder.py:283-287
Four variables, all with defaults. team-hearing.md:48-55
# variable → default
COMPANION_OUR_BOTS
~/.mila-companion/our-bots.json
COMPANION_BOT_PAIR_MAX
20
COMPANION_BOT_USERNAME
read from receiver.log
COMPANION_STATE
~/.mila-companion/state
python3 install/test_team_hearing.py expects ALL OK. The shared run, tests/run_all.sh, picks it up together with every other test_* file. team-hearing.md:57 test_team_hearing.py:27 tests/run_all.sh:14-16
The cases are the rules from above, checked one by one: a person, a bot without an address, a mention, a reply, a foreign bot, herself, the limit and the quote.
install/companion-feeder.py, which passes incoming messages from the journal into the Claude Code session. companion-feeder.py:3-11 REFERENCE.md:97_bot as a bot; everyone else goes through as a person. companion-feeder.py:317-321receiver.log — she hears no bot. companion-feeder.py:322-326 team-hearing.md:54 companion-feeder.py:297-313our-bots.json and canon/TEAM-CONTACTS.md are kept by each team; the repository has only examples. team-hearing.md:43-45 .gitignore:5 TEAM-CONTACTS.example.md:12 release.json:50-58 release.json:77| File | What it does |
|---|---|
| docs/team-hearing.md | addressing rules, registry, loop guard, settings |
| install/companion-feeder.py | the feeder: gate_message decides whether a bot message is fed |
| install/test_team_hearing.py | the test: nine cases, expects ALL OK |
| our-bots.example.json | registry example: three bots |
| TEAM-CONTACTS.example.md | template: who is called how |
| docs/REFERENCE.md | the feeder’s line in the reference |
The kit is open: skills, hooks, tools and templates. Run python3 install/test_team_hearing.py: the nine cases from this page, and the answer is ALL OK.
Facts on this page: github.com/shakhruz/mila (main, 88d0704), checked 27 Oct 2026; test_team_hearing.py printed ALL OK. The messages in the phone are cases from that test. “Mila”, “MILAGPT” and the logo are trademarks of MILAGPT.