For API/tool-facing code, treat the external API contract as non-negotiable: validate parameter bounds against the upstream model/docs, handle pagination only when the API is actually paginated, and ensure your client/tool surface (operation routing, errors, and side-effect metadata) is explicit and consistent.
Apply this checklist: 1) Parameter constraints must match upstream
NextToken, loop until exhaustion (or a hard cap) so you don’t produce false negatives.operation-routing when most ops share a core parameter set.error + error_type (or equivalent) uniform so clients/LLMs can reliably decide retry vs fix.
5) Keep mutation-risk metadata truthfuldestructiveHint=true (don’t mark it additive-only).Example: correct pagination loop + contract-aligned max_results validation
from typing import Any, Dict, List, Optional
def validate_max_results(max_results: Optional[int]) -> Optional[int]:
# Example of contract-aligned validation: 1–500 per AWS model
if max_results is None:
return None
if not (1 <= max_results <= 500):
raise ValueError("max_results must be between 1 and 500")
return max_results
def call_paged_list_api(client, *, start: int, end: int, max_results: int = 100) -> List[Dict[str, Any]]:
# Only do this if the upstream API is actually paginated and returns NextToken.
results: List[Dict[str, Any]] = []
next_token: Optional[str] = None
while True:
params = {
"StartTime": start,
"EndTime": end,
"MaxResults": max_results,
}
if next_token:
params["NextToken"] = next_token
resp = client.list_something(**params)
results.extend(resp.get("Items", []))
next_token = resp.get("NextToken")
if not next_token:
break
# Optional safety cap to prevent fan-out
# if len(results) > 10_000: break
return results
If you adopt this standard, you prevent the most common production failures seen in the discussions: silent truncation (missing pages), incorrect parameter ranges, ambiguous routing choices, and inconsistent error/side-effect semantics.