Skip to content

fix: Keep Dynamic Tool Context After Additional Instructions for Prefix Caching - #16369

Open
Shabonasar wants to merge 1 commit into
LibreChat-AI:devfrom
Shabonasar:fix/prompt-prefix-cache-order
Open

Shabonasar wants to merge 1 commit into
LibreChat-AI:devfrom
Shabonasar:fix/prompt-prefix-cache-order

Conversation

@Shabonasar

Copy link
Copy Markdown

Pull Request

Summary

The per-request web search context (Conversation Date & Time: <ISO timestamp with milliseconds>) is joined before agent.additional_instructions when the run builds the system prompt. additional_instructions carry mostly static text, most notably the artifacts prompt (~11k characters). Because the timestamp changes on every request, provider-side prefix caching stops at the timestamp and everything after it is recomputed each time. This affects self-hosted models with automatic prefix caching (e.g. vLLM, SGLang) and any provider that caches by prompt prefix; it is triggered whenever web search is enabled together with anything that lands in additional_instructions (artifacts, memory guard, instructions with temporal variables).

This PR moves the dynamic tool context to the end, so the static part stays a stable prefix across requests. The date/time is still present in the prompt, only its position changes.

How it works

-const additionalInstructions = [dynamicToolInstructions, agent.additional_instructions ?? '']
-  .join('\n')
-  .trim();
+const additionalInstructions = buildAdditionalInstructions(
+  agent.additional_instructions,
+  dynamicToolInstructions,
+);

buildAdditionalInstructions is a small exported helper in run.ts that puts static instructions first and the per-request context last, so the ordering can be unit-tested.

Type of change

  • Bug fix
  • Performance improvement

Testing

Captured the chat completion requests sent to an OpenAI-compatible endpoint for two consecutive new conversations (artifacts and web search enabled) and compared the system prompts character by character. Before the change they diverged at the timestamp, about 3k characters into the system message; after the change they are identical up to the timestamp, which is now the last line.

Measured on a locally hosted model served by vLLM with automatic prefix caching, ~8.6k prompt tokens per request: cached prompt tokens went from 3,168 to 6,336 per request (35% to 74%). The remainder is the user message, the timestamp and cache block rounding.

Tested environments/configuration:

  • Provider: custom OpenAI-compatible endpoint (vLLM, prefix caching enabled)
  • Agents with artifacts and web search enabled

Automated tests:

  • Added buildAdditionalInstructions tests in packages/api/src/agents/run.spec.ts

Screenshots / recordings

No user-facing change

Risk / compatibility

Only the order of text inside the system prompt changes; no content is added or removed.

Checklist

  • I reviewed my own changes
  • Relevant tests have been added or updated
  • The change does not introduce new warnings or errors

The per-request web search context (current date/time with milliseconds)
was joined before additional_instructions, which carry mostly static text
such as the artifacts prompt. Provider-side prefix caches stopped at the
timestamp, so the static text after it was recomputed on every request.

Move the dynamic context to the end via buildAdditionalInstructions and
cover the ordering with unit tests.

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant