Skip to content

Astrid multi-turn fix — system prompt no longer re-embedded each turn

Astrid multi-turn fix — system prompt no longer re-embedded each turn

Status: Delivered
CAS: CAS-2796
Delivered: 2026-05-14
PRs: #748

What’s new

Astrid now stays in character across a full conversation. Previously, every message the user sent caused Astrid’s entire persona definition to be re-injected into the conversation as if it were user content. This had two visible symptoms: Astrid would re-introduce herself (“Hi, I’m Astrid!”) on turn 2, and sometimes she would correctly identify and comment on the embedded prompt-injection pattern — because it was literally injecting a “SYSTEM (highest priority)” block into what Claude reads as user content. Both are fixed.

How to use it

No user-facing change — Astrid simply behaves correctly now. Open the bug report sheet, start a conversation, and Astrid maintains her persona and context across all turns without re-greeting or commenting on her own prompt.

What changed under the hood

  • ClaudeSpawner (claude_subprocess.rs) — new with_system_prompt() builder that passes --system-prompt <text> to the Claude CLI. System prompts are now delivered via the CLI flag rather than injected into user-content strings.
  • LocalCliService.chat_stream (local_cli.rs) — switched to the Claude CLI session mechanism. First turn uses --session-id + --system-prompt (persona set once per session). Subsequent turns use --resume only — user content is the raw user message, nothing more. chat_sessions: HashSet tracks which sessions have had their first turn.
  • ai_chat.rs daemon handler — passes ASTRID_SYSTEM_PREFIX via --system-prompt on the first turn only. Followup content is raw user message + ASTRID_FOLLOWUP_TURN_SUFFIX.
  • 7 new unit and smoke tests verifying: the system prompt flag is passed to the subprocess, subsequent turns do not embed the system prefix in user content, turn 2 does not re-introduce Astrid, and Astrid does not flag her own prompt as injection.

Why we built it

CAS-2721 noted that Astrid lost character after the first turn on desktop. Investigation found the root cause: the persona was being written into user-content on every turn, which caused the model to see it as something the user typed rather than a stable system instruction. On multi-turn conversations this produced the re-greeting and injection-acknowledgement bugs. The fix is structural — the persona is set once via the CLI’s proper system-prompt channel and never touched again mid-session.

Known limitations / follow-on work

  • Session state (chat_sessions) is in-memory and does not survive daemon restart. A restart mid-conversation will cause Astrid to re-introduce herself once (which is acceptable — it’s also what a human would do after reconnecting).
  • The --resume mechanism is specific to the Claude CLI local provider; the CloudBridge path uses a different session model and is not affected by this change.