For the error contract, isError should identify a failed tool execution without being treated as a universal instruction to retry. A missing required business value, an upstream outage, and a terminal business rejection need different next steps even when all arrive as tool errors.
I would return a stable error category and an explicit recovery hint, then test that the client changes arguments only for correctable input failures and does not keep reissuing a terminal rejection. That preserves the useful self-correction path you describe while keeping recoverability a property of the actual failure, rather than of the flag alone.