From 80d71e8d2e045f1e7d5f0f3541eeb6f2ae6c7198 Mon Sep 17 00:00:00 2001 From: qWaitCrypto Date: Thu, 25 Jun 2026 23:06:41 +0800 Subject: [PATCH] fix(anthropic): preserve tool use cache markers --- agent/anthropic_adapter.py | 5 +++++ tests/agent/test_anthropic_adapter.py | 22 ++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/agent/anthropic_adapter.py b/agent/anthropic_adapter.py index e4d1d5ac1..215911e09 100644 --- a/agent/anthropic_adapter.py +++ b/agent/anthropic_adapter.py @@ -1970,6 +1970,11 @@ def _convert_assistant_message(m: Dict[str, Any]) -> Dict[str, Any]: "name": fn.get("name", ""), "input": parsed_args, }) + if isinstance(m.get("cache_control"), dict): + for block in reversed(blocks): + if isinstance(block, dict) and block.get("type") in {"text", "tool_use"}: + block.setdefault("cache_control", dict(m["cache_control"])) + break # Kimi's /coding endpoint (Anthropic protocol) requires assistant # tool-call messages to carry reasoning_content when thinking is # enabled server-side. Preserve it as a thinking block so Kimi diff --git a/tests/agent/test_anthropic_adapter.py b/tests/agent/test_anthropic_adapter.py index abf3e7e3f..b7e24a65a 100644 --- a/tests/agent/test_anthropic_adapter.py +++ b/tests/agent/test_anthropic_adapter.py @@ -1024,6 +1024,28 @@ class TestConvertMessages: assert assistant_blocks[0]["text"] == "Hello from assistant" assert assistant_blocks[0]["cache_control"] == {"type": "ephemeral"} + def test_assistant_tool_use_cache_control_is_preserved(self): + messages = apply_anthropic_cache_control([ + {"role": "system", "content": "System prompt"}, + {"role": "user", "content": "Run the tool"}, + { + "role": "assistant", + "content": "", + "tool_calls": [ + {"id": "tc_1", "function": {"name": "test_tool", "arguments": "{}"}}, + ], + }, + {"role": "tool", "tool_call_id": "tc_1", "content": "result"}, + ], native_anthropic=True) + + _, result = convert_messages_to_anthropic(messages) + assistant_msg = [m for m in result if m["role"] == "assistant"][0] + tool_use = assistant_msg["content"][-1] + + assert tool_use["type"] == "tool_use" + assert tool_use["id"] == "tc_1" + assert tool_use["cache_control"] == {"type": "ephemeral"} + def test_tool_cache_control_is_preserved_on_tool_result_block(self): messages = apply_anthropic_cache_control([ {"role": "system", "content": "System prompt"},