← Blog
2026-08-20 · 5 min read

Sente に PIIスクラビングを追加した
— 送る前に、このMacで隠す

Sente(先手)は teai.io の CLI コーディングエージェントです。今回追加したのは、 送信直前にこのMac上のローカルLLM(Ollama)+正規表現で氏名・住所・電話番号・APIキーなどの 機微な情報を検出し、プレースホルダに置き換えてから teai.io へ送るオプトイン機能です。 応答が返ってきたら、こちら側で元の値に復元してから表示します。既定はオフで、有効化しない限り これまでと挙動は変わりません。

3行まとめ
# 有効化(ollama + qwen3.5:4b が必要)
ollama pull qwen3.5:4b
te privacy scrub on

# 使い方はこれまでと同じ
te run "この設計、機密情報込みで壁打ちしたい"

# 無効化
te privacy scrub off

なぜ作ったか

Senteは日常のコーディング相談だけでなく、社内の込み入った話や、実在の氏名・住所が混ざる文脈で 使われることがあります。teai.io はリクエスト本文を保存しませんが、それでも そもそも機微な情報をクラウドへ一切送らずに済むなら、それに越したことはない—— その発想から、送信の手前にもう一段、ローカルだけで完結する壁を作ることにしました。

仕組み

te privacy scrub on にすると、Senteの起動時にこのMac上へ小さなHTTPプロキシ (127.0.0.1のみでlisten)が立ち上がり、OpenCode の設定(baseURL)がそのプロキシへ 向け替わります。teai.io のAPIキーはこれまで通りOpenCode側がヘッダに載せるだけで、 プロキシ自身はキーの中身を知りません。

  1. 正規表現パス — メール・電話番号・郵便番号付き住所・APIキーらしき文字列を即座に検出し、[EMAIL_1] のようなプレースホルダへ置換
  2. ローカルLLMパス — 残りの地の文を Ollama(qwen3.5:4b)に渡し、人名・住所・組織名など機微になりうるスパンを検出だけさせる(書き換えはさせない — LLMにリライトさせると幻覚で内容が変わりうるため、置換は必ずコード側で決定的に行う)
  3. 置換したプレースホルダの対応表はこのMac上のプロキシ内に保持し、teai.io からの応答が返ってきたら元の値に復元してから画面に表示
送信前: 山田太郎さんの電話番号は090-1234-5678、メールはyamada@example.comです → teai.ioに実際に届く内容: [PERSON_1]さんの電話番号は[PHONE_1]、メールは[EMAIL_1]です ← 応答(復元後): 山田太郎さんの件、承知しました。090-1234-5678へ連絡します。

フェイルクローズ — 「送れないなら止める」

この手の機能で一番怖いのは、ローカルLLMが落ちている時に気づかず平文のまま送ってしまう ことです。Senteでは Ollama が起動していない・モデル未取得・プロキシ自体が異常な場合、 その場でエラーを出して停止し、上流には一切送信しません。実際に Ollama を止めた状態で試すと、 次のように止まります(フォールバックで黙って素通しする、ということはしません):

✗ ollama が起動していません。別ターミナルで 'ollama serve' を実行してから再試行してください

開発ログから2つ

日本語の地の文がメールアドレスに巻き込まれた

Pythonの正規表現で \w はデフォルトでUnicode文字クラスも含みます。うっかり [\w.+-]+@[\w-]+ と書いたところ、「メールはyamada@example.comです」の 「メールは」まで丸ごとメールアドレスの一部として飲み込まれました。英数字に明示的に絞って解決しています。

プレースホルダをもう一段プレースホルダ化してしまう

正規表現パスで [PHONE_1] に変換したあとのテキストをローカルLLMに渡すと、 LLMが「これも機微情報っぽい」と [PHONE_1] という文字列自体を拾ってきて [PERSON_2] のように二重にマスクしてしまう入れ子が起きました。 LLMが返したスパンが既にプレースホルダの形をしていたら再マスクしない、というガードを一行足して解決しています。

正直に書いておきます: ローカルLLM(4Bクラス)による検出は完全ではありません。 正規表現でカバーされる明確なパターン(メール・電話・APIキー)は高精度ですが、地の文中の人名・住所の 検出漏れはあり得ます。また、応答の復元には全文が必要なため、ストリーミング表示は失われ、 応答は一括表示になります。Ollamaの推論分でレイテンシも増えます(目安+1〜3秒)。 完璧な保証ではなく、「送る前にもう一段、手元だけで壁を作る」ためのオプトイン機能です。

コマンド早見表

コマンド動作
te privacy scrub on次回起動からPIIスクラビングを有効化
te privacy scrub off無効化(既定)
te privacyスクラブを含む、データの扱い全体を表示
TE_PII_SCRUB=1 te run "..."その場一回だけ有効化

関連記事