Nota について
Notaは、RYOの市場情報と独立した照合に基づき、再現可能な取引判断を作る読み取り専用の暗号資産リサーチシステムです。エージェント評議会、リスク計算、監査可能な記録、結果追跡を備え、RESTまたはMCPでRYOに接続します。
主な機能
- 01RYOの市場情報を集め独立照合
- 02エージェントの意見と引用を比較
- 03ATRと口座リスクから練習取引の規模を算出
- 04保存済みの証拠から判断を再現
- 05OKXのローソク足で見解を追跡・精算
- 06OpenTimestampsで記録をアンカー
活用シーン
- 01監査可能な練習取引の判断を確認
- 02過去の判断を再現して記録を照合
- 03後続価格でRYOの取引計画を追跡
- 04定期的な市場確認と通知を実行
MCP 対応
NotaはRESTの代わりにMCP JSON-RPCでRYOへ接続できます。RYO_TRANSPORT=mcpを設定すると、MCPクライアントが初期化を行い、JSONとSSEのレスポンスを処理します。
設定
リモートサーバーはインストール不要です。クライアントを選んで設定をコピーするか、ワンクリックで導入できます。
https://nota-ryo.vercel.app/mcpclaude mcp add --transport http pugarhuda-nota https://nota-ryo.vercel.app/mcp{"mcpServers":{"pugarhuda-nota":{"type":"http","url":"https://nota-ryo.vercel.app/mcp"}}}Cursor で開く{"servers":{"pugarhuda-nota":{"type":"http","url":"https://nota-ryo.vercel.app/mcp"}}}VS Code で開く{"mcpServers":{"pugarhuda-nota":{"type":"http","url":"https://nota-ryo.vercel.app/mcp"}}}{"mcpServers":{"pugarhuda-nota":{"serverUrl":"https://nota-ryo.vercel.app/mcp"}}}コマンドはターミナルで実行し、JSON は各クライアントの MCP 設定に貼り付けて再起動します。認可が必要なサーバーは初回接続時にログインを求めます。
ツール
9| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| hours | integer | いいえ | 遡る時間(時間単位、デフォルトは 24) |
| tokens | array | いいえ | 追跡するシンボル。デフォルトでは、見つかった既知の主要トークンの cashtag、ticker、または名前すべて |
| voices | array | はい | 最大 20 件の ID。例:tg:WatcherGuru、bs:handle.bsky.social、x:handle |
詳細
Nota
監査可能な AI 取引意見です。専門分野ごとのエージェントで構成される評議会が、RYO 市場の最新の証拠について議論し、実行する練習取引を再生可能な判断レシートとして記録します。
nota replay <id>を実行すると、保存された証拠から判断を再構築し、identical: trueと表示します。引用された数値はすべて、モデルが再入力するのではなく証拠から読み取られます。また、ポジションサイズを決める前に、独立した情報源が RYO 自体の価格と指標を監査します。RYO-CHAN Hackathon 2026 向けに開発されました。
参加トラック:1 自律エージェント(評議会、レシート、watchループ、評議会が議論で覆せないデリバティブのゲート)、2 ダッシュボード(差分優先のレシートダッシュボード、および
RYO Verdict Scorecard)、3 新しいスキル
(narrative_convergence、news_verify、price_crosscheck、technicals_crosscheck、
positioning_check、move_base_rate、verdict_track_record、liquidity_check、crowd_odds。すべて RYO のエンベロープ内)。
審査員の方へ。 https://nota-ryo.vercel.app/judges には、各トラックについて、何を開けばよいか、どの評価基準に答えるかが1画面ずつ表示されます。ダッシュボードでは、最新の RYO 証拠を使って評議会をリアルタイムで実行できます。Nota が行わないことについてはLIMITATIONS.mdを、こうした設計にした理由についてはDECISIONS.mdをご覧ください。
レシートとリプレイ機能だけを備えたエージェントにはない、Nota の機能:
- RYO 自体を監査します。 Verdict Scorecardは、結果が判明する前に、毎日25種類の主要銘柄について RYO 自身の
deep_analysisによる判定と取引計画を記録し、OKX のローソク足データを使って各計画の結果を確定します。RYO が自分自身を採点することはなく、すべての失敗が集計されます。 - RYO のデータの欠陥を発見し、ゲートで遮断します。 一部のデリバティブ関連フィールドでは、同じ日の無関係なトークンに同じ値が割り当てられます。コードでそれらの値を評議会に渡さないようにし、該当するトークンを明示します。
- 記録が書き換えられていないことを証明します。 すべてのレシートとロックは OpenTimestamps を通じて Bitcoin にアンカーされ、CI がプッシュするすべての台帳スナップショットは Sigstore によって証明されます。
- 意図的に壊して検証できます。 /drillでは、実際のパイプラインに7種類の実際に起こり得る障害をオフラインで注入し、正常な実行結果と並べて、それぞれの拒否を表示します。
RYO 判定スコアカード
deep_analysis の回答にはすべて、判定とトレード計画(ストップは1.5 ATR先、ターゲットは+1R)が含まれます。RYOは、その後どちらの結果になったかを報告しません。nota lock は、1日1回(20時間以内に2回目は不可)、25種類の主要通貨について回答全体を保存します。後から実行する nota settle は、OKXの公開ローソク足を使って、24時間後と72時間後までにどちらのレベルが先に到達したかを確認します。ロックから最初の1時間が終わるまでは1分足を使い、その後は1時間足を使います。同じ1時間の中で両方のレベルに到達した場合は、その時間帯の1分足で判定します。RYO自身の成績を採点することはありません。ブラケットはロック時点のOKX価格を基準に設定し、2つの価格の差が2%を超えるロックは basis_mismatch として記録し、決済しません。OKXが公開しなかった時間足を含む期間は1日間再試行し、その後 unsettleable として記録します。判定の組み合わせ、コンフルエンスの状態、RYOのモメンタムゲートは、それぞれターゲット先行率と期間末のリターンで比較します(どちらのレベルにも到達しなかったプランも含みます)。各ロック日内で比較し、マンテル・ヘンツェル重み付けを用いることで、偏りの大きい日によって符号が反転しないようにします。p値は、重複する期間のクラスター内でラベルをシャッフルして算出します。共通する日が10日以上あり、p < 0.10になるまでは、差があるとは判定しません。テストではシミュレーションによる帰無分布でこの判定率を確認します。失敗したロックもそれぞれ1行として数え、再試行の回数にかかわらずトークンごと、日ごとに1行記録します。無効なキーが使われた場合は1回の呼び出しで実行を停止し、aborted 行を記録します。このページでは、RYO自身の言葉に基づき、回答の各レーンで利用可能な結果が返された頻度も報告します。
/scorecard に、最も緊急性の高いものから順に表示します。/api/scorecard?horizon=24|72 は生データ、/api/scorecard.csv は同じ表のCSV版(ロックと期間ごとに1行、失敗も含む)です。このページには、両方のダウンロードを記載した schema.org の Dataset 説明(JSON-LD)も含まれます。
Notaの時計ではなく、ビットコインを基準とします。「値動きの前にロックした」という主張に意味があるのは、Notaも含め、誰もロックの時刻をさかのぼって設定できない場合だけです。nota stamp は、正常なロック行とすべてのレシートのSHA-256を、保存時の内容そのままで3つの公開OpenTimestampsカレンダーに送信し、.ots 証明を保存します。カレンダーに記録が追加された後の実行では、そのブロックのマークルルートをmempool.spaceと照合してから、ビットコインによる証明に差し替えます。スコアカードとダッシュボードには、保存されたステータスのみに基づいて「Bitcoin block N」または「timestamp pending (submitted …)」と表示します。自分で確認する方法は次のとおりです。
curl -o lock.json https://nota-ryo.vercel.app/api/scorecard/locks/<id>.json # the row as stored
curl -o lock.json.ots https://nota-ryo.vercel.app/api/scorecard/locks/<id>.ots
ots verify lock.json.ots # pip install opentimestamps-client; or drop both files on opentimestamps.org
レシートも同じ仕組みで、/r/<id>.json と /r/<id>.ots を使います。
0日目(2026-09-18):25件中25件をロック。4件がCONFIRMED、21件がMIXEDで、7つのプランがロングだった一方、RYO自身の判定は cautious でした(XRP、DOGE、ADA、LINK、SUI、BCH、WIF)。
審議会が引用してはならない情報
deep_analysis.data.derivatives は、2026-09-18 に調査したすべてのトークンについて、資金調達率が 0.0、ロング/ショート比率が null と報告しました。また、関連のないトークン間で、24 時間の建玉変化がまったく同じ値(ETH、SOL、WIF、ONDO で -10.44)を繰り返していました。positioning_check は、RYO の文書化されていない定義を推測せずに各フィールドを判定します。同じ日にロックされた他の 2 つのトークンで同じ値が見られた場合は not_token_specific、OKX のコイン建て建玉変化率が 3% 以上で、その符号と逆の場合は conflicts_with_venue、BTC の資金調達率がちょうど 0 で、RYO 独自のセンチメントツールが BTC の資金調達率を報告している場合は conflicts_with_ryo となります。保留されたフィールドは withheld: <reason> としてプロンプトに渡され、その引用は除外されます。scripts/gate_ab.py <id> はゲートなしでレシートの審議会を再実行します。最初の実行(docs/gate-ab/cd5ada18b179.json)では何も変わりませんでしたが、それでも公開しています。

その他のスクリーンショット(リプレイ検証、レシートカード、スマートフォン表示)

スクリーンショットは、同梱のデモ台帳から scripts/screenshots.py で生成されます。
実際の動作を見る: nota-ryo.vercel.app/demo — クリック可能なトランスクリプト付きの 3:36 のナレーション入りウォークスルーです。動画ファイルのみの場合は /demo.mp4 をご覧ください。
意思決定の仕組み
gather ──────────► council ──► judge ──► risk (pure ATR math) ──► receipt ──► ledger ──► notify
5 RYO tools macro weighs entry / stop / target id = hash(evidence, Telegram
+ own skills technician opinions or Blocked when price model, prompts) Discord
(price_check, narrative by Brier or ATR is missing
voices, news) weights
- エビデンスパック:
market_overview、monitor_market_sentiment_shift、deep_analysis、analyze_token、compare_tokens(対象トークンとBTC/ETHの同業トークンを比較します)。scan_marketは RYO が推奨するファネルであるnota scanを実行します。--direction negativeはfilter_directionを渡して、 ショート候補の敗者を絞り込みます。スキャン済みトークンの判断では、そのトークン独自のスキャン行(ランク、24 時間の変化、 取引高、モメンタムスコア、established_asset、RYO の理由)が、ハッシュ化されたパック内のscanセクションとして保持されます。ツールが失敗した場合も、ステータスがerrorのセクションとして記録され、 パック自体は作成されます。独自のスキルも追加セクションとして含まれます(デフォルトではprice_check、technicals_check、positioning_check、liquidity、crowd_odds、--voices指定時はnarrative_signal、--news指定時はnews_check)。 - 評議会:3 つのエージェント(マクロ、テクニカル、ナラティブ)が、それぞれ見解、確率、およびエビデンス内のドット区切りパスを使った引用を返します。欠落値または null 値を指す引用は、コード内で削除され(
x[0].yをx.0.yに正規化した後)、意見の確度が引き下げられます。 - サードパーティのテキストはデータであり、指示ではありません:
narrative_signalの投稿テキストやnews_checkの見出しとスニペットは、制御文字と双方向テキスト制御文字を除去し、{"untrusted": ...}でラップして評議会に渡されます。「自分のルールを無視しろ」のように読める場合はinjection_suspectのフラグが付けられ、すべてのエージェントに、そうしたテキストは考慮すべきエビデンスであり、従うべき要求ではないと伝えます。RYO のトークンプロフィールの説明文(約 2.7 KB。deep_analysisと各compare_tokens行に繰り返し含まれます)は、ナラティブエージェントに一度だけ表示されます。それ以外の全員には、同じパスにあるステータスと欠落入力が表示されるため、テクニカルエージェントのプロンプトは 30% 以上短縮されます(プロンプトv4)。プロンプトv5では、マクロエージェントにliquidity(ステーブルコインの供給量とチェーン TVL)が渡されます。どのエージェントにもcrowd_oddsは表示されません。これは、市場価格を基準に判定者を採点するために保持されます。 - 判定者:各エージェントの過去の Brier スコアに基づいて意見を重み付けし、ロング/ショート/取引なしを決定します。
- RYO 独自のプランはエビデンスであり、指示ではありません:
deep_analysis.data.trade_planには、RYO の ATR に基づくプレビュー(エントリー、ストップ、目標、倍率、方式)が含まれます。Nota は独自にサイズを計算し、その差をレシートに表示します。出荷時の ETH コールでは、RYO は 1.5× ATR で 2357.83 にストップを設定しますが、このサイジングでは 2.0× を使用するため、ストップはエントリー価格から 1.8% 低く、最初の目標は 5.4% 遠くなり、いずれも同じ方向にずれます。RYO のsqueeze_riskとliquidation_pressureも、この比較の横に表示されます。 - 各レシートに記録される RYO の見解:各レシートには
ryo_view(deep_analysis のコール、主な要因、それを変える条件、コンフルエンスの状態、analyze_token の判定、compare_tokens の選択)とagrees_with_ryo(強気/建設的/買い増しに対するロング、慎重/弱気/回避に対するショート)が記録され、「RYO said: constructive (confluence CONFIRMED) - council: long, agrees」のように出力されます。どちらもハッシュ化されたパックから取得されるため、リプレイ時に比較されます。これらが導入される前に保存されたレシートも、同一の内容でリプレイされます。/api/scores.vs_ryoとダッシュボードの「Nota vs RYO」行では、評議会が RYO 独自のコールを上回るかどうかが分かります。方向を選択した各コールについて、両者の的中率が表示されます。 - リスク:純粋関数です。ストップは 2×ATR(14)、目標は 3×ATR、サイズは口座リスク 1% を基準に計算し、口座の 20% を上限とします。RYO 独自のデリバティブ
vetoは、ポジショニングゲートが保留にした場合を除き、練習取引をブロックします(「RYO derivatives veto: 」)。価格がない、または ATR がない場合は Blocked となり、推測した数値は使いません。また、ATR が大きすぎてストップまたは目標がゼロ以下になる場合もブロックされます。そのようなボラティリティの高い銘柄には固定倍率ルールを適用せず、レシートに負の価格を表示してはいけません。 - リプレイ:LLM の出力は
(evidence hash, role, prompt version, model)をキーとしてキャッシュされます。nota replay <id>はレシートを完全に再現し、--freshはモデルに再度問い合わせて、差異をそのまま表示します。ダッシュボードの「Verify replay」ボタンは、キャッシュされた内容の確認のみを行います。 - キャリブレーション:
nota resolve --allは、7 日間の期間が経過したすべての判断を、その期間時点の OKX の 1 時間足終値に対して採点します(エージェントごとの Brier スコア)。サイクルの実行がどれだけ遅れても採点されます。OKX から価格を取得できない場合は、現在の RYO 価格または取引所の中央値を代わりに使い、late:<hours>h:と表示します。キャリブレーションテーブルには、期間に達した結果のみがカウントされ、そのコールのうち独立したものがいくつあるか(トークンごとに週 1 件)も表示されます。20 件に達するまで、テーブルは読み取れない状態です。判定者の重みは n/(n+20) に従って各エージェントの Brier スコアに近づくため、採点済みコールが 5 件あっても重みは大きく変わりません。Brier スコアの横には、2 つのベースラインも表示されます。トークン独自のベースレート(vs_base_rate)と、さらに比較が難しい、判断時点における予測市場の P(up)(vs_base_rate.vs_market、ダッシュボードの「Nota vs the crowd」)です。後者では、同じ確定済みコールについて、判定者の Brier スコアと市場の Brier スコアを比較します。 - 自律性:
nota watch SOL,BTC --every 3600 --notifyは、スケジュールに沿って判断し、期間が経過した判断を確定し、新しいレシートを Telegram/Discord に投稿します。--scan-top 3を指定すると、ループは各サイクルでscan_marketから候補を自動選択します。 - シミュレーションデータでは取引しません:RYO が主要なエビデンスに
data_mode: simulatedと指定した場合、サイジングはブロックされ、レシートにもその旨が表示されます。 - トランスポート:デフォルトでは REST(
/tools/{tool}/call)、または MCP JSON-RPC(同じベース URL でtools/list、tools/call)を使用します。MCP を使うにはRYO_TRANSPORT=mcpを指定します。MCP クライアントはクライアントごとに一度だけinitializeとnotifications/initializedのハンドシェイクを行い、RYO のserverInfoとプロトコルバージョンを保持します。また、Accept: application/json, text/event-streamを送信し、JSON の返信だけでなく SSE の返信も読み取ります。nota healthは whoami、キーの有効期限までの日数、ハンドシェイク、ライブカタログを表示し、Nota が送信するすべての引数を RYO が公開している入力スキーマ(必須キー、不明なキー、列挙値)と照合します。また、公開されている引数のうち Nota が使用しないものも一覧表示します。nota health --strictは、これらの問題がある場合、またはキーの有効期限が 14 日以内の場合に終了コード 1 で終了します。
公開インターフェースは公開されるものとして扱います
/api/skills/<name>/invoke と POST /mcp は意図的に認証なしで利用できるため、見知らぬ人向けに記述されています。
- 音声 ID は送信先 URL に含まれるため、まず検証します。以前は
../../evilがhttps://t.me/evilに解決され、呼び出し元に対象ホスト上のパスを渡していました。リダイレクトも追跡すると、このサーバーに任意の場所を取得させることにつながります。ハンドルに使えるのは英字、数字、アンダースコア、ドット、ハイフンで、最大 64 文字です。それ以外はリクエストを組み立てる前に拒否されます。 - すべてのスキル引数は、REST、MCP、CLI がすべて経由する共通の場所(
nota.skills.invoke)で、各スキルが宣言した独自のスキーマに照らして検証されます。型が誤っている場合、列挙型にない値、有限でない数値、64 文字を超える文字列(ニュースの主張は 500 文字)、または 20 件を超える配列は、422、JSON-RPC-32602、または CLI の使用エラーとなり、500 にはなりません。シンボルは、取引所 URL、プロンプト、台帳に渡される前に、英字または数字 1~15 文字であることが必要です。そのため、../xやBTC?xがプロセス外に出ることはありません。GET /api/decisionsのlimitは 1~200 で、バッキングのハンドルは 1 行でなければなりません。@Abcとabcは同じバッカーとして扱われ、abcは拒否されます。 - MCP 経由の
tools/callは、サードパーティ API にアクセスするため、REST ルートと同様にアドレスごとに 1 時間あたり 60 単位の制限が適用されます。呼び出しのコストは、実行する取得処理の数にほぼ応じます。価格またはテクニカル分析の確認は 1 単位、news_verifyは 2 単位、narrative_convergenceは音声 1 件につき 1 単位(そのため、音声 20 件の呼び出しは 1 ではなく 20 単位)です。initialize、tools/list、resources/*、および台帳のみを扱うverdict_track_recordは、プロセス外にアクセスしないため無料です。バッチは料金を加算する前に全体を検査し、拒否時にはRetry-Afterを伴う JSON-RPC429を返します。DATABASE_URLが設定されている場合、件数は Postgres のhitsテーブルに保存されます。そのため、すべてのサーバーレスインスタンスが個別に予算を付与するのではなく、1 つの予算を共有します。設定されていない場合、件数はプロセスごとに管理され、随時整理され、アドレス数が 10,000 に達した場合は消去されます。 - Telegram、X、Bluesky の各音声、および 4 つの RSS フィードは、プロセスごとに 5 分間に 1 回までしか取得されません。繰り返しの要求にはキャッシュから応答し、取得に失敗した場合はキャッシュしません。
- すべてのレスポンスには、
X-Content-Type-Options: nosniff、Referrer-Policy、Permissions-Policy、およびこのオリジンのみを許可するContent-Security-Policyが付与されます。フォントはセルフホストされ、サードパーティのスクリプトを読み込むページはありません。ページ内に動作を記述しているため、スクリプトとスタイルでは'unsafe-inline'を引き続き許可しています。これは、注入されたスクリプトへの対策としては nonce ポリシーより弱いため、ページに挿入するすべての値はあらかじめエスケープされます。Swagger UI は CDN から読み込まれるため、/docsは対象外です。/api/と/r/の読み取り専用 JSON、llms.txt、フィード、キャプション、エージェントカードはすべてのオリジンからのリクエストに応答します。また、スキル呼び出しルートは CORS プリフライトに応答するため、別の場所にあるページからスキルを呼び出せます。/mcpでは引き続きOriginの許可リストを使用します。すべてのページは、GETと同じヘッダーを付けてHEADに応答します。台帳に存在しない ID の/r/<id>は、noindexを付けた404を返します。 /api/healthは、プロセスごとに最大 1 分に 1 回 RYO を確認し(タイムアウト時は 1 回再試行)、確認時刻(checked_at)、バッキングの書き込み先(backing:postgres、ledger、noneのいずれか)、台帳の最新状況を返します。最新のロック、レシート、決済を示し、ロックもレシートも 36 時間書き込まれていない場合はstale: trueとします。- JSON-RPC バッチはメッセージ 25 件、リクエスト本文は 1 MB に制限されます(ストリーミング中に検査するため、チャンク化されたアップロードで制限を回避できません)。解析できないほど深くネストされたリクエスト本文は
-32700となります。また、トランスポート仕様のセキュリティ節で求められているとおり、すべての MCP リクエストでOriginを検証します。トランスポートレベルのものも含め、拒否はすべて JSON-RPC エラー本文で返されます。 idのないメッセージは通知です。202を返し、何も実行しないため、ツールの実行や予算の消費はできません。JSON の型が誤った Params は-32602となり、予期しない形で失敗したスキルは、ツール名を示すisErrorの結果を返します(詳細は呼び出し元ではなくサーバーログに記録されます)。また、スキルはワーカースレッドで実行されるため、応答の遅いソースがエンドポイント全体を停止させることはありません。- バッキングはアドレスごとに 1 時間あたり 30 件までです。以前はホスト環境で 503 を返していました。つまり、誰でも試せる唯一の場所で動作しない状態でした。サーバーレスのファイルシステムには書き込みできず、台帳もスナップショットだからです。現在は、
DATABASE_URLが設定されている場合は Postgres(nota/backings.py)に、それ以外の場合は台帳専用のテーブルにバッキングが書き込まれるため、ローカルで実行またはテストするためにデータベースは必要ありません。書き込みには単一のINSERT ... ON CONFLICT (decision_id, handle) DO UPDATEを使用します。ハンドルのマップを読み込み、1 件を変更して書き戻す方法では、2 人が同時にバッキングした際に一方の立場が失われる可能性があります。誰かの投票を通知なく失う公開記録は、公開記録がないよりも悪いものです。書き込み先がまったくない場合には、想定どおり引き続き 503 を返します。 - ハンドルを乗っ取ることはできません。アカウントがないため、あるハンドルで最初にバッキングを行った人がそのハンドルを取得し、
edit_tokenを一度だけ受け取ります。同じハンドルで以後バッキングを行うには、このトークンが必要です。トークンがない場合は409となります。保存されるのはトークンの SHA-256 のみで、比較は定時間で行われます。ダッシュボードは、ハンドルを取得したブラウザーにトークンを保持します。
このコードが適用する誠実性のルール
- レシート内のすべての数値には、そのソースパス、RYO
as_of、data_mode、トレース ID が付随します。 null/unavailableが 0 に変換されることはありません(Envelope.get、first_present、リスク、すべてのスキル)。- 記録済みフィクスチャは、RYO の元の
as_ofとdata_modeを保持し、source: recordedとラベル付けされます。tests/fixtures/内の RYO エンベロープも実際の応答です(2026-09-19 に記録されたものに加え、SOL のデリバティブレーンがダウンしていた 2026-09-07 のセットtests/fixtures/recorded_0907/、および RYO が実際に拒否した応答tests/fixtures/ryo_errors/があります)。sourceがliveまたはrecordedのエビデンスだけが、練習トレードのサイズ決定や Brier スコア、ベースレート、ソース、信頼性のスコアに使用されます。それ以外は表示されますが、集計には含まれません。CLI に偽の LLM モードはありません。 - RYO のインターフェースは読み取り専用です。練習トレードは
nota.dbにのみ保存されます。 - レシートにはコストが記載されます。モデル呼び出し、キャッシュヒット数、プロンプトと完了トークン、プロバイダーが独自に請求額として報告した数値、実時間です。いずれもプロバイダーが報告した値であり、このリポジトリで常に正確に保つ必要がある価格表から算出した値ではありません。報告されていない数値は「未報告」と表示され、応答のない呼び出しが 1 件でもあると、合計は少なくなるのではなく不明になります。
spendはリプレイ比較の対象外です。キャッシュからの再構築には費用がかからないため、このフィールドは測定値であり、再現性の保証ではありません。 - 外部ソースについては、できないことも明示します。Venice のウェブ検索には日付がなく、X のミラーは非公式です。取得に失敗した RSS フィードも一覧表示され、取引所価格が RYO の値に置き換わることはありません。
実行
uv sync
cp .env.example .env # RYO_MCP_KEY + an LLM key (Anthropic, or NOTA_LLM=openai for Venice/OpenRouter)
uv run nota health # MCP health (no key) + whoami, key expiry, handshake, catalog check (with key)
uv run nota health --strict # the same, exit 1 on an expiring key or an argument RYO would refuse
uv run nota llm-check --llm openai # one 1-token completion; exit 2 when the key or balance is refused
uv run nota decide SOL # live evidence + price cross-check, council, receipt
uv run nota decide SOL --voices tg:WatcherGuru,bs:decrypt.co,bs:unusualwhales.bsky.social --news --notify
uv run nota scan --top-n 5 --decide-top 2 # scan_market -> analyze_token -> council
uv run nota scan --direction negative # RYO's losers shortlist, the funnel for a short
uv run nota watch SOL,BTC --every 3600 --notify
uv run nota replay <id> # identical: True
uv run nota replay <id> --fresh
uv run nota resolve --all # after 7 days: Brier scores per agent
uv run nota stamp # OpenTimestamps: anchor new locks and receipts, upgrade proofs pending over 3 h
uv run nota export snapshot.json # receipts + scorecard as one JSON (the ledger cycle writes data/snapshot.json)
uv run nota merge-db other.db # add another snapshot's rows this ledger lacks (the cycle's push-conflict path)
uv run nota scores
uv run nota record SOL # capture all six live tools into fixtures/recorded (all or nothing)
uv run nota decide SOL --source recorded # replay those recordings without a RYO key (the council still needs an LLM key)
uv run nota positions # open practice positions vs the latest independent price
uv run nota serve # http://127.0.0.1:8000 overview, /app dashboard, /mcp
uv run nota skill spec # Track 3 definitions
uv run nota skill run price_crosscheck '{"symbol":"SOL","reference_price":150}'
uv run pytest -q
マルチ KOL エージェント(Track 1 の注目機能)
ハッカソンの注目アイデアを、最初から最後まで実現します。最大 20 人の暗号資産関連発信者を選び、Nota に彼らが言及したトークンをセンチメント、確信度、緊急度とともに見つけさせ、信頼できる発信者の意見が一致し、設定したすべてのルールを満たした場合にのみ、練習用ポジションを開始します。
uv run nota kol --voices x:handle,tg:WatcherGuru,bs:decrypt.co --min-voices 2 --min-sentiment 0.3 \
--min-conviction 0.2 --tokens SOL,ETH --account 10000 --risk-pct 1 --max-positions 3
uv run nota kol --voices ... --watch --every 3600 # run every hour; each run is stored
uv run nota kol-replay <id> # identical: True, from the ledger alone
または、ブラウザーで /kol を開く(フォーム、発信者ごとのカバレッジ、ルールの履歴、ポジション)か、{"voices": [...], "rules": {...}, "limits": {...}} を指定して POST /api/kol/run を呼び出します。GET /api/kol は保存済みの実行を一覧表示し、GET /api/kol/<id> はその実行をリプレイします。
- 読み取り。 発信者の情報は
narrative_convergenceスキルを通じて取得します。x:の発信者には、まず X 独自のシンジケーションエンドポイントを試し、次に Tavily 検索を試します。Tavily 経由で読み取った発信者にはvia tavily_search, coverage partialと記録し、読み取れない発信者は理由とともにunavailableとします。 - ルール(
nota/kol.py)。 モデルではなくコードで処理します。トークンごとに、発信者の意見が一致している(見解を示す発信者が 2 人以上で、全員の符号が同じ)こと、見解を示す発信者がmin_voices以上であること、|sentiment_mean|がmin_sentiment以上であること、conviction_meanがmin_conviction以上であることを確認します。任意でurgency_maxがmin_urgency以上であること、およびトークンが許可リストに含まれることも確認できます。各ルールは{rule, value, threshold, passed}として保存され、valueにはエンベロープの値がそのまま使われます。値が欠落している場合はそのルールを不合格とし、nullのままにします。 - ポジション。 発火したシグナルは、評議会と同じ
nota.riskコードを通ります。RYO のdeep_analysisが価格と ATR(14) を返し、ストップは 2 ATR、目標価格は 3 ATR 離れた位置に設定され、サイズは口座残高とリスク % に基づいて決まります。RYO のエビデンスがない、ATR がない、RYO が拒否した、トークンをすでに保有している、またはmax_positionsに達している場合、シグナルは残りますがトレードは拒否され、その理由が示されます。RYO に問い合わせるのは、空き枠に入る可能性があるトークンだけです。 - リプレイ。 実行結果は台帳の
kol_runsテーブルに、ナラティブのエンベロープ、ルールと制限、実行開始時点の保有資産、RYO のエビデンスパックとともに保存されます。そのため、kol-replayはネットワーク接続もキーも使わずに、すべての判断を再導出します。 - ホスト型デモ。 スナップショットは読み取り専用のため、そこで
/api/kol/runを実行すると、実行結果は保存されず、その旨が表示されます。取得内容に応じてアドレスごとにスロットリングされます(発信者 1 人につき 1 単位、x:の発信者 1 人につき 2 単位、RYO への問い合わせ候補 1 件につき 1 単位)。
スキル(Track 3)
9 つすべてが RYO の公開エンベロープをフィールド単位で返し(docs/skills/SKILL-SPEC.md)、RYO 自身のスキルパスで提供されるため、RYO への組み込みは移植ではなく、ルートの登録です。GET /api/skills/(SkillDefinition のリスト)、GET /api/skills/{name}、および SkillCallRequest {name, args, conversation_id} を受け取り、SkillCallResponse {name, status: success|error, result, latency_ms, xp, guard_decision} を返す POST /api/skills/{name}/invoke を利用します。ダッシュボードの「スキルを実行」パネルは、これらの定義からフォームを作成し、エンベロープを表示します。
contrib/positioning_check/ は、RYO 自身のバックエンドにそのまま組み込める形でパッケージ化された、主要スキルです。Nota のインポートはなく、インクルードする FastAPI ルーターと、独自のオフラインテストが用意されています(README を参照してください)。
contrib/move_base_rate/ も同じ方法で move_base_rate をパッケージ化しています。OKX のソースを 1 つ使用し、同じルーターとテストの構成です。
narrative_convergence:最大20件の投稿(tg:はTelegramの公開プレビュー、bs:はBlueskyの公開API、x:はX独自の公開シンジケーションエンドポイント経由。これは埋め込みタイムラインを配信するエンドポイントで、Tavilyによるフォールバックもあります)、VADERのセンチメント分析と暗号資産用語集を使い、トークンごとにそのトークンに言及する節を採点します(「BTC pumping while ETH dumping」は、反対方向の2つの読み取りになります)。単語全体で確信度と緊急度を判定し、2件以上の投稿に純センチメントがあり、すべて同じ符号である場合にコンバージェンスとします。トークンとして数えるのは既知の主要銘柄だけなので、$HODLや「CEO」はシグナルになりません。情報がない場合は0ではなくnullです。以前x:が経由していたNitterには2026年8月に停止要求書が送られ、公開ミラーは停止しました。そのため、応答できないソースを提供していると誤解させるリーダーになっていました。シンジケーションは認証キー不要で、日付情報があり、現在も利用できます。失敗はすべて推測せずunavailableとして報告します。試す前に知っておくべき実測上の制限が1つあります。シンジケーションには厳しいレート制限があり、さらに強化されています。まずデータセンターのアドレスが対象になり、ホスト型デモではx:がunavailableを返す一方、一般的な接続からは正常に読み取れていましたが、2026-09-10時点では一般的な接続でもsyndication HTTP 429が返されます。x:はベストエフォートとして扱い、信頼できるリーダーはtg:とbs:としてください。この2つはどちらの接続からも応答します。TAVILY_API_KEYを設定すると、レート制限時に検索ベースのフォールバックへ切り替わり、結果は日付情報なしとしてエンベロープに表示されます。このキーが設定されていない場合は、警告にその旨が明記されます。news_verify:CoinDesk、Cointelegraph、The Block、DecryptのRSSから日付付きの見出しを取得し、広範な情報を得るためにTavilyまたはVeniceのウェブ検索も使用します。独立したドメイン数を数え、RYOのanalyze_tokenのコンテキストを付加します。見出しは「Bitcoin」や「price」ではなく、主張に特有の語句で照合します。また、主張と逆の見解を示す見出しは主張に反するものとして数えるため、結果がdisputedになる場合があります。検索キーがなくても見出しに基づいて判定し、ステータスはpartialになります。price_crosscheck:キー不要のCoinGecko、Coinbase、Kraken、Binance(公開データミラー。USDの代用としてUSDTを使用)、DefiLlamaの現物価格、中央値、価格差、取引所価格からの基準価格(RYOの価格)の乖離を取得します。また、alternative.meのFear & Greed IndexとRYOの値も照合します。他のソースから2%を超えて乖離するソースにはoutlierのマークを付け、中央値から除外するため、CoinGeckoのシンボル検索で別のコインが見つかっても価格に影響しません。technicals_crosscheck:200本の確定済みUTC日足ローソク足から、Wilder方式でRSI(14)、ATR(14)、1日/7日/30日のパフォーマンスを再計算します(OKX、利用できない場合はBinance、さらに利用できない場合はCoinGeckoの4時間足OHLCを日足に集約します。この場合、30日分では収束しない旨が警告されます。未確定の当日ローソク足は使用しません)。基準値(RYOのtechnicals.rsi_14/atr_14)と独立した計算値の乖離も示します。テクニカル分析エージェントは、すべての判断でこれをtechnicals_checkとして参照します。positioning_check:前述のデリバティブ判定に加え、OKXの無期限先物プレミアム(ファンディングレートは1 bpの金利成分に留まり、情報を示さないため使用しません)、コイン建ての建玉変化、過去100時間に対するパーセンタイルで示したロング/ショートの口座比率、および第2の取引所としてHyperliquidのプレミアムを取得します。premium_consensusはすべての取引所で現物価格の同じ側を示すかvenues_disagreeのいずれかで、平均値にはなりません。英語と日本語で簡潔な説明文を1つずつ添え、見出しには両方の取引所の値を記載します。RYOのブロックなしで呼び出した場合、(RYO_MCP_KEYが設定されていれば)RYO自身のdeep_analysisを要求し、今日のスコアカードの確定値と比較します。BTCとETHについては、DeribitのDVOLも追加します。これはオプション市場が織り込む7日間の値動きで、atr_stop_pctがある場合は、ストップが通常の値動きの範囲内にあると警告します。その他のトークンにはDVOLがないため、追加されません。move_base_rate:このトークンがk ATRに達した(またはその水準を超えて終値を付けた)頻度を、h日以内について集計します。過去約400日分のOKXのUTCローソク足を使い、今日のボラティリティの三分位に該当する日に限定します。独立した日数と、発生率にドリフトがある場合に警告する時系列分割のホールドアウトも含みます(三分位の境界値は古い日付のみから算出するため、フィッティングにホールドアウトは使われません)。RYOのatr_14_pctが指定されている場合は、RYOのATRを基準に測定します(OKXのWilder ATRの0.91~0.98倍で、比率も表示されます)。採点対象となるすべての判断にはこのベースレートも含まれ、/api/scores.vs_base_rateはエージェントごとに1 - Brier / Brier(base rate)を示します。0を超えていれば、カレンダー情報だけでは得られない知見があったことを意味します。verdict_track_record:スコアカードに記録されたトークンの確定済み実績を、判定とコンフルエンスの状態別に表示します。分母、判定が計画の方向性と逆に傾いている計画(慎重な判定でのロング、または前向きな判定でのショート)、および直近の確定済み判定のトレースIDも含みます。liquidity_check:キー不要のDefiLlamaを使い、米ドル建てステーブルコイン総供給量(新たな購買力の流入または流出)と、そのトークン固有のチェーン上のDeFi TVLについて、7日間および30日間の変化を取得します。それぞれの最終行の日付も示します。BTCや独自のチェーンを持たないトークンについては、他のチェーンの値を流用せず、理由を示したうえでTVLを含めません。マクロエージェントはこれをliquidityとして参照します。crowd_odds:予測市場が示す、期間内に現在より高くなる確率P(higher than now)を取得します。Polymarketの「 above ___ on 」ラダーのうち、現在から7日後の前後1日以内に期限を迎えるもの(BTC、ETH、SOL、XRP)を使用し、該当するものがなければKalshiのKXDラダーを使用します(DOGEも対象です)。幅が最大10セントの両側注文板のみを対象とするため、新しいラダーの0.5という仮置き値は読み取りません。価格をストライクに対して単調になるよう調整し、現物価格で補間します。読み取り可能なラダーがない場合は、コイントスで補わずmarket_p: nullとします。すべてのパックに保存されますが、エージェントには表示されず、ジャッジに対して採点されます。
Nota は MCP サーバーでもあります(Track 3)
Nota は RYO の MCP クライアントです。また MCP サーバーでもあるため、RYO、Claude Desktop、Cursor、その他の MCP ホストは、ラッパーなしで 9 つのスキルを直接呼び出せます:
// claude_desktop_config.json, or any MCP client that speaks Streamable HTTP
{ "mcpServers": { "nota": { "url": "https://nota-ryo.vercel.app/mcp" } } }
curl -s https://nota-ryo.vercel.app/mcp -H 'content-type: application/json' -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | jq '.result.tools[].name'
curl -s https://nota-ryo.vercel.app/mcp -H 'content-type: application/json' -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"technicals_crosscheck","arguments":{"symbol":"SOL"}}}'
扱いやすいプリミティブだけでなく、4 つの MCP プリミティブすべてを提供します:
- ツール:9 つのスキルに対する
tools/listとtools/call。各inputSchemaは、REST ルートとダッシュボードのフォームが使うものと同じ定義から生成されます。 - リソース:
resources/list、resources/templates/list(nota://receipt/{id})、resources/read。レシートを Markdown と、それ自体の JSON で返します。このプロジェクトの HTTP API に一度もアクセスしないクライアントでも、判断内容の一覧を取得し、個別の内容を読み取れます。 - プロンプト:
prompts/listとprompts/get。audit_a_tokenは、呼び出し元のモデルに対し、RYO を独立した情報源と照合するよう指示し、null は null のままにするというルールを含め、誠実さに関するルールも渡します。read_a_receiptは保存済みの判断内容を順に確認します。 - 補完:
completion/completeは、このデプロイメントが実際に保持するレシート ID とシンボルを提示するため、クライアントは値を推測する必要がありません。また、参照先のプロンプトまたはテンプレートで宣言されている引数に限って提示します。
各ツールには、title、annotations(readOnlyHint: true、destructiveHint: false)、および RYO エンベロープ独自の JSON Schema である outputSchema が含まれます。これによりクライアントは、呼び出し前に、何も書き込まれないことと、返されるデータの形式を確認できます。一覧は、不透明な cursor を使って 50 件ずつページ分割されます。
MCP Apps ビューも同梱されています。すべてのツールは _meta.ui.resourceUri で ui://nota/receipt にリンクしており、その URI に対する resources/read は自己完結型の HTML ページ(nota/static/mcp_app.html、text/html;profile=mcp-app、許可リストが空の CSP:何も読み込みません)を返します。MCP Apps をレンダリングするホストは、ビューとの ui/initialize ハンドシェイクを行い、ツールの結果を渡します。ビューはエンベロープをスタンプ付きのカードとして描画します。ステータス、as_of、情報源ごとの利用可能状況、見出し、要点、警告を、マークアップではなくすべてテキストとして表示します。
Nota は、公式 MCP レジストリに io.github.PugarHuda/nota として公開されています(バージョン 0.1.0、2026-09-10。ここにある server.json は 0.2.0 で、スコアカードとデリバティブのゲートを記述しており、再公開後に有効になります)。そのため、クライアントは URL を渡されなくても見つけられます:
curl "https://registry.modelcontextprotocol.io/v0.1/servers?search=io.github.PugarHuda/nota"。
リポジトリルートの server.json は、このサーバーの公式 MCP レジストリ用エントリーです。デプロイメントではこれを /.well-known/mcp/server.json と /server.json で提供するため、記述内容とそこに記載されたエンドポイントが食い違うことはありません。レジストリが適用し、ここにあるテストでも確認するルールが 2 つあります。説明は 100 文字以内であること、そして公開済みバージョンは変更できないことです。再公開するたびに新しい version が必要なため、このファイルの内容を変更したら、バージョンを上げてください。リポジトリルートから mcp-publisher login github && mcp-publisher publish を実行して公開します。mcp-publisher validate は公開せずに、ファイルを稼働中のレジストリと照合して検証します。
GET /llms.txt は llms.txt の規約に沿っており、エージェント向けに、このプロジェクトの内容、MCP と A2A のエンドポイントの呼び出し方法、スコアカード、利用可能なスキル、台帳が保持するレシートを説明するページを 1 つ生成します。ページ一覧はアプリが実際に提供するルートでフィルタリングされるため、ルートと食い違うことはありません。
A2A. Nota は Agent2Agent 1.0 エージェントでもあります。/.well-known/agent-card.json は Agent Card です(タグとそれぞれの呼び出し例を含む9つのスキル、1つの JSON-RPC インターフェース、ストリーミングなし、プッシュなし)。POST /a2a はヘッダー A2A-Version: 1.0 を含む SendMessage を受け付けます(ヘッダーがない場合は 0.3 と見なされ、仕様のとおり VersionNotSupportedError で拒否されます)。メッセージにはデータパート {"skill": ..., "args": {...}}、または price_crosscheck SOL のようなテキストが含まれます。呼び出しは REST や MCP と同じ invoke チェックを通り、回答はエンベロープをアーティファクトとする完了済みタスクです。不正な引数には google.rpc.BadRequest の詳細を含む -32602 が返されます。各タスクはリクエスト内で完了するため、タスクは保存されません。GetTask は TaskNotFoundError を返し、ストリーミング、キャンセル、プッシュ設定には UnsupportedOperationError が返されます。/mcp と同じ Origin 許可リスト、1 MB のリクエストボディ上限、アドレスごとのスキル利用上限が適用されます。
オープンデータとディスカバリー。 /feed.xml(Atom)と /feed.json(JSON Feed 1.1)には、最新の50件のレシートが掲載されます。それぞれに判定、劣化したセクション、解決後は結果と判定者の Brier スコアが含まれ、確定済みのすべてのスコアカードプランも掲載されます。/api/outcomes.csv には、解決済みの各判断につき1行が含まれます(各役割の p_up_7d、ベースレート、実際の結果、役割ごとの Brier スコア)。/robots.txt と /sitemap.xml(すべてのページ、両言語のページを hreflang の代替ページとして掲載、すべてのレシート)はクローラー向けです。各ページの head には、正規 URL、絶対 URL の og:image、フィードが指定されています。
POST のみを受け付ける、ステートレスな単一のエンドポイントです。クライアントが要求するプロトコルバージョン(2026-07-28、2025-11-25、2025-06-18、2025-03-26、または RYO 独自の 2024-11-05)をネゴシエートし、未知のバージョンが要求された場合は最新のバージョンを使用します。server/discover にはバージョン、機能、サーバー情報を返します。対応していない MCP-Protocol-Version ヘッダーは、対応バージョンを列挙する仕様規定の UnsupportedProtocolVersionError(-32022)とともに 400 で拒否します。トランスポート仕様の要件に従って Origin ヘッダーを DNS リバインディングに対して検証し、バッチにはリクエストごとに1つのレスポンスを返します。ボディが通知のみの場合は、ボディなしで 202 Accepted を返します。開くストリームも削除するセッションもないため、GET と DELETE には 405 を返します。各ツールの inputSchema は、REST ルートとダッシュボードのフォームが使用するものと同じスキル定義から生成されるため、3者の定義が食い違うことはありません。tools/call は RYO エンベロープを2つの形式で返します。テキストのみを読み取るクライアント向けのテキスト形式と、解析を行うクライアント向けの structuredContent です。
ダッシュボード(トラック 2)
nota serve は、レジャーに対する読み取り専用 API(/api/decisions、/api/decisions/{id}、
/api/decisions/{id}/replay、/api/positions、/api/scores、/api/health、エクスポート
/r/{id}.json と /r/{id}.md、および /docs の OpenAPI)と、単一ページのダッシュボードを公開します。/api/decisions/{id} から読み込むレシートには、各エビデンスセクションを呼び出した際の正確な引数を示す requests と、Nota の ATR、RSI、価格を RYO の値と並べ、各スキルの警告しきい値を示す audit も含まれます。どちらも保存済みのエビデンスパックから読み取られます。トップページの監査テーブルはこの情報から作られ、独自の数値は保持しません。リストの行には availability と failed_sections(エラーまたは利用不可となった RYO のセクション)が含まれ、トップページの障害パネルに表示するレシートはこれに基づいて選ばれます。
- 30 秒でわかる要約:すべてのレシートの先頭に表示されます。今どうすべきか(取引するか、ブロックする理由)、最も大きな変化とその重要性、最新の独立価格に照らしてオープン中の練習ポジションがストップにかかるか目標に達するか、次に何が起こるか(採点時期またはスコア)を示します。
- 変更点:すべてのレシートを同じシンボルの前回のレシートと比較し、影響度順に行を並べます。判定の反転、取引の許可/ブロック、利用可能性、モデルの変更が先に表示され、次にリスクエンジンが読み取る数値(価格、ATR、RSI)が変化率順に表示され、その後にその他すべてのエビデンスリーフが表示されます。値が
nullになった場合は、0 ではなくnullと表示します。 - 縮退モード:
okではないすべてのエビデンスセクションをバナーに表示します。各セクションの来歴にはas_of、data_mode、トレース ID が表示されます。 - 最新のエビデンス価格に照らしたオープン中の練習ポジションと、ストップまでの距離。
- エージェントのリーダーボード:現在適用されている判定者の重みとともに Brier スコア順に表示します。また、判定が確定した後は、判定者のキャリブレーションテーブル(申告された
p_up_7dの区分と実際の的中率)も表示します。 - 1 ページで 2 言語に対応:
/と/jaはlanding.cssとlanding.jsを共有するため、翻訳されるのは文章だけで、動作はコピーではなく同じものです。テストで両方を紐付けます。セクション ID が同一であること、両方が同じスクリプトを読み込むこと、どちらもレシート ID やエビデンスハッシュをファイルに書き込めないことを確認します。 - どの情報源が役立ったか(
/api/scoresのsources):各エビデンスセクションについて、そのセクションが回答した判定と回答しなかった判定における判定者の平均 Brier スコア、および両者の差を示します。エージェントのリーダーボードでは答えられない、「どのエージェントが正しいか」ではなく「このフィードがあると判断が改善するか」という問いに答えます。対象データがない区分のスコアはnullとなります。また、テーブルにはenough_to_readがあり、独立した判定が 20 件採点されるまでは false です。各 3 件のサンプルから算出した平均値の差はノイズであり、それを調査結果として表示するのは、nullをゼロに変えるのと同じ誤りです。 - ページからのリプレイ検証(キャッシュ済みの出力のみを使い、新たなコストは発生しません)、X への共有、エクスポート。
- 誰もが使える設計:すべてのページにスキップリンクと
<main>ランドマークを設け、実際のボタン、視認できるフォーカス表示、キーボード操作(j/kで移動、Enterで開く、pで前のレシート、/で絞り込み、Escでリストに戻る、?でヘルプ)に対応します。レシートを開くと、そのタイトルにフォーカスが移り、タブのタイトルにレシート名が表示され、1 文で読み上げられます(レシート自体はライブリージョンではありません)。1 カラム表示では、タップするとレシートまでスクロールします。幅の広いテーブルはフォーカス可能な独立領域内でスクロールし、すべてのページが幅 320 px でリフローします。また、どのページで選んだダークテーマも全ページに適用されます。サードパーティーの内容は、マークアップに出力する前にすべてエスケープされます。tests/test_a11y_axe.pyは axe-core(axe-playwright-python 経由)を実行し、5 つすべてのページを両方のテーマで 1366 px と 390 px においてテストします。重大または深刻なルールへの違反、ランドマークの欠落、スクロール領域がフォーカスできない場合は失敗します。 - レジャーを 30 秒ごとにポーリングするため、実行中の
watchループがリロードなしで反映されます。
ダッシュボードが読み取るのはレシートのみです。裏付けとなるレシートのない数値は表示できません。
SocialFi レイヤー
- レシートカード:
/r/<id>.pngはレシートから 1200×630 のカードを生成します(Pillow、同梱フォント)。/r/<id>には、それを指す Open Graph と X カードのタグが含まれるため、パーマリンクを共有するとレシートのプレビューが表示されます。Discord の通知にも同じ画像が埋め込まれます。 - 支持表明:誰でもハンドル名を使って、ある判断を支持または不支持にできます(
POST /api/decisions/<id>/back、レシートごとにハンドル名1つにつき1つの立場を表明でき、最新の立場が有効になります)。判断の結果が確定すると、支持者は結果に照らして評価されます(/api/backers)。ロングの判断で価格が上がれば賛成は正解、不支持は不正解となり、no_tradeの判断は評価対象になりません。アカウントは不要です。あるハンドル名で初めて支持表明を行うと、そのハンドル名を編集トークンで取得し、このブラウザーに保存するため、ほかの人がそのハンドル名で投稿することはできません。台帳には、すべての立場表明がタイムスタンプ付きで記録されます。 - 公開推論フィード(
/feed、JSON は/api/feed):最新のレシートをカード形式で表示します。それぞれのカードには、各エージェントの立場と主張の最初の文、判定に異議を唱えたエージェント(アクションに必要な立場とは異なる立場を示したエージェント。no_tradeの場合は、どちらかの側を選んだすべてのエージェント)と裁定者自身の根拠、支持者数、パーマリンクとカードへの X 共有リンクが含まれます。 - 評判(
/api/reputation):支持者のハンドル名と4つのエージェント(マクロ、テクニカル、ナラティブ、裁定者)を同じ基準で評価します。評価対象となる同じ結果を使い、方向性を示した判断のうち、7日間の値動きと一致した割合を算出します。支持者は確率を示さないため、Brier スコアではなく的中率を使います。エージェントの Brier スコアも併記されます。中立およびno_tradeの判断は集計されません。各行にはn、n_independent(同じシンボルを7日以内に評価した場合は1回とみなす、キャリブレーションのルール)が含まれます。20の独立した週にわたる20件の判断に達した場合にのみ順位が付き、それまでは「評価するにはデータ不足」と表示されます。 - ウォッチリスト(
POST /api/watchlist {handle, symbol, watch, token}、GET /api/watchlist):ハンドル名ごとの公開リストです。各シンボルをウォッチしているハンドル名の数を集計します。シンボルにはclean_symbolが適用されます。ハンドル名の取得、編集トークン、1時間ごとのレート制限、読み取り専用ルールは、支持表明と同じ仕組みです。保存先も同じで、DATABASE_URLがある場合は Postgres、ない場合は台帳を使います。ハンドル名ごとに最大50件です。 - プロフィール(
/u/<handle>、JSON は/api/users/<handle>):あるハンドル名の支持表明とその評価結果、評判の行、ウォッチリストを表示します。ハンドル名は取得制のため、noindexで配信されます。
すべてのリストは空の状態から始まり、そのことが明示されます。これらのページにサンプルデータはありません。
API キーなしで評価する
このリポジトリには、ライブの RYO エビデンスに基づく4件のレシート(2026-09-07、SOL / BTC / ETH。それぞれ独自のソースを明記)が入った台帳スナップショットが同梱されており、その後も増えていきます。1時間ごとのサイクル(.github/workflows/ledger.yml、毎時15分)が、評価期間に達した項目を採点して確定します。08:23 UTC の実行でロックして判定し、失敗した項目は 16:41 に再試行し、実行ごとにスナップショットをコミットします。このスナップショット内のすべてのレシートは検証に合格します。これを確認するテストもあります。
uv sync # on PowerShell, set the variable first: $env:NOTA_DB = "data/demo.db"
NOTA_DB=data/demo.db uv run nota replay b80b42835b01 # identical: True - verified with no key at all
NOTA_DB=data/demo.db uv run nota serve # then open http://127.0.0.1:8000/app for the dashboard
NOTA_DB=data/demo.db uv run nota positions
uv run nota skill run price_crosscheck '{"symbol":"SOL"}' # live exchanges, no key
uv run pytest -q # no network, no keys
最初の行がこのプロジェクトの要点です。キャッシュ済みのリプレイでは、台帳に記録されたエビデンスと、その横に保存されたモデル出力を、それを生成したモデルにひも付けて使い、レシートを再構築します。そのため API にアクセスせず、結果が変わることもありません。同梱されているレシートはすべてこの方法で検証に合格します。ソースが記録されたレシートも同様です。キャッシュ済みのリプレイは、現在設定されているモデルではなく、出力を生成したモデルにひも付けられているためです。これとは逆に、--fresh は今日のモデルを同じエビデンスに対して実行し、差分をドリフトとして表示します。
評議会の判断には1つの LLM キー(Anthropic、または Venice などの OpenAI 互換プロバイダー)が必要です。ライブの RYO エビデンスにはビルダーキーが必要です。検証を含むそれ以外のすべては、どちらのキーも不要で実行できます。
CI と、提供されたスナップショットの確認
.github/workflows/test.ymlは、Playwright のブラウザーテストを含む全テストスイートを、プッシュとプルリクエストのたびに実行し、requirements.txt(Vercel がインストールするもの)がuv.lockと食い違うと失敗します。deploy.ymlは、mainでtestが成功した後にのみ Vercel のデプロイフックを呼び出します。サードパーティ製アクションはすべてコミット SHA に固定され、mcp-publisherは実行前に sha256 を検証するリリースに固定されています。また、Dependabot が毎週更新を提案します。- 台帳のサイクルでは、RYO または LLM を呼び出すステップにのみシークレットを設定し、判断の前に
nota llm-checkでトークンを 1 つ使うことで、停止した LLM キーによって RYO のクォータが消費されるのを防ぎます。最初の失敗で判断ループを停止し、最後にnota health --strictを実行するため、停止または期限切れ間近の RYO キーがあると実行は失敗します。ステップが失敗またはタイムアウトした場合でもスナップショットはコミットされます。mainが更新されたためにプッシュが拒否された場合は、nota merge-db(2 つの SQLite ファイルを行単位で統合し、各テーブルをキーで照合)で解決して再試行します。それでもプッシュできないスナップショットは、実行アーティファクトとして保存されます。各ステップは、ロック、決済、判断のテーブルを実行のサマリーページに書き込みます。 - プッシュされたすべてのスナップショットは、GitHub のアーティファクト証明を通じて Sigstore で証明され、
data/snapshot.json(nota export:レシートと、24 時間後および 72 時間後のスコアカード)も併せて証明されます。証明 URL はdata/attestations.jsonに記載され、最新のものは/api/healthにあります。台帳のコピーがこのリポジトリのワークフローから作成され、その後編集されていないことを確認するには、次のようにします。
gh attestation verify data/demo.db --repo PugarHuda/nota
ウォークスルーとその制作方法
/demo では、ナレーション付き動画と、その横にチャプター形式のトランスクリプトを表示します。行をクリックするとその位置に移動し、読み上げ中の行は表示されたままになります。同じチャプターは /demo.vtt で WebVTT 字幕としても提供されます(デフォルトで有効)。また、ページの og:video は絶対 URL なので、共有リンクから動画をインライン再生できます。3 つのステップで制作し、各ステップは推測ではなくタイミングを次のステップに渡します。
uv run --with edge-tts python scripts/narration.py # the voice, and it sets the pace
uv run python scripts/demo_video.py # Playwright records the real pages
cd video && npx remotion render # the two are composed
scripts/narration.pyには、各文とその説明対象のセレクターを組み合わせたビートとして、読み上げるスクリプトを記述します。Microsoft のen-US-AndrewNeuralがedge-ttsを通じて読み上げます。キーは不要で、ffprobeが生成された音声の長さを測定します。耳でタイミングを決めることはありません。scripts/demo_video.pyは、data/demo.dbを使って Playwright でアプリを操作し、各ビートをそれぞれの音声の長さに正確に合わせて表示します。通常の画面録画にはない 2 つの要素を描画します。説明中の対象に移動するカーソルと、その要素を囲む枠です。これにより、ナレーションがどの部分を指しているのかが明確になります。各ビートが実際に始まった秒数を記録します。ページの読み込みにはナレーションより時間がかかるためです。このファイルを使って、合成処理と/demoのトランスクリプトの両方を生成します。video/は Remotion のコンポジションで、記録されたオフセットに各行を配置し、MP4 をレンダリングします。
演出は一切ありません。検証ボタンはカメラの前で押され、その結果は API が返したままです。読み上げられる数値はすべて、このデプロイ環境がその場で生成したものです。
ホステッドデモ
ダッシュボードは https://nota-ryo.vercel.app で稼働しています(Vercel、main.py を通じてフレームワークとして FastAPI を検出、東京リージョン hnd1。CSS、スクリプト、画像、フォント、動画は Vercel の CDN にキャッシュされます)。コミット済みの台帳スナップショット data/demo.db(ライブ RYO のエビデンスに関するレシートで、それぞれトレース ID を含みます)を NOTA_READONLY=1 で提供しています。読み取り、リプレイ検証、カード、フィード、エクスポートが利用でき、バックアップも利用できます。サーバーレスのファイルシステムには書き込めないため、バックアップはハンドル要求と編集トークンとともに Neon Postgres(DATABASE_URL)に書き込まれます。新しい判断とロックは台帳サイクルのコミットとともに反映されます。RYO_MCP_KEY と LLM キーを設定すると、ダッシュボードの「Run the council live」(POST /api/council/{symbol})で、新しいエビデンスをもとに評議会を招集し、レシートを保存せずに返します。1 時間あたり、アドレスごとに最大 3 回、合計 20 回までに制限されています。ライブ RYO エビデンス、watch ループ、通知を含むシステム全体は、書き込み可能なディスクがある任意のマシンで uv run nota serve を実行すると稼働します。
障害処理
障害の様子は /drill で確認できます(POST /api/drill {"scenario": ...}、nota/drill.py)。7 種類の障害(RYO 停止、RYO 401、deep_analysis 欠落、レート制限および応答遅延、取引所停止、モデルプロバイダー停止、null を含む RYO の部分応答)のいずれかを注入し、正常な実行と並行して、記録済みのフィクスチャを使って実際のパイプラインをオフラインで実行します。ドリルのレシートには source: drill のラベルが付き、保存されることはありません。
- RYO クライアント:429/503/ネットワークエラーではジッターを伴う指数バックオフを行い、秒数または HTTP 日付で指定された
Retry-Afterを尊重しますが、60 秒を超えて待つことはありません。引数エラーの 4xx は再試行せず、X-RateLimit-*ヘッダーを記録します。RYO にはキーごとに 1 分間で 6 回のツール呼び出しに制限するファンアウトバケット(mcp_fanout)もあり、クライアントはその上限に合うように自身のツール呼び出しのペースを調整します(catalog、whoami、health は無料で、ペース調整の対象外です)。また、拒否応答からバケットのreset_atを取得し、fanout_reset_atとして保持します。MCP 経由でのレート制限は、isErrorとRetry-Afterを含む HTTP 200 として返されます。ツールの失敗として読み取るのではなく、REST の 429 と同様に再試行します。タイムアウトはツールごとに設定され(deep_analysisとcompare_tokensは 120 秒、それ以外は 30 秒)、タイムアウトした呼び出しは 1 回だけ再試行されます。 - 1 回の判断で行う 5 つの RYO 読み取りは、3 件ずつ並行して実行されます。パックは固定順序で組み立てられるため、ハッシュは 1 件ずつ収集した場合と同一です。失敗したセクションには RYO のトレース ID が保持され、スコアカードのロックに失敗した場合も同様に、HTTP ステータスとともに保持されます。
- LLM クライアントは、1 分を超える
Retry-Afterの間スリープするのではなく、「rate limited for N s」で失敗します。 - エビデンスの収集は、失敗したツールやスキルがあっても続行されます。審査役には欠落しているセクションが伝えられます。主要なエビデンス(
deep_analysis)がない場合、評議会はまったく招集されず、モデル呼び出し数が 0 のno_tradeレシートが生成されます。他のレシートと同様に保存され、リプレイも可能です。 - SQLite 台帳は WAL モードで動作します。すべての書き込みはコンテンツハッシュによって冪等となるため、再起動後も処理を再開できます。
watchは、失敗するシンボル、通知先、解決処理があっても動作を継続します。- RSS は
defusedxmlで解析されます(信頼できないフィードからのエンティティ展開を防止します)。 - 一部の ISP では、DNS により取引所のドメインがブロックされます(インドネシアでは、Coinbase と Kraken が不正な証明書を持つブロックページに解決されることを確認しています)。その場合、
price_crosscheckは該当ソースをunavailableとして報告し、利用可能なソースを使って動作します。Vercel のホステッドデモからは、3 つすべてにアクセスできます。この構築に使用したマシンでは、Polymarket と Kalshi も同様に DNS でブロックされています。その場合、crowd_oddsはmarket_p: nullを返します。パーサーは DNS over HTTPS 経由で取得したレスポンス(tests/fixtures/market/)をもとに作成されています。 nota stampには 3 つの OpenTimestamps カレンダーのいずれかが必要です。どのカレンダーからも応答がない場合、対象は次回実行まで未スタンプのままになります。また、カレンダーの Bitcoin パスが採用されるのは、mempool.space のブロックヘッダーと一致する場合に限られます。
レイアウト
main.py Vercel entry: the same app over the read-only snapshot data/demo.db
nota/
envelope.py RYO public response contract + REST/MCP parsers
ryo_client.py RyoClient (httpx, paced, MCP handshake) + RecordedRyoClient + record()
evidence.py EvidencePack, ryo_args(), gather() (parallel, fixed order), candidate_symbols(), path lookups
paths.py RYO's recorded field paths for price, ATR, derivatives, Fear & Greed
llm.py LLM protocol, AnthropicLLM (messages.parse), OpenAICompatLLM (Venice/OpenRouter)
council.py role prompts, untrusted-text framing, Opinion/Verdict, citation validation, cached run_council()
risk.py size_trade(): PracticeTrade | Blocked (incl. RYO's derivatives veto)
decide.py gather -> council -> size -> receipt
receipt.py Receipt + markdown rendering
replay.py cached or --fresh replay, field-by-field diff
calibration.py resolve at the horizon, Brier per role, base-rate / crowd / RYO baselines
scorecard.py lock RYO's plans, settle on OKX candles, Mantel-Haenszel contrasts
stamp.py OpenTimestamps: .ots writer/parser, calendar submit, upgrade checked against mempool.space
ledger.py SQLite: evidence, llm_cache, decisions, outcomes, backings, locks, settlements, stamps; merge_from()
backings.py Postgres store for backings, handle claims and the shared rate limit
api/ FastAPI, one APIRouter per area
__init__.py the app: HEAD handling, CSP and security headers, CORS, router mounting (pages last)
common.py shared helpers: ledger handle, absolute links, page templating, receipt loader, hourly budget
receipts.py decisions, impact-ranked diff, replay, positions, scores, health, /r/<id>.md|.json|.ots|.png
scorecard.py scorecard JSON, CSV, lock files and proofs, the /scorecard page
agents.py skills over REST, /mcp, /a2a, llms.txt, server.json, robots, sitemap, Atom and JSON feeds
social.py backings, watchlist, reputation board, reasoning feed, profiles
live.py on-demand runs: live council, failure drill, multi-KOL agent
pages.py HTML pages, fonts, images, walkthrough files, the /r/<id> permalink
mcp_server.py MCP server (tools, resources, prompts, completion, MCP Apps view)
a2a.py A2A 1.0 agent card and SendMessage
card.py receipt PNG card
notify.py Telegram Bot API + Discord webhook publishing
cli.py the `nota` command
skills/ contract, sources (Telegram, Bluesky, X syndication, RSS, Tavily, Venice), narrative, news, price_check,
technicals, positioning, base_rate, track_record, liquidity (DefiLlama), crowd_odds (Polymarket, Kalshi)
static/ landing.html + landing.ja.html (`/` and `/ja`), index.html (dashboard), scorecard.html,
demo.html + demo.mp4 + demo.json (walkthrough), mcp_app.html, landing.css + landing.js, fonts/, img/
data/ demo.db (the ledger snapshot); snapshot.json + attestations.json, written by the ledger cycle
fixtures/ recorded/: real RYO answers for `--source recorded`
scripts/ screenshots, narration, demo_video, font_subset, gate_ab, skill_spec_md, submission_pdf
video/ Remotion composition that puts the narration onto the recording
docs/ hackathon analysis, MCP builder guide copy, design spec, skill spec, submission form and notes
.github/ workflows (test, deploy, ledger, publish-mcp, probe) and dependabot.yml
tests/ pytest, no network (respx + the FakeLLM test double in tests/fakes.py)
開示しているサードパーティライブラリ
httpx、pydantic、anthropic、typer、python-dotenv、fastapi、uvicorn、vaderSentiment(MIT)、
defusedxml、pillow。開発用:pytest、respx、playwright、axe-playwright-python(MPL-2.0 の axe-core。ブラウザーのエンドツーエンドテストは
tests/test_dashboard_e2e.py、QA は tests/test_qa_browser.py にあり、
uv run playwright install chromium の実行後に実施)、edge-tts、Remotion(ウォークスルー専用。詳しくは以下を参照)。データソース:
RYO MCP、t.me/s のプレビュー、Bluesky の公開 AppView、X の公開シンジケーション、CoinDesk/
Cointelegraph/The Block/Decrypt の RSS、CoinGecko、Coinbase、Kraken、Binance(data-api.binance.vision)、
DefiLlama coins、OKX と Hyperliquid の公開 API、alternative.me、Tavily または Venice のウェブ検索。書体は
nota/static/fonts にセルフホストし、許可リストから配信しています。Dela Gothic One(ラテン文字と、
/ja の見出し用の76文字の日本語サブセット)および BIZ UDPGothic/BIZ UDGothic(モリサワ)で、
すべて SIL Open Font License 1.1 に基づき、Google Fonts からラテン文字のサブセットを取得しています。
スターターテンプレートは使用していません。リポジトリは空の状態から始まり、アプリケーションコードのすべての行を
ハッカソン中に作成しました。作業に関わったものの、成果物には含まれていない外部要素が2つあります。完全性のため、ここに記載します。
taste-skill のデザインルールセット(Leon Lin、MIT)は npx skills add でインストールし、インターフェースの再設計時に参照しました。
これはベンダー同梱せず、gitignore の対象としているため、そのファイルはここには含まれていません。また、docs/img 内のスクリーンショットは、
このプロジェクト独自のダッシュボードから scripts/screenshots.py で生成したものであり、外部から取得したものではありません
(scripts/demo_video.py の録画は docs/demo/ に出力されますが、ここは gitignore の対象です。コミットされているのは
最終版の nota/static/demo.mp4 のみです)。
ウォークスルーの作成には3つのツールを使用しますが、いずれもアプリケーションには含まれません。edge-tts
(GPL-3.0。Microsoft の公開ニューラル音声、キー不要)がナレーションを読み上げ、Playwright がページを録画し、
Remotion(Remotion License — 個人および3人以下の企業は無料、それを超える場合は有料。https://remotion.dev/license を参照)が
映像を合成します。これらは video/ の開発用依存関係であり、scripts/ から実行します。Remotion または edge-tts のコードが
訪問者に配信されたり、nota にインポートされたりすることはありません。ナレーションは生成したものではなく、ここで執筆したものです。
音声は合成音声ですが、台本はそうではありません。tests/fixtures/ と fixtures/recorded/ にある RYO エンベロープは、
nota record で取得した実際の RYO レスポンスで、source: recorded とラベル付けされています。tests/fixtures/x/ には、
2026-09-07 に X の公開シンジケーションエンドポイントから取得した実際のペイロードが1つ含まれています。
video/ 内の動画ツールチェーンはビルド専用で、デプロイ済みアプリには含まれません。その package.json では、
ws(8.21 以降)と webpack(5.104.1 以降)をパッチ適用済みリリースにオーバーライドしています。未解決のアドバイザリが1件あります。
Remotion がダウンロードする Chrome の展開のために @remotion/renderer が取り込む extract-zip 2.0.1 です。
パッチ適用済みのリリースは存在せず、このプロジェクトではこの処理を実行しません。レンダリングでは Playwright の Chromium を再利用するためです
(video/remotion.config.ts)。
シークレットをコミットしたことは一度もありません。作業ツリーだけでなく、履歴全体を対象に確認しました。
直近の確認日は 2026-09-20 です。ローカルの .env と .env.local にあるすべてのキーの正確な値(ビルダーキー、
LLM キー、Neon 接続文字列とパスワード、Vercel トークン)をすべてのコミットのすべてのパッチで検索し、見つかりませんでした。
また、13種類の認証情報パターン(RYO ビルダーキー、Anthropic、OpenAI、OpenRouter、Venice、Tavily、Telegram ボットトークン、
Discord Webhook、AWS、GitHub と Vercel のトークン、パスワード付き Postgres URL、PEM 秘密鍵)も見つかりませんでした。
唯一の一致は ryo_mcp_your_private_key で、RYO 独自のビルダーガイドにあるプレースホルダーを
docs/MCP-Builder-Guide.md で引用したものです。.env や認証情報ファイルをコミットに追加したことはありません。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。