Shipping no longer forces understanding
Previously, one of the best ways to learn software engineering was to build something.
You wanted a program that did something useful. Usually the idea was too large and your knowledge was too small, so you hunted for whatever got you to the next step: a tutorial, an API example, a forum post, a half-relevant answer, a page of documentation you did not understand yet.
The old loop looked roughly like this:
want something → investigate → build → fail → understand → improve → use it
The learning was badly organized but attached to a real need. A site-monitoring script hung, teaching you about timeouts. Five alerts arrived for one incident, so you learned about state and debouncing. A token leaked into Git, so you learned about secrets. The script died when your laptop slept, showing you the difference between a script and a service.
None of those topics were in the original idea. The project revealed them because reality kept refusing the naive version.
Coding agents change that forcing function. The new loop can be much shorter:
want something → prompt → receive something plausible → stop
Fast implementation is good. Asking someone to hand-type an inferior version for character development is fake nostalgia. Shipping just no longer guarantees understanding.
Learning is still available. It has become optional.
Answers give you vocabulary. Projects give you judgment.
Models make explanations cheap. I can ask how a database index changes a query, how a distributed system handles retries, or why a particular authentication flow is unsafe and get a useful map in seconds.
A model answer is a useful map, not a verified encyclopedia. It can simplify, omit, or confidently invent. Even a good explanation leaves out many of the constraints, failures, tradeoffs, and scars that produced the thing being explained.
Answers give you vocabulary. Projects give you judgment.
Judgment forms when a prediction meets reality and loses. You expected the system to behave one way. The run, user, incident, or test showed you something else. You had to decide whether your mental model was wrong, the implementation was wrong, the evidence was weak, or the requirement itself was confused.
Agents do not remove that learning loop. They can, however, carry us past it so quickly that we never notice we skipped it.
The chasm is the missing mismatch
Natural language lets us describe systems more elaborate than our engineering understanding would previously allow. We can ask for something secure, distributed, observable, autonomous, and production-ready in one paragraph. The agent can return code that looks like all five.
The easy side of the loop is now:
intent → description → agent attempt → reality
If reality looks plausible, vibe coding stops there.
The rest of the loop sits across a chasm:
mismatch → investigation → change
Without a prediction, reality has nothing concrete to contradict. Without evidence, the disagreement stays invisible. Generated complexity can outrun the mental model required to own it, and the user may not know what question to ask next.
That is the distinction I care about between vibe coding and agentic engineering. Agentic engineering crosses the gap deliberately. It makes an expectation explicit, inspects what happened, names the mismatch, and follows it until the understanding is sufficient for the consequences at stake.
We do not need to understand every generated line. We do need enough understanding to name what could fail, decide what evidence matters, and recover when reality disagrees.
Prediction and evidence repair the loop
The repaired loop is:
intent → prediction → agent attempt → reality → mismatch → investigation → change
Prediction gives reality something to argue with. Evidence lets us see who won.
This also makes ownership clearer across Product and Engineering. Product owns the problem, user outcome, and success conditions. Engineering owns the mechanism and operational consequences: state, failure, permissions, tests, deployment, and recovery. Both own evidence and tradeoffs.
Take a cancellation flow. Product decides what cancellation means, when it takes effect, and what the user sees. Engineering decides how billing failures, retries, audit events, and recovery behave. An agent can build a version. It cannot make those choices stop existing. If nobody names them, they are still there, buried in generated code and defaults.
The button can produce an implementation. It cannot make our judgment automatic.
Own the consequential seams
Owning the experiment does not mean building every model, runtime, and integration yourself. That would turn learning into a full-time maintenance hobby while the vendors sprint past you.
The useful skill is capability literacy. Can you inspect the context the agent receives or change the tools it can call? Do you know where permissions are enforced and whether verification ran?
Can you recover when the session or process dies? Can you move the work without losing the state and artifacts that matter?
The seams worth inspecting are usually:
- context
- tools
- permissions
- verification
- failure recovery
- provider choice
Rent commodity layers. Own the seams involving your data, trust, workflow, and evaluation.
Vendor names will churn. Context, authority, state, tools, feedback, and verification will remain useful concepts after the current command names become archaeology.
A smaller agent can be a microscope
Modern coding harnesses are dense operating environments. They wrap the model loop in project context, tools, permissions, background work, subagents, workflows, memory, plugins, hooks, worktrees, recovery, and a lot of UI that makes the whole thing usable.
All of that machinery makes the harness useful. It also makes the loop harder to inspect.
When generation outruns review, shrink the loop on purpose: use a smaller core, fewer tools, visible state, and one bounded task. The smaller core can still be unsafe or wrong. It simply puts less machinery between the question and the evidence.
For the talk, I used Pi 0.80.6 with Kimi K2.7 Code through Ollama Cloud. The clean baseline gave the model four consequential tools: read, bash, edit, and write. I disabled extensions, skills, prompt templates, context-file discovery, and project instructions for the experiment.
Four tools made the specimen legible. Moral superiority had nothing to do with it.
The first prompt produced the receipt and the doubt. The next prompt was not a larger spec. It was:
I want to understand it rather than just accept it.
For that turn, the agent's capability stopped at read and Bash. File-mutation tools were absent. "Do not change anything" was enforced by capability rather than trusted as prose.
Pi walked the JSONL session trail. It showed the session, user and assistant messages, tool calls, and linked tool results. The model was not remembering by magic. The harness was replaying structured state.
That trail still had limits. A logged request and result tell us what the harness recorded. They cannot prove every side effect or semantic correctness. The gap between 27 calls and 26 results came from the receipt observing one call before its matching result arrived.
Now the next move was obvious.
The next prompt came from the previous result
The experiment grew through four short prompts:
- Make a useful receipt.
- Show what the receipt can and cannot prove.
- Extract and test the parser; label in-flight calls.
- Expose the tested behavior as a project-local
/receiptcommand.
The final version had six passing tests. The extension reused the tested receipt behavior instead of duplicating it.
The learning did not happen because the model wrote a few hundred lines of JavaScript. It happened because the first result created a trust question, the question drove inspection, and the inspection changed what we built and how we tested it.
The agent shifted from producing software to helping dissect the system that produced the software.
Learning by building now includes more than implementation. The context, capability boundary, session trail, parser, tests, and local command are all part of the project.
A failure earns a tool
A small core does not need to stay small forever. Pi can load extensions and packages that add research, subagents, memory, permissions, workflows, and other machinery.
The catalog is a menu, not a checklist.
Before adding a capability, ask:
- What failed or became expensive?
- What smaller capability could change that?
- What new authority, context, maintenance, and failure modes arrive with it?
- What evidence will prove that it helped?
An overloaded context may earn subagents. Repeatedly lost corrections may earn durable memory. Meaningful risk may make permissions or isolation the actual requirement.
The right answer might be a 20-line project-local extension or a package. Often the honest answer is to use a larger harness instead of rebuilding one feature by feature.
A failure earns a tool. A package does not earn a requirement.
Thin highways between native harnesses
My own workshop did not grow from a clean platform diagram. It grew from repeated failures across real work.
I use native harnesses for different jobs: Hermes for routing and recurring work, Claude Code for long interactive refactors, Codex CLI for bounded implementation and review, and Pi when I want the loop small enough to inspect. Hindsight and LCM handle different memory and context problems around those runs.
The connective layer stays deliberately thin. The foreground owner keeps intent, acceptance criteria, delegation, and final judgment. Workers use isolated workspaces and return diffs, tests, artifacts, and review findings. Shared guidance can move between tools without pretending every harness is the same. A verification gate checks the current artifact before "done" means anything.
A board's done state is only a claim. The evidence has to refer to the exact head being accepted.
This workshop became real in the products:
- Relay owns a project-bound conversation, shared context, and operator handoffs without pretending to replace each provider runtime.
- SoundQ uses an agent to resolve messy track metadata against official SoundCloud or YouTube sources because a plausible title match is not source identity.
- Finn-Nancy turns statement ingestion into proposed matches and explicit ambiguity, then keeps financial authority with the human approving the result.
Each product forced a different understanding of state, trust, handoffs, or verification. The product changed the workshop, and the workshop changed the next product.
The vegetables still matter
Agentic coding does not make requirements, domain understanding, tests, security, deployment, recovery, or accountable decisions disappear.
Banning the tools and returning to writing every line by hand is a false choice. It confuses friction with learning.
What the tools can change is the tempo. They compress the wait between a question and a testable answer. The real project can keep moving while the mismatch is still interesting. Documentation and forum archaeology still matter, but they become evidence to interrogate rather than the only route forward.
That tighter loop can make engineering more engaging. Prediction, implementation, evidence, and mismatch happen close enough together that curiosity survives.
The sauce does not replace the vegetables. It makes us want to keep cooking.
Agents reduce iteration cost, not engineering responsibility. Use them without outsourcing understanding.
Do not build everything yourself. Build the workshop, and understand enough to own it.
The agent can write more of the implementation. You still learn by owning what happens next.