parsa
12/18/2025, 9:24 PMPrompt caching with Anthropic requires the use of cache_control breakpoints.
The cache_control breakpoint can only be inserted into the text part of a multipart message.
ive only been able to get this to work with the modular API in BAML but then that breaks BAML observability, is there something simpler that i should be doing to make this work?aaronv (BAML)
12/18/2025, 9:27 PMaaronv (BAML)
12/18/2025, 9:29 PMaaronv (BAML)
12/18/2025, 9:32 PMaaronv (BAML)
12/18/2025, 9:32 PMparsa
12/18/2025, 9:53 PMtypescript
// Build the request using BAML's modular API
const req = await b.request.AgentLoop(
bamlMessages,
commandValues,
conversationContext,
currentDateTime,
pdfAttachments,
imageAttachments,
{ clientRegistry },
);
// Extract body and inject cache_control
const body = req.body.json();
// Find system message and split at my static doc marker
const systemMsgIndex = body.messages.findIndex(m => m.role === 'system');
if (systemMsgIndex !== -1) {
const textContent = /* extract text from system msg */;
const staticEndMarker = '</static_documentation>';
const splitIndex = textContent.indexOf(staticEndMarker);
if (splitIndex !== -1) {
const staticContent = textContent.substring(0, splitIndex + staticEndMarker.length);
const dynamicContent = textContent.substring(splitIndex + staticEndMarker.length);
// Restructure with cache_control on static portion
body.messages[systemMsgIndex] = {
role: 'system',
content: [
{ type: 'text', text: staticContent, cache_control: { type: 'ephemeral' } },
{ type: 'text', text: dynamicContent },
],
};
}
}
// Add anthropic-beta header required for caching
const headers = {
...req.headers,
'anthropic-beta': 'prompt-caching-2024-07-31',
};
// Manual fetch
const response = await fetch(req.url, {
method: req.method,
headers,
body: JSON.stringify(body),
});
// Parse with BAML
const decision = await b.parse.AgentLoop(responseContent);
this works and i get ~96% cache hit rates, but the downside is that BAML observability is broken because im bypassing the normal b.AgentLoop() call with a manual fetch. i can still use traceAsync and setTags but the built-in prompt/response logging in the boundary dashboard doesnt capture the actual LLM call.
is there a cleaner way to inject cache_control into the request without losing observability? ideally something like:
typescript
await b.AgentLoop(args, {
modifyRequest: (body) => {
// inject cache_control here
return body;
}
});parsa
12/19/2025, 2:33 AMaaronv (BAML)
12/19/2025, 4:52 PMVaibhav (BAML 🐑)
12/19/2025, 4:59 PMVaibhav (BAML 🐑)
12/19/2025, 5:01 PMclient<llm> MyClient {
provider "openai-generic"
options {
base_url "https://openrouter.ai/api/v1"
api_key env.OPENROUTER_API_KEY
model "openai/gpt-5-mini"
allowed_role_metadata ["cache_control"]
}
}
https://cdn.discordapp.com/attachments/1451324383271325952/1451620508364968066/Screenshot_2025-12-19_at_9.01.32_AM.png?ex=6946d672&is=694584f2&hm=33649eaf1eb9463732c2e3a57c48d74905ae25649d0a07dd0f02be2af37649fb&