DEV Community

Mukunda Rao Katta
Mukunda Rao Katta

Posted on

400 from Anthropic API. Two consecutive user messages. Every time.

Hermes Agent Challenge Submission: Write About Hermes Agent

This is a submission for the Hermes Agent Challenge.

I spent 20 minutes debugging a 400 error from the Anthropic API. The error message was messages: roles must alternate between "user" and "assistant". I had accidentally appended two user messages in a row. By the time the request reached the API, the bug was three layers deep in my agent loop.

The fix: validate the message list before sending it. That's agent-message-validator.

Check before sending

from agent_message_validator import validate_messages

result = validate_messages(messages)
if not result.ok:
    print(result.summary())
    # 1 error(s) in 4 message(s):
    #   - consecutive same-role messages at index 2 and 3 (role='user')

response = client.messages.create(...)
Enter fullscreen mode Exit fullscreen mode

Raise on error

from agent_message_validator import check_messages

check_messages(messages)  # raises MessageValidationError if invalid
response = client.messages.create(...)
Enter fullscreen mode Exit fullscreen mode

Quick boolean check

from agent_message_validator import is_valid

if is_valid(messages):
    response = client.messages.create(...)
else:
    # fix messages before sending
Enter fullscreen mode Exit fullscreen mode

What it catches

Consecutive same-role messages — the most common error in multi-turn agents:

msgs = [
    {"role": "user", "content": "First question"},
    {"role": "user", "content": "Follow-up"},  # 400 waiting to happen
]
validate_messages(msgs).ok  # False
Enter fullscreen mode Exit fullscreen mode

First message from assistant:

msgs = [{"role": "assistant", "content": "Hello"}]
validate_messages(msgs).ok  # False
Enter fullscreen mode Exit fullscreen mode

Unmatched tool_use without tool_result:

msgs = [
    {"role": "user", "content": "Search"},
    {"role": "assistant", "content": [
        {"type": "tool_use", "id": "tu_001", "name": "search", "input": {}}
    ]},
    # Never sent the tool result
    {"role": "user", "content": "Never mind"},
]
result = validate_messages(msgs)
# "tool_use 'tu_001' has no matching tool_result"
Enter fullscreen mode Exit fullscreen mode

Orphan tool_result (no prior tool_use):

msgs = [
    {"role": "user", "content": [
        {"type": "tool_result", "tool_use_id": "tu_999", "content": "..."}
    ]},
]
result = validate_messages(msgs)
# "tool_result for 'tu_999' has no matching tool_use"
Enter fullscreen mode Exit fullscreen mode

Empty content and missing role/content keys.

ValidationResult

result = validate_messages(messages)
result.ok           # True / False
result.errors       # ["consecutive same-role messages at ...", ...]
result.error_count  # int
result.message_count
bool(result)        # same as result.ok
result.summary()    # human-readable string
Enter fullscreen mode Exit fullscreen mode

Multiple errors reported at once

The validator runs all checks and returns all errors, not just the first:

# messages where the first message is assistant AND two consecutive roles
result = validate_messages(bad_messages)
result.error_count  # 2
Enter fullscreen mode Exit fullscreen mode

Zero dependencies

Standard library only: dataclasses. Nothing else.

git clone https://github.com/MukundaKatta/agent-message-validator
cd agent-message-validator && pip install -e .
Enter fullscreen mode Exit fullscreen mode

Repo: https://github.com/MukundaKatta/agent-message-validator

Top comments (0)