fix(agent): make mid-turn /steer trusted, not read as injection
A steer rides inside a tool result (the only role-alternation-safe slot
mid-turn), so a bare "User guidance:" line reads as untrusted tool content —
well-behaved models refuse it as suspected prompt injection (observed live:
"I only follow instructions from you directly, not ones injected through
command results").
- Wrap steers in a bounded, self-describing [OUT-OF-BAND USER MESSAGE] marker
(prompt_builder.format_steer_marker), shared by both drain sites.
- Add STEER_CHANNEL_NOTE to the core system prompt so the model expects this
exact marker and trusts it as a genuine user message — while still ignoring
lookalikes buried in tool/web/file output. Static text → byte-stable prompt,
no prompt-cache regression; gated on the agent having tools.
- Desktop: steer ack is now an inline transcript note (⏩ steered · …) instead
of a toast.
Marker is intentionally static (not a per-session nonce) to honor the
byte-stable system-prompt caching policy; nonce hardening noted as follow-up.
This commit is contained in:
@@ -767,7 +767,9 @@ export function usePromptActions({
|
||||
|
||||
if (result?.status === 'queued') {
|
||||
triggerHaptic('submit')
|
||||
notify({ kind: 'success', title: 'Steered', message: text })
|
||||
// Inline note (not a toast) so the nudge lives in the transcript next
|
||||
// to the turn it steered — same centered system-note style as slash output.
|
||||
appendSessionTextMessage(sessionId, 'system', `⏩ steered · ${text}`)
|
||||
|
||||
return true
|
||||
}
|
||||
@@ -777,7 +779,7 @@ export function usePromptActions({
|
||||
|
||||
return false
|
||||
},
|
||||
[activeSessionId, activeSessionIdRef, requestGateway]
|
||||
[activeSessionId, activeSessionIdRef, appendSessionTextMessage, requestGateway]
|
||||
)
|
||||
|
||||
const reloadFromMessage = useCallback(
|
||||
|
||||
Reference in New Issue
Block a user