Repository navigation
fix: preserve Anthropic thinking in MCP tool turns - #1123
andreatnvidia wants to merge 2 commits into
Conversation
Fixes #1118 Signed-off-by: Andre Manoel <amanoel@nvidia.com>
|
Fern preview: https://nvidia-preview-pr-1123.docs.buildwithfern.com/nemo/datadesigner
|
[Medium impact] The PR appears safe to merge; no actionable new issues were found. SummaryPreserves Anthropic assistant content unchanged across MCP tool turns, including signed thinking and redacted blocks.
|
svcnvidia-nemo-ci
left a comment
There was a problem hiding this comment.
No confirmed Critical or Warning findings.
Reviewed all nine changed files and affected provider, MCP, generation, and trace contracts. Native assistant blocks remain intact through tool execution, refusals, parser corrections, and restart checkpoints; default trace and OpenAI-compatible serialization remain unchanged. The new integration tests cover these paths for synchronous and asynchronous generation.
Validation was static only: no tests were executed during this review, and live Anthropic API acceptance remains unverified.
Note: formal approval is not available for this request, so this review is posted as a comment only.
Review generated by codex. This was a full review. Request a full review with /review reset=true.
nabinchha
left a comment
There was a problem hiding this comment.
Thanks for putting this together, @andreatnvidia!
Summary
The fix preserves Anthropic assistant blocks through tool execution and retries, and the regression coverage exercises the important paths. Before merging, I’d like us to revise how provider replay data crosses the shared conversation layer.
Findings
Warnings — Worth addressing
packages/data-designer-engine/src/data_designer/engine/models/utils.py:112 — Keep provider replay handling behind the client boundary
- What:
anthropic_contentnow appears on both shared message types and passes throughChatMessage.as_assistant(), MCP response handling, and generation.ChatMessage.to_dict(provider_type=...)also makes the shared conversation type responsible for selecting provider-specific request data. - Why: This couples otherwise shared conversation and tool orchestration code to Anthropic’s wire representation. Supporting another provider with opaque replay requirements would extend the same provider-specific surface across these layers. Preserving signed blocks is necessary, but interpreting and serializing them should remain the adapter’s responsibility.
- Suggestion: Carry opaque, provider-tagged replay data on shared messages. Let the model facade and MCP preserve it without inspecting the payload, and let the matching adapter interpret it when constructing its request. Keep default trace serialization free of replay data. Please also revise the request boundary so the adapter can access replay data without adding provider selection to
ChatMessage.to_dict(); renaming the field alone would leave that coupling in place. Retain the existing replay regression tests and verify that unmatched provider data is ignored and unfamiliar payloads pass through orchestration unchanged.
One possible shape for the shared envelope is:
@dataclass(frozen=True)
class ProviderReplayData:
provider_type: str
payload: objectBoth AssistantMessage and ChatMessage could carry replay_data: ProviderReplayData | None, and ChatMessage.as_assistant() would accept that generic field. The Anthropic adapter would create the envelope from the original response blocks and consume it only when its provider tag matches. The payload stays opaque to the facade and MCP; the adapter owns any payload checks and interpretation.
This envelope is only part of the change: the client request boundary also needs to preserve access to replay data until the adapter builds the wire payload. Default ChatMessage.to_dict() should remain the canonical trace representation, without a provider-selection argument or replay data.
What Looks Good
- Replaying the original assistant content array preserves signatures, redacted thinking, whitespace, and interleaved ordering.
- Regression coverage includes synchronous and asynchronous execution, turn-limit refusals, corrections, and restart checkpoints.
- Default trace serialization excludes native replay data.
Residual Risk
At commit 3e8f398e, 310 focused tests passed, along with Ruff lint and formatting for all nine changed files. Live Anthropic API acceptance remains unverified; responses were simulated. The requested design revision will need those checks rerun.
Verdict
Needs changes — preserve the behavior and regression coverage, but move provider-specific replay interpretation and request serialization behind the adapter boundary before merge.
This review was generated by an AI assistant.
Carry opaque provider-tagged replay data separately from canonical messages. Keep provider payload interpretation in the matching adapter. Fixes #1118 Signed-off-by: Andre Manoel <amanoel@nvidia.com>
|
Thanks for the feedback, @nabinchha! Updated in Retained the replay regression tests and added coverage for unmatched provider tags and unfamiliar payloads passing through orchestration unchanged. |
nabinchha
left a comment
There was a problem hiding this comment.
Thanks for putting this together, @andreatnvidia!
Summary
Preserves Anthropic assistant content across tool turns, corrections, and restarts. The latest revision addresses the earlier provider-boundary request: shared layers carry opaque tagged replay data, and the matching adapter owns payload interpretation.
Findings
No new actionable findings.
What Looks Good
- Opaque replay data remains separate from canonical message dictionaries and default trace serialization.
- The adapter preserves original block order, signatures, redacted content, and whitespace.
- Tests cover sync/async execution, refusals, retries, unfamiliar payloads, unmatched tags, and alignment checks.
Residual Risk
949 model and MCP tests passed, along with Ruff lint and formatting. Live Anthropic API acceptance remains unverified; HTTP responses were simulated.
Verdict
Ship it
This review was generated by an AI assistant.
Summary
Anthropic MCP tool turns were rebuilt from text and tool calls, losing thinking signatures and redacted data. Replay each original assistant content array unchanged, including thinking interleaved with parallel tool calls, to preserve the message history required by Anthropic.
Related issue
Fixes #1118
Changes
ProviderReplayDatathrough shared assistant messages, MCP execution/refusal, parser corrections, and restart checkpoints.ChatCompletionRequest.message_replay_data. Validate message alignment at construction and keep replay metadata out of transport kwargs.ChatMessage.to_dict()provider-neutral and free of replay data; preserve existing trace and OpenAI-compatible serialization.Testing
.venv/bin/pytest: 5,051 passed, 11 skipped. Invoked directly because the Make targets useuv run.OK, preserving the signature and redacted data.Checklist
triaged.