
I’m writing less code by hand. But, that doesn’t mean I’m doing less software engineering.
However, it does mean that a familiar way of recognizing the work is becoming less useful. If the visible output of an engineer is code, and an agent produces much of that code, what exactly is the engineer contributing?
In my work as a software engineer at Microsoft, more of my attention now goes into deciding what needs to happen, giving agents enough context to act, and establishing whether the result actually meets the need. My agents do more of the investigation and implementation. I spend more time shaping the work.
This is my experience, not a prediction that every engineer should work this way or a broad statement about how everyone at Microsoft works.
But it has changed how I think about my job. It has also made me a lot more interested in how software fits one person’s needs, including my own.
The work hasn’t disappeared, it has moved
Software engineering has never been only about dropping code into an editor. Understanding a problem, choosing an approach, working through trade-offs and looking after the result were always part of it.
The difference in my agentic work is how much implementation I can delegate once those decisions are clear enough.
Instead of working through everything myself, I can ask my agents to investigate the relevant code, propose a change, implement it and run the checks. Depending on the task and its permissions, it can continue through several of those steps without further input from me.
My contribution is less about supplying the next line and more about recognizing whether we’re solving the right problem. Have I explained the intended behaviour? Is the agent making a decision I haven’t actually agreed to? Does its evidence establish the result, or merely something nearby?
That is still technical work. Sometimes it requires reading code closely. Sometimes it means narrowing an experiment, challenging an assumption or deciding that the evidence isn’t there yet.
I’ve written about how I run multiple engineering workstreams in the GitHub Copilot app. The useful interventions aren’t always instructions to do more. Sometimes they’re corrections to what the work is supposed to establish.
Less typing doesn’t make judgement less important. It makes the consequences of that judgement more visible.
A better ask is more important than a lengthy prompt
When an agent can carry a request through to a substantial implementation, the quality of that request matters.
“Build me a dashboard” leaves a lot for the agent to decide. Who is it for? Which questions should it answer? Which data may it use? What does a missing value mean? Does success mean that the page renders, or that the figures agree with an established definition?
A useful specification makes those choices more explicit.
I want to explain the outcome, the constraints that matter, the decisions already made and the evidence I’ll need before accepting the work. I also want the agent to know where its authority ends.
For example, here’s an illustrative ask:
Build a personal view that helps me identify work needing my attention. Use only the data sources I’m authorized to access, and preserve the existing metric definitions. Make missing or stale data visible. Start with a read-only view, explain any assumptions, and show how you checked that the displayed results agree with the source.
That still isn’t a complete specification. But it gives the agent a much better basis for investigation than a simple request for a dashboard.
It also leaves room to discover that my first idea was wrong.
I don’t see specification as writing a perfect document and then waiting for the solution to arrive. An agent may uncover conflicting behavior, an unavailable dependency or a question I hadn’t thought to ask. A prototype may show that the requested view doesn’t help me make the decision I care about.
The specification should improve as we learn. Sometimes the right next request is “compare these approaches” or “find out whether this is possible”, not “implement the feature”.
The goal is to make intent clear enough to support useful work, while keeping uncertainty visible. More words aren’t automatically better. A short request with the right boundaries can be more useful than lengthy instructions that leave the actual decision unresolved.
Coordination is part of the work
Looking through my Copilot sessions makes this change in working pattern visible. There are requests that frame an outcome, coordination that carries the context forward, and agent execution that follows from it.
I can spend a short period giving direction, then return when there’s something meaningful to inspect or a decision to make. The agent can spend the intervening execution working through its authorized task.
But then how can we determine what is honestly meaningful impact of the work that I do, not my agents. What I can say is that I’m less involved in every individual implementation step. More of my involvement is concentrated at the points where intent, evidence or acceptance needs judgement.
That doesn’t make coordination free. Writing a useful ask takes effort. So does checking the result. If I start more work than I can meaningfully review, I’ve created a queue of uncertain changes rather than improved delivery.
The useful question isn’t “How many agents can I keep busy?” It’s “How much useful work can I bring to a result I understand and can accept?”
My engineering flow agents capture how I want to work
There’s another problem with good asks: I don’t want to repeat all of my engineering expectations in every one. Sure, the details of a task change absolutely could be, but many of my expectations don’t.
I still want the existing system understood before it’s changed. I want assumptions surfaced rather than being filled in. I want a clear scope, suitable validation and an honest account of anything that remains unverified.
My own engineering setup is how I capture those recurring expectations in an agentic workflow. It gives different engineering responsibilities a place as separate agents with a shared contract. From shaping work through implementation and review, rather than asking one agent to interpret everything on its own.
The point isn’t the number of agents though. It’s that the next task can begin with the task-specific need instead of rebuilding my whole way of working.
That helps me move work forward with less repeated explanation. It’s a practical benefit I experience, and not a benchmark for speeding-up delivery. The workflow itself also needs maintenance, and an agent following it can still make a mistake.
This is an important form of personalization, and a conversation I’ve had recently with a colleague on my team.
Two engineers can use the same model and tools while expecting different things from them. One may want a small experiment before a design discussion. Another may need particular compatibility checks before considering a change. Their working environments, responsibilities and tolerance for uncertainty may differ.
I think part of working well with agents is making your own judgement explicit enough that they can act consistently with it. Not by documenting every preference you’ve ever had, but by capturing the expectations that repeatedly affect the quality of the work.
Your workflow should still fit your team’s standards and approval boundaries. Personalization isn’t permission to bypass them. And another agent acting on my behalf isn’t an independent person’s approval.
The useful setup is one that helps me apply my judgement, including knowing when the workflow needs to stop and bring a decision back to me.
Personalization also makes personal software more interesting
There are small tools I’d find useful that don’t need to become products for thousands of people. An application that removes a recurring piece of friction for me can be worth having even if nobody else needs precisely the same thing.
Before, I’d have weighed that need against the effort of building the interface, connecting the parts and maintaining the code. Those costs haven’t disappeared, but being able to delegate more implementation changes which ideas I’m willing to explore.
I don’t have to choose only between adapting my work to an existing application and taking on all the implementation myself.
I can take a useful interaction from one tool, a way of presenting information from another, and combine those ideas around my own need. That means learning from their design.
The result might be much smaller than either application. That can be an advantage. It doesn’t need settings for users who don’t exist or a roadmap built around a broader audience.
Sometimes the better answer is still an existing product, a saved query or a simple script. Agents make a new application easier to attempt; they don’t make it the right answer to every inconvenience. But I like having the choice.
There’s something genuinely encouraging about moving from “I wish this worked differently” to being able to investigate and build a version that does.
Easier to create still means something to look after
This is also where engineering judgement comes back into the picture.
A working first version isn’t the end of the cost. Someone still needs to understand where the data comes from, how the application behaves when a dependency fails, and what happens when access or requirements change.
For personal software, that someone is me.
If a tool is cheap to generate but difficult to understand, I’ve deferred the effort. If I let an agent add more complexity than the need justifies, I may end up maintaining a small platform when I only wanted a useful page.
I therefore want to inspect more than the polished result. Does the implementation fit the problem? Have the relevant checks actually run? What isn’t established? Can I return to this in a few months and still understand enough to change or retire it?
Reading code remains part of that. So does debugging it. Delegating implementation doesn’t remove the need to build a technical mental model of what I’m accepting.
That matters for learning, too. I don’t want faster generation to become a reason to stop understanding software. Asking an agent to explain a choice can help, but its explanation is another claim to examine, not a replacement for the code and evidence.
The freedom to build more personally useful software is valuable. So is the restraint to keep it small enough to remain useful.
Start with one expectation and one real need
I wouldn’t begin by copying someone else’s entire agent setup, including mine.
I’d start with one recurring engineering expectation that I keep having to explain. Make it explicit. Try it on real work. Notice when it helps, when it creates friction and when the agent follows the wording without satisfying the intent.
Then pick one small problem in my own workflow. A question I repeatedly have to reconstruct. An awkward step between two tools. Something useful enough to justify looking after, but bounded enough to evaluate.
That gives personalization a purpose. The workflow reflects how I want to engineer; the software reflects what I actually need.
I’m not interested in proving that I can avoid writing code. I’m interested in spending my effort where it improves the result.
Increasingly, that means better questions, clearer specifications, useful feedback and the judgement to know when an agent’s work is ready to become something I rely on.
The opportunity isn’t to stop being an engineer. It’s to put more of our engineering into deciding what is worth building, and making sure it deserves to be used.
Discover more from James Croft
Subscribe to get the latest posts sent to your email.


