microsoft / microsoft/amplifier

Cross-provider resume: thinking blocks with null signature passed to Anthropic API cause invalid_request_error

Open
#330 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
3.1k
Forks
261
Avg merge
3h 28m
Merged PRs (30d)
13

Description

Summary

When a session created with an OpenAI provider (e.g., gpt-5.6-sol) is later resumed while routing sends requests to Anthropic, the first new user message fails with HTTP 400: messages.9.content.0.thinking.signature.str: Input should be a valid string. The session becomes unusable until thinking blocks are manually stripped from the transcript.

Repro

  1. Create and run a session with OpenAI provider (e.g., gpt-5.6-sol) — transcript gets assistant messages containing thinking content blocks with signature: null (per OpenAI's reasoning-state usage of the canonical ThinkingBlock model in amplifier_core/message_models.py:42-49)
  2. Later resume the session while routing-matrix is active and routes to Anthropic provider
  3. Send a new user message → HTTP 400 error: invalid_request_error: "messages.9.content.0.thinking.signature.str: Input should be a valid string"
  4. Session is now broken until thinking blocks are manually removed from transcript.jsonl

Real example:

  • Session ID: 3aaf5712-7e3c-4d70-9b6e-a1743b84e745 (project: iago)
  • Created with: gpt-5.6-sol (OpenAI)
  • Resumed with: anthropic/claude-fable-5 (routing-matrix "balanced")
  • Error: [PROVIDER] Anthropic API error: {"type": "error", "error": {"type": "invalid_request_error", "message": "messages.9.content.0.thinking.signature.str: Input should be a valid string"}...

Root Cause

File: amplifier-module-provider-anthropic/__init__.py
Location: _clean_content_block() at approximately lines 3256–3276

The sanitizer checks only for the presence of the signature key, not its value validity:

if "signature" in block:
    cleaned["signature"] = block["signature"]   # copies None straight through

OpenAI-origin thinking blocks have signature: null, which Anthropic's API rejects. The core message model (amplifier_core/message_models.py:42-49) intentionally allows signature: str | NoneNone is the expected value for OpenAI reasoning blocks. Each provider module is responsible for sanitizing that canonical shape for its own API.

Proposed Fix

In provider-anthropic's _clean_content_block():

  • If signature is not a non-empty string, drop the entire thinking block (Anthropic requires a valid signature to accept a thinking block at all — you cannot omit the field and keep the block).
  • The two call sites (~lines 3404–3411 and 3457–3461) must gracefully skip a None return.
  • Message assembly must tolerate an assistant turn whose only content was thinking blocks (fall back to remaining text/tool_use content, or emit a minimal text block if all content was thinking).

This is provider-specific policy and correctly belongs in the provider module, not core (core's ThinkingBlock intentionally remains provider-neutral).

Module Responsibility

Per Amplifier's kernel architecture (mechanism, not policy):

  • Core: Canonical message shape, provider-neutral (correctly allows signature: None)
  • Provider module: Translates canonical shape to wire format, validates against its own API constraints

🤖 Generated with Amplifier

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in amplifier-module-provider-anthropic/init.py at _clean_content_block() and inspect its two call sites around lines 3404–3411 and 3457–3461. Read amplifier_core/message_models.py:42-49 to confirm the provider-neutral ThinkingBlock shape. Done means invalid or null signatures are removed with safe handling of None returns, and assistant messages containing only thinking blocks still assemble valid content for Anthropic.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend-api-design
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
65/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.