| name | mcp-architect-conflict-aware-response |
| description | Response schema for MCP tools consuming 2+ sources — surface disagreement structurally, no silent winner-pick. conflicts[] only when sources disagree. Use when: MCP tool synthesizing across sources (research synthesis, multi-doc Q&A, cross-reference, multi-source memory recall), tool answering with 2+ snippets, output read by conflict-detector. Skip: single-source tools, pure aggregation. |
| disable-model-invocation | true |
| version | 0.1.0 |
Conflict-Aware Response
Purpose
Define the response shape for MCP tools that synthesize across two or more sources, so contradictions are surfaced as structured output rather than papered over by a silent pick.
The pattern is design guidance for MCP server authors. The runtime detector is knowledge-hygiene:conflict-detector (commit b28aa0f); this skill specifies the response envelope so a tool's output is directly inspectable by that detector and so consumers can reason about disagreement without re-running the synthesis.
The only value-rule in this pattern (and one of the few in K2 overall) is: the tool must not silently pick a winner when sources disagree. Everything else is preference.
When to Apply
Apply when designing or auditing tools that:
- Take 2+ sources as input (or compose results from 2+ retrieval calls internally) and return a synthesized answer.
- Will be consumed by agents that themselves cite the synthesis as evidence.
- Operate over sources with independent provenance — different files, different URLs, different memory entries, different commits.
Skip when:
- The tool returns from a single source (no disagreement is possible).
- The tool returns raw multi-source results without synthesis (the consumer does the picking; the tool does not).
- "Sources" are not independent (e.g., 5 lines of the same file — not a multi-source case).
Pattern Shape
The response envelope:
{
"answer": "<the synthesized response>",
"sources": [
{
"id": "<stable identifier — file path, URL, memory id>",
"source_text": "<the cited excerpt>",
"provenance": "<file:path:line | memory:id | git:sha | web:url | \"guess\">",
"confidence": "<high | med | low>"
}
],
"conflicts": [
{
"conflict_type": "<direct-contradiction | numeric-mismatch | temporal-mismatch | scope-mismatch>",
"sources": ["<id of source A>", "<id of source B>", "..."],
"recommended_resolution": "<prefer-recent | prefer-authoritative | escalate-to-user>",
"reasoning": "<one or two sentences explaining the disagreement and the resolution choice>"
}
]
}
The conflicts[] field is omitted or empty when there is no conflict — adding an empty array on every response would dilute the signal and train consumers to ignore it. Surface only when there is something to surface.
The schema mirrors the output of knowledge-hygiene:conflict-detector (commit b28aa0f) so a synthesizing tool can route its sources through the detector and embed the detector's verdict directly in this response without reshaping.
The Four Conflict Types
These are the categories the runtime conflict-detector recognizes; a synthesizing tool's conflict_type field should match this vocabulary so consumers can dispatch on it:
direct-contradiction — mutually exclusive assertions ("X is true" vs "X is false").
numeric-mismatch — different numbers for the same quantity ("TTL = 60s" vs "TTL = 300s").
temporal-mismatch — different dates / versions / sequence orderings for the same event.
scope-mismatch — one source claims universally while another scopes narrowly ("always" vs "only on Linux").
A "no conflict" finding is the absence of a conflicts[] entry, not a conflict_type: "none" row. This matches the no-false-positive-bloat preference.
The Three Recommended Resolutions
When a conflict is surfaced, the tool defaults toward one of these named resolutions. The choice is driven by source metadata, not by the tool's opinion:
prefer-recent — when sources have a clear temporal ordering (newer commit, newer retrieved-at, explicit version numbers) AND no other signal favors the older source. Default for documentation drift.
prefer-authoritative — when one source is materially more authoritative for the entity in question:
file:<path>:<line> in the codebase beats web:<url> for behavioral claims about that codebase.
- Spec / RFC / official docs beat blog posts for protocol claims.
- Provenance with
confidence: high beats provenance with confidence: low | guess.
escalate-to-user — when neither recency nor authority cleanly dominates, OR when the contradiction touches a value-layer concern (security, data integrity, breaking changes). The tool does NOT silently pick in these cases.
These three names match the conflict-detector agent's vocabulary exactly so the wire format flows end-to-end without translation.
The No-Silent-Pick Value Rule
This is the only "must" in this skill. Everything else is preference.
A tool that detects disagreement across its sources MUST surface the disagreement in the response. It MUST NOT silently pick a winner.
Operationally, this means:
- If two sources disagree and the tool's answer reflects only one of them, the
conflicts[] array MUST contain an entry naming the disagreement.
- If the resolution is genuinely ambiguous,
recommended_resolution is escalate-to-user — not a hidden pick.
- The
answer field may still commit to one resolution (clients want a usable answer), but the conflicts[] entry makes the choice visible and auditable.
This rule is the operational form of K2 §3.3 (rationalization-trap, the value-layer rule). Silent picking is the rationalization-trap at design time — the tool decides which source to believe, then writes a fluent answer that hides the decision.
Worked Example — Conflict Present
Two sources disagree on a cache TTL. The tool surfaces the conflict:
{
"answer": "The cache TTL is 60 seconds (per src/cache/config.ts), though the README documents it as 300 seconds.",
"sources": [
{
"id": "src/cache/config.ts:42",
"source_text": "const DEFAULT_TTL_SECONDS = 60;",
"provenance": "file:src/cache/config.ts:42",
"confidence": "high"
},
{
"id": "README.md:128",
"source_text": "Cache entries expire after 300 seconds by default.",
"provenance": "file:README.md:128",
"confidence": "high"
}
],
"conflicts": [
{
"conflict_type": "numeric-mismatch",
"sources": ["src/cache/config.ts:42", "README.md:128"],
"recommended_resolution": "prefer-authoritative",
"reasoning": "Behavioral claim about this codebase; the source file beats README documentation drift. README likely stale."
}
]
}
The user gets a usable answer (the answer field commits to 60s) and sees that the README disagrees, so they can decide whether to fix the README.
Worked Example — No Conflict
Same tool, same shape, no disagreement found:
{
"answer": "OmniMEM proposes a 4-layer memory architecture: short-term, episodic, semantic, procedural.",
"sources": [
{
"id": "arxiv:2604.01007",
"source_text": "We organize memory into four layers...",
"provenance": "web:https://arxiv.org/abs/2604.01007",
"confidence": "high"
},
{
"id": "K2:101",
"source_text": "OmniMEM (2604.01007) 4-layer architecture",
"provenance": "file:docs/research/K2-knowledge-hygiene-from-papers.md:101",
"confidence": "high"
}
]
}
Note conflicts[] is absent, not present-and-empty. Consumers can use the existence of the key as a fast signal.
Anti-Patterns
Anti-pattern: Silent pick
{
"answer": "The cache TTL is 60 seconds.",
"sources": [
{"id": "src/cache/config.ts:42", "source_text": "const DEFAULT_TTL_SECONDS = 60;", ...},
{"id": "README.md:128", "source_text": "Cache entries expire after 300 seconds by default.", ...}
]
}
Why bad: violates the only value-rule in this skill. The consumer sees one answer with two supporting sources and concludes the sources agree. They do not. The tool's silent pick has rewritten the apparent state of the world.
Anti-pattern: False-positive bloat
{
"answer": "...",
"sources": [...],
"conflicts": []
}
Why bad: trains consumers to ignore the conflicts[] field. When a real conflict appears, the field looks like background noise. Omit when empty so the field carries signal when present.
Anti-pattern: Conflict surfaced, answer hidden
{
"answer": "Sources disagree on cache TTL — see conflicts[].",
"sources": [...],
"conflicts": [...]
}
Why bad: this is the over-correction. The user asked a question; "go look at conflicts[]" is not a usable answer. Commit to a resolution in answer AND surface the conflict — both, not either.
Anti-pattern: Wrong vocabulary
{
"conflicts": [
{
"conflict_type": "disagreement",
"recommended_resolution": "use the better one"
}
]
}
Why bad: breaks the wire format with knowledge-hygiene:conflict-detector. Consumers that dispatch on the typed vocabulary cannot route this; they fall back to string-matching, which silently fails. Default toward the four-type and three-resolution vocabulary even when a freer-form description seems more natural.
Cross-Plugin Notes
This skill is the emit-side response shape. The runtime side is knowledge-hygiene:conflict-detector (commit b28aa0f), which produces output in this same shape. The two plugins share a single wire format on purpose.
mcp-architect:citation-verification-pattern — every source in the sources[] array should also satisfy the 4-layer citation pattern. Conflict-aware-response handles the across-source discipline; citation-verification handles the per-source discipline.
mcp-architect:progressive-discovery — when conflicts span progressive disclosure layers, surface the conflict at the layer where both sources are visible (typically the synthesis layer, not the per-layer raw output).
- K2 §3.3 (rationalization-trap value-rule) — the silent-pick anti-pattern is the design-time form of the rationalization-trap. This skill operationalizes that rule for multi-source response design.
Citations
- K2 design doc:
docs/research/K2-knowledge-hygiene-from-papers.md §3.2 (Conflict surfacing across sources). Source for the response-must-emit-visible-output rule.
- K2 §3.3 (rationalization-trap, the only value-rule). The no-silent-pick rule above is the design-time form of K2's value-rule.
- ConflictQA + XoT: arxiv
2604.11209 §3 (cross-source knowledge conflict detection mechanism). Source for the four conflict types and the surface-then-reason mechanic.
- knowledge-hygiene:conflict-detector agent (commit
b28aa0f) — the runtime consumer this response shape is wire-compatible with.