Skip to content

Streamed Anthropic thinking content_block_start has no signature field #645

Open

Description

@gdevenyi

A streamed thinking block's content_block_start on /v1/messages is {"type":"thinking","thinking":""}, with no signature. _open_thinking() (server/anthropic_api.py) never sets it, and _event() serializes with exclude_none=True. The Anthropic SDK types ThinkingBlock.signature as a required str. The non-streaming response and the closing signature_delta already send "".

import asyncio
from freetoken.server import anthropic_api as A
from freetoken.server.generation import ReasoningDelta, ContentDelta, GenDone
async def ev():
    for e in (ReasoningDelta("x"), ContentDelta("hi"), GenDone("stop", 1, 1)):
        yield e
async def main():
    async for f in A.anthropic_event_stream(ev(), "m", 1):
        if "content_block_start" in f:
            print(f.splitlines()[1])   # ..."content_block":{"type":"thinking","thinking":""}...
asyncio.run(main())

Expected: {"type":"thinking","thinking":"","signature":""}.

Environment: main 07813248 (CPU-only check), Python 3.14.

Implementation (on my fork, with a test): e106a9e

Activity

  1. gdevenyi commented on Oct 13, 2026

    @gdevenyi
    ContributorAuthor

    Tested in the 1080 Ti deployment branch, rebuilt today on main 9c635a1 (torch 2.14.1+cu126, Triton 3.8, GTX 1080 Ti sm_61, Qwen3.8-Flash-Next-NVFP4 at 262K): a streamed /v1/messages request with thinking now opens with {"type":"thinking","thinking":"","signature":""}, and tool-call round trips pass on /v1/messages with and without thinking. tests/server/test_anthropic_api.py passes.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions