# Messages API structure guardrails

1. `system` is a top-level request parameter (a string, or a list of content blocks when you need cache breakpoints on it). It is not a message. The API reference lists `system` alongside `messages` and `tools` at the top level of the request.
2. `messages` contains only `user` and `assistant` roles. There is no `system` role inside `messages`; putting one there is rejected.
3. Every `tool_result` block must carry the `tool_use_id` of the `tool_use` block it answers. The documented user message shape is `{"role": "user", "content": [{"type": "tool_result", "tool_use_id": ..., "content": ...}]}`. A result without the matching id is rejected.
4. Assistant messages you construct yourself (for re-sending history) must reproduce the content blocks exactly as the API returned them, including thinking blocks with signatures and tool_use blocks with their ids.
5. `max_tokens` is required on every request and bounds the model's output. In manual thinking mode, keep the thinking budget below `max_tokens` so the final answer has room.
6. Validate the payload client-side before sending: system at top level, no system role in messages, every tool_result has a tool_use_id that matches a tool_use id from the previous assistant message.

Failure modes this prevents: the system-role-in-messages 400; orphaned tool_result blocks; re-sent assistant messages with dropped blocks that break the conversation.
