LLMに返信を書かせるとき、毎回「自然に返してください」と頼むだけでは、会話の続きにならないことがあります。前にこちらが何を聞いたかが入力になければ、相手の「はい」が何に対する返事なのか分からないからです。
GitMeshiというOSS情報アカウントの運用では、公開された原文をMarkdownのノートに保存し、返信対象と結び付ける仕組みを整備しています。この記事では、Xの会話とQiita・Zennのコメント運用で実装した、観測した原文・生成した下書き・投稿結果を混ぜない設計を紹介します。
対象は、LLMを使った返信支援やエージェントを実装していて、履歴の持たせ方に悩んでいる方です。フォロワー増加などの効果測定ではなく、記録と再実行の設計の話です。
1. 原文に「誰の、どの発言か」を付ける
文章だけを保存すると、後から出所を確認できません。少なくとも、チャネル、運用アカウント、著者、原文の識別子、観測時刻を一緒に持ちます。
次は説明用に簡略化した架空のレコードです。実際のSNS APIのレスポンスではありません。
{
"channel": "x",
"account": "example_bot",
"post_id": "example-post-002",
"author": "example_user",
"parent_id": "example-post-001",
"text": "はい。今回はローカル環境だけで試しています。",
"observed_at": "2026-09-13T10:00:00+09:00",
"source": "verified_public_post"
}
Xでは投稿IDと親投稿の関係で会話をたどります。一方、Qiita・Zennでは記事URLを起点に、記事本文と公開コメントを確認しています。チャネルによって取得できる関係が違うので、同じデータ構造がそのまま使えるとは考えません。
著者の確認も本文中の名前だけでは不十分です。たとえばZennのPublication記事では、URLの先頭部分が著者のユーザー名とは限りません。実装では著者欄のプロフィールリンクを確認しています。
2. 自分の過去の返信には、用途を付ける
公開済みの自分の発言を一切読ませないと、会話のつながりを失います。しかし、それを技術的な事実の根拠として使うと、過去に書いた誤りを次の返信でも繰り返しかねません。
そこで、次のように用途を分けました。
| 記録 | 使う目的 |
|---|---|
| 相手の原文、対象の記事 | 質問と説明内容を確認する |
| 公開済みの自分の発言 | 何を聞いたか、何に答えてもらったかを理解する |
| 未公開の下書き、生成した要約 | 原文の代わりにしない |
| ツールの機能や使用方法の根拠 | 対象の原文や公式資料で別に確かめる |
「前に自分がそう書いた」は、技術仕様の裏付けにはしません。公開済みの自分の文を読む場合も、現在の会話を理解するために範囲を絞ります。
3. Markdownの保管先と、投稿台帳を分ける
原文はObsidianで参照するボルトに、新しいノートとして追加しています。記事の内容が変わったときも、既存ノートを上書きせず、新しい観測として残します。
説明用の配置例です。
vault/
conversations/
channel/
account/
source-key/
capture-001.md
capture-002.md
delivery/
attempt-001.json
ノートには原文、出所、観測時刻、本文のハッシュを持たせます。ハッシュは取得した内容の差分確認に使うもので、文章が真実であることを証明するものではありません。
投稿台帳には「どの記事に、どのアカウントから、何を送ろうとしたか」と処理状態を保存します。原文の保管と投稿の進行状況を分けると、生成に成功しただけで投稿済みにしてしまう事故を防ぎやすくなります。
4. 「失敗」と「結果が分からない」を分ける
現在のコメント投稿経路では、概ね次の状態を区別しています。
| 状態 | 意味 | 次の扱い |
|---|---|---|
| preparing | 下書き・検証を処理中 | 別の実行から重ねて処理しない |
| held | 投稿前に保留 | 理由を確認する |
| reserved | 検証済みで投稿処理を予約 | 同じ対象への重複実行を防ぐ |
| unknown | 送信した可能性はあるが結果を確認できない | 公開画面と照合するまで再送しない |
| verified | 著者・本文・公開コメントIDを確認済み | 同じ記事には再投稿しない |
特に大事なのは、送信後のタイムアウトを単純な失敗として扱わないことです。サイト側では投稿が完了している可能性があります。実際にQiitaでは、投稿後にコメント欄の読み込みが必要なため確認を逃したケースがあり、再送せず公開コメントを照合して記録を直しました。
台帳だけでなく、送信直前にも対象記事の公開コメントを確認します。アカウント・記事単位の重複判定と、本文の変化の確認は別の役目です。
5. 作成者と検証者には、同じ原文を渡す
コメントの作成と検証は別プロセスにしています。検証側には作成者の「この返信でよい理由」を渡すのではなく、対象の原文と下書きを渡し、保存した原文も再確認させます。
ただし、別プロセスにすれば誤りがなくなるわけではありません。投稿先のアカウント、原文との一致、長さ、既存コメントの有無、投稿後の公開確認は、文章の評価とは別にコードで検証しています。
まだ残っている制約
現在の観測には件数と文字数の上限があり、全履歴を読めるわけではありません。Xの親投稿が欠けている場合や、著者と本文を確認できない場合は保留します。ブラウザ上のUI変更による確認失敗も起こります。
これは「一度作れば放置できる完全自動化」の完成報告ではありません。どの原文を読み、何を試し、どこまで確認できたかを後からたどれるようにするための実装メモです。
記憶を増やす前に、原文の出所と、投稿が終わった証拠を別々に残す。ここを決めておくと、文脈がずれたときにも、同じコメントを再送しそうになったときにも調査を始めやすくなります。
執筆・日本語の推敲にAIを使用しています。記載した実装上の挙動は、運用コードと実測記録に照らして確認しています。