
ブログ記事の公開をRSSで検知し、AIが要約してXへ自動投稿するn8nワークフローを、記事1本につきLLMを最大6回呼ぶ28ノード構成から「上位モデル1回+機械検証+保留」の10ノード構成に作り直しました。合格した投稿文だけを投稿待ちにし、少しでも怪しいものは自動で直さず理由つきで保留し、人が見る。この記事では、そこへ倒した経緯と、作り直した検証の中身、運用で分かったことをまとめます。
背景: 品質対策を積み上げたら、フローが長大化した
当社が運営するAIニュースブログでは、記事を公開するとRSS経由でn8nが検知し、Claudeが本文から要約と案内文を生成して、X(旧Twitter)に自動投稿しています(投稿URLへのUTM付与の設計は別の記事に書きました)。投稿文は「要約2〜3文+ハッシュタグ+案内文+URL」の形式で、Xの重み付き文字数280字以内かどうかをCodeノードで機械的に検証してから投稿キューに積みます。
運用を始めると、品質の問題が次々に出ました。要約が指定の字数を超えてハッシュタグが落ちる。記事中の操作手順の「→」をそのまま引き写す。体言止めになる。生成のグリッチで異常な文字列が混ざる。そのたびに対策を足していきました。
- 字数超過時に、Claudeへ1回だけ圧縮を再依頼する(超過が続けば再圧縮をもう1回)
- 別会社のAI(GPT)で投稿前チェックを行い、NGなら書き直し、再チェックしてダメなら保留する「校閲ゲート」
- 禁止記号の自動置換、長すぎるときの段階的な退避(タグ→案内文→タイトル形式)
どれも個別には効きました。要約モデルをClaude Opus 5に上げ、字数を80字厳守にしたところ、圧縮も退避も発生ゼロになったのは象徴的です。ただ、その結果できあがったのは、生成→圧縮→再圧縮→校閲→書き直し→再校閲と、記事1本で最大6回LLMを呼ぶ28ノードのフローでした。分岐が多いほどテストの組み合わせが増え、n8nの編集画面で保存するとLLMノードの設定が剥がれる事象に毎回対処する必要もあり、「安全のための仕組み」が運用の負担になっていました。
方針: 自動で直さない。合格だけ通し、残りは理由つきで保留
作り直しの方針は3つです。
- LLMは上位モデル1回だけ。Opusが一発で字数を守れることは実測済みなので、圧縮や書き直しのループは持たない
- 検証は厳格な機械判定に寄せる。曖昧な判定をAIに二重化させるのではなく、Codeノードで落とすべき条件を列挙する
- 不合格は自動で直さず「保留(held)」にして人が見る。自動書き直し・自動短縮・タイトル形式への退避・記号の自動置換はすべて廃止
投稿キューの台帳にはstatusとnoteの列があり、合格はpending、それ以外はheldに理由を書いて積みます。投稿を担う別ワークフローはpendingしか拾わないので、heldは投稿されません。保留の確認と解除はn8nのData Tables画面で行います。
実装: 28→10ノード
削除したのは19ノードです。GPT校閲まわりが7(投稿前チェック/判定/分岐/書き直し/再構築/再チェック/最終判定)、圧縮まわりが6(超過判定/圧縮/整形/再超過判定/再圧縮/整形)、中間処理が3、テスト用が3。残った本線は次のとおりです。
RSS検知 → 設定 → 要約生成(Claude Opus 5・1回) → 投稿文検証・確定(Code) → キューへ登録
├ 合格: status=pending
└ 不合格: status=held + note(理由)
「投稿文検証・確定」のCodeノードは全面的に書き直し、次の条件に1つでも当たればheldにします。
- モデルがSKIPを返した(記事の内容に矛盾がある、要約に自信がない等)
- 生成失敗(空応答・API例外)、出力の形式不正
- 要約が90字超(後日、91字で1件止まったため検証上限だけ95字に緩和。プロンプトの指示は90字のまま)
- 案内文の不備、要約へのURL・「#」・「→」の混入、常体の疑い、ハッシュタグの不正
- 投稿文全体が重み付き280字超
プロンプト側には「90字厳守」「出力は機械検証される」「後段にAIのチェックは無く、ここが最後の砦」「自信がなければSKIP」を明記しました。後段のゲートを外す以上、生成側に責任を持たせる書き方です。
再生成とテストの経路は本番フローから切り離し、別ワークフローから本番の入口を呼ぶ形にしました。本番フローにテスト用ノードが同居していると、テストのたびに本番を触ることになるためです。
検証: 異常系6パターンを費用ゼロで再現する
作り直したフローは、投稿側をdryRunにしたうえで、次の6パターンを通しました。
通常記事 → pending 1件
同じURLを再実行 → 重複なし(登録されない)
SKIP応答 → held
生成失敗(空) → held
要約111字 → held
重み付き306字 → held
すべて期待どおりでした。続けて実際のClaude Opus 5で実記事2本を流し、2本とも検証に合格(223字・198字/280)。投稿済み記事だったため重複ガードで登録されないところまで確認しています。
ここで効いたのが、n8nのテスト実行でLLMノードの出力をピン留め(pinData)する方法です。SKIPや空応答、長文といった異常系を、APIを呼ばずに再現できます。一方で台帳への書き込みは実書き込みなので、「投稿側のdryRun化+架空URL+テスト行の即削除」を1セットにして回しました。
ハマりポイント
- n8nのワークフロー更新で、LLMノードのresource/operationが剥がれる: 接続を1本足す更新で、LLMノード5つ全部の設定が消えたことがあります。公開前の版は無事でしたが、更新後は必ずvalidationWarningsを確認し、剥がれていたら復元してから公開する手順を定例化しました。編集画面の保存でも同じことが起きます。
- On Errorの設定はMCP(外部API)からは触れない: フォールバック経路を成立させるにはn8n画面での操作が要ります。しかも「Continue (using error output)」を選ぶと、エラー出力先を接続していない限りその記事は消えます。設定と接続はセットです。
- 推論型モデルは思考でmaxTokensを使い切る: 旧構成でGPTやSonnetを使ったとき、maxTokensが小さいと内部推論で上限に達し、本文が空になりました。推論型を使うなら、トークン上限を大きめに取り、応答の抽出も思考ブロックが先頭に来る前提で書く必要があります。
- 事実照合の「第2の目」を外した代償: GPT校閲は捏造や数字の改変まで記事本文と照合していました。機械検証では数字・固有名詞の誤りは拾えません。運用初期は実投稿を目で見る、と割り切っています。
- 実行結果の取得は対象ノードを絞る: 絞らずに取ると、HTTPレスポンス全文が返って巨大になります。一度やらかしました。
まとめ
自動投稿の品質は、「AIで直す仕組みを増やす」より「落とす条件を機械で明確にし、落ちたものは人が見る」ほうが、結果として安全で軽くなりました。生成は上位モデルに1回だけ任せ、検証はコードに、判断は人に。保留に理由が残るので、どこを直せばよいかも後から追えます。
こうした業務自動化の仕組みづくりは、AI自動化代行で構築から運用まで承ります。ご相談はお問い合わせフォームからどうぞ。
← TECH-BLOG一覧へ