Start with proven experience, not the length of the client list. Ask for a couple of case studies that sit close to your technology stack, and then ask whether those engineers are still with the company. A solid partner will put you on a call with the engineers. Vague answers at this stage generally mean the delivery team is not the dedicated team vs freelancers you were shown.
The contract deserves more scrutiny than the proposal. A few clauses carry most of the weight: ownership of the code, non-disclosure, and notice periods and handover. All the work product must transfer to you once invoices are settled, including designs, scripts and infrastructure configuration. Look closely at wording that keeps so-called reusable libraries with the vendor, as this is frequently the part you cannot replace later.
Ask where their numbers come from. A serious estimate arrives with the assumptions behind it, a task-level breakdown and a best case and a worst case. A fixed price works only when the requirements are stable and documented; when the scope is still moving the vendor pads the number and you pay for it anyway. Time and materials shifts that risk to you, so it requires visible weekly reporting and a spending cap.
Process matters as much as team size. Ask what happens when the scope changes, who writes the acceptance criteria and how testing is organised. A well-run team will be able to demonstrate running software development staff augmentation rather than status reports. Clear, written acceptance criteria remain your only real protection against an argument at delivery time.
Finally, think about the end of the engagement at the start rather than at the end. Ask that the source repository lives on infrastructure you own from day one, and that the documentation is refreshed in every sprint. A vendor with nothing to hide will agree quickly; resistance at this point says quite a lot.
