AI記事生成を実運用へつなぐ:Project G Coreで構築した安全なWordPress自動投稿基盤

AIに記事を書かせても、ブログに投稿するのは手作業では効率は同じ。

生成AIに「記事を書いて」と依頼すれば、数千文字の原稿は数分で作れる。ところが、その原稿を実際のメディア運営へ組み込もうとすると、急に問題が増える。タイトルを整え、本文を確認し、WordPressへログインし、カテゴリやタグを設定し、下書き保存する。記事数が数本なら耐えられても、数十本、数百本へ増えた瞬間、人間の手作業が全体のボトルネックになる。

「Project G Core」名付けの親はAI。あらゆる自動投稿をまじめに実証しているプロジェクト。

この「AIは書けるが、運用が続かない」という壁を越えるために構築した自動投稿基盤である。目的は、AIにWordPressを直接操作させることではない。生成、保存、投稿、失敗処理、監査を別々の責務として分離し、安全に接続することだ。

この記事では、PowerShell、SQLite、Pandoc、Rust言語、WordPress REST API、VPS(仮想サーバー)を使って、AI生成記事を下書き投稿まで運ぶ仕組みを解説する。華やかなAI機能よりも、実運用で重要になるキュー制御、排他処理、エラー記録、再実行性に焦点を当てる。

AIで記事を書けることと、自動投稿できることは別問題

生成AIの導入で最初に起こる誤解は、「文章を生成できれば自動化は完成する」というものだ。

実際には、記事生成の後ろに多くの工程がある。

テーマを決める
↓
AIへ指示する
↓
本文を生成する
↓
投稿対象として登録する
↓
HTMLへ変換する
↓
WordPressへ送信する
↓
成功または失敗を記録する

AIは上流の「考える、書く」という工程を得意とする。一方、投稿先への認証、二重投稿の防止、通信失敗時の再試行、処理履歴の保存は、決定的なルールで動くプログラムの方が適している。

そこでProject G Coreでは、AIの推論処理とWordPressへの配送処理を切り離した。AIがどれほど高性能になっても、投稿処理を直接支配させない。生成結果はいったん管理層へ渡し、投稿可能な状態になったものだけをVPS上のワーカーが処理する。

この分離により、AIモデルを変更しても投稿基盤は壊れない。ChatGPT、Claude、Gemini、ローカルLLMのどれを使っても、最終的に一定形式の記事データを出せば、同じ経路でWordPressへ送れる。

システム全体を4つの責務に分離する

Project G Coreの構成は、次の4層に分けて考えると理解しやすい。

1. 生成・編集環境

人間とAIが記事を作る場所である。現在はチャット型AIやローカルの編集環境を利用するが、将来的にはAI APIから構造化された記事パッケージを受け取る。

ここで重要なのは、特定のAIサービスへ依存しないことだ。生成AIは進化が速く、料金、品質、コンテキスト長、得意分野が変化する。生成部分を交換可能にしておけば、記事の種類ごとに最適なモデルを選べる。

たとえば、長大な資料の整理はGemini、構成と最終編集はOpenAI、既存プロンプト資産の活用はClaudeという役割分担も可能になる。

2. SQLite投稿キュー

生成された記事を、投稿待ちとして管理する層である。

単にMarkdownファイルが置かれただけでは投稿しない。SQLiteのpost_queueテーブルに登録され、statusreadyになった記事だけを処理対象とする。

hold        保留
ready       投稿可能
processing  処理中
posted      投稿成功
failed      再試行上限に到達

この状態管理が、安全装置として機能する。

AIが大量の記事を生成しても、すべてを即座に投稿する必要はない。人間が確認したものだけをreadyへ変更できる。投稿順はpriorityで制御でき、失敗回数はretry_countへ記録できる。

SQLiteを採用した理由は、構成が小さく、単一VPSで扱いやすく、バックアップも容易だからだ。大規模分散システムには別の選択肢が必要だが、個人または小規模メディアの自動投稿基盤としては十分に実用的である。

3. VPS常駐ワーカー

VPS上のPowerShellスクリプトが、投稿キューを定期的に確認する。

readyの記事を1件取得
↓
processingへ変更
↓
Markdownを読み込む
↓
PandocでHTMLへ変換
↓
WordPress REST APIへ送信
↓
postedまたはfailedへ更新

ワーカー自身は、記事の良し悪しを判断しない。AIのような推論も持たない。決められた規則に従って配送と状態更新を行う。

この「考えないワーカー」は、運用上の強みになる。生成AIの出力が揺れても、投稿処理は一定である。障害が起きた場合も、どの段階で失敗したかを追跡しやすい。

4. WordPress

WordPressは、完成した記事を受け取る公開基盤である。

外部プログラムからの記事作成にはREST APIを利用する。認証にはWordPressのアプリケーションパスワードを使い、通常のログインパスワードとは分離する。

投稿状態は原則としてdraft、つまり下書きにする。

自動投稿は行うが、自動公開は行わない。この違いは重要だ。誤字、事実関係、画像、内部リンク、カテゴリなどを人間が最終確認できる余地を残すことで、速度と安全性を両立できる。

Markdown(ドキュメント形式のこと)を中間形式にする理由

AIに最初から複雑なHTMLを書かせる方法もある。しかし、WordPressテーマやブロックエディタとの相性、不要なインラインスタイル、タグの閉じ忘れ、独自クラスの混入など、運用上の問題が増えやすい。

Project G Coreでは、記事本文の中間形式としてMarkdownを使う。

Markdownは、人間が読んでも理解しやすく、AIも安定して生成できる。見出し、箇条書き、引用、コードブロック、表などを簡潔に表現できる。さらに、WordPress以外の媒体へ展開する場合も再利用しやすい。

MarkdownからHTMLへの変換にはPandocを利用する。

正規表現で独自変換を書くこともできるが、見出し、リスト、コード、表、リンクが増えるほど処理が複雑になる。Pandocを挟むことで、変換ロジックを自作する範囲を減らし、比較的一貫したHTMLを生成できる。

もちろんPandocを導入すればすべてが無条件に解決するわけではない。WordPressテーマに合わせた微調整や、画像、キャプション、独自ブロックの扱いは別途設計が必要だ。それでも、Markdownから標準的なHTMLへ変換する基盤としては有力な選択肢になる。

二重投稿を防ぐ排他処理

自動投稿で怖い障害の一つが、同じ記事の二重投稿である。

たとえば、定期実行中のワーカーがまだ処理している間に次の実行が始まると、両方が同じready記事を取得する可能性がある。通信が遅い場合や、cronの実行間隔が短い場合に起こりやすい。

Project G Coreでは、複数の防御を組み合わせる。

まず、スクリプト起動時にロックファイルを排他的に開き、同じワーカーの同時実行を防ぐ。さらに、記事を取得した直後に状態をprocessingへ変更し、他の処理対象から外す。

UPDATE post_queue
SET status = 'processing',
    updated_at = CURRENT_TIMESTAMP
WHERE id = :id
  AND status = 'ready';

更新件数が1件なら占有成功、0件なら別プロセスが先に取得したと判断できる。

また、処理中にVPSが停止した場合に備え、一定時間以上processingのまま残った記事をreadyへ戻す復旧処理も用意する。排他制御だけでなく、異常終了後に再開できることまで含めて設計する必要がある。

失敗を隠さず、再実行可能にする

外部APIを利用する処理では、失敗は必ず起こる。

WordPress側の一時的なエラー、ネットワーク切断、認証情報の変更、Markdownファイルの欠落、Pandoc未導入、カテゴリIDの誤りなど、原因は多岐にわたる。

Project G Coreでは、失敗した記事を消さない。

エラー内容をlast_errorへ保存し、retry_countを増やす。再試行上限に達していなければreadyへ戻し、後から再実行できるようにする。上限へ達した場合はfailedへ移し、人間による確認対象とする。

1回目失敗 → readyへ戻す
2回目失敗 → readyへ戻す
3回目失敗 → failedへ移す

さらに、テキストログだけでなくpost_logsテーブルへ実行履歴を記録する。成功日時、WordPressの投稿ID、URL、エラー内容が残れば、管理画面や分析機能へ発展させやすい。

自動化では、エラーをゼロにすることより、エラーが発生しても原因を追跡でき、途中から再開できることの方が重要である。

実装時に発生した問題から分かったこと

今回の構築では、設計書だけでは見えない複数の問題が発生した。

最初は、旧SQLiteデータベースに新しい列が存在せず、インデックス作成で停止した。CREATE TABLE IF NOT EXISTSは、既存テーブルへ新しい列を追加しない。新旧スキーマが混在する環境では、バックアップとマイグレーション処理が必要になる。

次に、VPSへPandocが導入されておらず、Markdown変換前に停止した。必要な外部コマンドを実行開始時に確認する処理が役立った。

さらに、PowerShellで空配列を受け取った際、戻り値が$nullとして扱われ、.Countの参照で失敗した。カテゴリやタグが未指定でも必ず配列として扱うよう、@(...)でラップする修正を行った。

これらは、コードを書いただけでは発見できなかった問題だ。

実装
↓
VPSへ配置
↓
実行
↓
エラー確認
↓
最小範囲を修正
↓
再実行

この反復によって、最終的にVPSからWordPressへの下書き投稿が成功した。

自動化基盤は、一度に完璧な設計を作るより、小さな経路を実機で完走させ、問題が起きた部分だけを修正する方が確実に前進する。

AI生成部分は投稿基盤から交換可能にする

現在の投稿基盤は、記事データが準備されていることを前提としている。次の段階では、AI APIから記事パッケージを生成し、そのまま投稿キューへ登録する。

{
  "title": "記事タイトル",
  "slug": "article-slug",
  "excerpt": "概要",
  "markdown": "本文",
  "categories": [],
  "tags": [],
  "comic_script": [],
  "social_posts": [],
  "quality_check": {}
}

この形式を共通化すれば、生成元は自由に選べる。

Claudeで実績のあるプロンプトを利用してもよい。Geminiに長い技術資料を整理させてもよい。OpenAIに構成、本文、漫画脚本、SNS文を統合させてもよい。

重要なのは、AIごとの回答形式をそのままWordPressへ送らないことだ。共通の記事パッケージへ正規化し、検証してから投稿処理へ渡す。

これにより、AIサービスの変更が投稿エンジンへ波及しない。生成モデルと配信基盤の間に、明確なインターフェースができる。

次に必要なのはPrompt Engineと分析基盤

WordPressへの下書き投稿が成功したことで、Project G Coreの最小経路は動いた。

次に必要なのは、短い指示から記事パッケージを生成するPrompt Engineである。

「WordPress自動投稿を初心者向けに解説」
↓
記事設計を作成
↓
AI APIで本文を生成
↓
品質チェック
↓
画面へ表示
↓
WordPressへ下書き投稿

人間がMarkdownを手動保存する工程は、ここで不要になる。生成内容は画面へ表示しつつ、システムが自動的に履歴保存と投稿キュー登録を行う。

その次に、GA4、Search Console、SNS反応、商品クリックなどの分析データを接続する。

記事を大量に投稿するだけでは、成果は分からない。どの記事が検索流入を生み、どのテーマが読まれ、どの導線が商品やサービスにつながったかを測定する必要がある。

最終的には、生成、投稿、計測、改善を一つの循環にする。

記事を生成する
↓
WordPressへ下書き投稿する
↓
公開後の反応を計測する
↓
伸びたテーマを特定する
↓
関連記事、漫画、SNS投稿を生成する

ここまで到達して初めて、自動投稿は単なる作業削減ではなく、メディア運営を改善する仕組みになる。

まとめ

Project G Coreで重視したのは、AIにすべてを任せることではない。

AIには、調査、構成、執筆、要約、漫画脚本など、推論が必要な仕事を担当させる。SQLiteとPowerShellには、状態管理、排他処理、再試行、ログ記録、API送信など、決定的なルールで動く仕事を担当させる。

この役割分担により、次の性質を持つ自動投稿基盤ができる。

  • 使用するAIモデルを交換できる
  • 記事生成とWordPress投稿を分離できる
  • 二重投稿を防止できる
  • エラー内容と再試行回数を保存できる
  • 自動投稿しても自動公開はしない
  • 実行履歴を分析基盤へ発展させられる

生成AIを実運用へつなぐとき、最も重要なのは派手なプロンプトだけではない。生成結果を安全に受け取り、失敗しても再開でき、後から検証できるインフラである。

Project G Coreは、そのための最小構成から始まった。

VPSからWordPressへ一件の下書きが届いた時点で、この仕組みは単なる構想ではなくなった。次は、短い指示から記事を生成し、内容を表示し、下書き投稿までを一度に実行するPrompt Engineへ進む。

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です