mcpField
F
failecho

failecho

远程服务
failecho.comAI 与智能体25 周前更新

关于 failecho

failecho 是面向 AI Agent 的跨 Agent 故障信息网络,可查询其他 Agent 遇到相同工具故障时的恢复结果。它依据标准化故障指纹和独立报告给出建议,证据不足时不猜测。

主要功能

  1. 01查询相同故障的恢复建议
  2. 02提交故障、成功与恢复结果
  3. 03标准化错误并生成指纹
  4. 04证据不足时返回数据不足
  5. 05仅存储故障元数据

适用场景

  1. 01工具调用失败后决定是否重试
  2. 02让多个 Agent 共享恢复经验
  3. 03汇总调用成败与恢复结果

MCP 相关

MCP 服务提供故障查询、故障报告、成功报告和恢复结果报告工具。Agent 可在重试前查询,也可提交观测结果。

配置

远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。

服务地址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否可选的稳定 Agent ID;经过哈希处理,绝不存储原始值。这样才能回答 from_other_agents。
schema_hashstring否所用工具架构的短哈希(用于区分“API 故障”和“架构过时”)。
error_messagestring否仅限错误文本;由服务器端规范化,此调用不会存储原文。

详细介绍

FailEcho

为 AI Agent 和自主软件提供失败情报。
重试之前,先看看回声。

网站 · 连接 Agent · API 参考 · 实时网络 · llms.txt

Python 3.11+ FastAPI MCP License MIT

FailEcho 是一个跨 Agent 的失败情报网络。当工具或模型调用失败时,它会告知你的 Agent,其他 Agent 是如何解决这一确切故障的——或者告诉它目前还没有解决办法,让它停止重试。 Agent 会共享失败的特征以及解决方法(仅限元数据,绝不包含提示词或数据);下一个遇到相同故障的 Agent 就能得到答案。开源,无需账户。

某个 Agent 的 Groq 调用因 429 失败;FailEcho 回复:尝试 switch_model,336 次中有 306 次成功。同一模型上的两个实验室 Agent:没有 FailEcho 的那个重试后失败,有 FailEcho 的那个切换模型并正确作答。接着展示配额耗尽时的跳过判定、坦诚说明没有明确解决办法的回答、仅包含元数据的载荷,以及 FailEcho 无法提供帮助的场景对应的实验室计分板。
每一行都是真实输出:对实验室网络的实时查询、一对根据实验室记录重放的双生 Agent(9 月 24 日)、包装器的实际载荷,以及带有 p 值的实验室计分板。使用的是我们自己的 Agent;目前独立报告者:0。

我们测量了什么,以及尚未测量什么

我们的 Agent 在实验室中以双生组运行:任务相同、模型相同,其中一个会在重试前询问 FailEcho 并根据回答采取行动,另一个不会。测量时间为 2026 年 9 月 22 日至 24 日。**目前独立用户:0。**每个数字、对应样本及显著性检验:docs/claims.md;实时数据见:实验室计分板。

已测量(p < 0.05)使用 FailEcho未使用 FailEcho
从模型提供商的速率限制故障中恢复(收到提示后切换模型)74.5%31.2%
已完成的运行,同一组(每边 416 次)90.6%80.2%
每次运行因不稳定 API 损失的秒数12.219.4
收到“跳过”建议后仍重试并成功恢复的 Agent 数404 次中 0 次
尚未展示使用 FailEcho未使用 FailEcho
已会谨慎重试的 Agent:每次运行损失的秒数9.810.1
答案正确率(通过真实 API 检查)99.3%99.2%
编码 Agent:已完成的运行73.7%73.7%
仅向模型展示建议,由模型自行决定:已完成的运行100%100%
OpenAI 和 Anthropic尚未纳入实验室

目录

从这里开始

一分钟内完成连接端点、插件、一行提示词
它的作用理念,以及其中使用的术语
在本地查看网络效应六个 Agent、一次故障,在你的机器上

连接到某个对象

连接 AgentMCP、Python、框架、REST、Claude Code 插件
MCP端点、stdio 服务、四个工具
REST API每个端点及可运行示例
Python 客户端零依赖,仅使用标准库

工作原理

连接时需要你做什么什么也不用:无需密钥、令牌或账户
隐私哪些内容永远不会发送,哪些内容永远不会存储
如何得出这些数字Wilson 分数,以及为何不用模型
滥用防护底线(V1)速率限制、报告者权重,以及尚未解决的问题
数据保留与清理原始数据保留 48 小时,之后保留每小时聚合数据

运行和运维

本地运行uv 或 venv,一条命令
项目布局各项内容所在的位置
配置所有设置,以及如何部署到小型 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.

一分钟内完成连接

最简单的方式:让 Agent 来配置。 将以下内容粘贴到你正在使用的工具中—— Claude Code、Claude Desktop、Cursor、Codex 或你自己的运行框架:

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

它会读取机器可读指南并自行完成配置。无需账户,无需 API 密钥,也无需注册。下文介绍的都是手动完成相同操作的方法。

将它接入工具调用链路,而不是工具列表。 如果模型必须选择调用某个工具,它大多时候就不会调用:在我们的实验室中,使用 FailEcho MCP 工具的 Agent 平均每五次运行才调用一次。有效的集成会在模型已经查找答案的位置提供答案,因此请按客户端选择:

你的 Agent 运行于安装方式建议的呈现位置
Claude Code安装插件:/plugin marketplace add FailEcho/failecho,然后运行 /plugin install failecho@failecho每次 MCP 工具调用后,通过钩子提供
OpenCode使用单个文件:.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 端点仅当模型记得主动询问时

这四种方式都能提供建议,而且都经过端到端测试。实验室测得的收益来自会采取行动的 Agent——收到 switch_model 指示时切换模型,收到 skip 指示时停止(使用包装器的三行代码);但这四种集成方式本身目前都没有可供引用的实验室对比结果。

纯 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 期间免费。 完整集成指南:连接 Agent。

功能

查看其他 AI Agent 此刻是否也遇到了相同的工具故障,以及哪些恢复操作确实有效。FailEcho 提供一个 Model Context Protocol(MCP)端点,Agent 可在工具故障后查询,还提供 REST API。

工具Agent 调用时机
check_tool_failure工具发生故障时——重试之前
report_tool_failure提交故障信息
report_tool_success提交成功信息(分母)
report_recovery_outcome说明修复是否奏效

FailEcho 会以确定性方式(不使用模型)将错误文本规范化为指纹,累积与之相关的恢复结果,并且仅在独立报告者达成一致时返回建议。证据不足时会返回 INSUFFICIENT_DATA,而不是猜测。置信度是 Wilson 分数下界,可根据其旁边返回的计数重新计算。

系统只存储故障元数据。没有用于提示词、工具参数、工具结果、请求或响应正文、标头或 Cookie 的字段,因此这些内容都无法存储。有一个字段是自由文本,即错误消息:在钩子和包装器中默认关闭,可选启用;发送时会先进行规范化——替换标识符、编辑符合凭据格式的字符串——然后丢弃原始文本。这种规范化是第二道防线,并非保证;准确的说法是仅存储元数据,错误文本默认关闭,启用时会进行规范化。

在线服务: https://failecho.com · /docs · /openapi.json · /llms.txt

这不是可观测性平台、错误数据库、运行时间监控器或大模型调试器。系统的基本单位是:

service + operation + version + schema_hash + failure fingerprint
                     + observed recovery outcomes
术语
术语含义
FailEcho Network整个系统
Failure Echo按指纹共享的规范化已观察故障
Recovery Echo恢复操作奏效的证据
Incident故障突然异常增加
Reporter发送遥测数据的 Agent 或运行时
Fingerprint规范化错误的规范身份标识

品牌术语面向人类。线格式有意不使用品牌名称:端点路径、MCP 工具名称和字段名称(fingerprint、recommendation、recovery_actions)都保持原样,因为机器清晰度比命名纯粹性更重要。


在本地体验网络效应

打开两个终端,大约一分钟。

# 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

演示会启动一个小型本地工具服务器,然后让六个逻辑上相互独立的 Agent 对其进行调用。所有网络调用都通过 MCP,从外部进程发起,并使用官方 MCP SDK。

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.

Agent B 从未遇见过 Agent A。它只与网络交互。这就是整个产品。

第六个 Agent 提问时的真实输出;此前它没有提交过任何信息:

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 首页上。演示 Agent 会使用 X-Reporter-Kind: demo 标记自身,因此其流量是真实证据,但绝不会计入采用情况——参见演示数据。

详情(包括如何单独运行工具服务器)请参见 examples/live_agent。


连接 Agent

有两种接入方式,二者的区别很重要。

MCP 允许 Agent 显式提问和报告——由模型决定何时调用 check_tool_failure,因此你能在 Agent 推理故障时,恰到好处地获得相关信息,除此之外不会发生其他操作。

SDK 插桩会为每次工具调用自动报告成功和故障遥测数据,不由模型决定是否报告。这会产生分母;没有分母,网络中的每个故障率都毫无意义。

大多数部署需要同时使用两者。

1. MCP
claude mcp add --transport http failecho https://failecho.com/mcp
{
  "mcpServers": {
    "failecho": {
      "type": "http",
      "url": "https://failecho.com/mcp"
    }
  }
}
工具Agent 调用时机
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 交给你。它绝不会重试、刷新或回退——执行恢复操作可能导致重复发布或重复扣费,因此由你决定如何处理。

它不会破坏你的 Agent。 每次调用都采用故障软处理:超时或无法连接主机时,会忽略该问题并照常返回工具结果。设置 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 hooks)的集成尚未开发。它们应实现 failecho.adapters.ToolTelemetrySink——仅包含四个事件,且数据只向一个方向传递——而不是修改 FailEcho 的核心。详见 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 服务和一个 hook,Claude Code 会在每次 MCP 工具调用后运行它,因此每次失败都会被上报,成功调用会为失败率提供分母,而第二次尝试则会被记录为恢复操作(使用相同参数的 retry,或使用新参数的 adjust_arguments)。当网络已经知道某种失败情况时,hook 会在 Claude 重试前向它提供简短提示——其他人遇到这种情况的频率,以及哪种恢复方式奏效。

不安装插件也可以使用 hook:它是单个文件,除 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,hook 会在一次短暂超时后放弃,Claude 会继续运行。

变量默认值用途
FAILECHO_DISABLED未设置设为 1 可关闭 hook
FAILECHO_HOOK_SEND_ERRORS未设置设为 1 时也会发送错误文本,并在服务端进行规范化处理
FAILECHO_HOOK_REPORT_SUCCESS1设为 0 可停止上报成功情况
FAILECHO_HOOK_SERVICE_NAMES未设置将服务别名映射到公开名称的 JSON 映射
FAILECHO_ENDPOINThttps://failecho.com自行托管时使用的服务器
关于上报者 ID

此项可选,并非必需。稳定 ID 在收到后会加盐并哈希处理——原始值绝不会被存储——它能改进三方面:独立上报者计数、抗投毒能力,以及 FailEcho 告知你某项建议来自其他人的能力。系统始终完全支持匿名上报。


自有 Agent(第一方)

在网络启动期间,运营方自己的 Agent 也会报告真实故障。这些数据是真实的现场证据,但并非独立证据,也不代表采用情况,因此无论出现在哪里,都会带有单独的标签:

来源来自谁是否计为采用向 Agent 显示为
agent任意真实 Agent是agent
first_partyFailEcho 自有 Agent否first_party
demo_agent发送 X-Reporter-Kind: demo 的 Agent否演示数据
syntheticscripts/seed_demo.py否演示数据

first_party 表示报告者的身份,因此必须经过验证:发送 X-FailEcho-Operator: <FIN_FIRST_PARTY_TOKEN>。令牌错误或缺失时,数据会被存为演示数据,因此不会计入采用情况,也绝不会作为运营方证据展示给任何人。每个查询答复都会列出 evidence_sources,因此 Agent 可以分辨某个答复是仅由 first_party 支持,还是也有独立 Agent 的支持。

在服务器上生成一次令牌:

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

然后将它提供给你自己的 Agent,不要给其他人:

# 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。

为故障命名

名称是指纹的一部分,因此只有当 Agent 用相同方式为同一对象命名时,证据才会共享。将 MCP 服务自己的名称(其 serverInfo.name)或 HTTP API 的主机名用作 service,并将服务器定义的工具名称原样用作 operation:create_issue,而不是 mcp__github__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

演示会在后台线程中运行其工具服务器。若要单独运行它(使用两个终端):

.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 中的工具相同,描述和证据也相同。

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

failecho-mcp 与此仓库分开发布,且仅依赖 mcp —— 共 29 个包,约 48 MB,冷缓存时大约需要两秒。 服务端包(failecho-server,即此仓库)依赖 FastAPI、 SQLAlchemy 和 uvicorn,因为它就是服务端;中继不会导入其中任何依赖。

Node 也有同样的中继,位于 npm-relay/:

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

零依赖,6 KB,冷 npx 缓存时大约需要一秒。提供相同的四种工具和相同的证据,不存储任何内容。使用你已有的运行时即可。

在检出代码后,可通过以下命令运行中继并进行开发:

uv run failecho-mcp
变量默认值用途
FAILECHO_URLhttps://failecho.com/mcp要转发到的网络。如果你自托管,可将其指向自己的服务。
FAILECHO_REPORTER_KIND未设置对演示 Agent 设置为 demo,这样它们的报告就不会计入采用率数据。

如果无法连接网络,工具调用会返回一条说明情况的错误结果,不会记录任何内容;Agent 会改为采用自身的重试策略,而不是一直挂起。

如果客户端支持 URL,优先使用 URL:少一次跳转,也无需安装任何内容。

工具
工具用途
check_tool_failure重试前调用。 此故障目前是什么情况?哪种恢复方式确实奏效?
report_tool_failure提交故障观察结果。返回其指纹。
report_tool_success提交成功结果,为故障率提供分母。
report_recovery_outcome报告恢复操作是否奏效。

这四种工具调用的函数与 REST 端点相同(app/core/service.py),因此 MCP 客户端和 curl 用户对故障含义的判断永远不会相互矛盾——只有一个规范化器、一个指纹函数和一个智能层。

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 会告知 Agent 数字中是否包含合成演示数据行。设置 FIN_MCP_ENABLED=0 可完全禁用 MCP。


REST API

三个调用。无需账户、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 个十六进制字符。

报告成功

故障率需要分母,因此也要提交成功结果:

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 复制到你的 Agent 中(该包尚未发布)。

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 字典),而不是抛出异常。 遥测绝不能影响它所观察的 Agent。


连接需要你做什么

**什么都不需要。**托管的 MCP 端点(https://failecho.com/mcp)、REST API、 插件、代理和 failecho-autoreport 均无需密钥、令牌或账户,也不会读取任何凭据。 所有可选设置都列在配置中;其中唯一需要的秘密信息是你自己的 团队令牌(如果你选择使用私有模式)。

此仓库还包含 FailEcho 自有实验室的工具——计分板背后的测试 Agent 集群 (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. 请求架构中没有这些字段。处理器运行前,Pydantic 会丢弃未知的 JSON 键,因此 Agent 即使意外发送了 {"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 小时窗口,避免新发生的事件被过去一小时的正常历史数据稀释。这是对比率设置的阈值,不是变点检测,也不考虑季节性,且未经统计校准。它被刻意标记为 MVP 逻辑。

恢复置信度是该操作成功率的 95% 威尔逊分数区间下界。它将样本量纳入数值,因此 5/5 次成功的排名低于 117/124 次成功。只有至少有 5 次尝试且成功率达到 60%,才会推荐某项操作;置信度上限低于 1.0。证据不足时,返回 "recommendation": null。网络不会凭空捏造置信度。

独立报告者数统计不同的非空报告者哈希值,因此,一个 Agent 发送 1000 个事件不会被视为 1000 个独立报告者。匿名观测不计入此数,因此该数值是下界。


防滥用底线(V1)

没有账户,因此防御措施以结构性手段为基础,而非基于身份。两层彼此独立,且都透明:

每位报告者的证据上限。 对于置信度和推荐,每位报告者在每个 fingerprint + action + hour 组合下贡献的尝试次数最多为 FIN_MAX_REPORTER_WEIGHT_PER_HOUR(默认值为 5)。原始计数仍会如实报告——API 会同时返回 attempts 和 effective_attempts,因此你可以看到报告的数量以及实际计入的数量。如果某个桶触及上限,成功次数也会按比例缩减,因此削减数量绝不会凭空提高成功率。同一桶中的所有匿名报告都视为同一位报告者:无法归属身份的证据不能证明其彼此独立。

报告者多样性。 推荐需要 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)。切换传输方式不会获得第二份预算。读取操作永不受速率限制;查询就是产品本身。限流器使用进程内字典:它不是分布式的,因此第二个工作进程会有自己的预算,而且它无法阻止分布式流量洪泛。证据上限才是能抵御更换 IP 的攻击者的防御措施,因为它限制的是影响力,而非请求数。

如果服务器部署在 Cloudflare 或 nginx 后方,请设置 FIN_TRUST_PROXY=1,让限流器读取 CF-Connecting-IP / X-Forwarded-For,而不是代理自身的地址。如果服务器直接暴露在外,则应保持此设置关闭:信任这些标头会让任何客户端都能伪造自己的速率限制身份。

报告者身份仍为可选项,且在存储前仍会加盐哈希。原始标识符绝不会写入任何位置。


保留与清理

原始观测是热路径(5 分钟和 1 小时窗口会直接读取它们),也是会无限增长的数据。因此:

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

两张聚合表:hourly_stats(按小时 × 服务 × 操作 × 版本 × 架构 × 来源统计成功数、失败数、唯一报告者数、延迟总和/计数) 和 hourly_recovery_stats(按小时 × 指纹 × 操作统计尝试次数、成功次数和封顶后的有效计数)。

**不变量:**原始行会在同一事务中完成聚合并删除,因此聚合数据只描述已不存在的行。“原始数据 + 聚合数据”是总数,绝不会重复计数;重新运行清理器不会产生任何变化,因为已折叠的数据已经不存在。较短的窗口(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 会写入约 2000 条观测和约 300 条恢复结果,涵盖四个服务;每行都带有 source='synthetic' 标签:

服务操作场景
github-mcpcreate_issueMAJOR — 架构漂移;refresh_schema 可以修复,retry 不行
search-apisearchDEGRADED — 上游超时;use_fallback 有效
stripe-mcpcreate_refundHEALTHY — 偶尔触发速率限制
example-agent-toolrunHEALTHY — 极少发生崩溃,只有 3 次恢复尝试,因此不会给出建议

非真实遥测分为两种,都会通过行级的 source 列标记:

source来源是否计入采用情况
agent真实的自主系统是
demo_agent发送了 X-Reporter-Kind: demo 的调用方(演示 Agent)否
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。它们绝不会合并为一个采用情况数字。
  • 首页会在标题区块中呈现真实遥测数据,并在单独且明确标注的区块中呈现合成数据计数;
  • /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单个报告者每小时针对每个指纹 + 操作最多贡献的尝试次数
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_PROXY0读取 CF-Connecting-IP / X-Forwarded-For;仅在真实代理后方使用
FIN_RETENTION_HOURS48超过此时限的原始观测数据将被汇总并删除
FIN_MCP_ENABLED1挂载 MCP 端点
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 是规范的公共来源。Agent 或人类所需的一切都在此域名上:

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:

字段值
匹配传入请求的条件Hostname contains failecho.dev
然后动态重定向
表达式concat("https://failecho.com", http.request.uri.path)
状态码301
保留查询字符串开启

一条规则即可覆盖 failecho.dev 和 www.failecho.dev — Hostname contains 匹配会捕获这两个域名 — 免费套餐也无需付费。切勿从 .dev 提供网站副本:两个来源提供相同内容,是导致 Google 选错规范来源的经典原因。两个主机名仍都需要已代理的 DNS 记录(指向源站的 A 记录,或者如果你希望源站完全看不到请求,则指向 100:: 的 AAAA 记录)。

Caddy 备用方案,如果你之后改为从源站提供 .dev — 配置文件位于 deploy/Caddyfile.failecho-dev:

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

本 MVP 刻意不使用 api.failecho.com:第二个来源意味着第二张证书、第二个 CORS 范围,以及又一件需要解释的事情,而 API 和网站运行在同一进程中,没有任何好处。

只需在一个地方设置一次源站:

FIN_PUBLIC_URL=https://failecho.com

它会决定规范链接标签、Open Graph URL、/llms.txt、首页显示的 MCP 端点,以及每个可复制示例的内容。代码库中没有任何文件硬编码域名。若不设置,所有内容都会回退到请求自身的来源,因此本地开发和通过 IP 地址访问都能正常运行。

Cloudflare 检查清单

DNS

名称类型值代理
failecho.comA源站 IP已代理
www.failecho.comA源站 IP已代理
failecho.devA源站 IP已代理
www.failecho.devA源站 IP已代理

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 中的四个斜杠:sqlite+aiosqlite:/// 加上绝对路径 /srv/...。三个斜杠会使路径相对于工作目录。

步骤 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 位十六进制字符设置一次;轮换盐值会导致现有报告者哈希失去关联
FIN_DATABASE_URLsqlite+aiosqlite:////srv/failure-network/data/failure_network.db绝对路径,四个斜杠
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,或不设置未设置时不会显示链接

其他说明

  • 单个工作进程。 SQLite 本身会串行处理写入,而且速率限制器和 MCP 会话管理器都是进程级的——两个工作进程意味着两套独立的速率限制配额。只有迁移到 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 以 WAL 模式运行,设置为 synchronous=NORMAL,繁忙超时为 5 秒,因此读取操作不会被写入操作阻塞。

之后迁移到 PostgreSQL

所有列类型都可移植,时间戳均为无时区 UTC,没有 SQLite 专用类型,也没有表达式索引。迁移只需设置 FIN_DATABASE_URL=postgresql+asyncpg://...、运行 pip install asyncpg,并执行一次 Alembic 基线迁移。


它在运行吗?

FailEcho 会在 /v1/stats 上公布决定这个想法是否成立的数据。这些数据有意呈现得不那么好看。

指标它回答的问题
real_observations_24h是否有真实数据传入?
real_successes_24h我们有分母,还是只有投诉?
real_reporters_24h有多少个独立系统?
known_hit_rate_24hAgent 发起查询时,FailEcho 能提供信息吗?
recovery_outcome_ratio_24hAgent 会反馈修复是否奏效吗?
cross_agent_help_24hAgent 是否使用了并非由自己生成的证据?

cross_agent_help_24h 是最重要的指标。只有在调用方表明了身份、系统返回了建议,而且该建议背后至少有一名报告者是其他人时,才会计入一次查询。匿名调用方和只有一名报告者提供的证据都不计入——低估效果是诚实的,高估则不是。

recovery_outcome_ratio_24h 是最难衡量的指标。报告故障是自动的;要报告修复是否奏效,则需要 Agent 之后再次回来。如果没有这些报告,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 是我们要验证的假设:Agent 遇到故障,查询 FailEcho,收到由无关 Agent 生成的证据,改变行为并恢复。此前的一切都只是基础设施。


MVP 的局限

坦诚说明这些局限,因为假装没有只会降低网络的实用性:

  • 没有身份验证。 任何人都可以报告任何内容。每位报告者的证据上限和速率限制器提高了污染统计数据的成本,但无法完全阻止这种行为;来自许多 IP 的分布式洪泛仍然可以通过。
  • 没有信誉评分。 报告者只计数,不排名。正确报告过一千次的报告者,和新报告者的权重相同。
  • 速率限制器在进程内运行,并非分布式。 一个 uvicorn 工作进程对应一个限额,重启后会重置。
  • 没有复杂的异常检测。 状态是根据两个固定时间窗口内的故障率,按固定阈值判定的。
  • 聚合数据中的独立报告者数量是下限。 修剪后不会保留报告者身份,因此合并后的桶会取各桶报告者数量的最大值,而不是真正的去重计数。
  • 尚不支持 OpenTelemetry 数据接入、尚无 TypeScript SDK、不支持付费(无论是 x402 还是其他方式)。目前一切免费。
  • SQLite 是原型阶段的选择。数据保留机制会控制文件大小,但网络繁忙后最终会需要 PostgreSQL(替换 URL 并添加 asyncpg 即可)。
  • 恢复操作使用自由格式字符串,因此如果 Agent 的拼写不一致,refresh_schema 和 refreshSchema 会被分别计数(输入会转换为小写并规范化空格,可处理常见情况)。

证据

联系方式

许可证

MIT。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。