Turns the design doc into an ordered, dependency-correct build plan (phases 0-9) with an exit criterion per phase, and records the twelve architectural decisions it rests on as ADRs. Decisions: single Rust binary with routed compose services; Streamable HTTP only; per-agent bearer tokens with clientInfo as a display hint only; SQLite; get_rules delivered via session gating; full-document rule delivery; project_id from day one; enforcement tier scoped to Bridle-mediated actions; stable tool list on upstream failure; OpenAI-compatible embeddings with model/dim guarding; pattern RAG gated behind a spike; CLAUDE.md + AGENTS.md as v1 renderer targets. Deviates from the design doc's original 1-8 ordering by moving the audit log and multi-project schema into phase 1, building the admin API incrementally rather than all at the Web Panel phase, downgrading vendor guardrail sourcing to manual-first, and gating the pattern-example RAG behind a validation spike. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019RZerbsHGF9Ka3bKhCjJ9m
31 lines
1.5 KiB
Markdown
31 lines
1.5 KiB
Markdown
# ADR-0009: Stable tool list, structured errors on upstream failure
|
|
|
|
**Status:** Accepted (2026-08-08)
|
|
|
|
## Context
|
|
|
|
Bridle proxies several upstreams — the Gitea MCP server, Kanboard, Qdrant — any of which can be
|
|
down while the others are healthy. The design doc did not specify what a connected agent sees in
|
|
that case. Options: keep the tool list stable and error on call; health-check upstreams and omit
|
|
their tools from `tools/list`, notifying via `list_changed`; or refuse to serve at all unless every
|
|
upstream is healthy.
|
|
|
|
Hiding tools avoids the agent calling something dead, but mutates the tool list mid-session, which
|
|
some MCP clients cache or otherwise handle badly. Failing the whole session lets one flaky
|
|
container block unrelated work.
|
|
|
|
## Decision
|
|
|
|
The **tool list stays stable** for the whole session and always reflects the agent's permissions,
|
|
not upstream liveness. A call to a downed upstream returns a **clear structured error** naming the
|
|
upstream and the failure mode.
|
|
|
|
## Consequences
|
|
|
|
- No mid-session tool-list churn, so no dependence on client `list_changed` handling.
|
|
- A Qdrant outage does not block Gitea or Kanboard work — failure is isolated per upstream.
|
|
- Agents will occasionally call a tool that cannot currently succeed. The error must be specific
|
|
enough that the agent reports the real cause rather than inventing a workaround.
|
|
- Upstream health is still tracked and surfaced in the Web Panel; it just does not alter the
|
|
advertised tool list.
|