check_code_from_file() that rejects any Field(alias="...") value containing invalid characters ($, [], (), @, spaces)ACTION_BUILDER_PROMPT so the LLM knows how to handle API params with special charactersClaude's tool_use API requires all input_schema property keys to match ^[a-zA-Z0-9_.-]{1,64}$. Our LLM-generated action files were using raw API parameter names (e.g., $top, filter[store_id], mode(eq), @odata.nextLink) as Pydantic Field aliases — these become JSON Schema property keys and get rejected.
Root cause: The LLM prompts had no rules about alias character restrictions, and check_code_from_file() had no validation for alias values.
app_tester/common/utils.py — Hard gate: regex check rejects code with invalid alias characters. The error message tells the LLM exactly how to fix it (clean alias + PARAM_REMAP).
app_tester/action_builder/prompt.py — Teaches the LLM the valid alias pattern and PARAM_REMAP technique upfront, so it generates correct code on the first attempt.
| Layer | Coverage |
|---|---|
| Programmatic check (this PR) | Blocks 100% of invalid aliases at generation time |
| Prompt rule (this PR) | LLM generates correct code without retries |
| Mercury sanitizer (PR #18009) | Runtime safety net catches anything that slips through |
$top, $filter, filter[store_id], mode(eq), @odata.nextLink, First Nametop, displayName, user.id, odata.nextLink, simple-field.format() call on prompt string works correctly (braces properly escaped)🤖 Generated with Claude Code