When Developers Should NOT Use AI A developer argues that AI coding assistants should sit at the end of the engineering toolchain, used only when deterministic tools like compilers, tests, debuggers, profilers, and Git cannot answer a question. The writeup recommends running commands such as git diff, git blame, and pytest, and consulting official documentation for version-specific behavior, rather than routing every step through an LLM. The modern developer workflow increasingly looks like this: Problem → ask AI → copy code → ask AI why it failed → ask AI to fix it → ask AI to explain the fix. That workflow is convenient. It can also create a strange dependency: the developer becomes an API client for another intelligence instead of becoming better at engineering. The goal shouldn't be to eliminate AI from software development. The better goal is: Use AI where reasoning is expensive, and use deterministic tools where computation, verification, and repetition are cheaper. This becomes especially important as developers move into AI engineering and inference engineering. Tools such as Git https://git-scm.com/?utm source=chatgpt.com , GitHub https://github.com/?utm source=chatgpt.com , compilers, linters, debuggers, profilers, Docker https://www.docker.com/?utm source=chatgpt.com , Ollama https://ollama.com/?utm source=chatgpt.com , vLLM https://docs.vllm.ai/?utm source=chatgpt.com , Hugging Face https://huggingface.co/?utm source=chatgpt.com , and Unsloth https://unsloth.ai/?utm source=chatgpt.com can handle large portions of the development lifecycle without requiring an LLM for every step. There are many situations where calling an LLM is unnecessary. If you need to calculate: 1024 × 768 use a calculator. If you need to format code, use a formatter: ruff format gofmt prettier Asking an LLM to perform deterministic work introduces another failure mode: the model can be wrong about something that a machine can calculate exactly. Consider: python def add a, b return a + b You don't need an AI model to tell you that the program has a syntax error. Run the interpreter: python app.py The interpreter already knows. The same principle applies to: A useful engineering hierarchy is: Compiler ↓ Tests ↓ Debugger ↓ Profiler ↓ Documentation ↓ Search ↓ AI AI belongs toward the end of the chain when deterministic tools cannot adequately answer the question. Git is already an incredibly powerful developer reasoning system. Instead of asking: "What changed in my project?" run: git diff Instead of: "What did I change yesterday?" use: git log Instead of asking an LLM to reconstruct why a line exists: git blame file.py can identify the commit that introduced it. For source control, start with the official Git documentation https://git-scm.com/doc?utm source=chatgpt.com and GitHub documentation https://docs.github.com/?utm source=chatgpt.com . For AI-assisted development, see the official GitHub Copilot documentation https://docs.github.com/en/copilot?utm source=chatgpt.com . GitHub Copilot can assist with writing, understanding, reviewing, and changing software, but the important engineering principle remains: Don't use an LLM when your source-control system already contains the answer. Suppose you need to know how FastAPI handles dependency injection. There are two approaches. Ask: "How does FastAPI dependency injection work?" Read the official documentation and inspect the actual API. The second approach gives you something extremely important: authority and version-specific behavior. AI can generate an explanation, but documentation defines what the software actually supports. For production engineering, the workflow should often be: Official documentation ↓ Minimal reproduction ↓ Test ↓ AI assistance if necessary not: AI ↓ AI ↓ AI ↓ Maybe documentation One of the most underrated ways to reduce AI usage is to write good tests. Imagine a developer asks an AI: "Is my authentication implementation correct?" That's a weak question. Instead: pytest might tell you immediately. Even better: python def test invalid token is rejected : ... Now the machine can repeatedly verify the behavior. This changes the role of AI. AI decides whether the implementation works. you get: AI proposes an implementation → tests decide whether it works. For Python projects, pytest's official documentation https://docs.pytest.org/?utm source=chatgpt.com is the reference point. That's a much healthier architecture. Suppose you have: result = calculate price order and result is wrong. Instead of immediately asking AI: "Why is result wrong?" use a debugger. Inspect: order ↓ inputs ↓ function arguments ↓ intermediate variables ↓ return value A debugger gives you actual program state. An LLM gives you a hypothesis. Those are not equivalent. AI becomes more useful after you've collected evidence. For example: "At line 142, discount=0.2 , but calculate discount returns 0.0. Here is the function and failing test." Now the AI has a constrained debugging problem rather than a guessing problem. Performance engineering is particularly vulnerable to AI speculation. Developers often ask: "Why is my Python application slow?" An LLM may produce 20 possible explanations. A profiler can tell you where the program actually spends its time. request ├── database query 72% ├── JSON serialization 14% ├── Python computation 9% └── logging 5% Now you don't need a philosophical discussion about Python performance. You have evidence. The same principle applies to AI inference. Inference engineering is fundamentally about turning a model into a useful, reliable production system. Important variables include: Model Quantization KV cache Batch size Context length GPU memory Throughput Latency Concurrency Tokens/sec Cost/request Time-to-first-token You don't want an LLM guessing these numbers. You benchmark them. Model A batch=1 TTFT = 120 ms generation = 80 tok/s Model B batch=1 TTFT = 180 ms generation = 110 tok/s The benchmark is more useful than an AI-generated statement saying: "Model B should probably be faster." For production inference, use actual benchmark data. Unsloth https://unsloth.ai/?utm source=chatgpt.com is an open-source framework for local model training and inference workflows. Its documentation covers running models, fine-tuning, reinforcement learning, datasets, deployment, and other model-development workflows. See the official Unsloth documentation https://unsloth.ai/docs?utm source=chatgpt.com . That creates an important distinction. Developer ↓ Cloud AI API ↓ Answer Developer ↓ Local model ↓ Inference engine ↓ Application The second approach gives the developer more control over: Suppose you're building a developer tool. You don't necessarily need to send every request to a large proprietary model. You might use: Small local model ↓ simple classification ↓ local embedding model ↓ RAG ↓ large model only when necessary This is an important inference-engineering pattern: Use the smallest system that can reliably solve the task. For local model execution, developers can investigate tools such as: The use case differs between them: local experimentation, optimized inference, model serving, fine-tuning, quantization, or production deployment. Think of the modern development stack as a series of increasingly expensive reasoning tools. | Problem | Prefer first | AI needed? | |---|---|---| | Syntax error | Compiler/interpreter | Usually no | | Formatting | Formatter | No | | Linting | Linter | No | | Type error | Type checker | Usually no | | Regression | Tests | No | | Git history | Git | No | | Runtime state | Debugger | Usually no | | Performance | Profiler | Usually no | | API behavior | Official docs | Usually no | | Unknown error | Search/docs | Sometimes | | Complex debugging | AI | Often useful | | Architecture exploration | AI + human | Useful | | Novel implementation | AI + engineer | Useful | | Large refactoring | AI agent + tests | Useful | | Model optimization | Benchmarks + profiling + AI | Useful | The point isn't that AI is bad. The point is that AI shouldn't be the first tool for every problem. You don't need hundreds. A compact engineering stack can cover most repetitive work. Hugging Face provides tooling for model and inference workflows, including Inference Providers https://huggingface.co/docs/inference-providers/?utm source=chatgpt.com and Inference Endpoints https://huggingface.co/docs/inference-endpoints/?utm source=chatgpt.com . You don't need every tool. You need the right tool for the problem. Every AI interaction has a hidden cost. Not necessarily money. There is also: You stop remembering how systems work. You have to check generated code. You need to explain your project to the model. You wait for responses. Sensitive information may leave your environment depending on the service and configuration. Your workflow becomes dependent on an external model or provider. If AI constantly solves the problem before you understand it, your debugging ability may stagnate. Therefore: The cheapest AI request is sometimes the request you never had to make. Modern software systems are enormous. Developers cannot memorize: AI can dramatically reduce search and implementation time. The official GitHub Copilot documentation https://docs.github.com/en/copilot?utm source=chatgpt.com describes its use across software-development workflows, including coding assistance and agentic workflows. So the objective isn't: "Developers should use less AI." A better objective is: Developers should use less unnecessary AI. That's a completely different idea. This sounds contradictory. It isn't. Consider an inference engineer who builds: Developer │ ├── Git ├── Tests ├── Profiler ├── Benchmarks ├── Documentation ├── Local LLM │ └── Unsloth │ ├── Inference engine │ └── vLLM / llama.cpp / Ollama │ └── Cloud LLM └── Used only when necessary They may actually use more AI models than the average developer. But they don't ask an AI model to do everything. They build systems where: deterministic software handles deterministic work, and: probabilistic models handle problems where probabilistic reasoning is valuable. That's the real engineering advantage. A strong workflow looks like this: PROBLEM │ ▼ Can a deterministic tool answer it? / \ YES NO │ │ ▼ ▼ Use the tool Read docs │ ▼ Search existing solutions │ ▼ Build minimal example │ ▼ Test/measure │ ▼ Still blocked? / \ NO YES │ │ ▼ ▼ Done AI │ ▼ Verify output │ ▼ Tests/benchmarks This workflow produces a subtle but important benefit: AI becomes a force multiplier rather than a crutch. Before asking AI to solve something, ask five questions: If yes, compile it. If yes, test it. If yes, read it. If yes, benchmark or profile it. If yes: Use AI. And then verify the result. The strongest developers of the AI era won't necessarily be the people who generate the most code with AI. They may be the people who know when not to generate code at all . Git can answer questions about history. Compilers can find syntax errors. Type checkers can find type problems. Tests can verify behavior. Debuggers can expose program state. Profilers can identify bottlenecks. Benchmarks can measure inference performance. Documentation can define APIs. Local AI stacks such as Unsloth https://unsloth.ai/?utm source=chatgpt.com can let engineers run and customize models themselves. And when all of those tools reach their limits, AI becomes extremely valuable. The mature workflow is therefore not: Human → AI → code It is: Human → tools → evidence → AI when useful → verification AI doesn't have to replace the developer's tools. AI works best when the developer already has tools that can prove whether the AI is right. That is how we get developers who are AI-assisted without becoming AI-dependent.