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, GitHub, compilers, linters, debuggers, profilers, Docker, Ollama, vLLM, Hugging Face, and Unsloth 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:
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 and GitHub documentation.
For AI-assisted development, see the official GitHub Copilot documentation.
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:
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 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 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.
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 and Inference Endpoints.
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 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 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.