Skip to content

Reintroduce sink interceptor type for context-reactive workflows#1

Open
PederHP wants to merge 1 commit into
Degiorgio:SEP-1763from
PederHP:sep-1763-reintroduce-sink
Open

Reintroduce sink interceptor type for context-reactive workflows#1
PederHP wants to merge 1 commit into
Degiorgio:SEP-1763from
PederHP:sep-1763-reintroduce-sink

Conversation

@PederHP
Copy link
Copy Markdown

@PederHP PederHP commented May 14, 2026

Summary

Adds a third interceptor type, sink, for non-blocking, non-mutating interceptors that react to context to drive concurrent UX, workflow state, or downstream pipelines (avatar animation, voice-mode triggers, real-time UI affordances, background indexing) without affecting the request/response interaction.

This is additive to the validator/mutator split and mode: \"audit\" you introduced — both are preserved unchanged. The PR slots sink in as a structurally non-enforcing third type, distinct from audit-mode validators/mutators.

Why

There's a real class of agentic-UX interceptor that doesn't fit validators or mutators:

  • Avatar / character animation driven by conversation mood (concrete: implemented in the C# reference impl's AvatarMoodInterceptorSample)
  • Voice-mode triggers — TTS style switching, synthesis cues
  • Real-time UI affordances surfaced from tool / resource activity
  • Background context indexing of retrieved resources

These aren't silently-observing guardrails. They are first-class workflows that just happen to live outside the request/response trust boundary.

mode: \"audit\" doesn't quite cover this:

  • Audit-mode validators still produce validation results (valid, severity, messages) — not a meaningful interface for an avatar driver
  • Audit-mode mutators still propose payload changes (shadow mutations) — also not meaningful
  • Audit mode implies a promotion path ("flip the flag and it enforces"). Sinks have no enforcement to promote to, by design.

A separate type makes the intent legible at the boundary. The PR codifies this with a MUST-reject on mode: \"audit\" for sinks.

Naming

The original draft used observability for this third type. I think it was right to drop that name — it implies overlap with OpenTelemetry and general logging infrastructure, which sinks are not. Renamed to sink (drains/absorbs the payload, prior art in OTel exporters and log sinks without semantic collision). A callout in the Sink section makes the distinction from OTel explicit, since that was the original concern.

Open to bikeshed; happy to change before merging.

Changes

  • Type union extended to \"validation\" | \"mutation\" | \"sink\" (3 sites: Interceptor, ChainEntry, ChainExecutionResult.results)
  • New #### Sink section parallel to Validator / Mutator with use cases, SinkResult interface, and distinction callouts (vs OTel, vs mode: \"audit\")
  • Execution model: sink as third stage (parallel, fire-and-forget) on each phase — Mutate → Validate → Sink → Send and Validate → Sink → Mutate → Process
  • Type Behaviors table updated; sinks MUST NOT use mode: \"audit\"
  • audit-logger example in interceptors/list reframed as type: \"sink\"; new avatar-mood sink example added to anchor the UX-driver framing
  • Rationale section restructured: "Separation of Validation, Mutation, and Sink", "Why Sinks Are a Separate Type, Not Just `audit` on Validators", "Why 'Sink' and Not 'Observability'"

Deliberately not touched (candidates for a follow-up if you want):

  • The three large mermaid sequence diagrams (still show validator + mutator only — text now describes the right flow)
  • The "Full Request/Response Cycle" prose example
  • The detailed example chain interceptor list near the end of the chain-execution section

Reference implementation

The C# experimental reference implementation tracks SEP-2624 and includes sink as proposed here: https://github.com/modelcontextprotocol/experimental-ext-interceptors. The AvatarMoodInterceptorSample demonstrates the avatar-mood use case end-to-end.

Test plan

  • Render docs site to check the .mdx mirror still builds
  • Confirm no remaining references to the old observability type
  • Sanity-check execution-model description aligns with text descriptions everywhere

🤖 Generated with Claude Code

Adds a third interceptor type, `sink`, for non-blocking, non-mutating
interceptors that react to context to drive concurrent UX, workflow state,
or downstream pipelines (avatar animation, voice-mode triggers, real-time
UI affordances, background indexing) without affecting the request/response
interaction.

This is additive to the validator/mutator split and `mode: "audit"`
introduced in this SEP. Audit mode disables enforcement while preserving
the validator/mutator interface; sinks are structurally non-enforcing and
cannot be promoted to affect the interaction. The Rationale section now
covers why these are separate concepts.

Renaming from the original draft's `observability` to `sink` to avoid the
implication of overlap with OpenTelemetry / general logging tooling. A
callout block in the Sink section makes this distinction explicit.

Changes:
- Type union extended to "validation" | "mutation" | "sink" (3 sites)
- New Sink section parallel to Validator / Mutator with use cases and SinkResult
- Execution model: Sink as third stage (parallel, fire-and-forget) on each phase
- Type Behaviors table updated; sinks MUST NOT use `mode: "audit"`
- audit-logger example reframed as sink; new avatar-mood sink example added
- Rationale section restructured (Separation of three types, Why Sink vs audit,
  Why "Sink" and Not "Observability")

The C# experimental reference implementation
(modelcontextprotocol/experimental-ext-interceptors) tracks this and
demonstrates the avatar use case end-to-end in AvatarMoodInterceptorSample.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@PederHP
Copy link
Copy Markdown
Author

PederHP commented May 14, 2026

@Degiorgio Made this PR for reintroduction of non-blocking, non-mutating interceptors to the SEP.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant