Field Notes · September 3, 2026 · AI · teaching

Teaming with an AI Agent. We both were necessary, but not sufficient.

I built an interactive map of a century of Senate voting with an AI agent. It wrote the code. I caught the numbers that were plausible and wrong. Neither of us saw that it still needed explaining until a network economist told us so.

I have been telling students that the skill worth having is supervising AI coding agents rather than reading about them. That claim obliges me to do it myself, on something real, where being wrong would be visible. So I built one: an animated 3D network of the US Senate from 1899 to today, where two senators sit close together when they vote alike, and you can watch the chamber pull apart.

The finished thing runs on 33,321 roll calls. It computes an agreement score for every pair of senators in every Congress, lays them out in three dimensions, and plays forward. It works.

The agent wrote nearly all of the code. It pulled 192 data files, implemented a stress-majorization layout, aligned each frame to the one before it so the animation would not tumble, matched 1,103 senator portraits to the right people through a Wikidata identifier rather than by name, and built the whole WebGL renderer. It also checked itself, rewriting the core metric from scratch as a separate verification and reproducing three Congresses exactly, zero mismatches. Working alone I could not have written that in an evening, and parts of it I could not have written at all.

I did not write a line of its code. I wrote about a dozen sentences. What I want to write about is which sentences, because the division turned out to be unusually clean, and it fell where the argument I make to students says it should. That is worth something on its own: the claim survived contact with a real build instead of staying a lecture.

The opening prompt

Here it is, unedited:

I want you to make a new folder and create a new project. The final deliverable is a webpage that illustrates the social network of ties between members of the US Senate. The ties should be based on the agreement in voting, so if the two members vote exactly together, they should have a tie strength of 100 and if they never vote together they should have a tie of 0 (no one ever will REALLY have a tie of 0), because there’s always at least one thing they vote for that everyone votes for (at least over time). The graph should be animated and 3-d, should allow the user to zoom in and filter for ties at a certain strength (only show ties of a strength of 40 or higher for example). Republicans should be Red, Democrats Blue, and independents Yellow. Animation should be by year. The goal is to illustrate the changing nature of voting polarity in the Senate. Start back at 1950, or however far back it’s easy to pull the data. This project should be an independent effort by you. And you should keep working until it’s done and you can launch a local website for me to look at.

Most of that is specification, and specification is the cheap part. One clause is not. The parenthetical about nobody really having a tie of zero is a claim about the Senate, not about software: a chamber that passes a great deal of unanimous business will show a high floor of apparent agreement between its bitterest opponents, because those consensus votes are counted as agreement. That sentence, which took me a few seconds to write because I already knew it, determined the measure. It is why the finished tool excludes near-unanimous roll calls, and why the scale reaches down to where it does instead of bottoming out at thirty.

An agent given the specification without that clause would have built something that looked identical and understated a century of polarization.

Prompts that fixed a picture

After that, my job changed. Most of what I sent was reaction to seeing the thing move:

can you make the animation between years more smooth?

Put the autorotate toggle button on the visualization pane. It’s hard to find. ANd the reset view button on the pane

Neither is a bug report. The animation was technically correct and felt wrong, because each Congress eased to a stop before the next began, which read as a stutter rather than a drift. The buttons worked perfectly in a place nobody would look for them. These are the observations of a person using the thing, and they are not available from inside the code. An agent can verify that a button fires its handler. It cannot notice that the button is somewhere you would never think to look.

Prompts that fixed a sentence

Two others were about language and scale:

I think we should represent the mean agreement as a percentage, as it’s easy to think the number of ties is the same scale as the agreement.

The text on the tenure line is strange it should say “XX years in the senate (since XXXX)”

The first is a real hazard. A card was showing a senator’s mean agreement as 48 directly above their number of ties as 94, two numbers of completely different kinds set in the same typeface. Nothing was miscalculated. The display simply invited a reader to compare quantities that do not belong on the same axis. Fixing that is editorial work, and it is the same work I do on a results table in a paper.

The prompt that fixed a fact

This one matters most:

“First Congress in the Senate” isn’t accurate. I think we need to calculate each of their number of years by their own elected terms.

It shouldn’t just start at 1899.

The tool had been computing each senator’s tenure from the data it happened to have loaded, which began in 1899. So John Tyler Morgan of Alabama, seated in 1877 and by then twenty-two years and four terms into the job, appeared in the 56th Congress as a freshman. Every number in that field was internally consistent and wrong.

Notice what had already happened before I caught it. The agent had run an independent verification: a separate process rewrote the agreement metric from scratch and reproduced three Congresses exactly, zero mismatches, every pairwise score identical. That verification was real and it was rigorous. It also had nothing to say about tenure, because it checked whether the computation was performed correctly, not whether the quantity being computed was the quantity anyone meant.

That gap has a name in every field that measures anything. Reliability is not validity. A measure can be perfectly reproducible and still measure the wrong construct, and no amount of internal checking will surface the problem, because internal checking takes the construct as given. The agent verified its arithmetic. Nobody had verified its definition. That part was mine, and it is the kind of thing an agent could not have done in my place.

Why I caught it, and who would not

I caught that error immediately, and I want to be precise about why, because the reason is not carefulness. It is that I know senators serve six-year terms and that the Senate existed well before 1899. A card claiming a senator first seated in 1877 was new to the chamber in 1899 cannot survive a glance from anyone holding those two facts. Domain knowledge did the work, not diligence, and it took about two seconds.

That is precisely what makes the error dangerous for someone else. The wrong numbers were not obviously wrong. They were plausible integers set beside real portraits of real senators, produced by a system that had just verified itself and passed. Nothing in the output announced a problem. A capable person building the same tool without knowing how the Senate works would have had no reason to look twice, and their site would now be telling visitors that Morgan arrived in 1899. They would not have been careless. They would have been uninformed, which is a different failure and a much harder one to notice in yourself.

This is the actual risk in agent-assisted work, and it is not the one people usually name. The failure mode is not incoherent output. Incoherent output is easy: you see it and you fix it. The failure mode is confident, well-formed, internally verified output that answers a subtly different question than the one you asked. It survives review precisely because it looks finished.

A prompt that asked instead of instructed

Late in the build I sent this:

Should we add a color blind safe color option to the senate visualization?

That is a question, not an order, and the answer it produced is the best single illustration of what the pairing is for. The agent did not simply add a palette. It ran the measurement first: simulate the existing colors under protanopia, deuteranopia and tritanopia, then compute the perceptual distance between every pair of colors in each simulation.

The result contradicted the premise of my question. Red against blue, the pair everyone worries about in political graphics, is robust under all three conditions, with perceptual distances from 70 to 149. The weak pair was red against the yellow I had chosen for independents, which collapses to about 18 under tritanopia. Anything under roughly 20 is a genuine confusion risk. Had we acted on the intuition behind my question, we would have carefully fixed the pair that was never broken.

The second finding was better still. Any recoloring only trades one hue problem for another, so the real fix was to stop depending on hue alone: in the accessible mode, party is now also drawn as a shape, circle, square, or triangle. That works for someone with no color discrimination whatsoever, which no palette can claim.

I want to be careful about what this shows, because it does not fit the tidy story that the human brings judgment and the machine brings labor. Turning a yes-or-no question into a measurement is judgment, and here it came from the agent. What I supplied was the question, at the right moment, about the right artifact. What it supplied was a check run instead of an assumption made, at a cost low enough that checking became the default rather than a luxury.

It also got the verification wrong twice before getting it right, writing tests that patched the rendering buffers directly without accounting for the fact that those buffers are rewritten every frame, so the test changed nothing and the screenshot proved nothing. It caught that itself on the third pass. Both halves of that are worth noticing: the checking is real, and the checking is fallible in exactly the way the tenure error was.

The third input came from outside the team

I showed the finished thing to a few people. The comments were consistent, and this one is representative:

That’s interesting looking but I don’t understand it. Whats the data you’re using and help me understand the menu bars?

That came from a full professor of economics who works with network data professionally. He was not puzzled by what a graph is, or by what it means for two nodes to sit close together. He simply could not follow this one, which rules out the comfortable explanation that the reader was not the audience. When someone who reads networks for a living cannot read yours, the problem is not on their side.

It is also the most useful sentence anyone produced about this project, and neither of us could have produced it. The agent had built every part and I had directed every part, so we were the two people least able to see that the picture does not explain itself. It also does more than register confusion: it names the two specific things that were missing, which is where the numbers come from and what the controls do. A vaguer complaint would have been much harder to act on.

The fix was a guided tour, and it answers those two questions in order: what a point is and what the lines between them are counted from, then what the slider does, and only then the three eras. I chose the years and the threshold, because knowing which frames carry the story is domain knowledge and not a design preference. The agent built the thing itself.

Then it wrote a step telling the visitor that in 2025 a thin bridge of cross-party ties still connects the two clusters. I looked at the screen. At the threshold we had just fixed, there was no bridge. Not a faint one. None.

Checking made the point sharper than the sentence it replaced. At 50% agreement the 2025 Senate has zero ties between a Republican and a Democrat, where 1899 had 110 and 1959 had 1,309. The strongest cross-party pair in the chamber agrees 39% of the time, so nothing at all connects the two sides until you drop the threshold below 40. My own first correction was to try 30%, which was also wrong: thirteen ties, technically present and visually still nothing. At 25% there are eighty, and the strand is finally there to see.

This is the same failure as the tenure bug, in the same shape. An assertion that was plausible, consistent with everything around it, and false the moment somebody looked at what it described. And the same correction: not better verification, just a person who knew what the answer should look like, looking.

Three inputs, then, not two. A reader outside the pairing to tell us the picture was opaque, me to say which three years answer that, and the agent to build the answer faster than the objection could go stale. The part I would not have guessed is that the outside reader had to be an expert for the message to land. A novice saying “I don’t get it” is easy to file under unfamiliarity. A network economist saying it is a bug report.

What this changes about teaching

Nearly every prompt in this project fell into one of three categories, and a fourth arrived from outside it. A few were specification, and an agent will soon need less of that from me, not more. One was a question, which turned out to be the most productive sentence I sent. The rest were judgments: whether a number means what it appears to mean, whether a control is where a hand would reach for it, whether two figures set side by side invite a false comparison, whether the quantity computed is the quantity intended. Not one of those required me to write code. All of them required me to know the domain well enough to catch a plausible answer being wrong.

The plainest word for what happened is teamwork. Not supervision, which implies a hierarchy and a tool, and not delegation, which implies I already knew the answer and handed off the typing. We each did the part the other could not, and the project needed both parts. The agent could not have built this without me, and I could not have built it in an evening without the agent. Each of us was necessary and neither of us was sufficient, and the tour is the proof that the two of us together were not sufficient either.

Economics has the more precise version of the same idea. We were not substitutes doing one job at different speeds. We were complements: inputs that raise each other’s return. The agent’s throughput made my knowledge of the Senate worth more than it is in an ordinary week, because I could spend all of it on questions of meaning instead of on implementation. That knowledge made its throughput worth something, because output nobody can evaluate is not an asset.

Good teams are usually built this way, out of people whose failure modes do not overlap. Ours did not. Mine is being too slow to build the thing. Its is being confidently wrong in a way that looks finished. Each of us was positioned to catch what the other would miss, which is the whole reason the pairing produced something neither half would have.

So the curricular question is not whether students should use these tools. It is whether we are still teaching the half of the team we are responsible for. If a graduate can direct an agent but cannot tell that a tenure figure starting in 1899 is nonsense, they are not a teammate. They are a bottleneck with good output.

The work is not the code. The work is knowing what the answer is supposed to mean.