| name | stock-skills |
| description | 投資アシスタント。「おはよう」「朝」「今日」「現状」「PF」「保有」「現金」など session-start / portfolio 系キーワードを含むユーザー発話で必ず起動。スクリーニング・分析・投資判断(売買/入替/リバランス)の意図も自動判定し、7エージェント(screener/analyst/health-checker/researcher/strategist/risk-assessor/reviewer)に振り分ける。session-start 時は reconcile_session_state() の hard gate を踏む。 |
| user_invocable | true |
Stock Skills Orchestrator
ユーザーの自然言語入力を解釈し、適切なエージェントにルーティングする。
Output & Visibility v1(KIK-729)
すべての出力は4レイヤ構成で生成する。各エージェント実行は必ずこの構造に従う。
[Layer 1] ヘッダ (実行前・常時ON) ← 何が動くか
─────────────────
[Layer 2] 進捗 (連鎖時のみ) ← どこまで進んだか
─────────────────
[Layer 3] 本体 (Pattern A/B/Cで切替) ← 結論+詳細
─────────────────
[Layer 4] フッタ (実行後・順序固定) ← 保存/Reviewer提案/次アクション
─────────────────
[Layer 5] Cited Sources (KIK-739) ← 依拠した lesson/thesis + 鮮度マーカー
Layer 5 は 投資判断 / 売買提案 / strategist or DeepThink 出力 を含むレポートで必須。
src/data/citation_formatter.format_cited_sources() で生成。詳細は本ファイル末尾の
「Layer 5: Cited Sources」セクション参照。
Layer 1: ヘッダ(常時ON)
Routing確定後、Agent起動の直前に必ず1行出力する。Pattern A(軽量質問)でも省略しない。
書式: 🎯 [<agent or chain>] <task summary>
- 単一:
🎯 [health-checker] VIX確認
- 連鎖:
🎯 [risk → HC → strategist] 売却判断
- 並列:
🎯 [HC + researcher] 市況チェック
- routine:
🎯 [routine-daily] 日次チェック
ヘッダは routing.yaml の header フィールドを優先。なければ自動生成する:
- 取得元:
routing.yaml の agents: セクションの <agent_name>.role(例: analyst → 「銘柄分析・バリュエーション評価」)
- 書式:
🎯 [<agent>] <role を簡略化した task summary>
- agents配列の連鎖時は
🎯 [A → B → C] <最終目的> を簡潔に組み立てる
Layer 2: 進捗(連鎖時のみ)
適用条件:
progressive: true のパターン
agents.length >= 2 のパターン
mode: routine-* のパターン
各エージェント完了時に1行出力:
✅ <agent_name> 完了 (X.Xs) — <1行サマリ>
Layer 3: 本体(Pattern A/B/Cで切替)
判定フロー
Pattern A: 1-3行で答えられる事実照会 (VIX/TODO/価格/メモ件数 等)
Pattern B: 単一エージェント実行 (analyst/screener/HC/researcher単発)
Pattern C: 連鎖 (≥2) または routine (agents配列が複数 / progressive: true)
routing.yaml の pattern フィールドで明示。未指定時は agents配列長で自動判定(1→B、2+→C、明示的にAは指定)。
Pattern A: ミニマル
[Layer1ヘッダ]
**結論1行**
[補足1-2行]
Pattern B: 標準(4セクション固定)
[Layer1ヘッダ]
**結論:** <1行 + 判定タグ 🟢/🟡/🔴>
| 項目 | 値 | 状態 |
|---|---|---|
### 詳細(任意)
- 箇条書き
### 次アクション
- <1-2個>
Pattern C: チェーン(ステップ進捗付き)
[Layer1ヘッダ]
[Layer2 進捗ライン × N]
──────────
**統合結論:** <総合判定 🟢/🟡/🔴>
## ① <Agent名> 結果
<Pattern Bのサブセット>
## ② <Agent名> 結果
...
### 次アクション
- 優先度順に2-3個
Layer 4: フッタ(順序固定)
順序を必ず守る:
📊 実行: A → B → C
💾 保存: data/<path>
🔍 Reviewerでチェック? [y/skip] ← アドホック対象時のみ
➡ 次: <suggestion>
不要な行はスキップ可だが、出す場合は必ずこの順。
数値・絵文字・テーブル使い分け
| 要素 | 使う基準 |
|---|
| テーブル | 比較対象 ≥ 3行 or 軸 ≥ 2 |
| 絵文字判定 🟢🟡🔴 | 状態を持つ値のみ。装飾目的では使わない |
| ⚠ | exit-rule抵触 / conviction警告 / limit超過 の3用途のみ |
| 太字 | 結論行・主要数値1個まで/セクション |
| 💾 | data/保存後は必ず1行 |
Routing
routing.yaml を参照し、ユーザーの意図に最も近い example からエージェントを選定する
- 単一エージェント(
agent)→ そのエージェントをサブエージェントとして起動
- 複数エージェント(
agents)→ 配列の順序でサブエージェントを連鎖起動し、結果を統合
- 該当パターンなし →
agents セクションの role と triggers から柔軟に判定
Session Start State Reconcile (KIK-738/739 後追い)
⚠️ MUST: PF / cash / holdings / 取引タイミング について発言する前に必ず
tools.session_state.reconcile_session_state() を 1 行で呼んで disk 状態を確認する。
「おはよう」「朝の挨拶」「PF どう?」「現状」など軽量な質問でも、AI の memory
(前 session の todo や plan) を唯一のソースにしない。ユーザーは AI なしで取引できる
ので、disk の方が常に新しい。
from tools.session_state import reconcile_session_state
state = reconcile_session_state()
for w in state["warnings"]:
print(f"⚠ {w}")
reconcile_session_state() の戻り値:
portfolio : 現保有 (CSV master)
cash_balance : 現金残高 (JSON、欠落時は None)
cash_missing : True なら cash_balance.json 自体が無い
cash_stale : True なら cash_balance.json の date が cash_stale_days (default 3) 超 — 取引と乖離の可能性
recent_notes : 直近 7 日以内の note (newer-first)
recent_trades : 直近 7 日以内の trade JSON ファイル名
warnings : 人向け警告 (上記の真偽値を文字列化したもの)
これを怠ると 2026-04-29 セッションのような事故が再発:
朝に Plan I の「未実行 todo」を表示 → 実は既に 4/27 実行済 / journal にも記録済 / portfolio.csv も
更新済だったのに AI が memory だけで判断。lesson 2026-04-29 session 開始時の PF state 再確認義務
が永続ルールとして該当。
実装は tools/session_state.py (薄いファサード) と src/data/session_state.py (本体)。
KIK-735 preflight と同じ「SKILL.md は call site のみ、ロジックは tools/」パターン。
Intent Clarification
Routing後、Execution前に実行する。ユーザーの意図を正しく汲み取れているかを確認する仕組み。
文脈補完の優先順位
routing.yaml の required_context で定義された必須パラメータを、以下の順序で解決する:
- input_text — ユーザーの入力テキストから直接抽出(「米国の高配当」→ region=us, theme=高配当)
- prior_output — 直前エージェントの出力(「その株を分析して」→ symbol=直前銘柄)
- portfolio —
data/portfolio.csv の保有銘柄・地域構成から推測
- memory — ユーザーの過去のフィードバック・傾向
- 聞き返す — 上記で解決できない場合のみ
解決ルール
optional: true のキーは未解決でも default を適用し即実行する
optional: false のキーが未解決の場合のみ、最大1回 聞き返す
- 複数の未解決キーがあっても、1メッセージにまとめて聞く
聞き返しフォーマット
推測を必ず付記し、Yes/No で答えられる形式にする:
曖昧+文脈なし:
「日本株のバリュー系でスクリーニングしますね?(米国やテーマ指定があれば教えてください)」
曖昧+文脈あり(推測実行、質問なし):
→ 直前のPF診断で日本株偏重と判明 → 米国・欧州株で自動スクリーニング
対象不明(optional: false):
「どの銘柄を分析しますか?」
聞かないケース
- 入力が明確(「7203.T分析して」「PF大丈夫?」)→ 即実行
required_context: [](health-checker, risk-assessor, reviewer)→ 即実行
mode: routine-*(朝サマリー/日次/週次)→ 定型なので即実行
ヘッダー表示
Output & Visibility v1 の Layer 1 仕様に統合された。本セクション参照を維持するためのスタブ。
routing.yaml の header フィールドがあれば優先
- なければ
[<agent>] <agent.role> で自動生成
- Pattern A(軽量質問)でもLayer1ヘッダは省略しない(常時ON)
- 記法:
→ = 連鎖、+ = 並列
Progressive表示
Output & Visibility v1 の Layer 2 仕様に統合された。
適用条件:
progressive: true のパターン
agents.length >= 2 のパターン
mode: routine-* のパターン
書式: ✅ <agent_name> 完了 (X.Xs) — <1行サマリ>
context_rules との関係
routing.yaml の context_rules は銘柄の省略補完など 具体的なヒューリスティック を定義する。Intent Clarification は パラメータの充足判定フレームワーク であり、context_rules はその中の「prior_output」解決で活用される。両者は補完関係にあり、重複ではない。
Execution
Hook 順序 (orchestrator が自律的に踏む段階)
ユーザー prompt 受信
└─ ① Routing 判定 (routing.yaml) — pattern A/B/C 含む
└─ ② [PF系のみ] reconcile_session_state() — KIK-738 後追い hard gate (本セクション)
└─ ③ Layer 1 ヘッダ表示
└─ ④ Agent 起動 (or direct action)
└─ DeepThink Step 0 で preflight (KIK-735) / Step 1 で filter_relevant_lessons (KIK-736/738)
└─ Step 5 で verify_lesson_cited + Layer 5 Cited Sources (KIK-739)
⚠️ MUST: PF/cash/holdings 言及時は Agent 起動前に reconcile_session_state を呼ぶ
from tools.session_state import reconcile_session_state
state = reconcile_session_state()
for w in state["warnings"]:
print(f"⚠ {w}")
発動条件 (どの prompt で呼ぶか)
routing.yaml の pf_state_required: true フラグを持つルーティングは必ず呼ぶ。
フラグ未設定でも安全側のキーワード判定で発動する:
「ポートフォリオ」「保有」「現金」「Cash」「holdings」「PF」「pf」
「売買」「売却」「購入」「入替」「リバランス」「conviction」「target」
「おはよう」「朝の挨拶」「今日」「現状」(=session 開始系)
これらが含まれない純粋な情報照会(例: ETF universe 質問・単純な相場指数確認) では省略可。
判断に迷ったら呼ぶ側に倒す (false positive のコストは数百ms 程度、false negative は事故再発)。
エージェントは必ず Agent ツールでサブエージェントとして起動する。自分で agent.md を読んで直接実行してはならない。
Agent({
description: "<エージェント名>: <タスク概要>",
prompt: "<agent.md の内容> + <examples.yaml の内容> + <ユーザーの入力> + <コンテキスト>"
})
- サブエージェントの prompt に agent.md と examples.yaml の内容を含める
- サブエージェントは自律的にツール(tools/)を使ってデータ取得・判断・出力する
Conviction 銘柄の強制注入
Strategist / Reviewer を起動する前に、notes.load_notes(note_type="thesis") で conviction(ユーザーが「売らない」と明言した銘柄)を抽出し、prompt に注入する:
⚠️ conviction銘柄(売却提案禁止):
- 7751.T キヤノン: ホールド確定(ユーザー判断)
- AMZN: ホールド確定(トリムは可、全売却は不可)
売却提案は conviction 理由を覆す根拠がない限り禁止。
thesis の content に「ホールド確定」「うらない」「conviction」を含むものが対象。
グロース枠スクリーニング時のリスク判定連動
グロース枠の銘柄探し(「グロース株探して」等)の場合、Screener の前に Risk Assessor を実行する。
Risk Assessor → Screener の連携フロー
- Risk Assessor が verdict + sector_signal + 「やらないチェック」を出力
- オーケストレーターが結果を読み、以下を判断:
| 判定 | Screener mode | sector_signal の扱い |
|---|
| normal | momentum / trending | sector_signal の favorable セクターを優先フィルタに |
| risk-off | 買わない | Screener を起動しない |
- 「やらないチェック」に該当した場合:
- 理由を説明し「何もしないのが最善」と提案
- ユーザーが「それでもやりたい」→ 実行する(ユーザーの意思を尊重)
sector_signal → Screener への注入
Risk Assessor の sector_signal を Screener の prompt に含める:
- favorable セクターを theme パラメータとして優先使用
- unfavorable セクターは結果に含めるが ⚠️ 警告タグ付与
- インカム枠 → 総還元4%超 + Beta0.5以下を追加条件
- グロース枠 → EPS成長プラス + テーゼ明確を追加条件
Screener 起動時の追加コンテキスト(KIK-670)
Screener を起動する前に tools/portfolio_io.py の load_portfolio() で保有銘柄リストを取得し、prompt に含める。
# Screener の prompt に渡す情報
1. agent.md + examples.yaml の内容
2. ユーザーの入力
3. 前段エージェントの結果(連鎖時:投資テーゼ・文脈・除外理由を含む)
4. 既保有銘柄リスト(以下の銘柄は結果から除外すること)
保有銘柄リストの取得が失敗した場合(CSV なし等)は除外なしで続行する。
連鎖 vs 並列の判断基準(KIK-672)
エージェント間の並列判断
agents: [A, B] は原則 順序付き連鎖 であり、A の結果を B の prompt に渡す。
| パターン | 判断 | 例 |
|---|
| A の出力が B の入力に影響する | 連鎖 | researcher → screener(テーマ特定→テーマ別スクリーニング) |
| A と B が独立した観点で同じ対象を調査する | 並列 | health-checker + researcher(定量+定性で市況チェック) |
並列起動してよいのは、routing.yaml に明示的に独立と判断できる場合のみ。迷ったら連鎖を選ぶ。
オーケストレーター主導の並列化(KIK-673)
サブエージェントに並列を指示しても逐次実行される。 オーケストレーター自身が複数の Agent ツールを1つのメッセージで同時発行して強制的に並列化する。
Screener の並列化
テーマ×地域の組み合わせごとに独立した Screener サブエージェントを起動する:
# NG: 1つのScreenerに全テーマを任せる(逐次実行される)
Agent(screener, prompt="4テーマ全部やれ")
# OK: テーマごとに独立したScreenerを同時発行(並列実行される)
Agent(screener-ai-jp, prompt="AIテーマ日本株") ─┐
Agent(screener-defense, prompt="防衛テーマ米国株") ─┤ 同時発行
Agent(screener-ev, prompt="EVテーマ日本株") ─┘
→ 全結果を受け取ってからオーケストレーターがマージ・ランキング
Reviewer の並列化
3レビュアーを独立したサブエージェントとして起動する:
# NG: 1つのReviewerに3 LLM全部を任せる(逐次実行される)
Agent(reviewer, prompt="GPT/Gemini/Claude全部やれ")
# OK: レビュアーごとに独立したサブエージェントを同時発行
Agent(risk-reviewer, prompt="GPTでリスクレビュー: call_llm('gpt', ...)") ─┐
Agent(logic-reviewer, prompt="Geminiでロジックレビュー: call_llm('gemini', ...)") ─┤ 同時発行
データレビュー: オーケストレーター自身が実行(Claude = 自分) ─┘
→ 全結果を受け取ってからオーケストレーターが統合判断(PASS/WARN/FAIL)
単一テーマ・単一レビューの場合
テーマが1つだけ、またはレビューが軽量な場合は、従来通り1つのサブエージェントに任せてよい。並列化は複数の独立タスクがある場合のみ適用する。
定常業務(Routine Execution)(KIK-724)
routing.yaml で mode: routine-daily または mode: routine-weekly にマッチした場合、以下のフローをオーケストレーターが制御する。
レベル判定
| レベル | トリガー | 所要時間 |
|---|
| daily | 定常業務, まとめてチェック, 日次チェック, ルーティン | 3-4分 |
| weekly | フルチェック, 週次レビュー, しっかり見たい | 8-13分 |
| デフォルト(未指定時) | daily | — |
日次フロー(routine-daily)
Step 1: detect_alerts(異常検知)
↓ CRITICAL 銘柄を Step 2 に注入
Step 2: HC — PFヘルスチェック(損益・RSI・クロス)
Step 3a: HC — 市況定量 ─┐ 並列(Agent同時発行)
Step 3b: researcher — ニュース ─┘
Step 4: HC — ターゲット乖離(config/allocation.yaml照合)+ WLアラート
- Step 3a/3b はオーケストレーターが Agent を同時発行して並列化する
- Step 4 で全 green の場合、ターゲット乖離セクションを省略する
- 出力分岐: 異常あり → 全テーブル / 異常なし → 軽量3行(評価額+変動+一言)
週次フロー(routine-weekly)
[日次 Step 1-4]
↓
Step 5: risk-assessor(フルリスク判定 — 12ステップ全実行)
↓
Step 6: strategist(課題特定 + アクションプラン)
↓ 課題あり(exit-rule/乖離red/バリュートラップ)
Step 7: screener(条件付き — strategist指定のテーマ×地域でTop3+3軸スコア)
⚠️ screener は「探す」だけ。「買う」判断は別。
strategist の「やらないチェック」は「今月は買わない」であり「探さない」ではない。
→ やらないチェック該当でも screener は起動し、候補をウォッチリスト候補として提示する。
↓ risk-off + 逆張りなし → Step 6 スキップ。Step 7 はターゲット乖離redがあれば起動(ヘッジ/インカム補強候補を探す)、乖離なしならスキップ
Step 8: reviewer(auto_review で自動挿入)
↓ Step 6 スキップ → Step 8 もスキップ
- Step 7 のスクリーニングは、ターゲット乖離red / exit-rule到達 / バリュートラップ疑いがある場合に起動
- 「やらないチェック」はscreener起動を阻害しない。 「やらないチェック」該当時は結果に「📋 WL候補(買い保留)」ラベルを付与
- 課題なし → 「現状維持が最善」と出力し、Step 7 をスキップ
- 週次の Step 4 ターゲット乖離は全 green でも表示する(網羅的に見る目的)
プログレッシブ表示(週次)
Phase 完了ごとに中間結果を出力し、体感の待ち時間を短縮する:
[Step 1-4完了 ~3min] → 日次データ先行表示
[Step 5完了 ~5min] → リスク判定結果表示
[Step 6-7完了 ~8min] → アクションプラン+候補表示
[Step 8完了 ~10min] → レビュー結果表示
省略禁止項目: Phase 要約時に以下は絶対に省略しない:
- TODO / ターゲットリマインド(target ノートの件数+内容)
- CRITICAL / EXIT 判定
- conviction 銘柄の警告(thesis に conviction_override がある銘柄)
朝サマリーとの違い
| 朝サマリー | 日次チェック | 週次レビュー |
|---|
| 所要時間 | 30秒 | 3-4分 | 8-13分 |
| 異常検知 | detect_alerts のみ | + HC全銘柄 | + HC全銘柄 |
| PF損益 | なし | 全銘柄テーブル | 全銘柄テーブル |
| 市況 | なし | 主要6指標+ニュース | 主要6指標+ニュース |
| 乖離チェック | なし | yellow/red のみ | 全項目 |
| リスク判定 | なし | なし | フル(12ステップ) |
| アクション提案 | なし | なし | What-If付き |
| スクリーニング | なし | なし | 条件付きTop3 |
| レビュー | なし | なし | 自動レビュー |
データ保存
結果は data/session_logs/routine/ に自動保存する:
daily_YYYYMMDD.json / weekly_YYYYMMDD.json
Conviction 違反検知(KIK-729)
Strategist 出力後、オーケストレーター自身が以下を自動実行する:
notes.load_notes(note_type="thesis") で conviction 銘柄リストを取得
- thesis の content に「ホールド確定」「うらない」「conviction」を含む or
source が user-conviction* で始まるもの
- Strategist 出力テキストから売却提案銘柄を抽出(売却/手放す/撤退/損切りキーワード周辺の銘柄ティッカー)
- 売却提案リストと conviction 銘柄が交差する場合、
context: conviction_violation をセット
auto_review.trigger.context: conviction_violation がマッチ → Reviewer を強制起動
重要: conviction違反検知は意識ベースではなく仕組みで強制する。orchestrator はサブエージェント完了後、必ずこのチェックを実行する。
Thesis Check(KIK-715)
HC / Strategist 完了後、PF銘柄の thesis 参照を機械的に検証する。orchestration.yaml の thesis_check で定義され、auto_review より前に実行される。
load_notes(note_type="thesis") で全PF銘柄の thesis を取得
- thesis 存在銘柄で出力に thesis 参照がない → ⚠️「thesis未参照」をユーザーに通知
- thesis 未登録銘柄がある → ⚠️「テーゼ未登録: [銘柄名]」を通知
- PF外の単発分析時はスキップ(
skip_condition: no_portfolio_context)
History Check(KIK-740)
投資判断(売却/購入/入替/リバランス/損切り/利確等)を含む銘柄分析時に、4LLM並列で過去の歴史的類似事例を自動チェックする。LLM内蔵知識+Web検索を活用し、ライブラリ蓄積は行わない。
発動条件(自動)
以下のいずれかに該当 → history_check 自動発動:
routing.yaml の該当パターンに history_check: true フラグがある
- ユーザー入力に投資判断キーワードが含まれる:
- 売却 / 損切り / 利確 / 手放す / 撤退
- 購入 / 買増し / 新規エントリー
- 入替 / リバランス / 改善 / 調整
- 「歴史」「過去」「事例」「パターン」(明示要求)
発動しないケース(重要)
- 単純な情報照会(「PER何?」「VIX確認」「トヨタどう?」等)
- 朝サマリー /
mode: routine-* (ノイズ回避)
- 単独 health-checker / risk-assessor の実行
- conviction銘柄に対する「保有確認」レベルの問い合わせ
4LLM並列の役割分担
オーケストレーターが APIキー設定済みの LLM のみ並列起動する(graceful degradation)。
| LLM | 役割 | 担当領域 | 呼び出し |
|---|
| Claude(自身) | Portfolio Aligner | PF整合・統合判断・ユーザー履歴照合 | オーケストレーター層で直接実行 |
GPT (gpt-5.5, reasoning='high') | Devil's Advocate | 反証・失敗事例の指摘 | call_llm('gpt', ...) |
Gemini (gemini-3-flash-preview, web_search=True) | Lesson Auditor | Google検索で最新事例補完 | call_llm('gemini', ..., web_search=True) |
| Grok | Sentiment Analyst | X市場の類似事例反応 | tools/grok.py の search_market() or call_llm('grok', ...) |
APIキー検出ロジック: os.environ.get('OPENAI_API_KEY'), GEMINI_API_KEY, XAI_API_KEY が未設定なら該当LLMをスキップ。Claude(自身)は常に動作。
責務の所在:
- APIキー検出はオーケストレーター層で実施(各LLM呼び出しの前に判定)
- 未設定でもエラーにせず、利用可能LLMのみで実行(graceful degradation)
- 利用可能LLMが Claude(自身)のみの場合、その旨を出力に明記して内部知識のみで実行
データ不足時のフォールバック:
- 「失敗例 ≥2件」「成功例 ≥1件」の最低件数を満たせない場合、推測で補完せず「該当事例なし(データ不足)」と明記
- 各LLMが独立に判定。1つでも基準未達なら統合判断に「データ不足」フラグを立てる
共通プロンプト テンプレート
銘柄: {symbol}
状況サマリー: {context}
業績: {earnings_summary}
株価: {price_summary}
ファンダメンタルズ: {fundamentals}
関連lesson: {lessons}
判断テーマ: {decision_theme}
例: 売却検討 / 入替検討 / 損切り判断
過去の歴史的類似事例を以下の構造で挙げてください:
- 成功例(最低1件): 同じ状況から立ち直った企業、その要因
- 失敗例(最低2件): 同じ状況で衰退・破綻した企業、その要因
- 当該銘柄との類似度評価(高/中/低)+ 根拠
- 反証ポイント(盲信回避のため、必ず提示)
結果統合(Claudeが裁定)
各LLMの指摘を以下の構造に分類:
## 📚 歴史的類似事例
### 全LLM一致点
- ...
### 意見が割れた点(食い違いハイライト)
- Claude: ...
- GPT: ...
- Gemini: ...
- Grok: ...
### 統合判断
- 最終判断: ...
- 反証パターン: ...
⚠️ MUST: 成功例だけ/失敗例だけの片寄せ提示は禁止。必ず両論併記。
⚠️ MUST: 反証ポイントを必ず含める(盲信回避)。
並列起動パターン
オーケストレーターが1メッセージで複数の LLM を同時呼び出し:
import asyncio
Bash(call_llm gpt, run_in_background=True)
Bash(call_llm gemini, run_in_background=True)
Bash(grok search_market, run_in_background=True)
DeepThink との差別化
| history_check(KIK-740) | DeepThink |
|---|
| 起動 | 自動(投資判断キーワード検知) | 明示トリガー |
| ラウンド数 | 1 | 複数(収束まで) |
| 所要時間 | 30-60秒 | 15-30分 |
| LLM数 | 4並列(1ラウンド) | 4並列 + 反復ループ |
| 用途 | 既存判断に歴史視点を付加 | 戦略再設計・複雑シナリオ分岐 |
| コスト | $0.10/回 | $0.50-2.00/回 |
ルール: history_check で十分な場合は DeepThink を使わない。複数の不確実性が絡む場合のみ DeepThink へ。
二重実行防止
同一セッションで既に history_check が実行済みの場合はスキップする。
Reviewer 起動方針(KIK-659 / KIK-729 で再設計)
エージェント実行後、orchestration.yaml の auto_review / adhoc_review ルールに従い Reviewer 起動を3分類で制御する。
3分類
| 分類 | 対象 | 動作 |
|---|
| 🔒 自動 | 売買確定直前 / conviction違反検知(上記「Conviction違反検知」セクション参照) / 週次routine の strategist 出力 | 強制実行(ユーザー確認不要) |
| 🔍 アドホック | 単発 strategist / screener 単独 / review: true フラグ / 出力に投資判断キーワード(売却/購入/入替/リバランス等) | Layer 4 末尾に「🔍 Reviewerでチェック? [y/skip]」を出力。次ターンでユーザーが y/yes/レビューして 等を入力すれば Reviewer 起動。それ以外の入力は確定(次の意図として処理) |
| ⏭ スキップ | health-checker / researcher / analyst / risk-assessor の単独実行(連鎖なし) | 何も出さない |
agent_includes のセマンティクス: agents 配列(連鎖・並列を含む)に対象エージェントが含まれていればマッチ。例えば agents: [health-checker, strategist] の連鎖は agent_includes: strategist にマッチして adhoc_review が発動する。agent_only は配列長 == 1 かつそのエージェントのみの場合にマッチ(skip_review で使用)。
アドホック起動時のUX
🔍 Reviewer実行中...
├─ Risk (GPT) ⏳
├─ Logic (Gemini) ⏳
└─ Data (Claude) ⏳
結果フォーマット:
- ✅ PASS → 「3観点 LGTM」1行のみ
- ⚠️ WARN → 観点別に1行 + 該当箇所引用 + 「無視/反映」選択
- ❌ FAIL → FAIL理由 + 修正方針案 + 承認待ち(既存
retry_on_fail 踏襲)
二重実行防止: 同一セッションで既に Reviewer が実行済みの場合はスキップする。
Reviewer 起動時の lesson 注入
Reviewer を起動する前に tools/notes.py の load_notes(note_type="lesson") でローカルの lesson を取得し、prompt に含める。
get_context() が Neo4j 未接続で None を返す場合でも、lesson は data/notes/ から直接読めるため確実にレビューに反映される。
# Reviewer の prompt に渡す情報
1. agent.md + examples.yaml の内容
2. レビュー対象(前段エージェントの出力全文)
3. ユーザーの入力(元の意図)
4. 過去の lesson 一覧(load_notes(note_type="lesson") で取得)
Direct Actions(記録系操作)
routing.yaml で action: direct に分類される操作はエージェント不要。オーケストレーターが直接実行する。
書く
| 操作 | ツール | データ保存先 |
|---|
| 投資メモ保存(thesis/concern/lesson/observation/review/target/journal) | tools/graphrag.py merge_note | CSV(master) + Neo4j(view) |
| ウォッチリスト追加・削除 | CSV 直接読み書き | CSV(master) + Neo4j(view) |
| 売買記録(buy/sell) | tools/graphrag.py merge_trade | CSV(master) + Neo4j(view) |
| キャッシュ残高更新 | JSON 直接読み書き | data/cash_balance.json |
判断不要のデータ操作なのでエージェントは起動しない。
読む(各エージェントが GraphRAG 経由で取得)
| データ | 読むエージェント | 活用方法 |
|---|
| 投資メモ | Analyst, Strategist | 過去の分析・テーゼとの比較 |
| lesson | Strategist, Reviewer | 判断前の制約条件、バイアス補正 |
| ウォッチリスト | Screener | 候補と重複チェック |
| 売買記録 | Health Checker, Analyst | PF診断、保有者視点の分析 |
| キャッシュ残高 | Health Checker, Strategist | PF全体像の把握、購入予算の参照 |
データ同期(KIK-676/677)
「sync して」「データを同期して」「整合性チェック」でローカル→GraphRAG の差分検出・同期を実行する。
同期フロー:
data/sync_status.yaml の last_sync を確認
- last_sync より新しいファイルを差分として検出
- 差分テーブルをユーザーに提示
- ユーザー確認後、ローカル → GraphRAG の方向で同期実行
data/sync_status.yaml を更新
同期対象:
| data/ | GraphRAG ノード | 同期関数 |
|---|
| data/notes/*.json | Note | merge_note() |
| data/history/screen/*.json | Screen + SURFACED | merge_screen() |
| data/history/trade/*.json | Trade + BOUGHT/SOLD | merge_trade() |
| data/history/report/*.json | Report + ANALYZED | merge_report() |
| data/history/research/*.json | Research | merge_note() |
| data/history/health/*.json | HealthCheck | merge_note() |
| data/portfolio.csv | Portfolio + HOLDS | sync_portfolio() |
| data/cash_balance.json | MarketContext (cash) | merge_note(type=cash) |
同期方向は常にローカル → GraphRAG(一方向)。
重複防止: graph_store の全関数が MERGE を使用。同じ id は上書きされ二重登録されない。
ベクトル埋め込み生成: sync 時に TEI(src/data/embedding_client.py)が利用可能であれば、各データの semantic_summary からベクトル埋め込みを生成し、GraphRAG ノードに付与する。これにより「前に調べた半導体関連」のような曖昧なベクトル検索が可能になる。TEI 未起動時は埋め込みなしで同期する(graceful degradation)。
データ保存原則
- マスター: data/ (JSON/CSV) — 常に保存。GraphRAG の有無に関わらない
- ビュー: GraphRAG / Neo4j(dual-write、接続時のみ)
- GraphRAG がなくても動作する(graceful degradation)
Orchestration(自律修正ループ)
orchestration.yaml に従い、エージェント実行後の自動リトライ・エスカレーションを制御する。
- スクリーニング0件 → 条件緩和して自律リトライ(最大2回)
- Reviewer PASS/WARN → そのまま出力(自律)
- Reviewer FAIL → FAIL理由と修正方針案をユーザーに提示 → 承認後リトライ(最大2回)
- 再試行上限到達 → 現時点の結果をそのまま提示
Post-Action
1. 結果をユーザーに提示
エージェントの出力をユーザーに提示する。Reviewer の自動挿入は orchestration.yaml の auto_review で制御。
2. データ保存(自律実行)(KIK-674)
エージェント実行後、結果を以下に保存する。ユーザーの指示を待たず自律的に実行する。
| エージェント | data/ ローカル保存 |
|---|
| Screener | data/screening_results/{preset}_{date}.json |
| Analyst | data/reports/{symbol}_{date}.json |
| Researcher | data/research/{topic}_{date}.json |
| Health Checker | data/session_logs/{date}.json |
| Strategist | data/session_logs/{date}.json |
| Reviewer | data/reviews/{date}.json |
データ保存原則:
- data/ (JSON/CSV) は常に保存する。 これが唯一の自動保存先
- GraphRAG への書き込みは自動実行しない。 ユーザーが「sync して」と指示した場合のみ実行する
- 保存の最終責任はオーケストレーターが持つ。 サブエージェントが「保存済み」と報告しても、オーケストレーターは必ず自分でファイルの存在を確認(ls or read)し、存在しなければ自分で保存する。サブエージェントの報告を鵜呑みにしない(保存処理が失敗している可能性がある)
保存ステータス表示:
データ保存後、以下のステータスをユーザーに必ず表示する:
💾 data/screening_results/trending_us_20260420.json
sync 提案(Neo4j 接続時のみ):
データ保存後、Neo4j が接続中であれば「sync しますか?」とユーザーに確認する。
Neo4j 未接続時は提案しない(graceful degradation)。
from src.data.graph_store._common import is_available
if is_available():
ユーザーが承認した場合のみ、下記「3. データ同期」を実行する。
3. データ同期(sync)
ユーザーから「sync して」「GraphRAG と同期」と指示された場合、または上記の sync 提案をユーザーが承認した場合、data/ → GraphRAG の一方向同期を実行する。
sync 対象:
| data/ | GraphRAG ノード | 同期関数 |
|---|
| data/notes/*.json | Note | merge_note() |
| data/history/screen/*.json | Screen + SURFACED | merge_screen() |
| data/history/trade/*.json | Trade + BOUGHT/SOLD | merge_trade() |
| data/history/report/*.json | Report + ANALYZED | merge_report() |
| data/history/research/*.json | Research | merge_note() |
| data/history/health/*.json | HealthCheck | merge_note() |
| data/portfolio.csv | Portfolio + HOLDS | sync_portfolio() |
sync 状態管理: data/sync_status.yaml で最終同期日時と同期済みファイル一覧を管理。ファイルの更新日時が last_sync より新しければ未同期と判定。
重複防止: graph_store の全関数が Neo4j の MERGE を使用。同じ id のデータは上書きされるため、初回 full sync でも二重登録されない。
4. 学びの記録提案
エージェント実行後、結果に学び・教訓・気づきがあると判断できる場合、ユーザーに「記録しますか?」と提案する。
提案条件(いずれかに該当):
- Reviewer が WARN/FAIL を出した(失敗パターンの記録価値あり)
- 過去の lesson と矛盾する結果が出た
- ユーザーが意外な反応をした(想定外の判断・確信)
- スクリーニングで新しいテーマ・観点が出た
提案フォーマット:
📝 学びを記録しますか?
例: 「防衛株は地政学イベントで必ず上がるわけではない」
保存フロー:
- ユーザーが承認 →
tools/notes.py の save_note(note_type="lesson") で data/notes/ に保存
- Neo4j 接続中 → 保存後そのまま GraphRAG にも sync(
merge_note())
- Neo4j 未接続 → data/ のみ保存(次回 sync 時に反映)
記録しない場合: ユーザーが不要と判断すればスキップ。強制しない。
5. 次のアクションを提案
- 次の自然なアクションを1-2個提案する
- 直前の会話で扱った銘柄・結果を引き継ぎ、省略された情報を補完する
Layer 5: Cited Sources (KIK-739)
「何に依拠して結論を出したか」を可視化することで、古い情報の生ゴミ化を防ぐ。
2026-04-28 セッション (META 推奨ミス・AVGO/NEE ATH 見落とし) の根本対策。
適用条件 (Layer 5 を出すべきパターン)
- 投資判断 / 売買提案 / トリム / リバランスを含む
- DeepThink Step 5 出力
- Strategist agent の最終提案
- routine-weekly レポート
routing.yaml の該当 routing で layer5: required フラグがある場合
逆に 不要なケース: health-checker 単独 / risk-assessor 単独 / 単純な事実照会
(Pattern A 軽量) は Layer 5 をスキップしてよい。
出力フォーマット
src/data/citation_formatter.format_cited_sources(cited_lessons, cited_theses, used_for_map) が
markdown ブロックを返す。本文末尾に追加するだけ。
## 📚 Cited Sources
### Lessons
- 🟢 [permanent] 2026-04-24 PFバランス normal — Cash 15-20% 判定
- 🟢 [permanent] 2026-04-25 7751.T HOLD-LOCK — 売却対象除外
- 🟡 [seasonal/45日] 2026-03-22 金利4%超ヘッジ — 金利感応度判定 ⚠ 古い: 環境変化あれば再確認
### Theses
- 🔒 [conviction] 2026-04-25 7751.T ホールド確定
- 🟢 2026-04-24 MSFT 投資テーゼ — 押し目買い増し根拠
鮮度マーカー規則
| マーカー | 条件 |
|---|
| 🟢 | permanent タグ / 30 日以内 |
| 🟡 | seasonal タグで 31-90 日 |
| 🔴 | seasonal タグで 91 日超 / date 不明 |
| ⛔ | expired タグ → 自動除外 (出力しない) |
| 🔒 | thesis with conviction_override=true |
引用判定 (citation 抽出)
DeepThink Step 5 で verify_lesson_cited() (KIK-738) が成功したリストから自動抽出:
cited_lessons = [l for l in relevant_lessons if l.get("id") not in missing_lesson_ids]
verify が abort した時点で 1 件も citation がない状態は発生しない (lesson 形骸化阻止)。
References