Rupin Raveendra Nath

Rupin Raveendra Nath

// Software Engineer in Test

Writing Code by Hand Again

// Published On: Oct 30, 2026

One day I wrote most of my code by hand and debugged it myself, with AI only as a helper, and it felt strangely like a throwback.

For a while now I have been working with coding assistants and agents, and that is how most of my work goes. I give the agent the context, the prompt, and the requirements, and it writes the code. Even fixing and debugging was handled by the agent almost every time.

Recently I started building a brand new test automation framework for a complex logistics system. In the early phase, agents wrote most of the code, which made sense while the design was still fresh in my head. But as the framework grew, I did not want to lose my grip on it. It was a slow day, so I decided to get my hands dirty.

What I actually did

I was adding a new proxy layer to the framework, and one class grew a lot along the way, so I had to refactor it into several smaller ones. Then I ran the tests and, instead of handing the failures back to the agent, fixed them myself. The split left broken imports, and fixing them one by one taught me how the new classes depend on each other.

I still used AI for some of the typing. For example, I prompted a tool to generate functions and methods from an API specification. The difference was that I was not in fully agentic mode. I generated snippets, read them, and owned every change after that.

The debugging session

The most interesting part was a bug in that same proxy layer. An agent could have handled it on its own, but I chose to debug it myself, purely to learn. The backend API is not reachable from outside its environment, so tests that behave like a real client need a thin proxy in front of it. That proxy was the layer I had just built, and I called it from Postman.

GET requests worked, but POST requests timed out, and the test failed with a timeout stack trace. I logged into the environment and called the backend directly with curl, skipping the proxy entirely. It worked every time.

That narrowed it down quickly. Same endpoint, same payload, and the only difference was the hop through my proxy. GET has no body, so the problem had to be in how the body was forwarded. It was a content length problem. My proxy is a simple Node-RED flow that passes requests from outside to the backend, and its HTTP node was setting the Content-Length header wrongly when forwarding the request. The header did not match the body it actually sent, so the backend could not tell where the body ended and the request hung until it timed out. The fix was to clear the incoming headers before the request node, so the correct length was calculated from the body being sent.

The bug was in my proxy, not in the system, and the proxy looked correct when I read it. It only showed up when I compared the two paths. Had I gone fully agentic, I would only have seen the working end result, and I would probably never have learned about this Content-Length caveat when building a proxy in Node-RED. That is exactly the kind of knowledge I want to keep.

Why bother

You may wonder why bother when an agent can do all of this in seconds. Some people argue that code should be a black box, and that if the tests pass you do not need to understand what is inside. I get the appeal, but it does not fit where I am right now. The tests are the thing I am building, so if I misunderstand the system, I write wrong tests. Calling the backend by hand gave me ground truth from the real system.

Debugging by hand also forces you to follow the flow, read the stack trace, and figure out what the code is really doing. It is easy to drift into a codebase that works but that you only half understand, and I would rather stay ahead of that than fix it later. It also keeps the skill sharp, and I would rather not lose it.

How it felt

  • It was slower. Handing those failures to the agent would have taken a fraction of the time, so this only works when speed is not the goal.
  • I came away knowing how Node-RED handles forwarded headers, which I would not have picked up from a finished fix.
  • It was more satisfying than reviewing an agent’s output. Reviewing feels like checking someone else’s work, while fixing feels like building something.

Takeaway

This was not a new standard for how I work. For day to day development I will still lean on agents, especially for boilerplate and large changes. But I plan to do this occasionally. Pick a slow day, switch off the fully agentic workflow, and work through a problem myself.

The goal is not to write everything by hand. It is to stay close enough to the code that I still own it, whoever types.