on_call_tool and on_read_resource both wrap the result, store it, then return wrapped.unwrap() — putting the first caller's return value through the same serialize/deserialize path that cached callers get:
# on_call_tool (line 436)
return cachable_tool_result.unwrap()
# on_read_resource (line 464)
return cached_value.unwrap()
on_get_prompt skips this and returns the original value directly:
# on_get_prompt (line 490)
return value
This means the first caller gets the original PromptResult (with Message objects), while subsequent callers get CachablePromptResult.unwrap() (which reconstructs Message from CachableMessage). If the two representations ever diverge — e.g., Message gains a field that CachableMessage doesn't carry — the first and second callers will silently get different data.
The fix is to match the other methods:
cached_value = CachablePromptResult.wrap(value)
await self._get_prompt_cache.put(
key=cache_key,
value=cached_value,
ttl=self._get_prompt_settings.get("ttl", ONE_HOUR_IN_SECONDS),
)
return cached_value.unwrap()
on_call_toolandon_read_resourceboth wrap the result, store it, then returnwrapped.unwrap()— putting the first caller's return value through the same serialize/deserialize path that cached callers get:on_get_promptskips this and returns the original value directly:This means the first caller gets the original
PromptResult(withMessageobjects), while subsequent callers getCachablePromptResult.unwrap()(which reconstructsMessagefromCachableMessage). If the two representations ever diverge — e.g.,Messagegains a field thatCachableMessagedoesn't carry — the first and second callers will silently get different data.The fix is to match the other methods: