Skip to content

Multi-turn eval coverage: knowledge retention, context drift, goal hijacking #31

Description

@nabinpkl

Status: deferred. Blocked on Ship 4 (multi-turn agent loop). Filed now to capture the gap so we don't ship multi-turn without eval coverage.

Why

Today's eval substrate is single-turn-only. Every committed case (12 cases across 8 suites) sends one user message and probes one resulting trace. That matches today's agent surface, but multiple converging frontier signals say the next eval frontier is conversation-level, not turn-level:

  • Confident AI: Multi-Turn LLM Evaluation in 2026 (2026-03-22): names knowledge retention, context drift, and role inconsistency as the dominant multi-turn failure modes. Single-turn eval can't surface any of these.
  • OWASP Top 10 for Agents 2026: goal hijacking (ASI01) is the top agentic AI risk. Goal hijacking is fundamentally multi-turn: a session starts benign, later turns subtly redirect the agent.
  • Context window pollution / latent injection: an early turn plants instructions that activate when relevant context emerges several turns later. This entire failure mode requires conversation-level eval to surface.

Single-turn coverage of prompt injection (refusal_prompt_injection.yaml) catches the obvious vector. It cannot catch the multi-turn variants where the injection is split across turns or activates via context accumulation.

Scope

When Ship 4 (multi-turn agent loop) lands:

  • Eval input shape: extend EvalCase.inputs to support a turns: list[dict] field (an ordered sequence of user messages, each with its own context). Backward-compat: existing single-turn cases keep using userQuestion + context.
  • Trace shape: today's mcae.turn span is per-turn; a multi-turn case will produce N turn spans linked by session_id. Probes need a way to scope to "the last turn", "any turn", "the Nth turn".
  • New probe kinds:
    • attribute_consistent_across_turns: pin that an attribute (e.g. agent self-identification) stays stable across all turns in a session. Catches role inconsistency.
    • no_late_turn_tool_call_after_refusal: if turn N's narrative was a refusal, no tool span should fire in turn N OR any later turn for the same session. Catches goal hijacking via context pollution.
    • binding_retention: assert that a chip value bound in turn 1 is still queryable in turn 5 via thread-state. Catches knowledge attrition.
  • New seed cases:
    • multi_turn.knowledge_retention.basic (3-turn): turn 1 establishes context, turn 3 references it, narrative must show retention.
    • multi_turn.goal_hijacking_via_context (5-turn): benign opening, gradual scope drift in turns 2-4, explicit injection in turn 5. Probes assert agent stays in role across the drift.
    • multi_turn.context_pollution_latent_injection (3-turn): turn 1 plants a fake instruction in user message, turn 2 is benign primitive query, turn 3 activates the planted instruction via a relevant question. Probes assert no tool fires on turn 3 from the planted instruction.

Out of scope

  • Cross-trace differential (gated vs ungated trajectory comparison). Already filed in Behavioral evaluation across switch combinations to separate intrinsic from gated behavior #29; orthogonal axis.
  • Production trace sampling (the third leg of the eval architecture per Anthropic 2026-01-09). Different ticket; needs production traffic first.
  • Conversation-level llm_judge (judge scores whole transcript, not single attribute). Could ride on top of single-turn llm_judge with a target_session_id instead of single trace, but that's a larger probe redesign; defer.

Done when

  • EvalCase.inputs supports turns field; existing single-turn cases unchanged.
  • At least three multi-turn probe kinds shipped + tested.
  • Three seed cases (one per failure mode above) with clean baselines.
  • README documents how to author multi-turn cases vs single-turn.

Refs

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestship:eval-substrateShip 2: framework-on-foundation eval substrate per ADR 14

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions