Skip to content

feat(bench): Anthropic tool-use adapter for the multi-turn loop (#102)#121

Merged
Connorrmcd6 merged 1 commit into
mainfrom
feat/102-anthropic-step
Jun 14, 2026
Merged

feat(bench): Anthropic tool-use adapter for the multi-turn loop (#102)#121
Connorrmcd6 merged 1 commit into
mainfrom
feat/102-anthropic-step

Conversation

@Connorrmcd6

Copy link
Copy Markdown
Owner

Summary

Phase 4 (Anthropic only): make AnthropicModel a ToolModel so a real Claude model can drive the multi-turn agent loop built in #119. This is what turns the offline harness into something that can actually measure verification suppression. OpenAI + Gemini adapters land separately (#107).

Builds directly on merged #119 (phases 1–3).

What changed

  • models.pyAnthropicModel.step() plus three pure, module-level converters between the neutral loop format (agent.run_agent) and the Anthropic wire format:
    • _anthropic_tools — neutral TOOL_SPECS → Anthropic input_schema tools.
    • _anthropic_messages — neutral history → Anthropic messages, coalescing consecutive same-role turns so a tool_result user-turn followed by the forced-answer nudge stays one valid user message. Assistant turns are echoed back via Step.provider_msg so history round-trips losslessly.
    • _step_from_anthropic — response (text + tool_use blocks, usage, stop_reason) → neutral Step.
  • tests — 4 offline tests for the converters + response parsing (the riskiest part of any adapter), using a fake response. No network in the suite.

Verification

  • uv run pytest (in bench/) — 24 passed (4 new), no network.

  • cargo fmt --all --check — clean (no Rust touched).

  • Live smoke (haiku · --mode multi · cascade-quota-batcher-code · C0/C1/C2 · N=1) confirms the real tool round-trip and already previews the headline:

    Cond verified_hidden turns result
    C0 (no doc) ✅ read window.py 4 correct
    C1 (stale doc) 1 misled
    C2 (fresh doc) 2 (n=1 noise)

    With no doc the agent explores and checks the hidden dependency; with a confident stale doc it answers immediately and is misled. The real signal awaits N≥10 + the oracle tripwires (#105/#117).

Scope

Part of #102 (completes the loop so a real model can drive it). Not a full close: OpenAI/Gemini are Connorrmcd6/surface-bench#16 and the verification/compounding metrics + reporting are Connorrmcd6/surface-bench#13.

🤖 Generated with Claude Code

Phase 4 (Anthropic only): make AnthropicModel a ToolModel so a real Claude
model can drive the agent loop. OpenAI/Gemini adapters land separately
(#107).

- models.py: AnthropicModel.step() plus pure, module-level converters
  between the neutral loop format and the Anthropic wire format
  (_anthropic_tools, _anthropic_messages, _step_from_anthropic). The
  message converter coalesces consecutive same-role turns so a tool_result
  turn followed by the forced-answer nudge stays a single, valid user
  message. Assistant turns are echoed back via Step.provider_msg so history
  round-trips losslessly.
- tests: 4 offline tests for the converters + response parsing (the
  riskiest part), using a fake response — no network in the suite.

Live smoke (haiku, multi, cascade-quota-batcher, C0/C1/C2, N=1) confirms
the round-trip and already shows the effect: C0 (no doc) reads the hidden
window.py and is correct; C1 (stale doc) answers in one turn without
verifying and is misled. The real signal awaits N>=10 + the oracle.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Connorrmcd6 Connorrmcd6 merged commit 4942697 into main Jun 14, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant