[PR #208] [MERGED] fix(skills): use systemMessage.concat() instead of systemPrompt string #210

Closed
opened 2026-02-16 06:17:27 -05:00 by yindo · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/langchain-ai/deepagentsjs/pull/208
Author: @antonnak
Created: 2/9/2026
Status: Merged
Merged: 2/10/2026
Merged by: @christian-bromann

Base: mainHead: fix/skills-middleware-system-message


📝 Commits (3)

  • 29bd8c7 fix(skills): use systemMessage.concat() instead of systemPrompt string
  • ee235e6 style: fix Prettier formatting in skills.test.ts
  • cd0c625 fix(skills): update integration tests to use systemMessage API

📊 Changes

4 files changed (+53 additions, -40 deletions)

View changed files

.changeset/fix-skills-system-message.md (+10 -0)
📝 libs/deepagents/src/middleware/skills.test.ts (+30 -27)
📝 libs/deepagents/src/middleware/skills.ts (+3 -6)
📝 libs/deepagents/src/skills/index.int.test.ts (+10 -7)

📄 Description

Problem

SkillsMiddleware.wrapModelCall reads from request.systemPrompt (a string) and writes back to systemPrompt. When a SystemMessage with structured content blocks is passed to createDeepAgent (supported since PR #104), this middleware:

  1. Reads request.systemPrompt which is the .text getter output (flattened string)
  2. Appends skills section via string concatenation
  3. Sets systemPrompt: newString on the handler request

This triggers AgentNode's hasSystemPromptChanged branch (AgentNode.js:219-229), which recreates the SystemMessage from scratch as a single {type: "text", text: "..."} block — destroying all existing content block metadata including cache_control annotations for Anthropic prompt caching.

Root Cause

SkillsMiddleware is the only middleware in deepagents that uses the string-based request.systemPrompt API. Both FilesystemMiddleware (fs.ts:973) and SubAgentMiddleware (subagents.ts:1390) correctly use request.systemMessage.concat(), which preserves content block structure.

Fix

Replace string-based systemPrompt manipulation with request.systemMessage.concat():

- const currentSystemPrompt = request.systemPrompt || "";
- const newSystemPrompt = currentSystemPrompt
-   ? `${currentSystemPrompt}\n\n${skillsSection}`
-   : skillsSection;
- return handler({ ...request, systemPrompt: newSystemPrompt });
+ const newSystemMessage = request.systemMessage.concat(skillsSection);
+ return handler({ ...request, systemMessage: newSystemMessage });

---

<sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
## 📋 Pull Request Information **Original PR:** https://github.com/langchain-ai/deepagentsjs/pull/208 **Author:** [@antonnak](https://github.com/antonnak) **Created:** 2/9/2026 **Status:** ✅ Merged **Merged:** 2/10/2026 **Merged by:** [@christian-bromann](https://github.com/christian-bromann) **Base:** `main` ← **Head:** `fix/skills-middleware-system-message` --- ### 📝 Commits (3) - [`29bd8c7`](https://github.com/langchain-ai/deepagentsjs/commit/29bd8c7fd6def3d832b68cbd713b8fe13bbdc2be) fix(skills): use systemMessage.concat() instead of systemPrompt string - [`ee235e6`](https://github.com/langchain-ai/deepagentsjs/commit/ee235e64fdd49bb134060abd2f2a9939194b2503) style: fix Prettier formatting in skills.test.ts - [`cd0c625`](https://github.com/langchain-ai/deepagentsjs/commit/cd0c62561dcdb1abf72e0e7e5fe6684526577a9d) fix(skills): update integration tests to use systemMessage API ### 📊 Changes **4 files changed** (+53 additions, -40 deletions) <details> <summary>View changed files</summary> ➕ `.changeset/fix-skills-system-message.md` (+10 -0) 📝 `libs/deepagents/src/middleware/skills.test.ts` (+30 -27) 📝 `libs/deepagents/src/middleware/skills.ts` (+3 -6) 📝 `libs/deepagents/src/skills/index.int.test.ts` (+10 -7) </details> ### 📄 Description ## Problem `SkillsMiddleware.wrapModelCall` reads from `request.systemPrompt` (a string) and writes back to `systemPrompt`. When a `SystemMessage` with structured content blocks is passed to `createDeepAgent` (supported since PR #104), this middleware: 1. Reads `request.systemPrompt` which is the `.text` getter output (flattened string) 2. Appends skills section via string concatenation 3. Sets `systemPrompt: newString` on the handler request This triggers `AgentNode`'s `hasSystemPromptChanged` branch (AgentNode.js:219-229), which recreates the `SystemMessage` from scratch as a single `{type: "text", text: "..."}` block — **destroying all existing content block metadata** including `cache_control` annotations for Anthropic prompt caching. ## Root Cause `SkillsMiddleware` is the **only** middleware in deepagents that uses the string-based `request.systemPrompt` API. Both `FilesystemMiddleware` (fs.ts:973) and `SubAgentMiddleware` (subagents.ts:1390) correctly use `request.systemMessage.concat()`, which preserves content block structure. ## Fix Replace string-based `systemPrompt` manipulation with `request.systemMessage.concat()`: ```diff - const currentSystemPrompt = request.systemPrompt || ""; - const newSystemPrompt = currentSystemPrompt - ? `${currentSystemPrompt}\n\n${skillsSection}` - : skillsSection; - return handler({ ...request, systemPrompt: newSystemPrompt }); + const newSystemMessage = request.systemMessage.concat(skillsSection); + return handler({ ...request, systemMessage: newSystemMessage }); --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
yindo added the pull-request label 2026-02-16 06:17:27 -05:00
yindo closed this issue 2026-02-16 06:17:27 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langchain-ai/deepagentsjs#210