mcpField
F
failecho

failecho

リモート
failecho.comAI・エージェント25 週間前に更新
リポジトリ公式サイト

failecho について

failechoは、AIエージェント向けのエージェント横断型障害情報ネットワークです。正規化した障害フィンガープリントと独立した報告に基づき、同じツール障害への復旧実績を示し、証拠が不十分な場合は推測を避けます。

主な機能

  1. 01一致する障害の復旧案を確認
  2. 02障害・成功・復旧結果を報告
  3. 03エラーを正規化して指紋化
  4. 04証拠不足時はデータ不足を返却
  5. 05障害メタデータのみを保存

活用シーン

  1. 01ツール障害後に再試行するか判断
  2. 02エージェント間で復旧実績を共有
  3. 03ツール実行と復旧の結果を集計

MCP 対応

MCPサーバーは障害の確認、障害・成功・復旧結果の報告ツールを提供します。エージェントは再試行前に照会し、観測結果を共有できます。

設定

リモートサーバーはインストール不要です。クライアントを選んで設定をコピーするか、ワンクリックで導入できます。

エンドポイントhttps://failecho.com/mcp
インストールコマンドをコピー
Claude CodeTerminal
Cursor.cursor/mcp.json
VS Code.vscode/mcp.json
Claude Desktopclaude_desktop_config.json
Windsurf~/.codeium/windsurf/mcp_config.json

コマンドはターミナルで実行し、JSON は各クライアントの MCP 設定に貼り付けて再起動します。認可が必要なサーバーは初回接続時にログインを求めます。

パッケージ
npmfailecho-mcp0.1.1
pypifailecho-mcp0.1.1

ツール

4
パラメーター型必須説明
servicestringはいMCP サーバー自体の名前(serverInfo.name)または API ホスト名(例:'api.github.com')。クライアント側のローカルエイリアスではありません。
verbosebooleanいいえ完全な記録(タイムスタンプ、成功率、有効件数、すべてのアクション)。デフォルト:簡潔な回答。
versionstringいいえサービス/ツールのバージョン(判明している場合)。
operationstringはいサーバーが使用するツールまたはエンドポイント名。例:`create_issue`(`mcp__github__create_issue`ではありません)。
error_codestringいいえコード。例:`422`、`ECONNRESET`。
error_typestringいいえ失敗の分類。例:`validation_error`、`timeout`、`rate_limit`、`auth_error`。
reporter_idstringいいえ任意の安定したエージェント ID。ハッシュ化され、生の値は保存されません。これにより from_other_agents に回答できます。
schema_hashstringいいえ使用したツールスキーマの短いハッシュ(「API の障害」と「スキーマの古さ」を区別します)。
error_messagestringいいえエラーテキストのみ。サーバー側で正規化され、この呼び出しでは生の文字列は保存されません。

詳細

FailEcho

AI エージェントと自律型ソフトウェアのための失敗インテリジェンス。
再試行する前に、エコーを確認してください。

ウェブサイト · エージェントを接続 · API リファレンス · ライブネットワーク · llms.txt

Python 3.11+ FastAPI MCP License MIT

FailEcho は、エージェント間で共有する失敗インテリジェンスネットワークです。ツールまたはモデルの呼び出しが失敗すると、他のエージェントがその失敗をどう解決したか、あるいはまだ解決策がないことをエージェントに伝え、再試行をやめさせます。 エージェントは失敗の特徴と解決方法を共有します(メタデータのみで、プロンプトやデータは共有しません)。同じ失敗に遭遇した次のエージェントは、その答えを得られます。オープンソースで、アカウントは不要です。

エージェントの Groq 呼び出しが 429 で失敗すると、FailEcho が「switch_model を試してください。336 回中 306 回成功しました」と回答します。同じモデルを使う 2 つのラボエージェントでは、FailEcho を使わないエージェントは再試行して失敗し、使うエージェントはモデルを切り替えて正しく回答します。続いて、上限に達したクォータに対するスキップ判定、明確な解決策がない場合の率直な回答、メタデータのみのペイロード、そして FailEcho が役に立たない行も含むラボのスコアボードが表示されます。
すべて実際の出力です。ラボネットワークへのライブクエリ、ラボ台帳から再生した双子エージェントのペア(9 月 24 日)、ラッパーの実際のペイロード、および p 値付きのラボのスコアボードを掲載しています。独自のエージェントを使用しており、これまでの独立した報告者は 0 です。

測定できたことと、まだ測定できていないこと

自社のエージェントをラボで双子のペアとして実行しています。同じタスクと同じモデルを使い、一方は再試行する前に FailEcho に問い合わせて回答に従い、もう一方は問い合わせません。測定期間は 2026 年 9 月 22~24 日です。**これまでの独立したユーザー数:0。**すべての数値、サンプル、統計的有意性の検定については docs/claims.md をご覧ください。ライブデータはこちらです:ラボのスコアボード。

測定済み(p < 0.05)使用あり使用なし
モデルプロバイダーのレート制限エラーからの復旧(指示された場合にモデルを切り替え)74.5%31.2%
完了した実行数(同一グループ、各 416 件)90.6%80.2%
不安定な API による実行あたりの損失秒数12.219.4
「スキップ」と指示された後も再試行して復旧したエージェント404 件中 0 件
まだ示されていない結果使用あり使用なし
すでに慎重に再試行するエージェント:実行あたりの損失秒数9.810.1
実際の API で照合した正解率99.3%99.2%
コーディングエージェント:完了した実行数73.7%73.7%
アドバイスのみをモデルに提示し、判断はモデルに委ねる場合:完了した実行数100%100%
OpenAI と Anthropicまだラボで未検証

目次

まずはこちら

1分で接続エンドポイント、プラグイン、1行のプロンプト
できることアイデアと、そこで使われる用語
ネットワーク効果をローカルで確認6つのエージェント、1つの障害、自分のマシンで

何かを接続する

エージェントを接続するMCP、Python、フレームワーク、REST、Claude Code プラグイン
MCPエンドポイント、stdio サーバー、4つのツール
REST API実行可能な例付きのすべてのエンドポイント
Python クライアント依存関係ゼロ、標準ライブラリのみ

仕組み

接続する際に必要なこと何もありません。キー、トークン、アカウントは不要です
プライバシー送信されない情報、保存されない情報
数値の算出方法ウィルソンスコアと、モデルを使わない理由
不正利用への最低限の対策(V1)レート制限、報告者の重み付け、未解決の課題
データの保持と整理生データは48時間、その後は時間単位の集計データ

実行と運用

ローカルで実行するuv または venv、1つのコマンド
プロジェクト構成各ファイルの場所
設定すべての設定項目と、小規模な VPS へのデプロイ
動作していますか?確認に使えるチェック項目
MVP の制限事項現時点でできないことを率直に説明します

Agent A fails.
FailEcho learns.

Agent B encounters the same failure.
It sees what actually worked for other agents.

Agent B benefits from evidence it never generated itself.

1 分で接続

最も簡単な方法は、エージェントに任せることです。 実行している環境(Claude Code、Claude Desktop、Cursor、Codex、独自のハーネス)に、これを貼り付けてください。

Read https://failecho.com/llms.txt and set yourself up to use FailEcho.

機械可読なガイドを読み込み、自動で設定します。アカウントも API キーも、登録も不要です。以下はすべて、同じ設定を手動で行う方法です。

ツール一覧ではなく、ツールの実行経路に組み込んでください。 モデルが呼び出すかどうかを選ぶ必要があるツールは、ほとんど呼び出されません。私たちのラボでは、FailEcho の MCP ツールを利用できるエージェントが、それらを使ったのは 5 回の実行につき約 1 回でした。機能する連携では、モデルがすでに確認している場所に回答が表示されるため、クライアントに応じて選んでください。

エージェントの実行環境インストール方法アドバイスが表示される場所
Claude Codeプラグイン:/plugin marketplace add FailEcho/failecho の後に /plugin install failecho@failechoMCP ツールを呼び出すたびに、フック経由で表示
OpenCode1 つのファイル:.opencode/plugin/failecho.js(ソース)、または npm から "plugin": ["failecho-opencode"]bash や webfetch も含め、すべてのツールの出力に表示
Cursor、Claude Desktop、あらゆる MCP クライアント各 MCP サーバーの前に failecho-mcp proxy -- <server command> を配置失敗したツールのエラー内に表示
独自のコードfailecho-autoreport と FAILECHO_ADVISE=1すでに処理している例外に表示
何もインストールできない場合以下のベア MCP エンドポイントモデルが忘れずに問い合わせた場合のみ

どの方法でもアドバイスを届けられ、4 つすべてをエンドツーエンドでテスト済みです。ラボで測定された効果は、アドバイスに従って動作するエージェントによるものです。switch_model と指示されたらモデルを切り替え、skip と指示されたら停止します(ラッパーを使う 3 行のコード)。ただし、4 つの連携はいずれも、結果を引用できるラボでの比較検証はまだ行われていません。

ベア MCP エンドポイント — 最も簡素で、最も効果の低い方法

https://failecho.com/mcp

ほとんどの MCP クライアントでは、次の設定ブロックを使用します。

{
  "mcpServers": {
    "failecho": { "type": "http", "url": "https://failecho.com/mcp" }
  }
}

Claude Code ではファイル名は .mcp.json です。Cursor では .cursor/mcp.json を使用し、type を省略します。VS Code では .vscode/mcp.json を使用し、最上位のキーを servers とします。エンドポイントは変わりません。セットアップページに表があります。

Claude Code では、CLI が同じファイルを書き込んでくれます。

claude mcp add --transport http --scope project failecho https://failecho.com/mcp

失敗と成功の両方を自動で報告したい場合の Python:

from failecho import FailEcho

echo = FailEcho("https://failecho.com", reporter_id="my-agent-1")

outcome = await echo.observe_tool_call(
    service="github-mcp",
    operation="create_issue",
    call=lambda: github.create_issue(**args),
)

if outcome.failed and outcome.decision.actionable:
    do(outcome.decision.recommendation)   # your code decides, never FailEcho

アカウント不要。API キー不要。公開 MVP 期間中は無料です。 連携ガイド全文:エージェントを接続する。

できること

ほかの AI エージェントも今、同じツールの失敗に遭遇しているか、そしてどの復旧アクションが実際に有効だったかを確認できます。FailEcho は、ツールの失敗後にエージェントが照会できる Model Context Protocol(MCP)エンドポイントと、REST API を公開します。

ツールエージェントが呼び出すタイミング
check_tool_failureツールが失敗したとき — 再試行する前
report_tool_failure失敗を報告する
report_tool_success成功を報告する(分母となるデータ)
report_recovery_outcome修正が有効だったかどうかを伝える

FailEcho は、エラーテキストをモデルを使わずに決定論的に正規化してフィンガープリントを生成し、それに対する復旧結果を蓄積します。独立した報告者間で合意が得られた場合にのみ、推奨を返します。証拠が不十分な場合は推測せず、INSUFFICIENT_DATA を返します。信頼度にはウィルソンスコアの下限値を使用し、併記された件数から再計算できます。

保存するのは失敗のメタデータのみです。プロンプト、ツールの引数、ツールの結果、リクエストまたはレスポンスの本文、ヘッダー、Cookie を格納するフィールドはないため、これらが保存されることはありません。自由記述欄はエラーメッセージの 1 つだけです。これは任意で、フックとラッパーではデフォルトで無効です。送信された場合は正規化され、識別子は置き換えられ、認証情報のような文字列は秘匿されたうえで、元のテキストは破棄されます。この正規化は追加の防御策であり、保証ではありません。正確に言えば、メタデータのみ、エラーテキストはデフォルトで無効、有効時は正規化です。

ライブ環境: https://failecho.com · /ドキュメント · /openapi.json · /llms.txt

これは、オブザーバビリティプラットフォーム、エラーデータベース、稼働時間モニター、LLM デバッガーのいずれでもありません。このシステムの単位は次のとおりです。

service + operation + version + schema_hash + failure fingerprint
                     + observed recovery outcomes
用語
用語意味
FailEcho Networkシステム全体
Failure Echo正規化された観測済みの失敗。フィンガープリント単位で共有されます
Recovery Echo復旧アクションが有効だったことを示す証拠
Incident失敗が急増する異常事態
Reporterテレメトリーを送信するエージェントまたはランタイム
Fingerprint正規化されたエラーを一意に識別する標準表現

ブランド用語は人間向けです。通信形式では、意図的にブランド名を使っていません。エンドポイントのパス、MCP ツール名、フィールド名(fingerprint、recommendation、recovery_actions)は、命名の一貫性より機械にとっての明確さを優先し、そのままにしています。


ネットワーク効果をローカルで確認する

ターミナルを 2 つ使い、所要時間は約 1 分です。

# 1. the network
uv run uvicorn app.main:app --reload
#    or: .venv/bin/python -m uvicorn app.main:app --reload

# 2. six independent agents hitting the same broken tool
uv run python examples/live_agent/run_demo.py
#    or: .venv/bin/python examples/live_agent/run_demo.py

デモでは、小さなローカルツールサーバーを起動し、論理的に独立した 6 つのエージェントを実行します。ネットワーク呼び出しはすべて、外部プロセスから公式 MCP SDK を使って MCP 経由で行われます。

Agent A calls a tool. It fails: the provider renamed a field.
        |
        v
Agent A reports the failure          -> the network records it
Agent A has no evidence to go on, so it retries (fails),
        refreshes the tool schema (works), and reports both outcomes
        |
        v
Agents C, D, E, F hit the same failure with different repository ids
        -> normalization collapses all of them onto ONE fingerprint
        -> the network accumulates evidence from 5 independent reporters
        |
        v
Agent B hits the same failure with yet another id, and asks first
        -> the network recognises the fingerprint
        -> "refresh_schema: 5/5 successes, 5 reporters, confidence 0.57"
        -> "retry: 0/5. Do not bother."
        |
        v
Agent B skips the retry the others wasted a call on, refreshes, succeeds,
and reports its outcome -- which makes the next agent's answer better.

エージェント B はエージェント A に会ったことがありません。会ったのはネットワークだけです。それがこの製品のすべてです。

それまで何も報告せずに問い合わせた、6 番目のエージェントからの実際の出力:

Calling tool...
x tool failed

  422 validation_error
  Repository 987654 rejected field body: field "body" is no longer accepted, use "content"

Checking shared failure intelligence...

  Fingerprint:            6ed9ef705ff4037af2c977306b8b9f92
  Known failure:          YES
  Observed failures:      11
  Independent reporters:  6
  Service status:         MAJOR

  Recovery actions others reported:
    refresh_schema        5/5 (100.0%) confidence 0.57 reporters 5
    retry                 0/5 (0.0%) confidence 0.00 reporters 5

Best observed recovery:
  refresh_schema
  Skipping retry: other agents already proved it does not work here.

Applying recovery: refresh_schema
  Refreshed tool schema -> v3.0.0, field 'content'
  Retrying tool call...
  + tool call succeeded

Reporting recovery outcome...
+ accepted   (refresh_schema -> success)

デモの実行中、http://localhost:8000 のホームページに反映される様子を確認できます。デモのエージェントは X-Reporter-Kind: demo で自身を識別します。そのため、送信されるデータは実際の証拠ですが、導入状況として集計されることはありません。デモデータをご覧ください。

ツールサーバーを個別に実行する方法など、詳しくは examples/live_agentをご覧ください。


エージェントを接続する

接続方法は 2 つあり、その違いは重要です。

MCP では、エージェントが明示的に問い合わせや報告を行えます。check_tool_failure をいつ呼び出すかはモデルが判断するため、エージェントが失敗について推論する場面で的確な情報を得られ、それ以外の処理は行われません。

SDK の計測では、モデルの判断を介さず、すべてのツール呼び出しについて成功と失敗のテレメトリーを自動的に報告します。これによって分母が得られます。分母がなければ、ネットワーク上のあらゆる失敗率に意味がありません。

ほとんどのデプロイでは、両方を使います。

1. MCP
claude mcp add --transport http failecho https://failecho.com/mcp
{
  "mcpServers": {
    "failecho": {
      "type": "http",
      "url": "https://failecho.com/mcp"
    }
  }
}
ツールエージェントが呼び出すタイミング
check_tool_failureツールが失敗したとき — 再試行する前
report_tool_failure失敗を報告する
report_tool_success成功を報告する(分母)
report_recovery_outcome修正が機能したかどうかを伝える
2. Python

client/ をプロジェクトにコピーしてから(まだ PyPI には公開されていません)、次を実行します。

from failecho import FailEcho

echo = FailEcho(
    endpoint="https://failecho.com",
    reporter_id="my-agent-1",       # optional, hashed server-side
)

outcome = await echo.observe_tool_call(
    service="github-mcp",
    operation="create_issue",
    version="2.8.1",
    schema_hash="a817ce",
    call=lambda: github.create_issue(**args),
)

if outcome.failed and outcome.decision.actionable:
    # YOUR code decides. FailEcho never acts on your behalf.
    if outcome.decision.confidence > 0.8:
        refresh_schema()
        await echo.report_recovery(
            fingerprint=outcome.decision.fingerprint,
            action="refresh_schema",
            successful=True,
        )

observe_tool_call は成功または失敗を報告し、呼び出しが失敗した場合は FailEcho に問い合わせて、FailureDecision を返します。再試行、更新、フォールバックは行いません。復旧処理を実行すると二重投稿や二重請求が発生する可能性があるため、その判断はユーザーに委ねられます。

エージェントに影響を与えることはありません。 すべての呼び出しは障害時にも安全に処理されます。タイムアウトやホストに接続できない場合でも、そのエラーは無視され、ツールの結果がそのまま返されます。FAILECHO_DISABLED=1 を設定すると、クライアント全体が何もしなくなります。

3. フレームワークの計装

Pydantic AI とのリファレンス統合:

from failecho import FailEcho
from failecho.integrations.pydantic_ai import instrument_toolset

echo = FailEcho("https://failecho.com", reporter_id="my-agent-1")
agent = Agent("openai:gpt-4o", toolsets=[instrument_toolset(my_toolset, echo)])

これで、すべてのツール呼び出しの結果が報告されます。ラッパーは動作に影響を与えません。結果、例外、制御フローは変わりません。ツールの引数が読み取られたり、送信されたりすることはありません。

ほかのフレームワーク(LangChain、LlamaIndex、CrewAI、OpenAI Agents SDK、Claude Code のフック)はまだ実装されていません。FailEcho のコアに手を加えるのではなく、failecho.adapters.ToolTelemetrySink を実装する必要があります。イベントは4種類で、データの流れは一方向です。client/failecho/adapters.py を参照してください。

4. REST
curl -X POST https://failecho.com/v1/query \
  -H "Content-Type: application/json" \
  -H "X-Reporter-ID: my-agent-1" \
  -d '{
    "service": "github-mcp",
    "operation": "create_issue",
    "error_type": "validation_error",
    "error_code": "422",
    "error_message": "Repository 555812 was not found"
  }'
5. Claude Code プラグイン(自動)

MCP サーバーを接続しても、ツールが失敗したときに FailEcho を呼び出すかどうかはモデルに委ねられるため、モデルが呼び出しを忘れることがあります。プラグインを使えば、その判断が不要になります。

/plugin marketplace add FailEcho/failecho
/plugin install failecho@failecho

これにより、MCP サーバーと、MCP ツール呼び出しのたびに Claude Code が実行するフックの両方がインストールされます。そのため、すべての失敗が報告され、成功によって失敗率の分母が得られ、2回目の試行は復旧として記録されます(同じ引数での再試行は retry、新しい引数での再試行は adjust_arguments)。ネットワークですでに失敗が確認されている場合、フックは Claude が再試行する前に、ほかの人がその失敗に遭遇した頻度と、どの復旧方法が有効だったかを簡潔に伝えます。

プラグインを使わない場合、フックは Python 3 以外の依存関係がない単一のファイルです。

mkdir -p ~/.claude/hooks
curl -fsSL https://raw.githubusercontent.com/FailEcho/failecho/main/plugin/hooks/failecho_hook.py \
  -o ~/.claude/hooks/failecho_hook.py

次に、~/.claude/settings.json に追加します。

{
  "hooks": {
    "PostToolUseFailure": [{"matcher": "mcp__.*", "hooks": [
      {"type": "command", "command": "python3 ~/.claude/hooks/failecho_hook.py", "timeout": 10}]}],
    "PostToolUse": [{"matcher": "mcp__.*", "hooks": [
      {"type": "command", "command": "python3 ~/.claude/hooks/failecho_hook.py", "timeout": 10}]}]
  }
}

マシンの外に送信される情報:サーバーの公開名とツール名、大まかなエラーの種類とコード(rate_limit / 429)、および呼び出しのレイテンシーです。ツールの引数、ツールの結果、プロンプト、ファイルパス、セッション ID は送信されません。エラーテキストは、FAILECHO_HOOK_SEND_ERRORS=1 を設定した場合にのみ送信されます。サーバー名は、公開パッケージ(npx @scope/server、uvx server)または公開ホスト名から判定されます。ローカルスクリプトとプライベートホストは完全に除外されます。FAILECHO_HOOK_SERVICE_NAMES='{"alias": "public-name"}' を使って、名前を指定することもできます。FailEcho に接続できない場合、フックは短いタイムアウトを1回待って処理を諦め、Claude はそのまま続行します。

変数デフォルト用途
FAILECHO_DISABLED未設定1 にするとフックがオフになります
FAILECHO_HOOK_SEND_ERRORS未設定1 にすると、サーバー側で正規化されたエラーテキストも送信します
FAILECHO_HOOK_REPORT_SUCCESS10 にすると成功の報告を停止します
FAILECHO_HOOK_SERVICE_NAMES未設定サーバーのエイリアスと公開名を対応付ける JSON マップ
FAILECHO_ENDPOINThttps://failecho.comセルフホストする場合の独自サーバー
レポーター ID について

任意であり、設定は必須ではありません。安定した ID を指定した場合、受信時にソルトを加えてハッシュ化されます。元の値が保存されることはありません。これにより、レポーターの個別カウント、データ汚染への耐性、推奨が自分以外のユーザーから寄せられたことを FailEcho が判定する能力という、3つの点が改善します。匿名での報告も引き続き完全にサポートされます。

独自のエージェント(ファーストパーティ)

ネットワークのブートストラップ中も、運営者自身のエージェントから実際の障害が報告されます。このデータは実際の現場の証拠ですが、独立したものではなく、導入実績でもありません。そのため、表示される場所にはすべて独自のラベルが付いています。

ソース報告者導入実績としてカウントエージェントへの表示
agent実際のエージェントはいagent
first_partyFailEcho 独自のエージェントいいえfirst_party
demo_agentX-Reporter-Kind: demo を送信するエージェントいいえデモデータ
syntheticscripts/seed_demo.pyいいえデモデータ

first_party は誰が報告しているかを示すものなので、証明が必要です。X-FailEcho-Operator: <FIN_FIRST_PARTY_TOKEN> を送信してください。トークンが間違っているか、指定されていない場合はデモデータとして保存されるため、導入実績には含まれず、運営者の証拠として誰かに表示されることもありません。各クエリの回答には evidence_sources が含まれるので、エージェントは、first_party のみを根拠とする回答と、独立したエージェントも裏付けている回答を区別できます。

サーバー上でトークンを一度だけ生成します。

echo "FIN_FIRST_PARTY_TOKEN=$(openssl rand -hex 32)" >> /etc/failecho.env

次に、独自のエージェントにトークンを渡します。それ以外の人には渡さないでください。

# Claude Code
claude mcp add --transport http failecho https://failecho.com/mcp \
  --header "X-FailEcho-Operator: <token>"

# stdio relay
FAILECHO_OPERATOR_TOKEN=<token> failecho-mcp

Python クライアントでは operator_token="<token>" を指定するか、FAILECHO_OPERATOR_TOKEN を読み込みます。

失敗した対象の命名

名前はフィンガープリントの一部です。そのため、エージェントが同じ対象を同じ名前で指定した場合にのみ、証拠が共有されます。service には MCP サーバー自身の名前(その serverInfo.name)または HTTP API のホストを使用し、operation にはサーバーで定義されているツール名をそのまま使用してください。mcp__github__create_issue ではなく、create_issue とします。

コンセプト

Agent A fails
    |
    v
reports anonymously  ---------> network learns
                                    |
Agent B hits the same problem       |
    |                               |
    v                               v
queries the network  <---------  what happened to others
    |
    v
skips the useless retry, uses the recovery that works

ローカルで実行する

Python 3.11 以降。

# with uv
uv venv
uv pip install -r requirements.txt
uv run uvicorn app.main:app --reload

# or plain venv + pip
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
.venv/bin/python -m uvicorn app.main:app --reload

ホームページに表示するデータを用意するため、合成デモデータをシードします。

.venv/bin/python scripts/seed_demo.py            # add demo data
.venv/bin/python scripts/seed_demo.py --reset    # replace existing demo data
.venv/bin/python scripts/seed_demo.py --purge    # remove demo data

その後、次の場所にアクセスします。

テストを実行します。

.venv/bin/python -m pytest

期限切れの生の観測データを時間単位の集計データにまとめます(いつでも安全に実行できます)。

.venv/bin/python scripts/prune.py --dry-run
.venv/bin/python scripts/prune.py

エンドツーエンドの例(サーバーが実行中である必要があります)。

.venv/bin/python client/example_agent.py            # REST, single agent
.venv/bin/python examples/live_agent/run_demo.py    # MCP, six agents, network effect

デモでは、ツールサーバーをバックグラウンドスレッドで実行します。別々に実行する場合(ターミナルを2つ使用)は、次のようにします。

.venv/bin/python examples/live_agent/tool_server.py
.venv/bin/python examples/live_agent/run_demo.py --no-tool-server

MCP

MCP サーバーは 同じ FastAPI プロセス内で実行されるため、デプロイや監視が必要なサービスを別途用意する必要はありません。/mcp で Streamable HTTP を使用します。JSON レスポンスによるステートレスな構成で、セッションごとのメモリや長時間存続するストリームがありません。この構成により、小規模な VPS でも運用できます。

接続

Claude Code:

claude mcp add --transport http failecho https://failecho.com/mcp
# local:
claude mcp add --transport http failecho http://localhost:8000/mcp

汎用 MCP クライアントの設定(mcpServers 形式):

{
  "mcpServers": {
    "failecho": {
      "type": "http",
      "url": "https://failecho.com/mcp"
    }
  }
}

動作を確認したい場合は、生の JSON-RPC を使用します。

curl -s localhost:8000/mcp \
  -H 'content-type: application/json' \
  -H 'accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
ローカル stdio サーバー

ホストによっては、ローカルプロセスを起動し、stdin/stdout 経由で通信する方法しか利用できません。 failecho-mcp は、そうしたホスト向けです。これはリレーであり、FailEcho の別インスタンスではありません。データベースはなく、何も保存しません。すべての tools/list と tools/call は共有ネットワークに転送されるため、上記の URL と同じ説明と証拠を備えた、同じ 4 つのツールを提供します。

uvx failecho-mcp
{
  "mcpServers": {
    "failecho": {
      "command": "uvx",
      "args": ["failecho-mcp"]
    }
  }
}

failecho-mcp はこのリポジトリとは別に公開されており、依存するのは mcp のみです。パッケージ数は 29 個、サイズは約 48 MB、コールドキャッシュからの所要時間は約 2 秒です。サーバーパッケージ(failecho-server、このリポジトリ)はサーバーそのものであるため、FastAPI、SQLAlchemy、uvicorn を使用します。一方、リレーはこれらを一切インポートしません。

Node 用の同じリレーも npm-relay/ にあります。

{
  "mcpServers": {
    "failecho": {
      "command": "npx",
      "args": ["-y", "failecho-mcp"]
    }
  }
}

依存関係はゼロ、サイズは 6 KB で、コールド状態の npx キャッシュから約 1 秒です。ツールは同じ 4 つで、証拠も同じ、何も保存しません。すでに利用しているランタイムに合わせてお選びください。

開発中にチェックアウトからリレーを実行するには、次のようにします。

uv run failecho-mcp
変数デフォルト用途
FAILECHO_URLhttps://failecho.com/mcp転送先のネットワークです。セルフホストする場合は、自分のサーバーを指定してください。
FAILECHO_REPORTER_KIND未設定デモエージェントの場合は demo に設定し、レポートが導入数に含まれないようにします。

ネットワークに接続できない場合、ツール呼び出しはその旨を示すエラー結果を返し、何も記録しません。エージェントは応答を待ち続ける代わりに、独自の再試行ポリシーに従います。

クライアントが URL に対応している場合は、URL の使用をおすすめします。中継が 1 つ減り、インストールも不要です。

ツール
ツール用途
check_tool_failure再試行の前に呼び出します。 この障害で今何が起きているか、実際に効果のあった復旧方法は何かを確認します。
report_tool_failure障害の観測結果を投稿します。フィンガープリントを返します。
report_tool_success障害率の分母を得るため、成功を投稿します。
report_recovery_outcome復旧アクションが有効だったかを報告します。

4 つのツールはすべて REST エンドポイント(app/core/service.py)と同じ関数を呼び出します。そのため、MCP クライアントと curl ユーザーの間で障害の意味が食い違うことはありません。正規化処理は 1 つ、フィンガープリント関数も 1 つ、インテリジェンスレイヤーも 1 つです。

check_tool_failure の結果の例:

{
  "known": true,
  "fingerprint": "01ae47053fbb3eabf8f3e480cba45ba8",
  "status": "MAJOR",
  "observations": { "total": 418, "last_5m": 81, "last_1h": 201, "unique_reporters": 47 },
  "failure_rate": { "last_5m": 0.73, "last_1h": 0.31 },
  "recovery_actions": [
    { "action": "refresh_schema", "attempts": 124, "successes": 117,
      "success_rate": 0.9435, "effective_attempts": 124, "unique_reporters": 45,
      "confidence": 0.8881 }
  ],
  "recommendation": { "action": "refresh_schema", "confidence": 0.8881 },
  "demo_data_included": false
}

demo_data_included は、数値に合成デモ行が含まれているかどうかをエージェントに伝えます。FIN_MCP_ENABLED=0 に設定すると、MCP を完全に無効にできます。


REST API

呼び出しは 3 種類です。アカウントも API キーも支払いも不要です。

エンドポイント呼び出すタイミング
POST /v1/observeすべてのツール呼び出しの後。成功時も失敗時も呼び出します。
POST /v1/query呼び出しが失敗したとき、再試行する前に呼び出します。
POST /v1/outcome復旧アクションを試した後に呼び出します。
障害を報告する
curl -s localhost:8000/v1/observe \
  -H 'content-type: application/json' \
  -H 'X-Reporter-ID: my-agent-1' \
  -d '{
    "service": "github-mcp",
    "operation": "create_issue",
    "version": "2.8.1",
    "schema_hash": "a817ce",
    "outcome": "failure",
    "error_type": "validation_error",
    "error_code": "422",
    "error_message": "Repository 918272 was not found",
    "latency_ms": 421
  }'
{
  "accepted": true,
  "fingerprint": "01ae47053fbb3eabf8f3e480cba45ba8",
  "known": true,
  "observations": 143,
  "normalized_error": "Repository <N> was not found"
}

メッセージは保存前に正規化されます。 Repository 918272 was not found → Repository <N> was not found。フィンガープリントは sha256(service | operation | version | schema_hash | error_type | error_code | normalized_error) で、32 桁の 16 進文字列に切り詰められます。

成功を報告する

障害率の分母を得るには、成功も送信する必要があります。

curl -s localhost:8000/v1/observe \
  -H 'content-type: application/json' \
  -d '{
    "service": "github-mcp", "operation": "create_issue",
    "version": "2.8.1", "schema_hash": "a817ce",
    "outcome": "success", "latency_ms": 318
  }'
ネットワークに問い合わせる
curl -s localhost:8000/v1/query \
  -H 'content-type: application/json' \
  -d '{
    "service": "github-mcp",
    "operation": "create_issue",
    "version": "2.8.1",
    "schema_hash": "a817ce",
    "error_type": "validation_error",
    "error_code": "422",
    "error_message": "Repository 555812 was not found"
  }'
{
  "known": true,
  "fingerprint": "01ae47053fbb3eabf8f3e480cba45ba8",
  "status": "MAJOR",
  "looks_new": false,
  "observations": { "total": 418, "last_5m": 81, "last_1h": 201, "unique_reporters": 47 },
  "failure_rate": { "last_5m": 0.73, "last_1h": 0.31 },
  "recovery_actions": [
    { "action": "refresh_schema", "attempts": 124, "successes": 117,
      "success_rate": 0.9435, "confidence": 0.8881 },
    { "action": "retry", "attempts": 91, "successes": 17,
      "success_rate": 0.1868, "confidence": 0.12 }
  ],
  "recommendation": {
    "action": "refresh_schema", "confidence": 0.8881,
    "based_on_attempts": 124, "based_on_successes": 117
  }
}

ネットワークに有用な情報がない場合:

{ "known": false, "status": "INSUFFICIENT_DATA", "recommendation": null }

/v1/query は読み取り専用です。何も保存しません。

復旧結果を報告する
curl -s localhost:8000/v1/outcome \
  -H 'content-type: application/json' \
  -d '{
    "fingerprint": "01ae47053fbb3eabf8f3e480cba45ba8",
    "action": "refresh_schema",
    "successful": true
  }'
{ "accepted": true }

V1 では、アクションは自由形式の文字列です。一般的なものとして、retry、wait、refresh_schema、remove_optional_field、reconnect、use_fallback、reauthenticate、abort があります。

ステータス
curl -s localhost:8000/v1/services              # per service/operation health, worst first
curl -s localhost:8000/v1/stats                 # counters; real and synthetic kept separate
curl -s localhost:8000/v1/recovery-intelligence # best evidenced recovery actions
curl -s localhost:8000/health                   # {"status":"ok"}
curl -s localhost:8000/llms.txt                 # agent-readable description of the service

Python クライアント

依存関係はありません。標準ライブラリのみを使用します。client/failure_network.py と client/failecho.py をエージェントにコピーしてください(パッケージはまだ公開されていません)。

推奨されるインポート名は failecho です。これは failure_network を再エクスポートするだけで、 従来どおり変更なく動作します。名称変更は追加的なものなので、 既存のコードに影響はありません。

エラーテキストの送信はオプトインです。ラッパーのデフォルトの分類器は 例外クラスとステータスコードを報告し、メッセージは報告しません。テキストも送信するには、 FAILECHO_SEND_ERRORS=1 を設定してください。以下の例のように明示的に渡された error_message は、常に送信されます。これはデフォルトの動作ではなく、選択するのはあなたです。

from failecho import Client   # or: from failure_network import Client

client = Client("http://localhost:8000", reporter_id="my-agent-1")

client.observe_failure(
    service="github-mcp",
    operation="create_issue",
    version="2.8.1",
    schema_hash="abc",
    error_type="validation_error",
    error_code="422",
    error_message="Repository 91827 not found",
)

intel = client.query(
    service="github-mcp",
    operation="create_issue",
    version="2.8.1",
    schema_hash="abc",
    error_type="validation_error",
    error_code="422",
    error_message="Repository 12345 not found",
)

if intel["recommendation"]:
    action = intel["recommendation"]["action"]     # e.g. "refresh_schema"
    client.report_recovery(
        fingerprint=intel["fingerprint"], action=action, successful=True
    )

client.observe_success(service="github-mcp", operation="create_issue", latency_ms=318)

すべての呼び出しはフェイルソフトです。タイムアウトやサーバーに到達できない場合は例外を発生させず、 None(または query から中立的な INSUFFICIENT_DATA 辞書)を返します。 テレメトリが、監視対象のエージェントを決して停止させてはなりません。


接続に必要なこと

何もありません。 ホスト型 MCP エンドポイント(https://failecho.com/mcp)、REST API、 プラグイン、プロキシ、failecho-autoreport は、キー、トークン、アカウントを必要とせず、 認証情報を読み取りません。任意の設定はすべて Configuration に記載されています。設定に必要となるシークレットは、 プライベートモードを選択した場合に使う、ご自身のチームトークンだけです。

このリポジトリには、FailEcho 自身のラボ(スコアボードの背後で動作するテストエージェント群 (failecho_fleet、failecho_agent、failecho_sandbox、deploy/))用のツールも含まれています。 これらのツールは、モデルプロバイダーのキー (GROQ_API_KEY、GEMINI_API_KEY、...)と FailEcho の運用者トークンを、 当社のサーバー環境から読み取ります。これらは必要ありません。また、インストールするものが これらを読み取ることもありません。ラボの数値を確認できるよう公開しているのであり、 あなた自身が実行するためではありません。

app/web/static/vendor/ は Swagger UI です。上流のビルド成果物を変更せずに含めており、 チェックサムはその README に記載されています。 編集されるとテストが失敗します。

プライバシー

プライバシーは設定ではなく、製品の機能です。

収集するもの — 構造化された障害メタデータのみです。

フィールド説明
service、operation、version、schema_hash呼び出されたもの
outcomesuccess または failure
error_type、error_code短い分類情報
normalized_error識別子を置換し、シークレットを秘匿
latency_ms
fingerprintSHA-256 ダイジェスト
reporter_hash任意のヘッダーをソルト付きでハッシュ化した値、または NULL
created_at、source

収集せず、保存もしないもの:

  • プロンプト
  • モデルのメッセージ
  • ツールの引数
  • ツールの結果
  • リクエスト本文およびレスポンス本文
  • HTTP ヘッダーおよび Cookie
  • API キー、トークン、シークレット
  • 顧客の氏名、メールアドレス、およびユーザーコンテンツ
  • クレジットカード情報

メタデータのみです。上の表にないフィールドは、このネットワークでは必要ありません。 また、スキーマ上も保存先はありません。

これをどのように徹底しているか:

  1. リクエストスキーマには、これらの情報を格納するフィールドがありません。未知の JSON キーは ハンドラーの実行前に Pydantic によって破棄されるため、エージェントが誤って {"prompt": ...} を送信しても、ここに保存されることはありません。
  2. 生の error_message はエッジで正規化され、生の文字列は破棄されます。カラムに書き込まれることも、 ログに記録されることもありません。残るのは normalized_error のみです。
  3. 正規化では、まず秘匿処理を行います。認証情報の形式に一致する部分文字列(Bearer トークン、API キー、 JWT、カード番号形式の数字のまとまり)は分類・保存されず、<REDACTED> に置き換えられます。
  4. X-Reporter-ID は任意です。受信時に FIN_REPORTER_SALT を使ってソルト付きでハッシュ化されます。 生の値は保存されません。ソルトをローテーションすると、既存のハッシュ同士を関連付けられなくなります。
  5. 認証がないため、そもそも漏えいするアカウント、メールアドレス、請求先の識別情報はありません。

正規化の例:

Repository 918272 was not found              -> Repository <N> was not found
User [email protected] at 10.0.12.7 failed      -> User <EMAIL> at <IP> failed
GET https://api.example.com/v1/x?y=2 failed  -> GET <URL> failed
token=sk_live_9aBc12345678xyz rejected       -> <REDACTED> rejected
HTTP 422 unprocessable                       -> HTTP 422 unprocessable   (unchanged)

小さな数値は意図的に残しています。422 と 500 は識別子ではなく、意味を持つ値です。 app/core/normalize.py と app/core/privacy.py を参照してください。


数値の算出方法

すべて、観測件数に対する決定論的な算術処理です。モデルも学習済みパラメーターもなく、自分で再計算できないものはありません。

インシデントのステータス(MVP ヒューリスティック。定数は app/core/config.py にあります):

< 10 observations in the last hour        -> INSUFFICIENT_DATA
failure rate < 5%                         -> HEALTHY
failure rate >= 5%  and < 30%             -> DEGRADED
failure rate >= 30%                       -> MAJOR

5 分間のウィンドウに少なくとも 5 件の観測が含まれると、1 時間のウィンドウに代わります。これにより、新しいインシデントが 1 時間分の正常な履歴で薄められることはありません。これは比率に対するしきい値であり、変化点検出でも、季節性を考慮したものでも、統計的に較正されたものでもありません。意図的に MVP のロジックとして位置付けています。

復旧信頼度は、そのアクションの成功率に対する 95% Wilson スコア区間の下限です。サンプルサイズを数値に反映するため、成功率 5/5 のアクションは成功率 117/124 のアクションより低く評価されます。アクションを推奨するには、5 回以上の試行と成功率 60% 以上が必要です。また、信頼度は 1.0 未満に制限されます。証拠が不十分な場合は、"recommendation": null が返されます。ネットワークが信頼度を捏造することはありません。

ユニークな報告者数は、null ではない報告者ハッシュの重複を除いた件数です。そのため、1 つのエージェントが 1000 件のイベントを送信しても、独立した報告者が 1000 人いるようには見えません。匿名の観測はこの件数から除外されるため、実際より少ない値になります。


不正利用への最低限の対策(V1)

アカウントがないため、防御策は ID ベースではなく構造的なものです。どちらも透明性のある、独立した 2 つのレイヤーで構成されています。

報告者ごとの証拠上限。 信頼度と推奨の算出では、1 人の報告者が fingerprint + action + hour ごとに寄与できる試行回数は FIN_MAX_REPORTER_WEIGHT_PER_HOUR(デフォルトは 5)までです。生の件数はそのまま報告されます。API は attempts と effective_attempts の両方を返すため、報告された件数と実際に算入された件数を確認できます。バケットの上限を超えた場合、成功数も比例して減らされるため、件数を減らして成功率が上がることはありません。1 つのバケット内の匿名報告は、すべて1 人の報告者として扱われます。帰属先のない証拠は、それらが独立していることを証明できません。

報告者の多様性。 推奨には、有効な試行が 5 回以上あり、成功率が 60% 以上であることが必要です。FIN_MIN_UNIQUE_REPORTERS(デフォルトは 3)に満たない報告者数で裏付けられた証拠はブロックされません。匿名での報告もサポートされているためです。ただし、その信頼度には FIN_LOW_DIVERSITY_CONFIDENCE_FACTOR(デフォルトは 0.7)が乗算されます。

書き込みレート制限。 POST /v1/observe、POST /v1/outcome、および MCP の報告ツールは、クライアント IP ごとに FIN_RATE_LIMIT_WRITES_PER_MINUTE(デフォルトは 120)という 1 つの共通枠を使用します。トランスポートを切り替えても、別の枠は得られません。読み取りはレート制限されません。問い合わせることがこの製品の目的だからです。リミッターはプロセス内の dict です。分散型ではないため、2 つ目のワーカーには独自の枠が割り当てられ、分散型の大量リクエストを阻止することもできません。攻撃者が IP を変える場合にも機能する防御策は証拠上限です。リクエストではなく、影響を制限するためです。

Cloudflare または nginx の背後に配置する場合は、FIN_TRUST_PROXY=1 を設定して、リミッターがプロキシ自身のアドレスではなく CF-Connecting-IP / X-Forwarded-For を読み取るようにしてください。サーバーを直接公開する場合は、この設定を無効のままにしてください。これらのヘッダーを信頼すると、どのクライアントでもレート制限に使う ID を偽装できてしまいます。

報告者 IDは引き続き任意で、保存前にソルトを使ってハッシュ化されます。生の識別子がどこかに書き込まれることはありません。


保持とプルーニング

生の観測データはホットパス(5分および1時間のウィンドウが直接読み取ります)であると同時に、無制限に増え続けるデータでもあります。そのため:

raw observations   kept FIN_RETENTION_HOURS (default 48h)
                   then folded into hourly aggregates and deleted
hourly aggregates  kept indefinitely

2つの集計テーブルがあります。hourly_stats(時間 × サービス × 操作 × バージョン × スキーマ × ソースごとの成功数、失敗数、ユニークな報告者数、レイテンシの合計/件数)と、hourly_recovery_stats(時間 × フィンガープリント × アクションごとの試行数、成功数、および上限適用済みの有効件数)です。

不変条件: 生データの行は、1つのトランザクション内で集計され、削除されます。そのため、集計データは常に、すでに存在しない行だけを表します。「生データ+集計データ」の合計は常に全件数であり、二重カウントにはなりません。また、すでに取り込んだデータはなくなっているため、プルーナーを再実行しても何も起こりません。短いウィンドウ(5分、1時間)は常に生データの行のみを読み取るため、プルーニングによって現在のステータスが変わることはありません。リカバリーの上限は時間バケットごとに適用され、これは集計データの粒度と一致するため、プルーニングによって推奨内容が変わることもありません。

python scripts/prune.py                # use FIN_RETENTION_HOURS
python scripts/prune.py --hours 24     # override the window
python scripts/prune.py --dry-run      # report only, change nothing
python scripts/prune.py --vacuum       # also reclaim file space (briefly locks)
Retention window: 48h
Cutoff:           2026-09-08T09:51:18Z
Aggregated 18429 observations into 96 hourly buckets
Aggregated 812 recovery outcomes into 41 hourly buckets
Deleted 18429 raw observations
Deleted 812 raw recovery outcomes
Database size:    4.21 MB

推奨 cron(毎時15分)— ローカル開発では不要です:

15 * * * * /srv/failure-network/.venv/bin/python /srv/failure-network/scripts/prune.py >> /var/log/failure-network-prune.log 2>&1

または、同梱の systemd タイマー deploy/failure-network-prune.timer を使用してください。


プロジェクトの構成

app/
  main.py               FastAPI app, CORS, static homepage, /health, /llms.txt
  mcp_server.py         MCP tools + Streamable HTTP endpoint (same process)
  api/                  observe.py  query.py  outcome.py  services.py  deps.py
  core/                 normalize.py  fingerprint.py  intelligence.py
                        service.py  retention.py  ratelimit.py
                        privacy.py  config.py  clock.py
  db/                   database.py (async engine)  models.py
  schemas/              Pydantic request/response models with agent-readable docs
  web/static/           index.html  style.css  app.js   (no framework, no build)
                        logo.svg  favicon.svg  og-image.svg
client/
  failecho/             the public client package
    __init__.py         FailEcho: observe_tool_call, report_*, query
    adapters.py         ToolTelemetrySink -- the framework seam
    integrations/
      pydantic_ai.py    reference integration (optional dependency)
  failure_network.py    zero-dependency REST client (still supported)
  auto_recovery.py      the passive wrapper FailEcho is built on
  auto_recovery.py      failure-aware tool wrapper (reports + asks, never acts)
  example_agent.py      end-to-end REST usage example
examples/live_agent/
  tool_server.py        local tool that just shipped a breaking change
  tool_client.py        agent-side tool client with a stale cached schema
  network.py            MCP client (official SDK) for the four network tools
  agents.py             the autonomous loop: fail -> report -> ask -> recover
  run_demo.py           one command, six independent agents
scripts/
  seed_demo.py          synthetic demo telemetry (source='synthetic')
  prune.py              aggregate + delete expired raw rows
deploy/
  failure-network.service        systemd unit
  failure-network-prune.timer    hourly retention timer
  Caddyfile.failecho-dev         optional origin-level .dev redirect
LICENSE  SECURITY.md  CONTRIBUTING.md  .env.example
tests/                  the suite

app/core/service.py は、トランスポートの処理を一貫させる境界です。REST ハンドラーと MCP ツールは、どちらも record_observation、query_intelligence、record_recovery_outcome を呼び出します。app/core/ 内のコードは HTTP を認識しないため、次のトランスポート(OTel レシーバー、ワーカー、CLI)も同じ方法で接続できます。

デモデータ

scripts/seed_demo.py は、4つのサービスにわたる約2000件の観測データと約300件のリカバリー結果を書き込みます。すべての行には source='synthetic' というタグが付けられます。

サービス操作シナリオ
github-mcpcreate_issueMAJOR — スキーマの不一致。refresh_schema で修正できますが、retry では修正できません
search-apisearchDEGRADED — 上流のタイムアウト。use_fallback が機能します
stripe-mcpcreate_refundHEALTHY — ときどきレート制限が発生します
example-agent-toolrunHEALTHY — まれにクラッシュしますが、リカバリーの試行は3回のみのため、推奨内容は提示されません

実データではないテレメトリには2種類あり、どちらも行レベルの source 列で識別されます。

sourceデータの発生元導入実績としてカウント
agent実際の自律システムはい
demo_agentX-Reporter-Kind: demo を送信した呼び出し元(デモエージェント)いいえ
syntheticscripts/seed_demo.pyいいえ

demo_agent の行は、実際のツール呼び出しから得られた実際の観測データです。デモでは実際にツールを故障させ、実際に復旧させます。ただし、デモであるため、導入実績の指標には含まれません。自己申告によって報告が格下げされることはあっても、格上げされることはありません。呼び出し元が送信する情報によって行を実テレメトリに変えることはできないため、このヘッダーを信頼しても安全です。

FIN_DEMO_MODE=1 は、デプロイ環境をデモ用インスタンスとして識別します。この場合、/v1/stats は demo_mode: true を返し、ホームページには DEMO MODE バッジが表示されます。この設定によってトラフィックが生成されることはありません。すでに保存されているデータにラベルを付けるだけです。このプロジェクトは、起動時にテレメトリを捏造することはありません。

どちらの種類も、表示されるすべての場所で個別に追跡されます。

  • /v1/stats は、すべてのデモ行を除外した real_observations_total、real_observations_24h、real_reporters_24h、real_failure_fingerprints に加え、synthetic_observations と demo_agent_observations を別々に報告します。これらを合算して1つの導入実績数にすることはありません。
  • ホームページでは、実テレメトリを見出しのブロックに表示し、合成データのカウンターを、明確にラベル付けした別のブロックに表示します。
  • /v1/recovery-intelligence は各エントリーに demo_data: true|false のフラグを付けます(?include_demo=false を指定すると非表示になります)。
  • POST /v1/query と MCP の check_tool_failure ツールは demo_data_included を返すため、自律型の呼び出し元はデモの情報に基づいて動作しているかどうかを把握できます。

python scripts/seed_demo.py --purge を実行すると、すべて削除できます。


設定

すべての設定は環境変数です。デフォルト値は app/core/config.py にあります。

変数デフォルト意味
FIN_DATABASE_URLsqlite+aiosqlite:///./data/failure_network.db後で postgresql+asyncpg://... に差し替えます
FIN_REPORTER_SALTdev-salt-change-me本番環境では変更してください。ローテーションすると、古いハッシュとの紐付けが解除されます
FIN_WINDOW_SHORT_SECONDS300短いウィンドウ
FIN_WINDOW_LONG_SECONDS3600長いウィンドウ
FIN_MIN_OBSERVATIONS_FOR_STATUS10これを下回る場合:INSUFFICIENT_DATA
FIN_HEALTHY_MAX_FAILURE_RATE0.05
FIN_DEGRADED_MAX_FAILURE_RATE0.30
FIN_MIN_RECOVERY_ATTEMPTS5推奨を提示するために必要な最低限の証拠
FIN_MIN_RECOVERY_SUCCESS_RATE0.60
FIN_MAX_CONFIDENCE0.99確実であるとは決して断言しません
FIN_MAX_REPORTER_WEIGHT_PER_HOUR5フィンガープリント+アクション+1時間あたりに、1人の報告者が寄与できる試行回数の上限
FIN_MIN_UNIQUE_REPORTERS3これを下回る場合、信頼度を割り引きます(ブロックはしません)
FIN_LOW_DIVERSITY_CONFIDENCE_FACTOR0.7割引率
FIN_RATE_LIMIT_ENABLED1書き込みのレート制限のオン/オフ
FIN_RATE_LIMIT_WRITES_PER_MINUTE120クライアント IP ごと。REST と MCP の合計
FIN_TRUST_PROXY0CF-Connecting-IP/X-Forwarded-For を読み取ります。本物のプロキシの背後にある場合のみ有効にしてください
FIN_RETENTION_HOURS48これより古い生の観測データは集約され、削除されます
FIN_MCP_ENABLED1MCP エンドポイントをマウントします
FIN_MCP_PATH/mcpマウント先
FIN_MCP_ALLOWED_HOSTS(空)カンマ区切りのリスト。設定すると DNS リバインディング対策が有効になります
FIN_MCP_ALLOWED_ORIGINS(空)カンマ区切りのリスト。同様です
FIN_ALLOWED_ORIGINS*ブラウザー向けの CORS オリジン(カンマ区切り)
FIN_PUBLIC_URLhttp://localhost:8000正規の公開オリジン。正規/OG タグ、/llms.txt、ページ上のすべての例に反映されます
FIN_GITHUB_URL(空)リポジトリへのリンク(本番環境では https://github.com/FailEcho/failecho)。空の場合、GitHub リンクはどこにも表示されません
FIN_DEMO_MODE0このデプロイをデモインスタンスとして表示します(何も生成しません)
小規模な VPS へのデプロイ
ブランド素材
app/web/static/logo.svg       the mark, inherits surrounding text colour
app/web/static/favicon.svg    the mark with fixed neutrals, for tab bars
app/web/static/og-image.svg   1200x630 social card

このマークは、障害イベントとそのエコーを表しています。シグナルレッドの縦長の線が外側に向かって繰り返され、次第に薄れていきます。ロゴタイプは埋め込まれていません。「FailEcho」は常に隣に HTML テキストとして表示されるため、マークは 16px のサイズでもアバターとしても使いやすいままです。

og-image.svg はそのまま配信されます。ほとんどのソーシャルプラットフォームは SVG のプレビューを表示しません。PNG が必要になった場合は、任意のツールで一度書き出し、レンダリング用の依存関係をサービスに追加するのではなく、SVG の隣に配置してください。

ドメイン

failecho.com が正規の公開オリジンです。エージェントや人が必要とするものは、すべてここにあります。

https://failecho.com/              homepage
https://failecho.com/mcp           MCP endpoint (Streamable HTTP)
https://failecho.com/docs          API reference
https://failecho.com/openapi.json  machine-readable schema
https://failecho.com/llms.txt      plain-text summary for agents

failecho.dev はセカンダリドメインで、パスを維持したまま failecho.com に恒久的にリダイレクトされます。

https://failecho.dev/*      ->  301  ->  https://failecho.com/*
https://failecho.dev/docs   ->  301  ->  https://failecho.com/docs
https://failecho.dev/mcp    ->  301  ->  https://failecho.com/mcp

これはアプリケーションではなく、エッジで行ってください。アプリはセカンダリドメインを認識せず、そのための機能を追加すべきではありません。

www.failecho.com → failecho.com は、オリジン側の Caddy(redir https://failecho.com{uri} permanent)で処理されるため、Cloudflare のルールは不要です。必要なのは、プロキシ済みの www DNS レコードだけです。

.dev ドメインには Cloudflare(推奨)を使用します。 同じアカウントに failecho.dev を追加し、Rules → Redirect Rules → Create rule を選択します。

フィールド値
When incoming requests matchHostname contains failecho.dev
ThenDynamic redirect
Expressionconcat("https://failecho.com", http.request.uri.path)
Status301
Preserve query stringon

1 つのルールで failecho.dev と www.failecho.dev の両方をカバーできます。Hostname contains の条件がどちらにも一致し、無料プランでも料金はかかりません。.dev からサイトのコピーを配信することは絶対に避けてください。同じコンテンツを複数のオリジンから配信すると、Google が誤った正規 URL を選ぶ典型的な原因になります。どちらのホスト名にも、プロキシ済みの DNS レコード(オリジンを指す A レコード、またはリクエストをオリジンに一切到達させたくない場合は 100:: を指す AAAA レコード)が必要です。

Caddy のフォールバックは、オリジンから .dev を配信する場合に使用します。設定は deploy/Caddyfile.failecho-dev に含まれています。

failecho.dev, www.failecho.dev {
	redir https://failecho.com{uri} permanent
}

api.failecho.com は、この MVP では意図的に使用していません。API とサイトは同じプロセスなので、オリジンを分けてもメリットがない一方で、証明書、CORS の対象範囲、説明する対象がそれぞれもう 1 つずつ増えるためです。

オリジンは一度だけ、1 か所で設定します。

FIN_PUBLIC_URL=https://failecho.com

この設定は、canonical タグ、Open Graph URL、/llms.txt、ホームページに表示される MCP エンドポイント、コピー可能なすべてのサンプルに適用されます。コードベース内のどのファイルにもドメインはハードコードされていません。設定しない場合は、すべてリクエスト自身のオリジンにフォールバックするため、ローカル開発でも IP アドレスでのアクセスでも正しく動作します。

Cloudflare のチェックリスト

DNS

名前タイプ値プロキシ
failecho.comAorigin IPproxied
www.failecho.comAorigin IPproxied
failecho.devAorigin IPproxied
www.failecho.devAorigin IPproxied

www.failecho.com → failecho.com は Caddy(redir ... permanent)で処理されます。.dev のホスト名は、上記のリダイレクトルールで処理されます。

初回セットアップでは順序が重要です。 Caddy が Let's Encrypt 証明書を取得するまでは、レコードを**プロキシなし(灰色の雲)**にしておきます。その後、プロキシを有効にして SSL/TLS → Overview → Full (strict) に設定します。先にプロキシを有効にしたり、モードを「Flexible」のままにしたりすると、通常は問題が発生します。

キャッシュ。 稼働中のエンドポイントは、絶対にキャッシュしないでください。Caddy はすでに /v1/*、/health、/mcp に Cache-Control: no-store を送信し、/static/* には max-age=3600 を設定しています。包括的なキャッシュルールを追加するのではなく、Cloudflare は「Respect origin headers」のままにしてください。/mcp をキャッシュすると MCP セッションが壊れ、/v1/stats をキャッシュすると、稼働中のネットワークが停止しているように見えてしまいます。

レート制限。 Cloudflare のレート制限は補助的なものであり、代わりになるものではありません。FailEcho 独自の IP ごとの書き込み制限と、報告者ごとの証拠上限は、プロキシがオフでも機能し続ける必要があります。これらがデータ汚染を防ぐ仕組みであり、CDN の有無はデータ汚染に関係ありません。ここで挙げた内容に、有料の Cloudflare プランは必要ありません。

デプロイトポロジー

想定されるトポロジー。 アプリはループバックのみでバインドし、TLS と公開アドレスは Cloudflare とローカルのリバースプロキシが担います。

   internet
      |
      v
  Cloudflare (TLS, DNS, DDoS)
      |
      v
  nginx / caddy on the VPS  (:443 -> :8000)
      |
      v
  uvicorn 127.0.0.1:8000    FastAPI + SQLite (WAL)

このトポロジーでは、uvicorn を 0.0.0.0 にバインドしないでください。公開アドレスにバインドするとプロキシを迂回してオリジンが直接公開され、FIN_TRUST_PROXY=1 が安全でなくなります(任意のクライアントが X-Forwarded-For を偽装してレート制限を回避できるようになります)。 Docker は任意であり、必須ではありません。

ステップ 1 — レポーターソルトを一度だけ生成し、保持します。

sudo install -d -o failurenet -g failurenet /srv/failure-network/data
printf 'FIN_REPORTER_SALT=%s\n' "$(openssl rand -hex 16)" \
  | sudo tee /etc/failure-network.env > /dev/null
sudo chmod 600 /etc/failure-network.env

コマンドラインでインライン生成すると、再起動のたびに新しいソルトが生成され、すべてのレポーターハッシュとユニークレポーター数が気付かないうちにリセットされます。一度だけ生成し、一度だけ保存してください。

ステップ 2 — 本番環境のコマンド(systemd ユニットで実行するコマンド):

set -a; . /etc/failure-network.env; set +a
export FIN_DATABASE_URL="sqlite+aiosqlite:////srv/failure-network/data/failure_network.db"
export FIN_PUBLIC_URL="https://failecho.com"
export FIN_TRUST_PROXY=1
export FIN_ALLOWED_ORIGINS='*'
export FIN_RETENTION_HOURS=48

/srv/failure-network/.venv/bin/python -m uvicorn app.main:app \
  --host 127.0.0.1 --port 8000 --workers 1 \
  --proxy-headers --forwarded-allow-ips '127.0.0.1' --no-server-header

SQLite URL のスラッシュが4 つあることに注意してください。sqlite+aiosqlite:/// に絶対パス /srv/... が続きます。スラッシュが 3 つの場合、作業ディレクトリからの相対パスになります。

ステップ 3 — リバースプロキシ。 Caddy:

failures.example.com {
    reverse_proxy 127.0.0.1:8000
}

nginx:

location / {
    proxy_pass         http://127.0.0.1:8000;
    proxy_set_header   Host $host;
    proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header   X-Forwarded-Proto $scheme;
    proxy_buffering    off;   # keeps /mcp responsive
}

続いて、sudo cp deploy/failure-network.service /etc/systemd/system/ と sudo systemctl enable --now failure-network を実行します。

環境変数チェックリスト

変数本番環境での値理由
FIN_REPORTER_SALT/etc/failure-network.env にある 32 桁の 16 進数文字列一度だけ設定します。変更すると既存のレポーターハッシュとの紐付けが解除されます
FIN_DATABASE_URLsqlite+aiosqlite:////srv/failure-network/data/failure_network.db絶対パス、スラッシュ 4 つ
FIN_TRUST_PROXY上記のプロキシの背後にある場合のみ 1そうでない場合、クライアントが独自のレート制限識別情報を偽装できます
FIN_ALLOWED_ORIGINS*、または https://yourdomainカンマ区切りです。* にすると公開 API をブラウザーから呼び出せます
FIN_RETENTION_HOURS48これより古い生データ行は時間単位の集計データになります
FIN_DEMO_MODE本番環境では 0デモ用インスタンスの場合のみ 1
FIN_PUBLIC_URLhttps://failecho.comリンク、タグ、例で使用する正規オリジン
FIN_GITHUB_URLリポジトリ URL、または未設定未設定の場合、リンクは表示されません

その他の注意事項

  • ワーカーは 1 つにしてください。 SQLite は書き込みを直列化します。また、レートリミッターと MCP セッションマネージャーはプロセスごとに動作するため、ワーカーを 2 つにすると、レート制限の枠が独立して 2 つになります。PostgreSQL に移行した後にのみ、スケールアウトしてください。
  • MCP は同じプロセスから /mcp で提供されます。プレーンな JSON を返すため、バッファリングを無効にする以外に、SSE 固有のプロキシ調整は不要です。
  • 保持期間: deploy/failure-network-prune.timer、または上記の cron 行を使用します。
  • バックアップ: data/(-wal/-shm を含む)をコピーするか、sqlite3 data/failure_network.db ".backup backup.db" を実行します。停止は不要です。

MCP サーバーをマウントした状態でも、常駐メモリは 150 MB を大きく下回ります。SQLite は synchronous=NORMAL と 5 秒のビジータイムアウトを設定した WAL モードで動作するため、読み取り処理が書き込み処理によってブロックされることはありません。

後から PostgreSQL に移行する

すべてのカラム型は移植可能で、タイムスタンプは UTC のタイムゾーン情報なし形式です。SQLite 固有の型や式インデックスはありません。移行には、FIN_DATABASE_URL=postgresql+asyncpg://... の設定、pip install asyncpg の実行、および Alembic のベースラインを 1 つ適用します。


機能していますか?

FailEcho は、このアイデアが成り立つかどうかを判断する数値を /v1/stats で公開しています。意図的に、見栄えのしない数値にしています。

指標答える問い
real_observations_24h実際のデータは届いていますか?
real_successes_24h分母はありますか、それとも苦情だけですか?
real_reporters_24h独立したシステムはいくつありますか?
known_hit_rate_24hエージェントが問い合わせたとき、FailEcho は何か把握していますか?
recovery_outcome_ratio_24hエージェントは修正が機能したかどうかを報告していますか?
cross_agent_help_24hエージェントは、自分が生成していない証拠を利用しましたか?

重要なのは cross_agent_help_24h です。この指標では、呼び出し元が自身を識別し、推奨事項が返され、その推奨事項の根拠となる報告者のうち少なくとも1人が別の誰かである場合に限り、クエリを数えます。匿名の呼び出し元や、報告者が1人だけの証拠は数えません。効果を過小評価するのは誠実ですが、過大評価するのは誠実ではありません。

recovery_outcome_ratio_24h は不安定な指標です。失敗の報告は自動ですが、修正が機能したかどうかを報告するには、エージェントが後から戻ってくる必要があります。そうした報告がなければ、FailEcho はエラーカウンターにすぎません。

ローンチのマイルストーン

マーケティング上の主張ではなく、内部実験の指標です。

1   one real reporter
2   ten independent real reporters
3   100+ real observations per day
4   the first repeated real fingerprint
5   the first real cross-agent recovery benefit

マイルストーン5が仮説です。エージェントが失敗に遭遇し、FailEcho に問い合わせ、無関係なエージェントが生成した証拠を受け取り、行動を変えて復旧します。それ以前はすべて、基盤づくりです。


MVP の制限事項

率直に記載します。そうしないと、ネットワークの有用性が損なわれるためです。

  • 認証はありません。 誰でも何でも報告できます。報告者ごとの証拠上限とレートリミッターにより、統計を汚染するコストは上がりますが、不可能になるわけではありません。また、多数の IP から分散して大量のリクエストを送れば、依然として通過します。
  • レピュテーションスコアリングはありません。 報告者は順位付けされず、人数だけが数えられます。千回正しい報告をした報告者も、新しい報告者も同じように数えられます。
  • レートリミッターはプロセス内で動作し、分散されていません。 uvicorn ワーカー1つにつき、予算は1つです。再起動するとリセットされます。
  • 高度な異常検知はありません。 ステータスは、2つの固定された期間における失敗率に対する固定しきい値です。
  • 集計での報告者のユニーク数は下限です。 報告者の識別情報はプルーニング後に保持されないため、バケットをマージする際は、実際の重複のない報告者数ではなく、バケットごとの数の最大値が維持されます。
  • OpenTelemetry の取り込みはまだありません、TypeScript SDK もまだありません、決済機能もありません(x402 など、方式を問わず)。すべて無料です。
  • SQLite はプロトタイプ段階での選択です。保持期間の設定によりファイルは小さく保たれますが、ネットワークが活発になれば、いずれ PostgreSQL が必要になります(URL の差し替えと asyncpg の追加で対応できます)。
  • 復旧アクションは自由形式の文字列のため、エージェント間で表記が異なると、refresh_schema と refreshSchema は別々に数えられます(入力は小文字化され、スペースも正規化されます。一般的なケースはこれで処理できます)。

証拠

  • docs/claims.md — FailEcho が行うすべての主張、その正確な根拠、および行ってはならない主張
  • lab.failecho.com/fleet — 敗北したグループも含む、リアルタイムのスコアボード

お問い合わせ

ライセンス

MIT。

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。