failecho について
failechoは、AIエージェント向けのエージェント横断型障害情報ネットワークです。正規化した障害フィンガープリントと独立した報告に基づき、同じツール障害への復旧実績を示し、証拠が不十分な場合は推測を避けます。
主な機能
- 01一致する障害の復旧案を確認
- 02障害・成功・復旧結果を報告
- 03エラーを正規化して指紋化
- 04証拠不足時はデータ不足を返却
- 05障害メタデータのみを保存
活用シーン
- 01ツール障害後に再試行するか判断
- 02エージェント間で復旧実績を共有
- 03ツール実行と復旧の結果を集計
MCP 対応
MCPサーバーは障害の確認、障害・成功・復旧結果の報告ツールを提供します。エージェントは再試行前に照会し、観測結果を共有できます。
設定
リモートサーバーはインストール不要です。クライアントを選んで設定をコピーするか、ワンクリックで導入できます。
https://failecho.com/mcpclaude mcp add --transport http com-failecho-failecho https://failecho.com/mcp{"mcpServers":{"com-failecho-failecho":{"type":"http","url":"https://failecho.com/mcp"}}}Cursor で開く{"servers":{"com-failecho-failecho":{"type":"http","url":"https://failecho.com/mcp"}}}VS Code で開く{"mcpServers":{"com-failecho-failecho":{"type":"http","url":"https://failecho.com/mcp"}}}{"mcpServers":{"com-failecho-failecho":{"serverUrl":"https://failecho.com/mcp"}}}コマンドはターミナルで実行し、JSON は各クライアントの MCP 設定に貼り付けて再起動します。認可が必要なサーバーは初回接続時にログインを求めます。
ツール
4| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| service | string | はい | MCP サーバー自体の名前(serverInfo.name)または API ホスト名(例:'api.github.com')。クライアント側のローカルエイリアスではありません。 |
| verbose | boolean | いいえ | 完全な記録(タイムスタンプ、成功率、有効件数、すべてのアクション)。デフォルト:簡潔な回答。 |
| version | string | いいえ | サービス/ツールのバージョン(判明している場合)。 |
| operation | string | はい | サーバーが使用するツールまたはエンドポイント名。例:`create_issue`(`mcp__github__create_issue`ではありません)。 |
| error_code | string | いいえ | コード。例:`422`、`ECONNRESET`。 |
| error_type | string | いいえ | 失敗の分類。例:`validation_error`、`timeout`、`rate_limit`、`auth_error`。 |
| reporter_id | string | いいえ | 任意の安定したエージェント ID。ハッシュ化され、生の値は保存されません。これにより from_other_agents に回答できます。 |
| schema_hash | string | いいえ | 使用したツールスキーマの短いハッシュ(「API の障害」と「スキーマの古さ」を区別します)。 |
| error_message | string | いいえ | エラーテキストのみ。サーバー側で正規化され、この呼び出しでは生の文字列は保存されません。 |
詳細
AI エージェントと自律型ソフトウェアのための失敗インテリジェンス。
再試行する前に、エコーを確認してください。
ウェブサイト · エージェントを接続 · API リファレンス · ライブネットワーク · llms.txt
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.2 | 19.4 |
| 「スキップ」と指示された後も再試行して復旧したエージェント | 404 件中 0 件 |
| まだ示されていない結果 | 使用あり | 使用なし |
|---|---|---|
| すでに慎重に再試行するエージェント:実行あたりの損失秒数 | 9.8 | 10.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@failecho | MCP ツールを呼び出すたびに、フック経由で表示 |
| OpenCode | 1 つのファイル:.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_SUCCESS | 1 | 0 にすると成功の報告を停止します |
FAILECHO_HOOK_SERVICE_NAMES | 未設定 | サーバーのエイリアスと公開名を対応付ける JSON マップ |
FAILECHO_ENDPOINT | https://failecho.com | セルフホストする場合の独自サーバー |
レポーター ID について
任意であり、設定は必須ではありません。安定した ID を指定した場合、受信時にソルトを加えてハッシュ化されます。元の値が保存されることはありません。これにより、レポーターの個別カウント、データ汚染への耐性、推奨が自分以外のユーザーから寄せられたことを FailEcho が判定する能力という、3つの点が改善します。匿名での報告も引き続き完全にサポートされます。
独自のエージェント(ファーストパーティ)
ネットワークのブートストラップ中も、運営者自身のエージェントから実際の障害が報告されます。このデータは実際の現場の証拠ですが、独立したものではなく、導入実績でもありません。そのため、表示される場所にはすべて独自のラベルが付いています。
| ソース | 報告者 | 導入実績としてカウント | エージェントへの表示 |
|---|---|---|---|
agent | 実際のエージェント | はい | agent |
first_party | FailEcho 独自のエージェント | いいえ | first_party |
demo_agent | X-Reporter-Kind: demo を送信するエージェント | いいえ | デモデータ |
synthetic | scripts/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
その後、次の場所にアクセスします。
- ホームページ — http://localhost:8000
- MCP エンドポイント — http://localhost:8000/mcp(Streamable HTTP)
- エージェント向け概要 — http://localhost:8000/llms.txt
- API ドキュメント — http://localhost:8000/docs
- 機械可読なスキーマ — http://localhost:8000/openapi.json
- ヘルスチェック — http://localhost:8000/health
テストを実行します。
.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_URL | https://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 | 呼び出されたもの |
outcome | success または failure |
error_type、error_code | 短い分類情報 |
normalized_error | 識別子を置換し、シークレットを秘匿 |
latency_ms | |
fingerprint | SHA-256 ダイジェスト |
reporter_hash | 任意のヘッダーをソルト付きでハッシュ化した値、または NULL |
created_at、source |
収集せず、保存もしないもの:
- プロンプト
- モデルのメッセージ
- ツールの引数
- ツールの結果
- リクエスト本文およびレスポンス本文
- HTTP ヘッダーおよび Cookie
- API キー、トークン、シークレット
- 顧客の氏名、メールアドレス、およびユーザーコンテンツ
- クレジットカード情報
メタデータのみです。上の表にないフィールドは、このネットワークでは必要ありません。 また、スキーマ上も保存先はありません。
これをどのように徹底しているか:
- リクエストスキーマには、これらの情報を格納するフィールドがありません。未知の JSON キーは
ハンドラーの実行前に Pydantic によって破棄されるため、エージェントが誤って
{"prompt": ...}を送信しても、ここに保存されることはありません。 - 生の
error_messageはエッジで正規化され、生の文字列は破棄されます。カラムに書き込まれることも、 ログに記録されることもありません。残るのはnormalized_errorのみです。 - 正規化では、まず秘匿処理を行います。認証情報の形式に一致する部分文字列(Bearer トークン、API キー、
JWT、カード番号形式の数字のまとまり)は分類・保存されず、
<REDACTED>に置き換えられます。 X-Reporter-IDは任意です。受信時にFIN_REPORTER_SALTを使ってソルト付きでハッシュ化されます。 生の値は保存されません。ソルトをローテーションすると、既存のハッシュ同士を関連付けられなくなります。- 認証がないため、そもそも漏えいするアカウント、メールアドレス、請求先の識別情報はありません。
正規化の例:
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-mcp | create_issue | MAJOR — スキーマの不一致。refresh_schema で修正できますが、retry では修正できません |
search-api | search | DEGRADED — 上流のタイムアウト。use_fallback が機能します |
stripe-mcp | create_refund | HEALTHY — ときどきレート制限が発生します |
example-agent-tool | run | HEALTHY — まれにクラッシュしますが、リカバリーの試行は3回のみのため、推奨内容は提示されません |
実データではないテレメトリには2種類あり、どちらも行レベルの source 列で識別されます。
source | データの発生元 | 導入実績としてカウント |
|---|---|---|
agent | 実際の自律システム | はい |
demo_agent | X-Reporter-Kind: demo を送信した呼び出し元(デモエージェント) | いいえ |
synthetic | scripts/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_URL | sqlite+aiosqlite:///./data/failure_network.db | 後で postgresql+asyncpg://... に差し替えます |
FIN_REPORTER_SALT | dev-salt-change-me | 本番環境では変更してください。ローテーションすると、古いハッシュとの紐付けが解除されます |
FIN_WINDOW_SHORT_SECONDS | 300 | 短いウィンドウ |
FIN_WINDOW_LONG_SECONDS | 3600 | 長いウィンドウ |
FIN_MIN_OBSERVATIONS_FOR_STATUS | 10 | これを下回る場合:INSUFFICIENT_DATA |
FIN_HEALTHY_MAX_FAILURE_RATE | 0.05 | |
FIN_DEGRADED_MAX_FAILURE_RATE | 0.30 | |
FIN_MIN_RECOVERY_ATTEMPTS | 5 | 推奨を提示するために必要な最低限の証拠 |
FIN_MIN_RECOVERY_SUCCESS_RATE | 0.60 | |
FIN_MAX_CONFIDENCE | 0.99 | 確実であるとは決して断言しません |
FIN_MAX_REPORTER_WEIGHT_PER_HOUR | 5 | フィンガープリント+アクション+1時間あたりに、1人の報告者が寄与できる試行回数の上限 |
FIN_MIN_UNIQUE_REPORTERS | 3 | これを下回る場合、信頼度を割り引きます(ブロックはしません) |
FIN_LOW_DIVERSITY_CONFIDENCE_FACTOR | 0.7 | 割引率 |
FIN_RATE_LIMIT_ENABLED | 1 | 書き込みのレート制限のオン/オフ |
FIN_RATE_LIMIT_WRITES_PER_MINUTE | 120 | クライアント IP ごと。REST と MCP の合計 |
FIN_TRUST_PROXY | 0 | CF-Connecting-IP/X-Forwarded-For を読み取ります。本物のプロキシの背後にある場合のみ有効にしてください |
FIN_RETENTION_HOURS | 48 | これより古い生の観測データは集約され、削除されます |
FIN_MCP_ENABLED | 1 | MCP エンドポイントをマウントします |
FIN_MCP_PATH | /mcp | マウント先 |
FIN_MCP_ALLOWED_HOSTS | (空) | カンマ区切りのリスト。設定すると DNS リバインディング対策が有効になります |
FIN_MCP_ALLOWED_ORIGINS | (空) | カンマ区切りのリスト。同様です |
FIN_ALLOWED_ORIGINS | * | ブラウザー向けの CORS オリジン(カンマ区切り) |
FIN_PUBLIC_URL | http://localhost:8000 | 正規の公開オリジン。正規/OG タグ、/llms.txt、ページ上のすべての例に反映されます |
FIN_GITHUB_URL | (空) | リポジトリへのリンク(本番環境では https://github.com/FailEcho/failecho)。空の場合、GitHub リンクはどこにも表示されません |
FIN_DEMO_MODE | 0 | このデプロイをデモインスタンスとして表示します(何も生成しません) |
小規模な 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 match | Hostname contains failecho.dev |
| Then | Dynamic redirect |
| Expression | concat("https://failecho.com", http.request.uri.path) |
| Status | 301 |
| Preserve query string | on |
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.com | A | origin IP | proxied |
www.failecho.com | A | origin IP | proxied |
failecho.dev | A | origin IP | proxied |
www.failecho.dev | A | origin IP | proxied |
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_URL | sqlite+aiosqlite:////srv/failure-network/data/failure_network.db | 絶対パス、スラッシュ 4 つ |
FIN_TRUST_PROXY | 上記のプロキシの背後にある場合のみ 1 | そうでない場合、クライアントが独自のレート制限識別情報を偽装できます |
FIN_ALLOWED_ORIGINS | *、または https://yourdomain | カンマ区切りです。* にすると公開 API をブラウザーから呼び出せます |
FIN_RETENTION_HOURS | 48 | これより古い生データ行は時間単位の集計データになります |
FIN_DEMO_MODE | 本番環境では 0 | デモ用インスタンスの場合のみ 1 |
FIN_PUBLIC_URL | https://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 — 敗北したグループも含む、リアルタイムのスコアボード
お問い合わせ
- 一般のお問い合わせ:[email protected]
- インテグレーションのサポート:[email protected]
- セキュリティに関する報告:[email protected] — SECURITY.md をご覧ください。脆弱性について公開の Issue を作成しないでください
ライセンス
MIT。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。