カテゴリー
Web開発者向け
Web開発者向けに関する記事を公開しています。
Jev に偶数判定・正解の無い 3択・日本語の建前・危険なコマンドを判定させた実験集
確率だけを返す Jev は応答が速くコストも極めて低いため、if 文の代わりに使えないか、偶数判定・正解の無い 3択・日本語の建前・危険なコマンド・プロンプトインジェクションで実測しました。崩れたのは計算と正解の無い選択だけでした。
Jev が LLM の代わりに使えた処理と任せられなかった処理
TypeSafe AI の Jev は文章を生成せず、宣言した選択肢への確率だけを返す。自分の記事と問い合わせ文 8件で日本語の判定を実測すると、原因の分類や窓口の振り分けは英語とほぼ同じ確率で当たり、好みの判定は Jev も Sonnet も当てられなかった。
AI エージェントの PR で GitHub Actions の無料枠が尽きた
GitHub Actions は Free で月2,000分。支払い方法が無ければ使い切った時点で停止します。PR が増えた月は残り83分まで減り、止まればデプロイもバックアップも止まる計算でした。PR を減らすのは本末転倒なので月4ドルで課金し、CI のジョブを束ねて分数を減らしました。
EmDash の Cron は Free プランだと5本まで
EmDash は全サイトに Cron Trigger がある前提で作られています。9サイトに足すと6サイトでデプロイが落ちました。Workers Free の Cron はアカウント全体で5本までなので、置くサイトを2つに絞り1日1回にしました。
D1 にトランザクションが無い中で EmDash が整合性を保つ仕組み
Cloudflare D1 にはトランザクションが無く、EmDash はそれをソースに書いています。本番のリビジョンを数えて仕組みを追うと、守っているのはコンテンツの行が1つだけで、残りは多めに作って後で捨てる設計でした。
EmDash が真っ白になるのは Free プランの CPU 上限
Cloudflare Workers の Free プランで動く EmDash のトップが真っ白になりました。原因は CPU 時間 10ms の上限を日常的に超えていたことで、件数を絞る修正は実測で前提が崩れました。
障害検知のトリアージから対応まで AI エージェントに任せる設計手法例
監視アラートの一次判定から修正の PR まで AI エージェントに任せ、判定に使う道具を読み取り専用に絞った設計。13週間で起票14件、人の本番操作0件。
戻せない D1 マイグレーションは本番のダンプで先に流す
EmDash は merge した瞬間に本番の D1 スキーマを自動で書き換える。down が空で戻せない 2本を含む 20本のアップグレードを、本番のダンプに先に流して検証してから通した設計を記す。
サンドボックスに鍵を置かずに EmDash の CLI を使う
CMS への記事投入を内蔵 MCP 経由で行うと本文がモデルの入出力を通り、トークン消費も文字化けの危険も増えます。サンドボックスの環境変数にプレースホルダーを置き、ホストのプロキシが差し替える経路に切り替えた設計を実例で示します。
X 公式 MCP が Docker サンドボックスで認可できない
X 公式 MCP を Docker サンドボックスから直接使おうとすると認可サーバーの制約と噛み合わない。接続して分かったツールの中身と読み取りの単価を示し、認証をホスト側のブリッジに置く設計を記す。
AI エージェントに X の鍵を渡さず投稿させる権限設計
X 公式 MCP に投稿ツールが無い前提で、鍵を neta-bot だけに残したまま AI エージェントに X へ投稿させる権限設計を実例で示します。承認は会話に一本化し、投稿口は 1 つに閉じて台帳に必ず載せます。
AI エージェントの記憶を git だけに置き環境は捨てる「秘書戦略」
サンドボックスは作り直すと中身がすべて消えます。事業の判断・手順・議事録を責務ごとに git の文書へ分けて置き、規約の書き換えだけを PR 必須にする、消える環境を前提にした記憶の設計を実例で示します。
GitHub Actions の OIDC で AWS の鍵を手元から無くした
Claude Code の Docker Sandbox に AWS の認証情報を渡すスクリプトを 3 本書きましたが、docker sandbox exec が別のコンテナに書き込んでいて一度も機能していませんでした。渡すこと自体をやめ、Terraform の bootstrap 層(Actions が引き受ける IAM ロールと OIDC)まで GitHub Actions の workflow_dispatch で plan / apply する構成にしました。ロールが自分自身を書き換える権限の線引きと、信頼ポリシーのリポジトリ名の既定値が古いままで自分を締め出しかけた話も残します。
changesets を AI エージェントに書かせると変更履歴が読める物になる
8 サイトのモノレポの変更をほぼ AI エージェントの PR で回していると、git log では「あのサイトはいつ何が変わったか」を追えなくなりました。changesets を入れ、PR を作るその瞬間にエージェントへ変更記録を書かせ、Release PR の merge でサイトごとの CHANGELOG に集約する形にしました。誤った記録を次の記録が訂正して並ぶ実例と、別リポジトリで踏んだ罠(タグの系統が 2 つになる、changeset status は commit 済みしか数えない、Release PR の merge がデプロイになる)を書きます。
.github リポジトリの PR テンプレートに「ハマったこと」欄を置く理由
AI エージェントに gh pr create --body で PR を作らせると、リポジトリの PR テンプレートは使われません。適用されるはずだと思い込んでいて、しばらく気づきませんでした。組織の .github 公開リポジトリにテンプレートを 1 つ置いて全リポジトリの既定にし、エージェントには「テンプレートを先に読んで本文を組む」手順を渡しました。テンプレート末尾の「ハマったこと・試行錯誤」欄は、commit には残らない物語を作業直後に残す場所で、別の bot が毎朝拾って素材にします。拾う側の本文上限が 300 文字で、一番下にあるこの欄ごと落ちていた失敗も書きます。
自動投稿 bot の設計を「ネタ→投稿」から「背景→投稿」に変えた
LLM で X に自動投稿する bot にテキスト投稿を足そうとして、「ネタの粒度」で機能を分ける設計を始め、書く前に破綻しました。bot を通す理由は「投稿を書くこと」ではなく「そのままでは投稿にならない背景を変換すること」で、境界線を「変換が要るか」の 1 本にしました。毎朝 GitHub の活動と PR 本文の「ハマったこと」欄を集めて Slack に提示する push 型に反転させ、返信がどのネタに届くか分からなくなった混線を 1 ネタ 1 スレッドで、状態機械の使い回しで生まれた競合を条件付き更新で塞いだ記録です。
Slack bot が 3 秒で切られるので Lambda を受付と処理に分けた
Bolt for JavaScript と Lambda の Function URL で Slack bot を動かすと、レスポンスは全リスナーの完了後にしか返らず、Slack の 3 秒制限を毎回超えていました。当初は http_timeout の再送を無視する分岐で凌いでいましたが、初回の処理が失敗するとイベントが静かに消える構造でした。Lambda を「受付」と「処理」に分け、重い処理は自分自身を非同期 invoke して委譲する形に直しました。lazy リスナーは Bolt for Python にしか無い、という前提の取り違えから始まった記録です。
X API への自動投稿が二重になる経路を入口と出口で塞ぐ
Slack から X に 4 コマを自動投稿する bot に、同じ投稿が 2 回出る経路が 2 つありました。入口は Slack の再送(3 秒で切られ最大 3 回届く)とボタンの連打で、イベント ID の条件付き書き込みと status 遷移のロックで塞ぎました。出口は X API の応答が返らないまま再試行することで、失敗を「確実に失敗・結果不明・重複」に分け、結果不明は自動で再試行しないようにしました。実際に二重投稿は起きておらず、コードを読み直して先に塞いだ記録です。
Cloudflare D1 の無料枠を守るためだけに作らなかった 4 つの仕組み
D1 の読み取りを 1 日 2,110 万行(無料枠の 422%)から 190 万行前後まで下げる過程で、「次はこれを作ればさらに減る」という案が 4 つ出ました。公開時にキャッシュ済みの 404 を消すミドルウェア、404 ページを D1 を読まない静的ページにする案、リダイレクト表を Bulk Redirects へ同期する仕組み、スキャナをエッジで落とす WAF ルール。どれも半日で作れて効果も数字で見えていましたが、4 つとも作りませんでした。守る対象が今は圧迫されていないこと、持ち続ける費用が作る費用より高いこと、圧迫されたときの第一手は課金の方が確実なこと。判断の材料と、再訪の条件をまとめます。
Bot Fight Mode を無料プランで使うと GitHub Actions が 403 になる
Cloudflare の Bot Fight Mode を有効にしていた 2 サイトだけ、GitHub Actions からの死活チェックが 403 になりました。切って再実行すると全サイト 200。無料プランの Bot Fight Mode は Ruleset Engine の外で動くため WAF カスタムルールの Skip / Allow が効かず、例外を作るには Pro の Super Bot Fight Mode が要ります。監視・CLI・Webhook 受信・確認の curl など自分の非ブラウザ通信が全部判定の対象になる一方、守りたい Workers の起動枠(34%)も D1(30%)も圧迫されていなかったので、8 月に再検討して入れないと決めた経緯と、再訪の条件をまとめます。