Skip to content

feat: Pass the Stable Context as the SDK Conversation Block - #17514

Draft
Shabonasar wants to merge 71 commits into
LibreChat-AI:devfrom
Shabonasar:feat/conversation-block
Draft

Shabonasar wants to merge 71 commits into
LibreChat-AI:devfrom
Shabonasar:feat/conversation-block

Conversation

@Shabonasar

Copy link
Copy Markdown
Contributor

Summary

With #17146, the conversation-stable context joins instructions, and only the per-turn parts (memory, RAG, queued files) stay in additional_instructions, which the SDK moves before the last user message on Anthropic, OpenRouter and Bedrock with promptCache. The SDK puts a summary from an earlier run into that moved part too, so after every compaction the summary is written to the cache again on each turn. With endpoints.agents.promptCache.stableContext and those providers, this PR passes the stable context as the SDK conversation_instructions (own breakpoint right after instructions, never moved), also when empty, so the SDK keeps the summary as a message of its own.

Related to #17102. Based on #17146. Depends on LibreChat-AI/agents#613 (conversation_instructions).

How it works

#17146:      [tools][S + stable context|bp] u1 a1 ... [summary + per-turn: memory, RAG]  uN    <- moves every turn
this PR:     [tools][S|bp][stable context|bp][summary] u1 a1 ... [per-turn]              uN

Results

Live, Claude Haiku 5.5, thinking medium, cache TTL 1h, G3 (12 turns, large tool results, max context 12000, compaction):

cached misses
#17146 without this PR (2 runs) 35.4-41.0% 13
with this PR 48.2% 8 (compactions and tool set changes)
all PRs of #17102 together 40.8% 9 (one extra compaction from longer answers)

No API errors.

Type of change

  • Feature

Testing

Automated tests: promptPrefixStability.test.ts (requests built by the SDK per provider), run.spec.ts, systemParts.spec.ts, turnContext.spec.ts; guard run.spec.ts "passes no conversation block without stableContext". tsc --noEmit in packages/api; eslint and prettier on the touched files. Against the npm SDK (without LibreChat-AI/agents#613) tsc and 7 tests in promptPrefixStability.test.ts fail, as expected.

Risk / compatibility

Default off: unchanged. Needs the SDK release with LibreChat-AI/agents#613.

Checklist

Shabonasar and others added 30 commits September 25, 2026 20:51
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.
…che-order

# Conflicts:
#	packages/api/src/agents/initialize.ts
…e date changes in history

The web search runtime context and temporal special variables were anchored
to the turn start with millisecond precision. The system message precedes the
whole history, so every turn invalidated the cached history and new
conversations could not reuse the system prompt (LibreChat-AI#16877).

- Web search runtime context states the conversation start in the user's
  timezone with minute precision; temporal variables resolve against the
  same persisted anchor.
- A user message sent on a later local date than the model last saw gets a
  <context_update> block in its prompt copy only, derived from stored
  createdAt values so it renders identically on later turns; compaction
  boundaries follow the agents SDK formatter.
- Optional endpoints.agents.promptMessageTimestamps adds the send time to
  every user message; the turn's user message is stored with
  createdAt = turnStartedAt on every save path.
- Provider payload stability tests through createRun for OpenAI, an
  OpenAI-compatible endpoint, Anthropic, OpenRouter, Bedrock and Google.
… routes

The browser resolved promptPrefix with its own clock on every send, so turn 1
of a spec-backed conversation carried the raw template while turn 2 carried
resolved text in a different system-prompt position. Only Assistants routes
resolve on the client now; the server resolves against the conversation start.
… of a conversation

Adds `endpoints.agents.promptCache.stableContext` (default off). Off, the prompt is
built as before. On:

- prompt time (`{{current_datetime}}` and friends, the web search runtime context) is
  anchored to the conversation start, and a date change is announced by a
  `<context_update>` block at the start of the first user message sent after it;
- the conversation-stable part of `additional_instructions` is merged into the system
  instructions for Anthropic and OpenRouter with prompt caching, while memory, RAG and
  one-turn queued file context stay in `additional_instructions`, where the SDK moves
  them next to the newest user message;
- dynamic tool context goes after the additional instructions;
- the user message is inserted with the turn start as `createdAt`, so later turns render
  the same stamp.

`promptMessageTimestamps` (default off) additionally prefixes each user message with the
time it was sent.

The history notes, the instruction split and the lever live in `packages/api`; the
controller only calls them. `applyContextToAgent` accepts the run context as parts and
records which are volatile, so no text is split by matching.
…assified parts

Producers (project, memory guard, artifacts, skills catalog, RAG, memory,
agent context files, always-apply skills of isolated subagents) contribute
keyed parts through contributeContext instead of concatenating strings into
additional_instructions. One registry fixes the canonical order and classifies
every part, tool context map entries included, as static, conversation or
turn. A runtime key the registry does not know counts as turn, so a new
producer cannot break the stable prefix by default.

assembleSystemPrompt builds the strings handed to the SDK. Once parts exist
they are the only source of the tail; a direct write to additional_instructions
is ignored with a warning. Without promptCache.stableContext it reproduces the
previous request; with it, createRun moves only the turn parts with the
prompt-cache tail and merges the rest into the instructions.

The assembled text is byte-identical to string concatenation for both values of
the lever, guarded by a snapshot recorded on the previous implementation.
Isolated subagents with an always-apply skill place the skill ahead of the tool
runtime context when stableContext is on.
…m prompt per segment

Behind `endpoints.agents.promptCache.stableContext`; off, nothing here runs and
the prompt is built as before.

A single send-time step (turnContext) decides what the primary agent's model
sees. Context sources (project, artifacts mode, memory tool guard, skills
catalog, tool runtime context, memory, date, send time, retrieved context,
queued upload files) are sampled once when the user sends a message; only the
net difference from what the model already knows along the parent chain is
stored on that user message (message.contextUpdates) and rendered as one
<context_update> block at the start of its prompt copy. Toggles flipped back
and forth before sending leave no trace, and stored values render the same
bytes on every later turn, whatever the timezone. A regeneration sends no
message: it renders what the message stored and writes nothing.

The system prompt is rendered from the segment's anchor instead of the live
parts, so it stays byte-identical until the next compaction. The anchor of the
first segment is stored on the conversation, the anchor of a segment opened by
a compaction on the message carrying the summary (contextAnchor); a
conversation without one is anchored to its first turn after the upgrade. A
re-anchor keeps the previous order, drops what is off and appends what is new,
and dates itself, so the first message after the boundary announces nothing.

Memory is a state source: an update lists the entries added, changed and
removed (by key where the memory has keys) instead of the whole memory, and no
longer rewrites the system prompt; memory switched off is withheld from the
whole request. Retrieved context is stored with the user message it was
retrieved for, like the file context bound to the message that carried the
files; isolated subagents still take it in their system prompt. Queued upload
files describe their own message only.

A resumed turn (tool approval or an answered question) renders its system
prompt from the paused turn's anchor, not from the live state.

The planning, the anchor storage and the token accounting live in
packages/api; the controller calls them. The conversation anchor is read with
the conversation the ingress already loads, and a resume reads the messages
once with a projection.

contextUpdates and contextAnchor are server-written only, select: false, and
stripped from client input, so they stay out of reads, shares and forks.
…assified parts

Producers (project, memory guard, artifacts, skills catalog, RAG, memory,
agent context files, always-apply skills of isolated subagents) contribute
keyed parts through contributeContext instead of concatenating strings into
additional_instructions. One registry fixes the canonical order and classifies
every part, tool context map entries included, as static, conversation or
turn. A runtime key the registry does not know counts as turn, so a new
producer cannot break the stable prefix by default.

assembleSystemPrompt builds the strings handed to the SDK. Once parts exist
they are the only source of the tail; a direct write to additional_instructions
is ignored with a warning. Without promptCache.stableContext it reproduces the
previous request; with it, createRun moves only the turn parts with the
prompt-cache tail and merges the rest into the instructions.

The assembled text is byte-identical to string concatenation for both values of
the lever, guarded by a snapshot recorded on the previous implementation.
Isolated subagents with an always-apply skill place the skill ahead of the tool
runtime context when stableContext is on.
…m prompt per segment

Behind `endpoints.agents.promptCache.stableContext`; off, nothing here runs and
the prompt is built as before.

A single send-time step (turnContext) decides what the primary agent's model
sees. Context sources (project, artifacts mode, memory tool guard, skills
catalog, tool runtime context, memory, date, send time, retrieved context,
queued upload files) are sampled once when the user sends a message; only the
net difference from what the model already knows along the parent chain is
stored on that user message (message.contextUpdates) and rendered as one
<context_update> block at the start of its prompt copy. Toggles flipped back
and forth before sending leave no trace, and stored values render the same
bytes on every later turn, whatever the timezone. A regeneration sends no
message: it renders what the message stored and writes nothing.

The system prompt is rendered from the segment's anchor instead of the live
parts, so it stays byte-identical until the next compaction. The anchor of the
first segment is stored on the conversation, the anchor of a segment opened by
a compaction on the message carrying the summary (contextAnchor); a
conversation without one is anchored to its first turn after the upgrade. A
re-anchor keeps the previous order, drops what is off and appends what is new,
and dates itself, so the first message after the boundary announces nothing.

Memory is a state source: an update lists the entries added, changed and
removed (by key where the memory has keys) instead of the whole memory, and no
longer rewrites the system prompt; memory switched off is withheld from the
whole request. Retrieved context is stored with the user message it was
retrieved for, like the file context bound to the message that carried the
files; isolated subagents still take it in their system prompt. Queued upload
files describe their own message only.

A resumed turn (tool approval or an answered question) renders its system
prompt from the paused turn's anchor, not from the live state.

The planning, the anchor storage and the token accounting live in
packages/api; the controller calls them. The conversation anchor is read with
the conversation the ingress already loads, and a resume reads the messages
once with a projection.

contextUpdates and contextAnchor are server-written only, select: false, and
stripped from client input, so they stay out of reads, shares and forks.
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.
…e date changes in history

The web search runtime context and temporal special variables were anchored
to the turn start with millisecond precision. The system message precedes the
whole history, so every turn invalidated the cached history and new
conversations could not reuse the system prompt (LibreChat-AI#16877).

- Web search runtime context states the conversation start in the user's
  timezone with minute precision; temporal variables resolve against the
  same persisted anchor.
- A user message sent on a later local date than the model last saw gets a
  <context_update> block in its prompt copy only, derived from stored
  createdAt values so it renders identically on later turns; compaction
  boundaries follow the agents SDK formatter.
- Optional endpoints.agents.promptMessageTimestamps adds the send time to
  every user message; the turn's user message is stored with
  createdAt = turnStartedAt on every save path.
- Provider payload stability tests through createRun for OpenAI, an
  OpenAI-compatible endpoint, Anthropic, OpenRouter, Bedrock and Google.
… routes

The browser resolved promptPrefix with its own clock on every send, so turn 1
of a spec-backed conversation carried the raw template while turn 2 carried
resolved text in a different system-prompt position. Only Assistants routes
resolve on the client now; the server resolves against the conversation start.
… of a conversation

Adds `endpoints.agents.promptCache.stableContext` (default off). Off, the prompt is
built as before. On:

- prompt time (`{{current_datetime}}` and friends, the web search runtime context) is
  anchored to the conversation start, and a date change is announced by a
  `<context_update>` block at the start of the first user message sent after it;
- the conversation-stable part of `additional_instructions` is merged into the system
  instructions for Anthropic and OpenRouter with prompt caching, while memory, RAG and
  one-turn queued file context stay in `additional_instructions`, where the SDK moves
  them next to the newest user message;
- dynamic tool context goes after the additional instructions;
- the user message is inserted with the turn start as `createdAt`, so later turns render
  the same stamp.

`promptMessageTimestamps` (default off) additionally prefixes each user message with the
time it was sent.

The history notes, the instruction split and the lever live in `packages/api`; the
controller only calls them. `applyContextToAgent` accepts the run context as parts and
records which are volatile, so no text is split by matching.
…assified parts

Producers (project, memory guard, artifacts, skills catalog, RAG, memory,
agent context files, always-apply skills of isolated subagents) contribute
keyed parts through contributeContext instead of concatenating strings into
additional_instructions. One registry fixes the canonical order and classifies
every part, tool context map entries included, as static, conversation or
turn. A runtime key the registry does not know counts as turn, so a new
producer cannot break the stable prefix by default.

assembleSystemPrompt builds the strings handed to the SDK. Once parts exist
they are the only source of the tail; a direct write to additional_instructions
is ignored with a warning. Without promptCache.stableContext it reproduces the
previous request; with it, createRun moves only the turn parts with the
prompt-cache tail and merges the rest into the instructions.

The assembled text is byte-identical to string concatenation for both values of
the lever, guarded by a snapshot recorded on the previous implementation.
Isolated subagents with an always-apply skill place the skill ahead of the tool
runtime context when stableContext is on.
…m prompt per segment

Behind `endpoints.agents.promptCache.stableContext`; off, nothing here runs and
the prompt is built as before.

A single send-time step (turnContext) decides what the primary agent's model
sees. Context sources (project, artifacts mode, memory tool guard, skills
catalog, tool runtime context, memory, date, send time, retrieved context,
queued upload files) are sampled once when the user sends a message; only the
net difference from what the model already knows along the parent chain is
stored on that user message (message.contextUpdates) and rendered as one
<context_update> block at the start of its prompt copy. Toggles flipped back
and forth before sending leave no trace, and stored values render the same
bytes on every later turn, whatever the timezone. A regeneration sends no
message: it renders what the message stored and writes nothing.

The system prompt is rendered from the segment's anchor instead of the live
parts, so it stays byte-identical until the next compaction. The anchor of the
first segment is stored on the conversation, the anchor of a segment opened by
a compaction on the message carrying the summary (contextAnchor); a
conversation without one is anchored to its first turn after the upgrade. A
re-anchor keeps the previous order, drops what is off and appends what is new,
and dates itself, so the first message after the boundary announces nothing.

Memory is a state source: an update lists the entries added, changed and
removed (by key where the memory has keys) instead of the whole memory, and no
longer rewrites the system prompt; memory switched off is withheld from the
whole request. Retrieved context is stored with the user message it was
retrieved for, like the file context bound to the message that carried the
files; isolated subagents still take it in their system prompt. Queued upload
files describe their own message only.

A resumed turn (tool approval or an answered question) renders its system
prompt from the paused turn's anchor, not from the live state.

The planning, the anchor storage and the token accounting live in
packages/api; the controller calls them. The conversation anchor is read with
the conversation the ingress already loads, and a resume reads the messages
once with a projection.

contextUpdates and contextAnchor are server-written only, select: false, and
stripped from client input, so they stay out of reads, shares and forks.
A handoff target that shares the primary agent's memory partition kept a live
copy of the memory in its per-turn tail. With prompt caching the SDK relocates
that tail next to the newest user message, so the memory sat at a different place
on every turn: the target's earlier requests no longer matched its next one, which
missed the cache and, for models that bind thinking blocks to the prefix, made the
API drop the target's own thinking blocks.

The memory the turn context anchors for the segment now goes into the target's
conversation block, and its changes reach it as the <context_update> blocks already
stored on the history messages, as they reach the primary agent. Targets on another
memory partition keep their live copy.
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.
Shabonasar and others added 25 commits October 22, 2026 17:03
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.
…e date changes in history

The web search runtime context and temporal special variables were anchored
to the turn start with millisecond precision. The system message precedes the
whole history, so every turn invalidated the cached history and new
conversations could not reuse the system prompt (LibreChat-AI#16877).

- Web search runtime context states the conversation start in the user's
  timezone with minute precision; temporal variables resolve against the
  same persisted anchor.
- A user message sent on a later local date than the model last saw gets a
  <context_update> block in its prompt copy only, derived from stored
  createdAt values so it renders identically on later turns; compaction
  boundaries follow the agents SDK formatter.
- Optional endpoints.agents.promptMessageTimestamps adds the send time to
  every user message; the turn's user message is stored with
  createdAt = turnStartedAt on every save path.
- Provider payload stability tests through createRun for OpenAI, an
  OpenAI-compatible endpoint, Anthropic, OpenRouter, Bedrock and Google.
… routes

The browser resolved promptPrefix with its own clock on every send, so turn 1
of a spec-backed conversation carried the raw template while turn 2 carried
resolved text in a different system-prompt position. Only Assistants routes
resolve on the client now; the server resolves against the conversation start.
… of a conversation

Adds `endpoints.agents.promptCache.stableContext` (default off). Off, the prompt is
built as before. On:

- prompt time (`{{current_datetime}}` and friends, the web search runtime context) is
  anchored to the conversation start, and a date change is announced by a
  `<context_update>` block at the start of the first user message sent after it;
- the conversation-stable part of `additional_instructions` is merged into the system
  instructions for Anthropic and OpenRouter with prompt caching, while memory, RAG and
  one-turn queued file context stay in `additional_instructions`, where the SDK moves
  them next to the newest user message;
- dynamic tool context goes after the additional instructions;
- the user message is inserted with the turn start as `createdAt`, so later turns render
  the same stamp.

`promptMessageTimestamps` (default off) additionally prefixes each user message with the
time it was sent.

The history notes, the instruction split and the lever live in `packages/api`; the
controller only calls them. `applyContextToAgent` accepts the run context as parts and
records which are volatile, so no text is split by matching.
…m prompt per segment

Behind `endpoints.agents.promptCache.stableContext`; off, nothing here runs and
the prompt is built as before.

A single send-time step (turnContext) decides what the primary agent's model
sees. Context sources (project, artifacts mode, memory tool guard, skills
catalog, tool runtime context, memory, date, send time, retrieved context,
queued upload files) are sampled once when the user sends a message; only the
net difference from what the model already knows along the parent chain is
stored on that user message (message.contextUpdates) and rendered as one
<context_update> block at the start of its prompt copy. Toggles flipped back
and forth before sending leave no trace, and stored values render the same
bytes on every later turn, whatever the timezone. A regeneration sends no
message: it renders what the message stored and writes nothing.

The system prompt is rendered from the segment's anchor instead of the live
parts, so it stays byte-identical until the next compaction. The anchor of the
first segment is stored on the conversation, the anchor of a segment opened by
a compaction on the message carrying the summary (contextAnchor); a
conversation without one is anchored to its first turn after the upgrade. A
re-anchor keeps the previous order, drops what is off and appends what is new,
and dates itself, so the first message after the boundary announces nothing.

Memory is a state source: an update lists the entries added, changed and
removed (by key where the memory has keys) instead of the whole memory, and no
longer rewrites the system prompt; memory switched off is withheld from the
whole request. Retrieved context is stored with the user message it was
retrieved for, like the file context bound to the message that carried the
files; isolated subagents still take it in their system prompt. Queued upload
files describe their own message only.

A resumed turn (tool approval or an answered question) renders its system
prompt from the paused turn's anchor, not from the live state.

The planning, the anchor storage and the token accounting live in
packages/api; the controller calls them. The conversation anchor is read with
the conversation the ingress already loads, and a resume reads the messages
once with a projection.

contextUpdates and contextAnchor are server-written only, select: false, and
stripped from client input, so they stay out of reads, shares and forks.
…assified parts

Producers (project, memory guard, artifacts, skills catalog, RAG, memory,
agent context files, always-apply skills of isolated subagents) contribute
keyed parts through contributeContext instead of concatenating strings into
additional_instructions. One registry fixes the canonical order and classifies
every part, tool context map entries included, as static, conversation or
turn. A runtime key the registry does not know counts as turn, so a new
producer cannot break the stable prefix by default.

assembleSystemPrompt builds the strings handed to the SDK. Once parts exist
they are the only source of the tail; a direct write to additional_instructions
is ignored with a warning. Without promptCache.stableContext it reproduces the
previous request; with it, createRun moves only the turn parts with the
prompt-cache tail and merges the rest into the instructions.

The assembled text is byte-identical to string concatenation for both values of
the lever, guarded by a snapshot recorded on the previous implementation.
Isolated subagents with an always-apply skill place the skill ahead of the tool
runtime context when stableContext is on.
A handoff target that shares the primary agent's memory partition kept a live
copy of the memory in its per-turn tail. With prompt caching the SDK relocates
that tail next to the newest user message, so the memory sat at a different place
on every turn: the target's earlier requests no longer matched its next one, which
missed the cache and, for models that bind thinking blocks to the prefix, made the
API drop the target's own thinking blocks.

The memory the turn context anchors for the segment now goes into the target's
conversation block, and its changes reach it as the <context_update> blocks already
stored on the history messages, as they reach the primary agent. Targets on another
memory partition keep their live copy.
…he runtime note stays byte-stable

The code-file note of an attached workspace is runtime context that the turn context
anchors and updates. Priming returns files by last update, which moves with usage, so the
same files could be listed in another order on a later turn and the note was announced
again without having changed.
…memory

Since LibreChat-AI#16301 formatMemoryContext('') returns the bare memory instructions sentence, and
prepareRuntimeAgent applied it to the primary agent whenever the user had no saved memories.
An agent with no memory tools and no automatic memory extraction can neither read nor write
memory, so the sentence told the model nothing it could act on, yet it reached the model as
per-turn context. The empty-store notice is now added only when the agent has memory tools or
automatic extraction is on. Saved memories are still injected as before.
…m prompt per segment

Behind `endpoints.agents.promptCache.stableContext`; off, nothing here runs and
the prompt is built as before.

A single send-time step (turnContext) decides what the primary agent's model
sees. Context sources (project, artifacts mode, memory tool guard, skills
catalog, tool runtime context, memory, date, send time, retrieved context,
queued upload files) are sampled once when the user sends a message; only the
net difference from what the model already knows along the parent chain is
stored on that user message (message.contextUpdates) and rendered as one
<context_update> block at the start of its prompt copy. Toggles flipped back
and forth before sending leave no trace, and stored values render the same
bytes on every later turn, whatever the timezone. A regeneration sends no
message: it renders what the message stored and writes nothing.

The system prompt is rendered from the segment's anchor instead of the live
parts, so it stays byte-identical until the next compaction. The anchor of the
first segment is stored on the conversation, the anchor of a segment opened by
a compaction on the message carrying the summary (contextAnchor); a
conversation without one is anchored to its first turn after the upgrade. A
re-anchor keeps the previous order, drops what is off and appends what is new,
and dates itself, so the first message after the boundary announces nothing.

Memory is a state source: an update lists the entries added, changed and
removed (by key where the memory has keys) instead of the whole memory, and no
longer rewrites the system prompt; memory switched off is withheld from the
whole request. Retrieved context is stored with the user message it was
retrieved for, like the file context bound to the message that carried the
files; isolated subagents still take it in their system prompt. Queued upload
files describe their own message only.

A resumed turn (tool approval or an answered question) renders its system
prompt from the paused turn's anchor, not from the live state.

The planning, the anchor storage and the token accounting live in
packages/api; the controller calls them. The conversation anchor is read with
the conversation the ingress already loads, and a resume reads the messages
once with a projection.

contextUpdates and contextAnchor are server-written only, select: false, and
stripped from client input, so they stay out of reads, shares and forks.
A handoff target that shares the primary agent's memory partition kept a live
copy of the memory in its per-turn tail. With prompt caching the SDK relocates
that tail next to the newest user message, so the memory sat at a different place
on every turn: the target's earlier requests no longer matched its next one, which
missed the cache and, for models that bind thinking blocks to the prefix, made the
API drop the target's own thinking blocks.

The memory the turn context anchors for the segment now goes into the target's
conversation block, and its changes reach it as the <context_update> blocks already
stored on the history messages, as they reach the primary agent. Targets on another
memory partition keep their live copy.
…he runtime note stays byte-stable

The code-file note of an attached workspace is runtime context that the turn context
anchors and updates. Priming returns files by last update, which moves with usage, so the
same files could be listed in another order on a later turn and the note was announced
again without having changed.
…se memory

The send snapshot formatted an empty memory store as the bare memory instructions sentence
whatever the agent could do with it, so the turn context anchored a sentence that tells the
model nothing it can act on. The snapshot now applies the rule of prepareRuntimeAgent: an
empty store is announced only to an agent with memory tools or when automatic extraction is
on. Saved memories are anchored as before.
No file changes (tree of dev c81e244). Joins earlier snapshots of the series that the
branches share, so any two of them have a single merge base and merge cleanly.
…AI#17146)

No file changes (tree of dev c81e244). Joins earlier snapshots of the series that the
branches share, so any two of them have a single merge base and merge cleanly.
With endpoints.agents.promptCache.stableContext, prompt time is anchored to the
conversation start, a later date is announced in the history, the attached
workspace's attachment note lists files in upload order, and the Agents route
receives promptPrefix as a template that the server resolves against the
conversation start instead of the browser clock.
endpoints.agents.promptMessageTimestamps (default false) states the send time
on each user message.

Co-authored-by: Lia <lia@librechat.ai>
With endpoints.agents.promptCache.stableContext, memory, project, artifacts, skills and the date are
sampled at Send; changes reach the model as <context_update> on the user message and the system
prompt is rendered from a per-segment anchor. Includes LibreChat-AI#17145.
With stableContext and a provider whose system message the SDK caches,
the conversation-stable part goes to conversation_instructions (its own
breakpoint right after the instructions) instead of being merged into
instructions. The block is passed even when empty, so the SDK keeps a
compaction summary as its own message after it instead of moving it
with the per-turn part. Needs LibreChat-AI/agents#613.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants