Dynamic forms and the agent-to-user communication grammar

Failure modes

Rendering on a surface that has none

If a form is rendered to the widget surface but the client cannot post back (sendPrompt unavailable), the submit button reports it and the caller should fall back to form_to_askuserquestion. A rich widget needs a widget-capable client; a plain terminal degrades to the menu fallback by design.

"Registered ≠ working until the server reboots"

A newly added construct or field reaches the live MCP server only after the server restarts on the new version — the tool schema is loaded at startup. Verify the live elicitation_render_widget schema actually carries a new enum value before asserting the construct works end-to-end.

A progress form whose blocked items disagree with its options

The bridge enforces set(blocked labels) == set(options); a mismatch raises FormValidationError. The picker can never offer a non-existent blocker or omit a real one.