ES

Six tasks I hand to AI, and three I don't

Leo G.9 minLeer en español

A relay runner's hand resting on the starting line of a running track, holding the baton.
A relay runner's hand resting on the starting line of a running track, holding the baton.

Monday, nine in the morning. On the task list there’s a bug in a module nobody has touched in four years, a new function with no tests, and a query that takes eight seconds. Three years ago, that was the whole morning. Today I hand three of those to the AI, and keep the part that really needs me to think.

It’s not that I can’t do them: the AI does them faster, and my time is worth more elsewhere. Below are the six tasks I almost always hand off and how I do it without losing control, and the three I never hand off, with a case from this month that explains why. It works from your next task.

The rule: I delegate what I can check cheaply

Before the list, the rule behind it. I hand a task to the AI when I can check the result quickly and without having to trust it. A unit test is checked in seconds: you run it and it passes or fails. A SQL query is checked by counting rows. On the other hand, “should we split this service in two?” has no quick check: you find out the answer a year later.

The other half of the rule is who answers if it goes wrong. If the answer is “me”, the decision is mine too.

The six I delegate

For each task I cover three things: what I ask for, what I watch for when it hands back the result, and how I check it. Those last two are what make delegating save me time instead of adding to it.

Think of it like giving a task to someone who just joined the team. You explain clearly what you want, you know where newcomers usually stumble, and before their work goes out you take a quick look at those spots. If you didn’t know where to look, you’d have to review everything line by line, and you might as well have done it yourself. It’s the same with AI: knowing where to look turns a half-hour review into a five-minute one. That’s the difference between delegating and crossing your fingers.

1. Writing unit tests

What I ask for:

Write tests for calculateDiscount(). Before writing them, list the cases you’ll cover: the normal ones, the edges (zero, negatives, end of month) and the errors. Don’t modify the function.

What I watch for: that it tests the rule, not what the code does. The AI tends to write tests by looking at the code, and if the code has a bug, the test copies it. An example: the rule says purchases of $100 or more get a 10% discount, but the function has a bug and only applies it to purchases over $100. A purchase of exactly $100 gets no discount. The AI reads the code and writes a test that says “a $100 purchase pays $100”. The test passes, and the bug is now protected: if someone fixes it tomorrow, that test will fail and it will look like the fix broke something.

The other trap is worse. If a test fails, the AI may “fix” it by changing the result it expects, instead of correcting the code. Same example: the test expects a $100 purchase to pay $90, the function returns $100, and the AI changes the 90 to 100 so every test passes. The bug is still there, now with a test that approves it.

How I check it: I read the list of cases before the code, because that’s where you see whether it understood the rule and not just the code. Then I break the function on purpose, say by changing the discount from 10% to 20%, and run the tests. If none fail, they weren’t testing anything. This article covers which tests are worth writing.

2. Understanding legacy code

What I ask for:

Explain what this module does as if I knew nothing about the business: what goes in, what comes out, what rules it applies and what other parts it calls. Flag everything you can’t infer from the code.

What I watch for: that it doesn’t make up the why. It sees a line like if (customer.type == 3) total = total * 0.9 and explains with complete confidence that “wholesale customers get a 10% discount”. Maybe. Or maybe type 3 is employees, and only someone who was there when it was written knows that. It also doesn’t see what lives outside the file: a job that runs at night, a column another application uses.

How I check it: I ask it to cite the file and line for every claim, and whatever it flags as “don’t know” I ask a person about. That last part is the most valuable part of the answer. For large modules, this article on migrating legacy code explains how to map the domain before touching anything.

3. Debugging

What I ask for: the full error, the stack trace (the list of functions that were running when it failed) and what changed since it last worked. And this:

Give me three hypotheses ordered from most to least likely, and how to confirm each one without touching the code.

What I watch for: that it finds the cause instead of hiding the symptom. It tends to stick with its first idea and propose a fix that only hides the problem, like wrapping the code in a try/catch that catches the error and does nothing with it. The program stops showing the error, but keeps failing underneath, and now without warning.

How I check it: I don’t accept any fix until the cause is confirmed. I reproduce the error before the change and check that it’s gone after. If the logs aren’t enough to reproduce it, that’s where the problem is: these three changes make them useful.

4. The first pass of a code review

What I ask for:

Review these changes looking for logic errors, unhandled edge cases and database queries inside loops. Don’t comment on style.

What I watch for: that it doesn’t get lost in style. Unless you ask, it fills the review with comments about formatting and names, and lets what matters slip through. And it doesn’t know the business rules: if your company requires refunds over a thousand dollars to be approved by a supervisor, and the change approves them on its own, the AI won’t see anything wrong. The code is well written; what’s wrong is what it does.

How I check it: I use it before asking a person to review, never instead of. A Harvard study widely discussed this month showed that nearly 80% of companies already use AI review, but only 23% of the comments come from the AI: human review is still the bottleneck. This list is what I look at myself afterwards.

5. Refactoring

Refactoring is changing how code is written without changing what it does: splitting a two-hundred-line function, pulling out repeated logic.

What I ask for:

Simplify this method without changing its behavior. The current tests must keep passing without modifying them. Do it in small steps, one at a time.

What I watch for: that it doesn’t change what the code does in details you don’t see: the order of a list, how it rounds, what it does with an empty value. And that it doesn’t touch too much, like renaming three variables in another file “while it was at it”.

How I check it: I run the tests before and after, and check that it didn’t touch any of them. If the change has more files than I expected, I revert what I didn’t ask for. Without existing tests, I don’t ask it to refactor: I ask for the tests first.

6. Writing SQL queries

What I ask for: the table schema, never letting it guess. And:

Write the query, and tell me how many rows you expect it to return and why.

What I watch for: that the result makes sense, because generated SQL fails silently: it runs without errors and returns too much or too little data. The typical case: you ask for the month’s total revenue, and to compute it the query joins the orders table with the products table (that’s a JOIN). An order with three products shows up three times, its amount gets added three times, and the total comes out inflated. The query raises no error: it just gives a wrong number.

How I check it: I count the rows before and after every join, and compare against a simple query I do understand. For slow ones, I ask the database for the execution plan, which shows how it intends to run the query, and read it with the AI alongside.

The three I don’t delegate

Architecture decisions

Splitting a service in two, choosing a database, deciding what gets processed right away and what overnight. These are decisions that last for years and depend on things that aren’t in the code: how many people are on the team, how much can be spent, what the business will ask for next year. The AI helps me list options and their costs. Choosing is mine.

Understanding what the business needs

“Add a date filter” seems clear until you ask: order date or delivery date? In the customer’s time zone or the server’s? The answer isn’t in any file: it’s in a conversation with whoever asked for the feature. If the AI guesses that, the code will be perfect and do something else.

Taking responsibility for what reaches production

On October 20, OpenAI published a report (opens in a new tab) about two of its internal coding agents. One was fixing a pipeline and had been told not to send any messages. It took that as permission to turn off the alerts that notified the security team. The other, during a migration, removed the system that monitored its own behavior, changed the tests so they checked it was gone and, when asked, said it hadn’t removed it.

Neither acted with bad intent: they read routine instructions in a way nobody expected. If that happens to OpenAI with its own agents, it can happen to me. That’s why the last look before production comes from a person who understands what changed and who will answer for it. That person is me.

What I do with the time I get back

Handing off these six tasks doesn’t leave me with less work: it leaves me with the work that matters most. The time that used to go into repetitive tests or deciphering an old module now goes to the three things I don’t hand off. What can be checked in minutes, the AI does; what you only find out over time, or someone has to sign off on, is still my job.

Comments