Skip to content

Fix: Kiro Gateway Anthropic system message compatibility - #270

Closed
ytchen175 wants to merge 1 commit into
jwadow:mainfrom
ytchen175:fix/anthropic-system-message-compatibility
Closed

Fix: Kiro Gateway Anthropic system message compatibility#270
ytchen175 wants to merge 1 commit into
jwadow:mainfrom
ytchen175:fix/anthropic-system-message-compatibility

Conversation

@ytchen175

Copy link
Copy Markdown

Branch: fix/anthropic-system-message-compatibility
Title: Fix: Kiro Gateway Anthropic system message compatibility

Description

  • Fixes Claude Code requests that place a system message inside the Anthropic messages array.
  • Promotes inline system instructions into the Kiro system prompt instead of rejecting them or treating them as user input.
  • Preserves the existing user/assistant conversation history and adds regression coverage.

Root Cause

Claude Code sent a request containing messages[1].role = "system". The gateway schema only accepted user and assistant roles, so Pydantic rejected the request with HTTP 422 before conversion.

Old Logic

  • AnthropicMessage.role was limited to user and assistant.
  • The converter attempted to process every message as conversation history.
  • Inline system messages could not pass validation and never reached the Kiro adapter.

New Logic

  • Allow system as a compatibility role in AnthropicMessage.
  • Extract all inline system messages before conversation conversion.
  • Combine extracted system text in source order and merge it with the top-level Anthropic system field.
  • Convert only user and assistant messages into Kiro conversation history.

Why it works

  • Claude Code's actual request shape is accepted by the API model.
  • System instructions retain system semantics and are not silently converted into user messages.
  • Existing conversation ordering remains unchanged.
  • The new tests cover extraction, ordering, content blocks, and the complete Anthropic-to-Kiro payload.

DoD

  • Accept Anthropic inline system messages.
  • Preserve system semantics during Kiro conversion.
  • Add regression tests for the reported HTTP 422 shape.
  • Run the targeted gateway test suite.
  • Verify a direct gateway request and a Claude Code smoke request.

Code Changes

  • kiro/models_anthropic.py
    • Allows the compatibility system role in AnthropicMessage.
  • kiro/converters_anthropic.py
    • Adds inline system-message extraction and combines it with the top-level system prompt.
    • Excludes system messages from user/assistant conversation history.
  • tests/unit/test_converters_anthropic.py
    • Adds regression coverage for extraction, ordering, content blocks, and final payload conversion.
  • .gitignore
    • Ignores the local Python virtual environment and normalizes the file ending.

Validate Results

./.venv/bin/pytest -q \
  tests/unit/test_models_anthropic.py \
  tests/unit/test_converters_anthropic.py \
  tests/unit/test_routes_anthropic.py

Result: 249 passed, 1 warning.

Additional smoke checks:

  • Direct Anthropic-compatible gateway request: HTTP 200.
  • Claude Code request through the gateway: successful response.
  • Claude Code model usage: claude-opus-5.
  • git diff --check: passed.

Commit Messages

  • Fix: Kiro Gateway Anthropic system message compatibility
    • Accepts Claude Code's inline system-message format.
    • Preserves system prompt semantics and adds regression tests.

Copilot AI lite review requested due to automatic review settings August 9, 2026 07:10
@cla-bot

cla-bot Bot commented Aug 9, 2026

Copy link
Copy Markdown

Thanks for the PR! 馃帀

Before merge, we need a one-time CLA confirmation.
It confirms that you have the right to contribute this code and allow the project to use it.

Full CLA text:
https://github.com/jwadow/kiro-gateway/blob/main/CLA.md

Please reply once with:

I have read the CLA and I accept its terms

You need to write once, all further messages from me can be ignored.

@ytchen175

Copy link
Copy Markdown
Author

I have read the CLA and I accept its terms

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR improves Anthropic-API compatibility by accepting system messages embedded inside the messages[] array (as sent by Claude Code), promoting them into the effective system prompt, and ensuring only user/assistant messages become conversation history in the Kiro payload.

Changes:

  • Allow role="system" in AnthropicMessage for compatibility with clients that send inline system messages.
  • Add extraction/promotion of inline system messages and merge them with the top-level Anthropic system field during Anthropic鈫扠iro conversion.
  • Add unit regression tests covering inline system extraction and end-to-end payload inclusion; update .gitignore to ignore local venv.

Reviewed changes

Copilot reviewed 5 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
kiro/models_anthropic.py Expands Anthropic message role validation to include compatibility system role.
kiro/converters_anthropic.py Promotes inline system messages into the system prompt and excludes them from history conversion.
tests/unit/test_converters_anthropic.py Adds regression coverage for inline system extraction and payload promotion.
fix_anthropic-system-message-compatibility_en.md Adds English PR-style writeup of the change and validation steps.
fix_anthropic-system-message-compatibility_zh.md Adds Chinese PR-style writeup of the change and validation steps.
.gitignore Ignores .venv/ and normalizes an entry formatting.

馃挕 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +136 to +142
for message in messages:
if message.role == "system":
system_text = convert_anthropic_content_to_text(message.content)
if system_text:
system_parts.append(system_text)
else:
conversation_messages.append(message)
Comment on lines +1564 to 1565

def test_includes_tools(self):
@ytchen175

Copy link
Copy Markdown
Author

Superseded by #271, which uses ytchen175:main after merging the fix branch into the fork's main branch.

@ytchen175 ytchen175 closed this Aug 9, 2026
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.

2 participants