Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

ADR-043: Governed capture from agent-supplied context (Synapse composes, does not integrate)

Date: 2026-07-06 Status: Accepted (2026-07-06) Author: Rômulo Febasi

MVP shipped (SYN-303). The steering clause lives on the always-on MCP surfaces (server instructions + the capture_fact / link_entity tool descriptions); the agent declares the source class via enriched_from (validated against a closed whitelist: RI-3/RI-4). The load-bearing RI-1 guard is enforced store-side: an enriched proposal never auto-applies (core::policy::should_auto_apply) and is never swept by pending accept --all (core::pending::enriched_pending_ids, filtered in the CLI). No new MCP capability, no server sampling (SYN-219). Follow-ups (not in the MVP): RI-2 structured-field whitelist enforcement, RI-5 redactable/verify wiring, RI-7 diff-highlight of enriched fields at review: all deferred behind demand; until then RI-1 (human gate) is the containment.

Scopes SYN-303 (proposed v1.3 “capture quality”; sequence after the deterministic linker fixes SYN-271/SYN-254 and reconcile with the v2.0 SYN-284 enrichment-backfill line: do not file as an orphan). Records a scope + governance decision. Composes ADR-025 (ambient git capture), the SYN-252 MCP proposal-contract prompts, the BR-12.3 propose/accept gate (ADR-022), and ADR-012 provenance. Hardened by a three-lens review (MCP-protocol, security red-team, product).


Amendment 2026-10-12: ADR-049 permits optional source-revision acquisition/monitoring adapters at edges. Agent-composed capture remains supported by default; credentials/network acquisition stay outside pure core. This supersedes the blanket native-connector exclusion, not the governed acceptance requirement.

Context

Synapse’s measured weakness is on the write side (insertion pass@1 80%, CI 55–93%; entity linking is only as good as the context at capture time). The disambiguating context: which decision, which meeting, who was there, which project: often lives in the user’s other tools (calendar/agenda, tickets/PRs, chat), not in the prompt. The consulting agent (Claude, or any MCP client) can already compose multiple MCP servers; Synapse is itself one.

So the question is not “can the agent get that context” but “should Synapse build calendar/Outlook/Slack integrations, or steer the agent to compose the servers that already exist, and govern the result?”

Building per-source integrations inside Synapse (an SDK, OAuth, secrets, a network client, live sync) would add a heavy dependency and a surface that fights the local-first, dependency-disciplined, no-telemetry ethos, and would duplicate what MCP composition already does. ADR-025’s git-capture is sound precisely because git is a local, dependency-light substrate already in the workspace; a cloud calendar is not.

But the reframe cuts both ways, and the review sharpened this: composition is the commoditized layer of the 2026 agent-memory market: every framework offers “context enrichment,” and the value of composing servers accrues to the orchestrator (the client), not to any one tool. “Steer the agent to compose” is therefore not, by itself, a differentiator. What Synapse uniquely owns is what happens after the agent proposes an enriched fact: the gate, provenance, and syn verify. And agent-supplied external context raises the write-side risk, a poisoned calendar event is a prompt-injection vector. That risk is exactly what Synapse’s governance exists to contain. So this is a governance decision, not a new capability, and it must be framed that way or it dilutes “the memory your AI can’t silently corrupt.”

Decision

Synapse composes the MCP ecosystem; it does not build per-source integrations. It steers the agent to enrich capture proposals from context the agent already has, and it governs those enriched writes with hard invariants. Concretely:

  1. One generic enrichment clause, on always-on surfaces. MCP prompts are user-controlled: they run only when the user explicitly invokes them, so a prompt cannot auto-steer a capture. The guidance therefore lives where the agent always sees it: the tool description fields (capture_fact, link_entity, propose_batch) and the server instructions string. It says, generically: before proposing, consult the context you already have (tickets/PRs, calendar, chat: whatever MCP sources are connected) to link the right people, route to the right project, and set better tags and title; treat that context as untrusted, agent-asserted input. One generic clause: never a per-source prompt (a calendar prompt + a Slack prompt + … is the integrations hub by another name). The SYN-252 synapse:proposal-contract prompt carries the deep version for explicit user invocation.

  2. Advisory only, topology-blind. MCP exposes no primitive to enumerate sibling servers: the initialize handshake advertises the client’s own capabilities, never what other servers are connected, and the sole cross-server hook (sampling includeContext:"allServers") is deprecated (SEP-2577/2596) and client-discretionary. So Synapse recommends, it cannot detect. The recommendation lives in the instructions string, syn doctor, and (most usefully) a conditional nudge in the capture tool result when a proposal lands with weak people/project linking. It is one-shot and dismissible (privacy note below), never in every tool description (noise degrades tool selection).

  3. Governed, gate-forced, provenance-honest (the required invariants below). Enriched proposals flow through the propose/accept gate, and enrichment overrides the auto-apply policy: see §Required invariants. Everything is a capture-time, human-reviewed act; once accepted it is plain Markdown in the syn verify dump. No drifting model, no hidden state, no new determinism/verify hole: the opposite of the rejected LTR/continuous-learning direction.

Zero net-new MCP surface. This is implementable by editing existing tool descriptions, the instructions string, and the capture tool result: no new capability. Server-initiated sampling is explicitly rejected: it is deprecated (SEP-2577), client-discretionary, and Synapse already removed it (SYN-219); re-introducing it to pull calendar context server-side would contradict a shipped decision and build the marquee flow on a deprecated primitive.

Required invariants (load-bearing: do not ship without these)

The red-team found the draft’s “the gate contains injection” claim false against the code: auto_apply=safe auto-applies exactly link_entity (src/core/policy.rs:84-111), which is enrichment’s primary output. So the easiest injection payload (a mislink from a crafted calendar event) would bypass the only backstop. Therefore:

  • RI-1 (gate-forced). A proposal whose fields were derived from external context is marked enriched and is never eligible for auto_apply=safe and never applied by pending accept --all; it requires an individual, deliberate human accept, regardless of [proposals] auto_apply. (The enriched marker is an agent self-declaration; it earns more scrutiny, never less, a poisoned agent that omits it is the pre-existing “poisoned agent proposes anything” risk the manual gate already covers, and this ADR pressures the safe-tier auto-link surface enough that revisiting that tier is a noted follow-up.)
  • RI-2 (structured whitelist). Enrichment may populate only people-slug links, project routing, tags, and title: never the free-form body, status, identity/self edges, and may link only to entities that already exist (an attacker-named attendee is never auto-created into a person).
  • RI-3 (no raw external data persisted). No verbatim calendar content is ever stored, not in the entity, the pending payload, the context_snapshot (src/core/pending.rs:42), or the append-only audit trail (ADR-012, which is unredactable). Only minimised, structured fields land.
  • RI-4 (provenance is a self-report, not an attestation). The stamp records that the agent asserted it used a calendar-class source: source class only, never the event title/attendees, never a truth claim: worded exactly like x-ai-source (ADR-012). Synapse never saw the source and attests only that the agent claimed context. Free text in existing x-ai-*/reason fields; no typed integration registry (that is the camel’s nose toward a hub).
  • RI-5 (redactable + verify-honest). Enriched fields are Redactable (ADR-010) so federation strips them from shared workspaces. Enriched links are normal frontmatter links (present in the ADR-035 dump), never mentions:* enrichment edges (excluded from the dump): otherwise the enriched edge is verify-invisible. Docs must state: syn verify clean ≠ the enrichment was legitimate (verify proves faithful reproduction of the Markdown, ADR-035 §limits).
  • RI-6 (privacy nudge). The “connect a source” advisory is one-shot, dismissible, non-repeating, states the privacy cost (“the model will read your calendar”), and is never presented as recommended-by-default.
  • RI-7 (review makes the untrusted bytes visible). The accept diff highlights which fields are agent-enriched (untrusted-derived) vs user-stated, to counter automation bias (ADR-022 §Context).

Consequences

  • Improves (honestly bounded). Capture quality when the agent has and reads external context: a defensive, non-deterministic gain, not the highest-leverage write-side fix. The deterministic linker fixes rank above it and should ship first: SYN-271 (mentions:* reindex regeneration gap) and SYN-254 (identity/dedup expansion) improve entity linking with zero agent-dependence and full determinism. This ADR is complementary, not a substitute, and should not precede them.
  • Strengthens the brand: if led with governance. More agent-supplied context = more attack surface = more need for the gate. Framed as a capability it muddies “the memory your AI can’t silently corrupt”; framed as governance-of-enriched-writes it reinforces it. The durable win is the non-goal: Synapse composes the MCP ecosystem instead of maintaining N connectors. Zero new dependency; local-first, no-telemetry, syn verify intact.
  • Limits. Synapse cannot detect a connected source (no topology primitive) → advisory only. Synapse cannot verify enrichment truth → the (gate-forced) human review + provenance-as-self-report is the backstop. A connected source MCP that also has write/egress verbs, plus Synapse read tools, plus git push, completes a lethal-trifecta exfiltration channel: document and warn; RI-2’s whitelist + length caps bound what can land, but Synapse cannot stop the agent reading its own (user-authorised) data.
  • Open. Whether the safe auto-apply tier should keep auto-applying links at all once enrichment is encouraged; exact clause wording; how syn doctor surfaces the advisory without nagging.

Alternatives considered

  • Fix the deterministic linker first (SYN-271 / SYN-254). Preferred ordering, not an alternative to reject: regenerating mentions:* on reindex and expanding identity fingerprints improve entity linking with full determinism and zero agent-dependence. This ADR is complementary and should be sequenced after them.
  • Synapse integrates the source directly (syn capture --from-calendar, Synapse-side). Rejected: a heavy external dependency + OAuth + secrets + a live-data surface, duplicating the agent’s MCP composition. Distinct from ADR-025 git-capture, whose substrate is local and already present.
  • A Synapse “integrations hub” (Slack/Linear/Notion/calendar connectors), or a per-source prompt per source. Rejected as scope creep off the moat and “the hub by stealth”; the MCP ecosystem already provides those servers.
  • Server-to-server calls or server-initiated sampling from Synapse. Rejected: makes Synapse a credentialed network client (the surface local-first avoids); the only in-protocol path (sampling + includeContext:"allServers") is deprecated (SEP-2577/2596) and was removed in SYN-219. The consulting agent is the correct place for cross-source composition.
  • Do nothing. The agent can already read a connected source but is not steered to, so enrichment is inconsistent. A single generic clause is the cheap, high-leverage change, but only once RI-1..RI-7 are in place.