First off, if you're not already using code formatters and linters, you should be. Without them, consistency relies entirely on the self-discipline of your team, which is... optimistic at best. Running AI-generated code through a formatter and feeding selected linter errors back to the AI already gives you a much more coherent result. It won't be perfect, but it's like brushing your teeth. Basic hygiene.
Next, define what you want: structuring, naming conventions, preferred patterns. Just put them in a clear instruction file like agents.md. Most tools don't have persistent memory yet, so you need to remind them. Even for tools that do remember, restating your expectations never hurts.
When AI gives you code that looks off, pause and ask: Could a formatter or linter catch this? Should it be in the instruction file? Did I just forget to mention it in the prompt?
Additionally, you can use QA agents. Write prompts that describe what's wrong, get a second agent to detect those issues, and then reuse that agent to evaluate future output. It's like building a tiny QA team.
With this setup, I've almost completely eliminated the mismatch between AI-generated code and my existing codebase. The tradeoff is a bit more time, some extra token spend, and the joy of watching AI argue with itself about brace positioning.