Skip to content

fix(chat): stop conversations dropping silently or on over-eager moderation#38

Merged
albanm merged 4 commits into
mainfrom
fix-interrupted-conversation
Jun 19, 2026
Merged

fix(chat): stop conversations dropping silently or on over-eager moderation#38
albanm merged 4 commits into
mainfrom
fix-interrupted-conversation

Conversation

@albanm

@albanm albanm commented Jun 19, 2026

Copy link
Copy Markdown
Member

Fixes conversations that ended with no useful outcome, on two fronts: silent drops and moderation-driven interruptions.

Silent drops — the AI SDK surfaces a mid-stream provider failure as an in-band error part (it does not throw), and result.response only rejects when zero steps completed. After a tool step the error was captured but never surfaced, and an empty model completion rendered as a blank turn.

  • client loop and server gateway now handle the error part (the gateway re-throws so it emits a real error chunk instead of a clean [DONE])
  • a clean finish with no assistant text now shows a fallback instead of a blank bubble
  • tool-error invocations settle (no perpetual spinner); a failing sub-agent shows a visible error rather than an unhandled tool-error

Moderation — legitimate work was being blocked, especially sub-agent delegations:

  • whitelist resource-metadata authoring (title, description, summary, topics, tags) so it isn't classified as "writing an essay"
  • a moderation-blocked sub-agent now hands the main assistant an actionable notice (re-formulate a legitimate task or explain — no blind retry loop; each re-delegation is itself re-moderated)
  • the user-facing refusal names the decision as content moderation and invites rephrasing

Why: users reported conversations ending with no response and no error, and legitimate requests (notably sub-agent tasks like writing a resource description) being interrupted by moderation.

Heads-up:

  • behavior change in the shared chat loop: a turn with no assistant text now appends a fallback message — confirm no flow ends intentionally text-free
  • the gateway now emits an error chunk on mid-stream provider failure where it previously sent a clean [DONE]
  • new user-facing fallback strings (empty-response, sub-agent error) are English-only / not yet wired to AgentChat.vue i18n

albanm and others added 4 commits June 19, 2026 19:20
…empty completions

The AI SDK reports a mid-stream provider failure as an in-band fullStream
'error' part (it calls onError but does not throw), and result.response only
rejects when zero steps completed. After a completed tool step the error was
captured but never surfaced, and an empty model completion rendered as a blank
turn — both ended the conversation with no response and no error.

- client loop (use-agent-chat.ts): handle the 'error' part and re-throw the
  captured streamError after the loop; add a fallback assistant message for
  empty completions / empty sub-agents / step-limit-on-tool; mark tool-error
  invocations done so chips stop spinning; wrap the sub-agent generator so a
  failing sub-agent shows a visible error instead of an unhandled tool-error
- server gateway (router.ts): re-throw on an 'error' part so the catch emits a
  proper error chunk instead of a clean [DONE] that the client reads as empty
- mock model: add "empty" and "stream error" seams
- add chat-silent-drop e2e covering both paths

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…or prompt

Writing a description/summary for an application (or dataset, processing,
catalog) is legitimate metadata management, but the moderator classified it as
"writing an essay" and blocked it. Because the gateway moderates every model
call by caller role, this most often hit sub-agent task delegations (e.g. "write
a description for application X"), interrupting the conversation with a
content_filter refusal.

- buildModerationSystemPrompt: add an explicit in-scope rule that authoring/
  editing resource metadata (title, description, summary, topics, tags, keywords
  of an application/dataset/processing/catalog) is always allowed; narrow the
  off-scope "essay" criterion to general-purpose prose unrelated to a platform
  resource
- add a unit test guarding the metadata whitelist language

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…gent is moderation-blocked

A delegated sub-agent that gets content_filter'd previously handed the main
assistant the same vague user-facing refusal, so it could only dead-end. Now:

- sub-agent moderation blocks return a distinct, assistant-directed notice
  (SUBAGENT_MODERATION_NOTICE) via a non-rendered `moderationBlocked` flag read
  by toModelOutput: it states this is a content-policy decision (not a tool
  error), allows re-formulating a legitimate task or explaining to the user, and
  discourages resubmitting identical wording. No auto-retry loop — the model
  decides within stepCountIs(10) and each re-delegation is itself re-moderated.
- the user-facing refusal (AgentChat.vue en/fr + DEFAULT_REFUSAL fallback) now
  names the decision as content moderation generically and invites rephrasing,
  without leaking a category/reason.
- update the moderation e2e refusal constant to match.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added the fix label Jun 19, 2026
@albanm albanm merged commit 709e101 into main Jun 19, 2026
3 checks passed
@albanm albanm deleted the fix-interrupted-conversation branch June 19, 2026 17:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant