Skip to content

Conversation

gooseprogrammers
Copy link

Summary

Enables Anthropic's prompt caching feature for all system messages when using the Anthropic Chat Model node. This automatically adds cache_control markers to system prompts, reducing costs by up to 90% and latency by up to 85%
for repeated calls.

Changes

  • Wraps ChatAnthropic model's invoke method to inject cache_control into system messages
  • No user configuration required - works automatically
  • Added comprehensive unit tests (9 test cases, 386 lines)

Benefits

  • 90% cost reduction on cached input tokens (cache reads are 10x cheaper than regular input)
  • 85% latency reduction for repeated calls with the same system prompt
  • Zero configuration - automatically enabled for all Anthropic workflows
  • Universal benefit - helps AI Agent nodes with large system prompts, multi-turn conversations, and any workflow with static system messages

Technical Details

Cache Implementation:

  • Type: ephemeral (5-minute TTL, refreshed on each use)
  • Minimum: 1024 tokens for Sonnet/Opus, 2048 for Haiku models
  • Compatible with all Claude models (Opus 4.1, Sonnet 4.5, Haiku 4.5, etc.)
  • No beta header required (prompt caching is GA since December 2024)

Code Example:

// Automatically converts:
new SystemMessage("You are a helpful assistant")

// To:
{
  type: 'text',
  text: 'You are a helpful assistant',
  cache_control: { type: 'ephemeral' }
}

Testing

- Added promptCaching.test.ts with 9 comprehensive test cases
- Covers: string content, array content, multiple messages, edge cases
- Follows testing patterns from PR #20253 and #20484
- All tests use proper mocking and assertion patterns

Related

- Closes #13231 (community request for system prompt caching)
- Related to PR #20484 (AI Workflow Builder uses similar caching strategy)
- Anthropic docs: https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching

Checklist

- Code follows n8n style guide
- TypeScript compliance (no ts-ignore)
- Comprehensive tests included
- Small, focused PR (single feature)
- Proper commit message format
- No breaking changes

…tem messages

Enable Anthropic's prompt caching by automatically adding cache_control markers to system messages. This wraps the ChatAnthropic model's invoke method to inject caching without requiring user configuration.

Benefits:
- Reduce input token costs by up to 90% (cache reads cost 10% of base)
- Reduce latency by up to 85% for repeated calls with same system prompt
- Works automatically for AI Agents with large system prompts containing tool descriptions and instructions
- Compatible with all Claude models (Opus 4.1, Sonnet 4.5, Haiku 4.5, etc.)

Cache details:
- Type: ephemeral with 5-minute TTL (refreshed on each use)
- Minimum: 1024 tokens for Sonnet/Opus, 2048 for Haiku models
- No beta header required (prompt caching is generally available since Dec 2024)

Testing:
- Added comprehensive unit tests covering system message caching scenarios
- Tests verify string and array content handling, multiple messages, and edge cases
- 9 test cases following n8n testing patterns from PR n8n-io#20253 and n8n-io#20484
@CLAassistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.


AbleBox Engineer seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR is being reviewed by Cursor Bugbot

Details

Your team is on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle for each member of your team.

To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

}
}
return originalInvoke(input, options);
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Function Mutates Input Objects, Causing Reuse Issues

The enablePromptCaching function directly mutates the content property of input BaseMessage objects. This can lead to unexpected behavior if messages are reused, as their content is permanently altered (e.g., string content converted to an array with cache_control) after the first invocation.

Fix in Cursor Fix in Web

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 2 files

Prompt for AI agents (all 1 issues)

Understand the root cause of the following 1 issues and fix them.


<file name="packages/@n8n/nodes-langchain/nodes/llms/LMChatAnthropic/LmChatAnthropic.node.ts">

<violation number="1" location="packages/@n8n/nodes-langchain/nodes/llms/LMChatAnthropic/LmChatAnthropic.node.ts:111">
Rule violated: **Prefer Typeguards over Type casting**

The new `as { text: string; cache_control?: { type: &#39;ephemeral&#39; } }` assertion narrows `lastBlock` via casting, violating the “Prefer Typeguards over Type casting” rule. Please replace the cast with a proper type guard (or tighten the typings so `cache_control` is recognized) before mutating the object.</violation>
</file>

Since this is your first cubic review, here's how it works:

  • cubic automatically reviews your code and comments on bugs and improvements
  • Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
  • Ask questions if you need clarification on any suggestion

React with 👍 or 👎 to teach cubic. Mention @cubic-dev-ai to give feedback, ask questions, or re-run the review.

'text' in lastBlock &&
typeof lastBlock.text === 'string'
) {
(lastBlock as { text: string; cache_control?: { type: 'ephemeral' } }).cache_control =
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Oct 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rule violated: Prefer Typeguards over Type casting

The new as { text: string; cache_control?: { type: 'ephemeral' } } assertion narrows lastBlock via casting, violating the “Prefer Typeguards over Type casting” rule. Please replace the cast with a proper type guard (or tighten the typings so cache_control is recognized) before mutating the object.

Prompt for AI agents
Address the following comment on packages/@n8n/nodes-langchain/nodes/llms/LMChatAnthropic/LmChatAnthropic.node.ts at line 111:

<comment>The new `as { text: string; cache_control?: { type: &#39;ephemeral&#39; } }` assertion narrows `lastBlock` via casting, violating the “Prefer Typeguards over Type casting” rule. Please replace the cast with a proper type guard (or tighten the typings so `cache_control` is recognized) before mutating the object.</comment>

<file context>
@@ -70,6 +71,58 @@ const modelField: INodeProperties = {
+							&#39;text&#39; in lastBlock &amp;&amp;
+							typeof lastBlock.text === &#39;string&#39;
+						) {
+							(lastBlock as { text: string; cache_control?: { type: &#39;ephemeral&#39; } }).cache_control =
+								{
+									type: &#39;ephemeral&#39;,
</file context>
Fix with Cubic

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.

2 participants