Skip to content

Conversation

jxnl
Copy link
Collaborator

@jxnl jxnl commented Oct 1, 2025

Summary

Fixes #1829 - Resolves 400 error from Anthropic API when validation fails in ANTHROPIC_TOOLS mode

Problem

When using ANTHROPIC_TOOLS mode with validation that fails on the first attempt, the retry mechanism was creating malformed message structures. The reask_anthropic_tools function had an overly restrictive condition that prevented proper tool_result blocks from being created when exceptions were wrapped in InstructorError.

This caused Anthropic's API to reject requests with:

Error code: 400 - 'tool_use' ids were found without 'tool_result' blocks immediately after

Root Cause

The condition checking for tool_result creation required:

  1. Exception to be an instance of ValidationError or InstructorValidationError
  2. Exception title to match the tool name

However, during the reask process, exceptions are wrapped in InstructorError via InstructorError.from_exception(), losing their original type. This caused the condition to fail, resulting in plain text user messages instead of properly formatted tool_result blocks.

Solution

Simplified the logic to always create a tool_result block whenever there's a tool_use in the response, regardless of exception type or title matching. This ensures:

  • Proper message structure for Anthropic's API
  • Claude can understand validation errors and correct responses
  • Retry mechanism works as intended

Testing

  • Reproduced the issue with a test case that triggers validation failure
  • Verified the fix resolves the 400 error
  • Confirmed successful retry and proper error handling
  • Both validation failure and success cases work correctly

Generated with Claude Code


Important

Fixes 400 error in Anthropic API by ensuring tool_result blocks are created for all tool_use responses in reask_anthropic_tools().

  • Behavior:
    • Fixes 400 error in Anthropic API by ensuring tool_result blocks are created for all tool_use responses in reask_anthropic_tools().
    • Simplifies condition to always create tool_result block when tool_use is present, regardless of exception type or title.
  • Testing:
    • Added test case to reproduce validation failure and verified fix resolves the error.
    • Confirmed retry mechanism and error handling work correctly for both failure and success cases.

This description was created by Ellipsis for 8de8b36. You can customize this summary. It will automatically update as commits are pushed.

…e responses during reask

Fixes #1829

When validation fails in ANTHROPIC_TOOLS mode, the reask mechanism was incorrectly
skipping tool_result block creation due to an overly restrictive condition that checked:
1. Exception type (ValidationError or InstructorValidationError)
2. Exception title matching the tool name

However, when exceptions are wrapped in InstructorError during the reask process,
they lose their original type, causing the condition to fail. This resulted in
plain text user messages instead of properly formatted tool_result blocks, which
violates Anthropic's API requirement that every tool_use must have a corresponding
tool_result block.

The fix simplifies the logic to always create a tool_result block whenever there's
a tool_use in the response, regardless of exception type or title matching. This
ensures proper message structure for retries and allows Claude to understand the
validation error and correct its response.

Generated with Claude Code (https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Copy link

cloudflare-workers-and-pages bot commented Oct 1, 2025

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
instructor 8de8b36 Oct 01 2025, 02:20 PM

Copy link
Contributor

claude bot commented Oct 1, 2025

Claude finished @jxnl's task —— View job


Code Review: Anthropic Tool Result Fix

Todo List

  • Read and analyze the changed file (instructor/providers/anthropic/utils.py)
  • Understand the broader context and related files
  • Check existing test coverage for this functionality
  • Evaluate code quality and best practices
  • Assess for potential bugs or issues
  • Review performance considerations
  • Check for security concerns
  • Provide comprehensive review feedback

🔍 Review Summary

This PR addresses a critical bug in the Anthropic tools retry mechanism. The fix is well-reasoned and correct, simplifying overly complex conditional logic that was causing 400 errors from Anthropic's API.

Positive Aspects

Correct Problem Identification

  • The root cause analysis is spot-on: InstructorError.from_exception() wraps original exceptions, changing their type from ValidationError to InstructorError
  • This caused the overly restrictive condition isinstance(exception, (ValidationError, InstructorValidationError)) and content.name == exception.title to fail

Appropriate Solution

  • Simplifying to always create tool_result blocks when tool_use is present is the right approach
  • Aligns with Anthropic's API requirement: every tool_use must have a corresponding tool_result
  • The change reduces complexity and eliminates edge cases

Code Quality

  • Clean, minimal change (+1/-5 lines)
  • Preserves all existing functionality
  • Maintains proper error message formatting for Claude

⚠️ Areas of Concern

1. Test Coverage Gap

Priority: High

The most significant concern is the lack of test coverage for this critical path:

# instructor/providers/anthropic/utils.py:163-176
if tool_use_id is not None:
    reask_msgs.append({
        "role": "user", 
        "content": [{
            "type": "tool_result",
            "tool_use_id": tool_use_id,
            "content": f"Validation Error found:\n{exception}\nRecall the function correctly, fix the errors",
            "is_error": True,
        }]
    })

Recommendations:

  • Add a test that reproduces the original 400 error
  • Test validation failure scenarios with ANTHROPIC_TOOLS mode
  • Verify tool_result blocks are properly formatted in retry attempts
  • Test with both ValidationError and wrapped InstructorError exceptions

2. Exception Handling Robustness

Priority: Medium

The new logic assumes any tool_use should get a tool_result, but consider edge cases:

# What if content.id is None or malformed?
if content.type == "tool_use":
    tool_use_id = content.id  # Could this ever be None?

Recommendation: Add defensive checking:

if content.type == "tool_use" and content.id:
    tool_use_id = content.id

3. Error Message Consistency

Priority: Low

The error message format could be more consistent:

# Current:
f"Validation Error found:\n{exception}\nRecall the function correctly, fix the errors"

# Consider standardizing error formatting across providers

🔒 Security Assessment

Status: ✅ No Issues

  • No security concerns identified
  • Error messages don't expose sensitive information
  • API interaction follows Anthropic's specifications

Performance Assessment

Status: ✅ Improved

  • Reduces conditional complexity (fewer checks)
  • Eliminates potential for failed condition matching
  • Minimal performance impact overall

🐛 Bug Risk Assessment

Status: ✅ Low Risk

  • The simplified logic reduces bug surface area
  • Aligns with Anthropic API requirements
  • Maintains backward compatibility

📋 Specific Code Comments

/instructor/providers/anthropic/utils.py:159-161

# BEFORE (problematic):
if (
    content.type == "tool_use"
    and isinstance(exception, (ValidationError, InstructorValidationError))  
    and content.name == exception.title  # This was too restrictive
):

# AFTER (correct):
if content.type == "tool_use":

Analysis: The simplified condition is much better. The original logic failed because:

  1. exception gets wrapped by InstructorError.from_exception()
  2. content.name == exception.title was fragile and unnecessary
  3. Anthropic requires tool_result for every tool_use regardless

🎯 Recommendations

  1. High Priority: Add comprehensive tests for this retry scenario
  2. Medium Priority: Consider defensive null checking for content.id
  3. Low Priority: Standardize error message formatting

🏁 Verdict

✅ APPROVE - This is a solid fix that addresses a real production issue. The solution is correct, well-reasoned, and improves code reliability. The main concern is test coverage, which should be addressed in a follow-up.

The change properly fixes the 400 error from Anthropic's API while maintaining all existing functionality.


@github-actions github-actions bot added anthropic bug Something isn't working python Pull requests that update python code labels Oct 1, 2025
Copy link
Contributor

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important

Looks good to me! 👍

Reviewed everything up to 8de8b36 in 1 minute and 59 seconds. Click for details.
  • Reviewed 17 lines of code in 1 files
  • Skipped 0 files when reviewing.
  • Skipped posting 2 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. instructor/providers/anthropic/utils.py:159
  • Draft comment:
    The condition has been simplified to always capture a 'tool_use' by checking only content.type. This resolves the issue with wrapped exceptions, but please add an inline comment noting that the exception-type check was removed because exceptions are wrapped in InstructorError and lose their original type.
  • Reason this comment was not posted:
    Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 20% vs. threshold = 85% The comment is about a real code change in the diff - the removal of exception type checking. The suggestion to add documentation seems reasonable since this is a non-obvious change that affects error handling behavior. However, the comment is asking for documentation rather than pointing out a clear bug or issue. Per the rules, we should not make purely informative comments or ask authors to add documentation unless it's for library code changes. This could be an important change in error handling behavior that deserves documentation. Removing the validation checks could have unintended consequences. While documentation would be nice, our rules explicitly state not to make purely informative comments. The code change appears intentional and works correctly without the additional checks. Delete the comment. While documentation would be helpful, we should not make comments that merely suggest adding documentation unless it's for library code changes.
2. instructor/providers/anthropic/utils.py:159
  • Draft comment:
    Note that if multiple 'tool_use' messages are present in response.content, only the last one's id will be used when appending the tool_result block. Confirm that this behavior is acceptable with Anthropic’s API, or consider handling multiple tool_use blocks if needed.
  • Reason this comment was not posted:
    Confidence changes required: 80% <= threshold 85% None

Workflow ID: wflow_AEVUqusuWQKgFY6g

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

anthropic bug Something isn't working python Pull requests that update python code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Using ANTHROPIC_TOOLS mode throws 400 from Anthropic API in 1.11.3

1 participant