MILAGPT
Start with “For business”: three steps to launch.
Book a reviewTelegram will open
RU·EN
Docs · Client secrets

Client secrets: every message is checked

Before each message in Telegram, Mila’s text goes through a guard. A wrong chat, a key, a card number, the name of another client’s chat — and the message does not go out. Mila gets the reason and writes it again. Every line below links to the code.

For an agency or a consultant with many clients in one Mila.

How it works

A check before every message

The guard is a small script that Claude Code runs before Mila sends anything to Telegram. A rule in a prompt can be forgotten; a script on the way out cannot. send-guard.py:1-5 settings.json:35-46

01 · EVERY TIME

Before a reply and an edit

It runs on a new message and on an edit of one already sent. Other tools are not touched.

send-guard.py:13-15
02 · WHAT IT SEES

The chat and the text

It sees which chat the message goes to and the text itself, and compares both with its rules.

send-guard.py:16-21
03 · NO

A reason instead of a send

If something is wrong, the message stays. Mila gets “Not sending:” and every reason, and writes the text again.

send-guard.py:179-187
04 · FAILURE

The guard fails — nothing goes out

In the settings template the guard has onFailure: block: if it crashes or hangs, the message is not sent unchecked. The test runs on every change in the repository.

settings.json:42 skills.yml:12 CHANGELOG.md:121
Client secrets

Another client’s business stays in its chat

Mila has one session for all chats; there is no wall between them inside. So the lock is on the way out: the check happens at the moment of sending. It is law 1 of her constitution: a detail of one case is not heard in a talk about another. send-guard.py:116-120 CONSTITUTION.md:15

The guard learns who is where from the journal of incoming messages: which people wrote in which chat and what each chat is called. send-guard.py:137-155

Does not go to this chat
Who she writes to

Only where she was connected

A message goes to the owner, to groups the owner connected her to, and to private chats of people let in through the access list. Any other chat gets nothing: “I speak only where I was connected.” send-guard.py:23-36 test_send_guard.py:23-24

If the owner’s id is not set, the access list is enough. If there is neither, as in a Mila not yet connected, the recipient is not checked. send-guard.py:33-35 test_send_guard.py:44-49

✓ owner (OWNER_ID)
✓ groups in access.json
✓ people in allowFrom
✗ any other chat
What else stays

Keys, cards, internals do not leave

The same guard looks for things that should never be in a chat, whoever the message is for.

01 · KEYS

Keys and tokens

Provider keys, a Telegram bot token, AWS, GitHub and Slack keys, API tokens. The message stays, and the advice is “reissue the key”.

send-guard.py:38-48 test_send_guard.py:26
02 · CARDS

Card numbers

13–19 digits that pass the card checksum never go to a group. In a private chat the number goes out masked as ****1234. Your own payment details can be allowed; a phone number with “+” is not a card.

send-guard.py:49-83 send-guard.py:179-184 test_send_guard.py:59-75
03 · INTERNALS

Paths, ids, raw errors

Server paths, container commands, raw provider errors, hook internals, chat ids like -100… She says the result in plain words instead.

send-guard.py:84-95 test_send_guard.py:27
04 · APOLOGIES

The case, not “sorry”

“Sorry”, “my fault”, “unfortunately I could not” do not go out, to a client or to the owner: a fact, a conclusion and the next step instead. Law 7 of the constitution. Exceptions: the developers’ chat and a report with a defect number.

send-guard.py:97-104 CONSTITUTION.md:21 test_send_guard.py:25

One more rule: bold, lists or links without Telegram formatting do not go out either, so nobody sees raw asterisks. More on the Telegram page. send-guard.py:106-114

On your server

The installer puts it in place

The installer copies send-guard.py into the hooks folder and writes it into Claude Code’s settings for replies and edits. A second run does not add it twice; a test checks both. install/install.sh:116-121 install/install.sh:292-297 test_install_hooks.sh:23-26

The owner’s id comes from MILA_OWNER_ID and goes into the settings, so the guard knows whose DM is whose. install/install.sh:305-309

Updates bring new guard code with the other core hooks. Your settings file is never touched by an update. release.json:41-49 release.json:71

$ python3 templates/home/.claude/hooks/test_send_guard.py
# 24 cases: wrong chat, key, path, apology,
# another client’s @username, card in a group,
# masked card in a DM, chats of one case
# 24 of 24 passed on 8a6b97d
Honestly

What the guard does not catch

In the repository

Read every line yourself

Files behind the send guard in the mila repository
FileWhat it does
send-guard.pythe guard: recipient, keys, cards, internals, apologies, another chat’s business
test_send_guard.py24 checks of the guard (in Russian)
settings.jsonsettings template: the guard on reply and edit, onFailure: block
install/install.shcopies the guard and writes it into the settings
test_install_hooks.shchecks that the installer registered the guard once
release.jsonupdates bring the hooks, never the settings file
CONSTITUTION.mdlaw 1 (secrets) and law 7 (no apologies), in Russian
SECURITY.mdhow to report a hole in the guard
Open source · Apache-2.0

Fork it, teach it, send a PR

The kit is open: skills, hooks, tools and templates. Run test_send_guard.py yourself; found a hole in the guard? SECURITY.md says how to report it.

Facts on this page: github.com/shakhruz/mila (main, 8a6b97d, v1.5.2), checked 24 Oct 2026; test_send_guard.py passed 24 of 24. The chat in the phone is an illustration. “Mila”, “MILAGPT” and the logo are trademarks of MILAGPT.