What an agentic product engineer actually does all day
Less typing. More wiring up agents that can. A field note from the messy middle.
- #agents
- #product-engineering
I used to ship features by typing them. Now I ship features by typing the spec, watching an agent type the feature, reading the diff, and pressing approve.
That sounds glib. It isn’t.
The shape of the day shifted
A year ago, my unit of work was a function. I’d open a file, hold a small mental model of “what calls this,” and edit. The output was a commit.
Today the unit of work is a task that an agent can run. The hard part isn’t the implementation - the agent can do that. The hard part is writing a task the agent can actually execute without me babysitting it. Names. Shapes. The weird invariant that lives in the head of a senior engineer and nowhere in the code. If I leave any of that out, the agent fills it in by guessing, and the guess is plausible, fluent, and wrong.
So my morning looks like this:
- Open a TODO.md.
- Write a task that - if a stranger picked it up cold - they could finish.
- Dispatch an agent to a fresh git worktree.
- Move on to the next task. Come back when it’s
[?].
Why this actually works (when it works)
Three things make it not-snake-oil:
Worktrees. Every agent gets its own checkout. Two tasks running at once can’t step on each other; if one of them ruins the tree, I delete a directory. This is unglamorous infrastructure that turns “AI did something to my repo” from a disaster into a yawn.
Squash merges. Nothing reaches main until I read the diff. The agent can fail loudly, fail silently, or hallucinate a beautiful new architecture - none of it matters until I press approve. The cost of a bad agent run is the time to read a diff and type discard.
Reviewable spec. This is the new craft. A task description is now production code: ambiguous prose ships ambiguous features. I find myself writing TODOs the way I used to write integration tests - adversarial, listing the edge cases out loud, naming the thing that should not happen.
What I miss
The tactile pleasure of typing a function from scratch is largely gone, and I think that’s actually the loss people are feeling and not naming. There’s a real grief in trading “I made this with my hands” for “I directed an agent to make this.” Some days I write a small utility by hand just to keep the muscle warm.
The other thing I miss: the false confidence of “I read the code, therefore I understand it.” With agents, I read more code than I write, and I’m constantly reminded that “I read it” and “I understand it” are different states. Pair-debugging with an agent that’s confidently wrong is a humbling teacher.
What I’d tell someone starting
- Optimize for the spec, not the prompt. A good prompt with a vague spec is a faster way to ship a worse feature.
- Treat agent runs as cheap and disposable. The whole point of the worktree is that you can throw it away. Throw it away.
- Keep one tool you can build by hand without an agent. It keeps your taste calibrated.
The job hasn’t really changed shape - it’s still about shipping things people can use. What changed is the throat I’m grabbing when something breaks.