投稿する

経営者向けThreads自動投稿

エンジニア向けの技術記事を経営者視点の言葉へ翻訳し、Threadsへ自動投稿する運用支援エージェントです。RSSから収集した情報を独自のナレッジベース(Kojiの声)に基づきスコアリング・要約・生成し、Discord経由で人間に承認を求めます。 特徴は、収集・分析・投稿の3層をSQLiteで分離した堅牢なアーキテクチャと、プロンプトをMarkdownで管理する柔軟な設計です。人間はDiscord上で絵文字を1タップするだけで運用が完結するため、最小限の工数で専門性と一貫性のある情報発信を継続できます。 技術的な深掘りよりも、リアルな経営層に向けた「信頼装置」としての発信を目指す方に最適です。特定ドメインの知見を組み込むことで、あらゆる専門分野の経営者向けメディアへとカスタマイズして活用できます。
zip未取得

09_threads_curator

経営者向け Threads 自動投稿システム。 HOOTL(Human Out of the Loop)24 時間自走 + HITL は Discord 絵文字 1 タップだけ。knowledge/ で「Koji の声」を保つ。

RSS 収集・スコアリング・So What 抽出・ドラフト生成・投稿までを 24 時間自走させ、人間の判断は Discord 絵文字 1 タップに圧縮。フォロワー数を伸ばす装置ではなく、リアルで会った経営者に「ちゃんと活動している」と伝わる信頼装置であり、Koji の頭の中に情報を地図化していく思考補助装置。

---

TL;DR

項目内容
何を作ったか経営者向けに「翻訳」する Threads アカウントの自動運用システム
技術構成3 層分離(collector / analyzer / publisher)+ SQLite 経由通信、すべて短命 cron、常駐プロセスゼロ
人間の介入Discord 絵文字 1 タップ(✅承認 ❌棄却 🔥即出 📝編集)、48h 無反応で自動棄却
実装ステータスPhase 1 完了(Loop 1:投稿ループ)、本番投稿は Task Scheduler で自走中
横展開可能性knowledge/ + agents/ + feeds.yaml を差し替えれば別テーマに丸ごと転用可能(Phase 2 で実証予定)

---

3 評価軸での自己評価

評価軸自己評価主張の根拠
① 稼働性 — 止まらず動き続け、障害から自己復旧する強み3 層分離 + SQLite 経由通信、claim パターンによる二重実行防止、stuck 検知、トークン自動 refresh、48h 自動棄却、Codex レビュー反映による稼働性指摘の修正済み
② 進化性 — 実行するほどデータが溜まり、自動で賢くなる現状は弱い、Phase 2 で集中強化Phase 1 では SQLite はトランザクション用途のみ。棄却理由・反応データの蓄積 → プロンプト自動反映ループは未実装。Phase 2 で rejection_log / engagement_log 追加と週次バッチで knowledge/07_lessons.md への集約を実装予定
③ 事業性 — 解いた課題の大きさ・実世界でのインパクト思想として強い「経営者向け翻訳」というポジションは、エンジニア向け技術メディアにも、純粋な情報メディアにも代替されにくい。機能の提供者ではなく、人生の節目に立ち会う人としてのポジショニングを AI で支える試み。テーマ可換性により別ジャンルへの横展開も可能

以下、3 軸それぞれを詳述。

---

① 稼働性 — 止まらず動き続け、障害から自己復旧する

1.1 設計上の稼働性

3 層分離 + SQLite 経由通信:各層は SQLite (data/threads.db) を介してのみ通信する。直接 import しない。

flowchart LR
    subgraph L1["Layer 1: Collector"]
        a1[RSS 取得] --> a2[pre_filter]
    end
    subgraph L2["Layer 2: Analyzer"]
        b1[scorer] --> b2[distiller] --> b3[drafter]
    end
    subgraph L3["Layer 3: Publisher"]
        c1[discord_notifier] --> c2[discord_listener] --> c3[publisher]
        c4[expirer] & c5[token_refresher]
    end
    DB[(SQLite WAL<br/>busy_timeout=30s)]
    L1 --> DB --> L2 --> DB --> L3 --> DB

    style DB fill:#fff3e0,stroke:#f57c00,stroke-width:2px

この構造による稼働性上のメリット:

  • 1 層が落ちても他は生きる:collector が RSS 取得に失敗しても、analyzer は既存の articles を処理し続ける
  • 状態が DB に永続化:プロセスがいつ死んでも、次の cron が続きから走る
  • 常駐プロセスゼロ:すべて短命 cron。メモリリーク・プロセス死リスクを構造的に排除

1.2 障害自己復旧の具体的実装

シナリオ対策実装
二重投稿claim パターン(BEGIN IMMEDIATE + rowcount 確認)で、同時に複数プロセスが同じドラフトを掴めないようにしたpublisher/publisher.py
二重通知notifying 状態を経由してから pending に戻す。Discord notifier の二重起動でも通知は 1 回publisher/discord_notifier.py
publish 後の通信断(Threads 側が成功したか不明)post_unknown 状態を新設、再試行禁止、人間確認に回す。creation_id を DB 保存してリカバリ可能にpublisher/publisher.py, shared/db.py
判断滞留Koji が 48h 反応しなければ自動 expired、通知が溜まらないpublisher/expirer.py
トークン失効(Threads は 60 日 long-lived)token_refresher を 30 日ごとに走らせて自動延長publisher/token_refresher.py
API レート制限Discord API は 429 を Retry-After 尊重で待機、5xx は警告のみで status 変更しないpublisher/discord_listener.py
誤承認(承認権限の越境)APPROVER_DISCORD_USER_ID 環境変数で押せるユーザーを 1 人に限定publisher/discord_listener.py
@everyone 事故allowed_mentions: {"parse": []} を Discord payload に追加publisher/discord_notifier.py
並行アクセス(複数 cron が同時に DB 触る)SQLite WAL モード + busy_timeout=30000shared/db.py

1.3 「静かに失敗する」原則

通知が鳴っていいのは 「トークン失効」と「投稿 stuck」だけ。それ以外のエラー(RSS が空、ドラフトが 0 件、スコアが全部低い、など)はログに残して静かに終わる。Koji の Discord に通知が来た = 本当に対応すべき何か、という信号価値を保つ。

1.4 稼働性に関する Codex ダブルチェック

実装後、別 AI(Codex)にコードレビューを依頼。重大な稼働性指摘(二重投稿防止の不完全さ、publish 後の通信断対応の欠如、@everyone 事故防止、API エラー処理不足など 8 点)はその場で反映済み。詳細は IMPLEMENTATION_LOG.md を参照。

1.5 現時点の制約

  • 稼働実績:Task Scheduler で 5 本(collect / listen / publish / expire / refresh)が自走中、本番投稿モード(DRY_RUN=False)で運用継続中
  • token_refresher の有効期限ログ:「有効期限タイムスタンプ: 不明」のままで、次回失効時期が明示記録されていない(運用上は 60 日 long-lived の前提で 30 日ごとに走らせている)
  • docs/architecture.md のディレクトリ図が古いまま(1_collector/ などの数字プレフィックス時代の表記)

---

② 進化性 — 実行するほどデータが溜まり、自動で賢くなる

正直に書く:Phase 1 では進化性はほぼ実装されていない。 ここが本システムの現状最大の弱点。

2.1 現状(Phase 1):DB はトランザクション用、学習用ではない

SQLite には 3 テーブル(articles / drafts / post_log)あるが、すべて「いま処理中の状態を持つ」ためのテーブル。以下が記録されていない:

  • 棄却したドラフトの理由(なぜ ❌ を押したか)
  • 投稿後の反応(いいね・コメント・伸び)
  • Koji が手で修正した差分(drafter の生成物と最終投稿の差)

結果として、システムは毎回ゼロから判断している。人間が回数を重ねるほど賢くなるはずの装置が、現状そうなっていない。

2.2 進化性の「種」は仕込んである

ただし、進化に必要な土台は Phase 1 で用意した:

仕組み進化の意味
**agents/*.md と Python コードの分離**プロンプト改修コストがほぼゼロ。shared/agent_loader.py が agents/scorer.md の frontmatter から knowledge/*.md を結合して system prompt を組み立てる。プロンプトを直したいときに .py を一切触らない
knowledge/ フォルダ構造(8 ファイル)「Koji の声」「対象読者」「原則」を分離管理。drafter のプロンプトに自動的に挿入される。ここに気づきを追記すれば即座に出力に反映される
config/feeds.yaml情報源 RSS をコード変更なしで増減可能

つまり「進化の入口」は用意してあるが、「進化を駆動するデータ収集とフィードバックループ」が抜けている、というのが現状。

2.3 Phase 2:学習ループの実装

DB スキーマ追加(2 テーブルのみ、既存テーブルに影響なし):

rejection_log    棄却理由 + 棄却時刻 + draft_id + Koji の自由記述(Discord で 📝 + コメント)
engagement_log   Threads API から取得した投稿後の反応(いいね・コメント・閲覧数)

週 1 のバッチで両テーブルを集計 → knowledge/07_lessons.md に追記 → 次回以降の drafter / scorer プロンプトに自動的に含まれる。

flowchart LR
    A[棄却・反応データ蓄積<br/>rejection_log / engagement_log] --> B[週次バッチ<br/>集計・抽象化]
    B --> C[knowledge/07_lessons.md<br/>追記]
    C --> D[agents/drafter.md<br/>agents/scorer.md<br/>のシステムプロンプトに含まれる]
    D --> E[次回のドラフト生成・スコアリング]
    E -.経験を反映.-> A

    style C fill:#fff3e0,stroke:#f57c00,stroke-width:2px

実装コストは小さい(2 テーブル追加 + 週次バッチ 1 本)。Phase 2 の最優先論点。

2.4 進化の 3 階層

進化性は単一の層ではなく、以下の 3 階層で動かす設計:

階層何が進化するか駆動データ
プロンプト層scorer / distiller / drafter の判断基準knowledge/07_lessons.md(週次バッチ)
ナレッジ層Koji の声・現場知の解像度knowledge/04_domain/ への現場体験追加(Koji が随時)
テーマ層システム全体が扱う対象ドメインknowledge/ + agents/ + feeds.yaml の差し替え

最上位の「テーマ層」の進化が、後述のテーマパッケージ可換性につながる。

2.5 複数ループ並走による進化(Phase 2 以降)

docs/concept.md で設計済み。Phase 1 は Loop 1 のみ:

flowchart TB
    K((Koji の<br/>頭の地図))
    L1["Loop 1: 投稿ループ<br/>『これ、出していい?』"] --> K
    L2["Loop 2: 深掘り提案ループ<br/>『このテーマは調べながら書いた方がよくないか?』"] --> K
    L3["Loop 3: 対比構造提案ループ<br/>『経営の○○と対比すると面白くない?』"] --> K
    L4["Loop 4: 投稿パターン拡張ループ<br/>『今日は問いの形で出してみたら?』"] --> K
    K -.判断.-> L1 & L2 & L3 & L4

    style K fill:#ffeb3b,stroke:#f57c00,stroke-width:3px
    style L1 fill:#e3f2fd

異なる問いを投げてくる複数ループを持つことで、AI 生成の同質化を防ぎつつ Koji の頭の中の地図が複数軸で太る、という仮説。

---

③ 事業性 — 解いた課題の大きさ・実世界でのインパクト

3.1 解こうとしている課題

非エンジニアの経営者は、AI 時代の発信で 2 つの罠にハマる:

  1. 手で書くと続かない:本業が忙しい
  2. AI に丸投げすると差別化が消える:当たり障りない要約・解説は、AI 時代に最も価値が出ない情報になる

この狭間に「経営者向けに翻訳する」という独自ポジションがある:

  • HowTo・ツール紹介ではなく、「経営者として何が見えているか・何ができるのか」を発信する
  • 技術的に正しい解説ではなく、経営の文脈での So What を出す
  • 機能紹介ではなく、それが経営判断にどう効くかを読み解く

このポジションは、エンジニアにも、純粋な情報メディアにも代替されにくい。経営者の文脈を持っている人だけが書けるものを、自動化と人間の判断を組み合わせて出し続ける。これが本プロジェクトの本丸。

3.2 想定ターゲット

「自分と同じような 非エンジニアの経営者」。ただし以下の条件付き:

  • 自分より忙しい
  • プロダクト(Claude / ChatGPT など)はすでに少し触っている
  • 触ってはいるが、本格的な活用にはまだ踏み込めていない
  • 情報を自分で集める時間がない

このターゲットには、HowTo を投げても消費されない。「自分の事業に持ち込む時、何が変わるのか」を判断する材料が欲しい。

3.3 2 つの目的

目的 A:発信の信頼装置

フォロワー数を伸ばすこと自体は目的ではない。

リアルで会った経営者に「こんな投稿もしてるんですよ」と伝えた時に、「ちゃんと活動している人だ」と伝わる状態を作る。質を作ることで、結果的にフォロワーの質も上がり、リアルの信頼関係につながる。

目的 B:思考の地図化

毎日いろんな Web サイトを見に行くのではなく、選別された情報が手元に届く。それを判断する過程で、Koji の頭の中に全体像が地図として整理されていく。

このシステムは「投稿を量産する装置」ではなく、「Koji の頭の中の地図を太らせる装置」でもある。発信は、その地図化プロセスの副産物。

3.4 単なる自動投稿システムとの違い

観点A: 単なる自動投稿B: 本プロジェクト
目的フォロワー数・PV翻訳ポジションの可視化・思考の地図化
視点記事の要約・分析経営者として「何が見えているか」
出力AI 文体(誰が書いても同じ)knowledge/ により Koji の声で出る
介入なし or 手動レビューDiscord 絵文字 1 タップ(HITL 最小)
学習なし棄却・採用ログから AI の判断が育つ(Phase 2)
副産物なし棄却ドラフトが思考の素材庫になる

3.5 横展開可能性:テーマパッケージ可換性

このシステムは「経営者 × Claude Code」という現テーマに密結合させない設計にしている。3 つのフォルダを差し替えれば、テーマ丸ごと別のものに切り替えられる:

フォルダ役割差し替えるとどうなるか
knowledge/発信主体の声・対象読者・原則(8 ファイル)別の発信主体に切り替わる
agents/scorer / distiller / drafter のシステムプロンプト翻訳の切り口が変わる
config/feeds.yaml情報源 RSS取得する情報ジャンルが変わる

候補:「中小医療法人 × AI」「不動産オーナー × データ活用」「サプライチェーン × 生成 AI」など、別ドメインに丸ごと差し替えても、3 層パイプライン自体は同じものが走る。

現状は設計レベルでの分離に留まる。実際に別テーマで品質維持できるかは Phase 2 で実証する必要がある。実証ゴールは「別テーマでも 1 週間 5 投稿、人手大幅修正なしで通せるか」。

仮に「経営者 × Claude Code」という現テーマが当たらなかったとしても、システム自体は別パッケージで生き続けられる。これが事業性として一番伝えたいポイント。

3.6 経営者個人へのインパクト

このシステムが Koji 自身に与える効果(事業性の隠れた本丸):

  • AI で「機能の提供者」ではなく「人生の節目に立ち会う人」へのポジショニングを支える
  • 中小企業・医療法人・オーナー経営者が AI で価値を上げる入口と設計を担うときに、「自分も実践している」という具体物を持っている状態を作る
  • 知性・ロジックはコピーされるが、文脈と信頼関係の蓄積はコピーされない

---

設計の全体像(再掲・データフロー)

flowchart TB
    RSS[Zenn RSS<br/>config/feeds.yaml] --> F[collector.fetcher]
    F --> PF[collector.pre_filter<br/>重複・鮮度・NG除外]
    PF --> DB1[(articles<br/>status=fetched)]
    DB1 --> S[analyzer.scorer<br/>agents/scorer.md<br/>閾値 8.0]
    S --> DB2[(articles<br/>status=scored)]
    DB2 --> D[analyzer.distiller<br/>agents/distiller.md<br/>So What 抽出]
    D --> DB3[(articles<br/>status=distilled)]
    DB3 --> DR[analyzer.drafter<br/>agents/drafter.md<br/>500字本文]
    DR --> DB4[(drafts<br/>status=pending<br/>expires=+48h)]
    DB4 --> N[publisher.discord_notifier<br/>4絵文字プリセット]
    N --> Koji{Koji<br/>✅❌🔥📝}
    Koji --> L[publisher.discord_listener]
    L --> DB5[(drafts<br/>status=approved/<br/>force_post/rejected)]
    DB5 --> P[publisher.publisher<br/>Threads 2ステップ投稿]
    P --> Threads[Threads]
    P --> DB6[(post_log)]

    EX[publisher.expirer<br/>48h 経過 → expired] -.-> DB4
    TR[publisher.token_refresher<br/>30日ごと] -.-> Threads

    style Koji fill:#ffeb3b,stroke:#f57c00,stroke-width:3px

---

ディレクトリ構造

09_threads_curator/
├── collector/          Layer 1: 情報収集(外→DB)
│   ├── fetcher.py
│   └── pre_filter.py
├── analyzer/           Layer 2: 分析・ドラフト生成(DB→DB)
│   ├── scorer.py
│   ├── distiller.py
│   └── drafter.py
├── publisher/          Layer 3: HITL & 投稿(DB→Discord/Threads)
│   ├── discord_notifier.py
│   ├── discord_listener.py
│   ├── publisher.py
│   ├── expirer.py
│   └── token_refresher.py
├── shared/             共通基盤
│   ├── db.py           SQLite 初期化・状態遷移
│   ├── llm_client.py   Anthropic SDK ラッパ
│   └── agent_loader.py agents/*.md + knowledge/ を system prompt に結合
├── agents/             各機能のシステムプロンプト(MD 分離)
├── knowledge/          AI に渡す「Koji の声」8 ファイル
├── config/feeds.yaml
├── scripts/            run_*.bat(Windows Task Scheduler 用 5 本)
├── data/               SQLite 置き場(gitignore)
├── docs/
│   ├── concept.md      何を作るか・なぜか
│   ├── architecture.md どう作るか(Mermaid 5 枚)
│   └── status_machine.md articles/drafts の全状態遷移表
├── CLAUDE.md
└── IMPLEMENTATION_LOG.md  進捗・引き継ぎ

注:当初設計の 1_collector/ 2_analyzer/ 3_publisher/ はディレクトリ名から数字プレフィックスを外した(Python の python -m がモジュール解決できない仕様への対応)。

---

セットアップ

  1. .env.example をコピーして .env を作成し、5 変数を埋める
  • ANTHROPIC_API_KEY
  • DISCORD_BOT_TOKEN / DISCORD_CHANNEL_ID
  • THREADS_ACCESS_TOKEN / THREADS_USER_ID
  1. knowledge/ の 8 ファイルを Koji の情報で埋める(特に 06_principles.md)
  2. pip install -r requirements.txt
  3. python -m shared.db init で DB 初期化
  4. Task Scheduler 5 本登録:scripts\install_tasks.bat

詳細手順と Discord Bot 作成方法は IMPLEMENTATION_LOG.md 朝の手順 を参照。

---

進捗

Phase 1 実装完了(2026-05-09)。コード一式・構文チェック・Codex レビュー反映・DB スキーマ自動マイグレーションまで完了。

項目状態
ディレクトリ構造・knowledge/ テンプレ・docs・.env.example✅
Layer 1(fetcher / pre_filter)✅
Layer 2(scorer / distiller / drafter)✅
Layer 3(discord_notifier / listener / publisher / expirer / token_refresher)✅
shared 基盤(db / llm_client / agent_loader)✅
agents/*.md(scorer / distiller / drafter / critic)✅
Codex レビュー反映(重大 + 中の指摘 8 件)✅
Discord Bot 作成・サーバー招待✅
knowledge/ 中身執筆(04_domain/executive_insights.md 含む 8 ファイル)✅
Task Scheduler 5 本登録✅
end-to-end 本番連続走行(DRY_RUN=False)✅
Phase 1.5: 編集機能(📝 → reply → 再通知 → ✅)✅
Phase 1.5: critic agent + executive_insights によるドラフト品質改善✅
Phase 2: rejection_log / engagement_log未
Phase 2: テーマパッケージ可換性の実証未

詳細は IMPLEMENTATION_LOG.md、設計プランは C:\Users\kouji\.claude\plans\zippy-tumbling-micali.md。

---

設計原則

  1. Streamlit を起動しない(HOOTL 概念維持)
  2. 常駐プロセス禁止、すべて短命 cron
  3. Discord 操作は 4 種のみ(✅承認 ❌棄却 🔥即出 📝編集)
  4. 48h 無反応で自動棄却、判断疲れを防ぐ
  5. 静かに失敗する、通知が鳴っていいのは「トークン失効」と「投稿 stuck」だけ

---

関連ドキュメント

  • docs/concept.md — 何を作っているか・なぜか(経営者向け翻訳という本丸、2 つの目的、複数ループ設計)
  • docs/architecture.md — どう作るか(3 層構造、Mermaid 5 枚で全データフロー可視化)
  • docs/status_machine.md — articles / drafts の全状態遷移表、claim パターン、post_unknown リカバリ手順
  • IMPLEMENTATION_LOG.md — Phase 1 実装ログ、Codex レビュー反映記録、朝の手順
  • CLAUDE.md — Claude Code 用ガイド(コマンド一覧・SQLite スキーマ・ハマりポイント)