Go back

SE Radio 730: Birgitta Boeckeler on Harness Engineering for AI Agents

from Software Engineering Radio - the podcast for professional software developers

54m 13s

SE Radio 730: Birgitta Boeckeler on Harness Engineering for AI Agents

Harness engineering is a growing discipline focused on improving AI-powered coding agents by designing systems—called harnesses—that sit atop language models and use structured guidance and feedback mechanisms. These harnesses incorporate "guides" like context files and coding rules, and "sensors" such as static analysis tools, test suites, or LLM-based judgment systems that provide real-time feedback to ensure code quality, maintainability, and correctness. Key challenges include balancing tool density to avoid noise, ensuring agents make reliable decisions (e.g., on code complexity or modularity), and establishing trust through risk-based evaluation. The future lies in enhanced observability, such as tracking agent actions and sensor feedback over time, and in integrating these systems into developer workflows to catch issues early—before commits or PRs. Human oversight remains essential due to the probabilistic and interpretive nature of AI models, and developers must evolve into strategic decision-makers who assess risk, define what "good" code looks like, and manage trade-offs. As AI takes over more coding tasks, the role of engineers expands from writing code to setting context, defining quality standards, and conducting critical risk assessments—emphasizing a shift toward more thoughtful, human-driven software engineering practices.

Transcription

10859 Words, 59058 Characters

English
This is Software Engineering Radio, the podcast for professional developers on the web at se-radio.net. SeRadio is brought to you by the IEEE Computer Society by IEEE Software Magazine, online at computer.org/software Hi everyone, this is Priyanka Ragwin for Software Engineering Radio and my guess today is Brigita Boclo and the topic is Harness for Coding Agents. Brigita is a principal consultant and a software developer with ThoughtWorks and is passionate about helping teams and organizations break down complexity and find new perspectives to look at their systems. She's a frequent conference speaker and podcasts guests on many platforms. You can just Google her or YouTube her and welcome to the show Brigita. Hi Priyanka, thanks for inviting me. Is there anything in your bio that you would like the audience to know other than what I've mentioned here? Yeah, maybe the thing that's interesting is what my current role is or what my role has been for the past over two and a half years at ThoughtWorks. So in 2023 ThoughtWorks decided to introduce a full-time role for somebody to just look into the topic of using. Generative AI or language models for software delivery and how it changes that. We're a consultancy so we have to always keep our advice up to speed and speed is definitely something that's happening a lot in this space. So yeah, I'm a distinguished engineer there and I've basically been fully immersed full-time in this space for the last two and a half years and so kind of seen the history. Okay, great. So that will bring us right into our show at Software Engineering Radio. We've done a few shows on AI and software development whether it's episode 711 with Scott Hanselman on AI assisted tools. We did an episode 603 with Rishi Singh on using Jenny AI for test code generation and episode 693 on AI assisted debugging. So before we start the show, we thought we'll spend some time on the first part of the show where we'll go through some definitions and I'm heavily quoting here from the article you wrote on Hans is engineering. So to start with what exactly is Hans is in Hans is engineering and how is it different from say from 10 engineering or context engineering? I mean, as I just mentioned and as everybody's feeling right now, this space is like really fast evolving and one of the challenges there is what language we're all using, right? I mean, we can come up even faster with stuff as well, right? So we're all throwing lots of terms out there and I think that's been a challenge for me like to find the right words to describe what is happening because that also helps me think about it better, right? And this word harness it has gone through a little bit of an evolution but recently it's increasingly being used for describing something that sits on top of a language model and orchestrates everything we want to do with the model, right? So it has a system prompt, it can ask the language model for tool calls and stuff like that, right? So basically what we've also been calling an agent and then when we talk about a coding harness like that as examples that would be like cloud code or cursor or the pie coding harness, so increasingly people are calling that harness, right? And then in combination with the model, when you run it, it becomes an agent, right? So I'm almost now starting to think of like an agent as something that is like an instance of something running and maybe harness is the tool that skeleton of what runs it, right? Like I don't so that's where my head is at now, right? And then so harness engineering is like how you make those harnesses better. So for example, in a coding harness, you can make it better by thinking about providing it with different tools or there's like other schools of thought where you make it better by providing it with less tools and with less complexity, right? So there's these different approaches of how to make the coding harness better, but then the part that I wrote about in my article is about the users of the coding harness. So us or me as an application developer, I'm using cloud code as a coding harness and I'm trying to extend the harness for my specific code base, right? So I'm trying to give the harness the agent, whatever we want to call it, like even more information, even more tools specifically to my application that I'm working on to make the results better. So that's like it's almost like an onion multiple layers type of things. So first I choose the base harness that I'm going to use, for example, cloud code, and then I give it even more stuff like skills and tools and stuff like that to get the results that I want for my situation. I think the timing seems apt because most people are now using AI coding agents and AI agents for doing all the coding work. And I guess the question I wanted to ask you is, when do you feel there's a need to have a harness? Is it immediately as soon as you start coding with the coding agent? I mean, the coding harness itself, you need, right? Like that's the coding agent basically. That's what I was saying. There's the terms that people use are changing right now a little bit, right? But when I think about that expanded harness, you can totally start without anything. And I see this also as a barrier that some people now who are coming to a gente coding a bit later, maybe and there's like all of this tooling and all of these terms. And like it's almost like some people before they even want to start, they ask, oh, what skills do I need? What should I put into the agent MDE? It's almost like they're afraid to get started because it feels like this is whole discipline of how to use these things, right? But you can absolutely just get started playing vanilla without putting anything in there. And I would actually recommend it when you first do a gente coding, just to like feel what it actually does without it, right? So it's like a big skill that we now need as developers, I think to understand what's actually going on, what tools are already there, like how does this tool work out of the box? Like I said before, it might be quite different using cloud code or cursor versus like a much more lightweight harness like the pie coding agent, right? So getting a feeling for what already works without putting anything in there. The models have gotten a lot stronger. I feel like some people have already built up skills and lots of instructions might want to revisit that as well with newer models because some things are maybe not necessary anymore, right? So it's worth understanding what it feels like to work with them without your custom stuff and then build your own stuff up step by step on top of that. So you describe as the harness is something that goes around the model, right? So can you break it down to us? For example, in the article you talk about these things, calls us guides and sensors and you break that down for us. Yeah, so this again, it's all about like I was trying to come up with vocabulary for us to talk about this, right? So this is not necessarily new stuff. In particular, the part that I call guides. So by guides, I mean, everything that we feed forward into the agent. So we try to anticipate both what we wanted to do, but also what we do not want it to do. And we write it down, right? So this is what lots of people are already doing and have been doing for quite a while. It usually manifests in like a bunch of markdown files. So that agents MD or the cloud MD file is the most prominent one that has been around for quite a while. And so we write into that file, I want you to do this. I do not want you to do that. Never, ever do that. It's these important, important, this type of stuff. And it can actually be all kinds of different guides, right? So it can be normative ones, right? That set up the norms and the conventions that we want to use in this repository. Or it can be informative, right? So it can describe the context of the application, what we're trying to achieve, describing what the architecture is, stuff like that, right? So it can be lots of different things. And then on the flip side of that, so this is like feed forward, we anticipate and try to increase the probability that it will do very well on the first go, but it's often not perfect on the first go, right? So then we want to give it feedback as well. And that's like what in the Arctic like all the sensors. So there we think about what sensors do I want to make available so that it can self correct before I even have to look at it and find all of these, maybe even small hygiene type of things, right? And a sensor can be both another large language model or like the large language model itself, right? So a sensor can be a skill that has code review instructions, right? That again tells it, we want this. We don't want that. This is bad. This is good. But a sensor can also be something computational, right? Something that actually runs on the CPU, not on the GPU. So that would be something like static code analysis or our test suite or coverage data or any of those types of things. And on the feed forward side, by the way, we can also have computational guides. So the most powerful example of that, I would say, is that of code modules. So those are tools like open rewrite is a very prominent in that area. There are a bunch of those in the JavaScript space as well. And so code modules basically can do like mass, refactoring, mass, changing off your code base, right? And there are lots of case studies and use cases out there where you combine language models and these code mods as extra guides to do migrations and upgrades and stuff like that version upgrades that require a lot of stuff, right? Where this computational guide can maybe cover like 80, 90% of the work. And then the rest of the is a bit more semantic and the large language model fills in there, right? So the guides are all about increasing the probability that it does a good job in the first place. And then the sensors are about giving it direct feedback and maybe a little bit of additional guidance to self correct. So you feel that the role of the feedback loops makes the code more reliable? Yeah, definitely. I mean, there's a school of thought that the language models will just get better and better and better until they're just perfect at coding. And the code will always be perfect, right? But yeah, I don't think that's realistic or like if it ever gets to that point that we do have setups that can write good code almost all of the time. I think it will have to involve these types of sensors to help the model correct also in like the existing big experimental and less experimental. mental stuff like where people orchestrate lots and lots of agents that just collaborate with each other and they orchestrate it and they go off and do a task. There's also a lot of censoring going on, right? This censoring with the sea almost like each other, right? So yeah, I think they play a huge role in my experimentation that I've done with, for example, static code analysis. We can go into that a bit later if you want or like checking for coupling lots of stuff about the maintainability of software. I've definitely seen them kick in a lot even when I was using powerful models to do the coding. So, yeah, there's always like little flaws the same as when we as humans write code and it's just like a great feedback mechanism. Are architectural constraints good guardrails for AI agents? Yeah, I actually write in the article about how, to me, there's different dimensions that we can think through for the guides and sensors, right? Like, what are the things we want to regulate for, right? So I was thinking about some parallels to cybernetics that like the code base that we're generating is actually like something that we're regulating, right? And so these different things that we're regulating can be maintainability, for example. So trying to make the risk of a change in the future as low as possible, or it can be architecture fitness, right? So thinking about sensors and also guides that describe what we want in the architecture and then sensors that check if it's there, right? It can be around the typical illities and architecture fitness functions like performance and those types of things. Or in a way you could say architectures also people often call the code based design architectures well, right? So that could be about coupling and stuff like that, which maybe goes in the direction of maintainability again. And then of course, another big thing that we want to regulate is that the code actually does what we wanted to do, right? So like functional correctness. But so yeah, your question about architecture, like depending on what one means by architecture, which is a big topic as well. Yeah. I would say absolutely. I noticed something on Twitter a few days back when someone said that they tried to make a prompt very abstract. And then the AI agent didn't perform very well. So I guess it had to be at a level where it could understand abstractness. It doesn't do very well. It's right. So I think in that sense, it does meet sense, what you're saying about defining the architectural constraints properly so that the AI agents can pick it up. Yeah, I mean, it depends on what is meant by abstraction, right, when you create an abstract instruction that abstract means with little detail, right, that could be a problem. But of course, language models are actually sometimes good at doing abstractions, right? It's sometimes all that they do because they translate stuff, right? They translate from one thing to another. So it depends on what is meant by the abstraction in that context. But you were also initially asking me what's the difference between harness engineering and prompt engineering and context engineering. I would say it's all different forms of a similar thing, right? So I mean, we started two and a half, three years ago with saying prompt engineering super important, right? Like exactly how you craft your prompt and where you put stuff and you give the agent or the LLM a role in which order do you put it? And that has become a lot less important with the big models, right? If we want to go back to smaller models, which there are lots of good reasons for it, it might be more important again, right? When we came to context engineering, which is all about integrating, ideally, the information that the model, so you tune the information that you give to the model in a way that you get better results. And I think harness engineering is a specific form of that. So with guides, you tune information and instructions, right? And then with the sensors, again, you give it information. So I think it's a specific form of context engineering, but you're crafting the prompts exactly is not as important anymore with the latest models. So harness engineering, it can be also coupled with all these traditional practices like unit testing, integration testing, CICV and static analysis, right? Can you talk a little bit about that? Yeah, so that's what I've been experimenting a lot with on the sensors side of things, right? So we have a lot of existing tools actually that we can use and now make available to these agents. And interestingly, some of those tools that we have, we have not used a lot in the past as humans, right? So static code analysis, for example, I'm a consultant, right? So I've seen lots of different organizations build software. And I often see them having a setup of code analysis like a sonar server somewhere in the corner, but then it's not really being monitored or used. And I think one of this, maybe two main reasons, one of them is that I think especially experience of offers are aware that it can only do so much, right? Like it's not like a linter can actually like guarantee the quality and changeability of a code base in the future. But the other thing is also that it often becomes noise overload, right? Like or the signal to noise ratio was often not very good, right? So you get like even when you use them from the beginning in a code base, you often get like overwhelmed by all the messages and you don't want to like fine tune every single one where you want to make an exception or not. So you just like get overwhelmed by it, right? And I think there's a new opportunity now with large language models and with coding agents to maybe get through that and actually have like a good baseline that is always clean with the analysis methods because what you can do is you can write custom messages for these link messages, right? So let's take an example, the very common pitfall or very common failure mode of AI coding agents as well, functions that I have too many lines that are too long, right? Like max lines per function or whatever I was doing this with ESLint in a TypeScript code base, so it was max lines per function. So now I overwrote the message that comes back. It doesn't just say this function is 120 lines long. We only allow X lines long, but it also says this might be a smell. Please consider if we should refactor this, if we should split this up, if this function is doing too many things, make a judgment call. But if you decide that it's okay that this function is five lines longer or we just can't do anything about it or it's just like a test data function or whatever, then you're allowed to create a rule that increases that threshold for this function. So you give the large language model guidance and ask it to make a judgment call, right? So this makes it explicit for me. I can actually review and go through the places where it increased the threshold and say, I'm okay with that. I'm not okay with that. But this automatically does this tuning for me, right? But I would usually never suppress it directly in the code because it's just too tedious when I was doing it myself. But with the help of the agent, I can actually try and get like a clean slate all the time and then it becomes a much better sensor. Well, it's very interesting. You talked a little bit about the lines of code and I was thinking about this cyclomatic complexity, which when we wrote code as humans would be something that we would have very hard targets on. And nowadays, I noticed when I'm reviewing code of someone who's generated the code completely with AI, if they don't have say these constraints, then you might see cyclomatic complexity like 125 or something, that's huge, right? That's, yeah. That feels like a seismic event or something compared to say what we would have it in. So for those kind of cases is what you're saying that you can actually add things in your guides to restrict the agent. That's what you're saying. You can actually have sort of a constraint that you can place on the agent for your particular repository, like coding guidelines. Yeah. So the sensor triggers another little loop. So I define my constraints in the configuration of the static code analysis. For example, I say what my maximum allowed cyclomatic complexity is, right? Then the agent writes some code and then the analysis tool says over there, cyclomatic complexity is too high. And then it also has this additional little prompt that tells it more about how we wanted to handle cyclomatic complexity with the soul like you are allowed to increase it. If you make a judgment call it, then rely on the LLM a lot again, but it just makes it more explicit where you need to review. And then that starts another little loop where the agent tries to self correct and then asks the sensor again, right? So it's an extra little loop that you start. And the cyclomatic complexity definitely another great example of a very typical failure mode of AI generated code. So that one triggered a lot for me as well, even with the big models and not just like the complexity, but also sometimes just very brittle, hard to read Boolean expressions. Like combinations of different that maybe as a human, I would have turned the does not equal around to an equal or just doesn't feel very expressive and very readable. And some people say, oh, but it doesn't matter if it's readable because AI changes it in the future, but when you have these weird Boolean expressions, it's a lot riskier for AI to change it as well in the future and have like an unintended side effect that breaks something else, right? So what do you mean by AI change it in the future? Do you mean by a refactoring attempt? Yeah. So some people say that all of these things about like code readability or code quality is not as important anymore because as a human, I will not have to deal with the details anymore, I just deal with like a little bit higher level and AI will change the details in the future. So it doesn't matter to me if I'm able to read this Boolean expression, but it turns out that AI needs a lot of the same things that we need to make safe changes to stuff. Okay. Got it. So what about even the practices like unit testing and regenerate, obviously use a lot of AI agents to generate the test, but one thing I've noticed is sometimes when I write the test as a human, then the code becomes better. Is that something that you have seen in your experience? Because I'm able to describe the behavior better in a writer unit test and therefore I feel the code gets generated better. Yeah. are definitely an important sensor, but they have two overarching roles. I mean, there's probably more, but two have in mind, right? Like, one is we try to use them to check the functional correctness of what we're building. Is it correct? And there, if we just have AI generate all the tests and the code, then other than doing manual tests and observing what the application does, it's not 100% guarantee that it actually does what we wanted to do, right? Because we didn't write the test. Test suite's also have another function as a regression sensor, right? Just telling us how good are they at telling us that something broke, right? That's more maintainability concern, but that's also like an interesting part of a sensor that we can also talk about next if you want to. But yeah, this whole thing about the correctness of tests. I mean, the tests might all be green, but just test things that we don't want, right? And in the past, like you said, we often, like, that's why it's called test driven development, right? It wasn't just about making sure we have tests, but it was about writing the test first because the tests are the ultimate specification, right? They made us think through what we actually want. And so this for me is still like a largely unsolved problem, let's say, because you might argue that maybe we could say as a human, my main role is to review the tests and okay, let's say AI has gotten good at the code. I have some sensors in place. Maybe I'm exaggerating because that's not enough. But let's say, okay, I don't want to look at the code anymore, but I want to review the tests. But tests are very tedious to review when you haven't written them yourself, right? They're very verbose and you have to like, it's a lot of detail. And you actually want to think about the big picture, like, have I thought about everything, all the combinations and stuff like that, right? So I recently talked a lot to my colleague Mateo Vakari about this who has been on some teams where he's trying to look for a good acceptance test level. And then he's trying to find a way to write those acceptance tests and their input and outputs in particular in a way that is really easy to review so that he can really think about the input output data. That is very relatively easy to do, for example, when you have HTTP, when you have APIs, right? There's always a request and a response. And you want to like have different scenarios of requests and response combinations that you test. In other parts of the code base, it's a lot messier like there's different combinations and unit tests that's much different. And then when you write these acceptance tests, they're often not as detailed as the unit tests. And so do you just leave the unit test way? I mean, ultimately, it's a bit of a risk assessment, a risk decision in your situation. How good do you think I will be at writing these unit tests? So I think it's like a very unsolved problem in a way, but a very, very important one, right? It's all about thinking about our feedback loops for the correctness of what we're doing. And they can be very different, depending on what type of application you build, right? Is it an API? Is there UI? Are you writing to a database? Are you writing events that need to land in some other system? All of those situation need very different type of testing. So it's also hard to find just one simple way to do this. Okay, sounds good. I think let's move on to some of practical implementation tips and maybe we'll cover some of the questions I had. The first thing I want to ask you in this practical implementation segment is, what does a minimum viable harness look like for a new dream? Can you give some tips and tools to add? It's actually hard to answer because this is like still so much evolving. So also in the experiments that I've been doing, I'm just like poking around and trying to use different sensors and to even see like which of these are valuable, which are not, right? And that's definitely like one of the big questions here, the meta questions as well, when you build this harness, when you have these guides and sensors in place, how do you know that they're effective? It's like on the guides side because the guides are often inferential. So they often like markdown files that get interpreted by a large language model. So on the guides side, there are now some ways to do like skills evals, right? So like to have your skills and then write some scenarios and run them one time with the skill one time without the skill and see if the skill actually makes the results better or if the model would have been good at it by itself, right? That's the whole thing I said earlier about the model's getting more powerful and when you use a very powerful model, you might not even need some of those instructions, right? Especially like when you think about that, many skills these days are actually generated by large language models. So people have large language models generate the skills and then I'm sometimes like, yeah, but then if the model already knows all of this, sometimes it's still useful, I'm not saying it doesn't make sense, right? But it sometimes makes me wonder, is there like some kind of cycle that I should consider if it actually needs it or not, right? Unfortunately, models are changing all the time their capabilities as well. So evals, that's one way to check if your skills are actually being effective. On the sensor side, especially the computational sensors, like the code analysis and all of that that I was talking about, there's not really like tooling for that yet, right? So I've been experimenting a bit of the speculative kind of way, what type of tooling I would want for this. I'll write a bit about that publicly soon, but there I was also thinking about, okay, during my coding agent session, I was giving it access to all of these sensors in one big suite and one big like let's say sidecar that was running next to my agent. And so I had it write a history of every time the agent checked for the state of the sensors, I had it write a history and then I could see across the coding session, how did the test coverage evolve, how did the number of analysis violations evolve and different security static code analysis and stuff like that as well. And I would sometimes see that in the middle of the session, some issues would come up and then they would go away again. So that's maybe the first step to have some like observability of what's going on with the sensors. And then it's like a similar dilemma to our pipelines. It's very similar to our integration pipelines, right? If my pipeline is always green, is that a good thing? It's actually not, right? You wanted to go red sometimes because that gives you the good feeling that, oh yeah, it's actually a safety net that works, right? If it's always green, I would get suspicious. But if it's red all the time, that's also bad, right? So it's kind of this dilemma of what level of like the sensors firing and actually giving feedback is good or bad. But that would be something that would be great in the future if we had more tools that would introduce this type of observability. There's a lot of that happening in the base harnesses space, right? So around what people are calling agent traces. So there's a company founded by the ex GitHub CEO called Entire. And they just like as their first little thing, they released a CLI that helps you track all of the stuff that is going on in a coding agent session so that it can be analyzed later. And there's some other tooling popping up at the moment around that. So that's another way to look at how well is my harness working. Once we figure out how to analyze all of these traces of what's going on in the session and can then maybe compare when I have these guides and sensors in place, I actually got to my goal a lot faster than when I did not. Or can we, I don't know how to practically measure this, but can we have metrics around how long did the agent go until I had to intervene or like how much feedback would I give it before it could actually create a commit? Or so I think that's also an emerging space of monitoring and analyzing how well our coding agent sessions are going, which would tell us about the harness effectiveness, both of the base harness that we're using. So again, Cloud Code, Pi cursor and of the harness that we put around it. Yeah, because sometimes I also notice that when you ask it to change a particular file based on constraints, as you say, this changes all over the place. And sometimes it feels like you're losing control of the file. And every time I'm always doing the diff pretty slowly on the agent, almost stopping it at every time and checking the change. So I think an observability log on the changes would also be good. Sometimes it feels like it's all over the place. And it also completely re-rides things because I've had a case that on last Friday, where I was rewriting a bunch of unit tests, the unit test was not functioning okay. And then I was trying to go and investigate it. And when I investigated, I found the exact part where it was failing. And I asked, just give instructions to redo that part with the correct logic. And then the entire stop got over it. And you know, other previous functions, because I had forgotten to say that, you know, please do not change anything at this. Even though I had it in my guide, I don't know. So that can be sometimes where you feel you're losing control like the base just very fast. And that also goes beyond single file, right? Like we talked about static code analysis before a lot. And the type of analysis that I gave examples of was mostly related to the file level, right? Or a function level or something like that. Psychromatic complexity and stuff like that. But we also usually as developers think a lot about one level higher about cross-file, cross-modular. What is our coupling and stuff like that, right? Because we know that when that gets messy, changes will get harder and harder and harder and riskier and riskier in the future. So for example, often when I use a coding agent, let's say build up like a POC that I actually want to be maintainable for a little while at least, right? I start noticing that after a while, my change sets get bigger and bigger. Because when I change something, it has to change suddenly, like, I did a change recently where I just added a new query parameter to one of the end points. And it changed 15 files, I think. So this is a relatively small application. So that was actually quite a lot. So that's like a smell usually for, oh, there's some repeatability here. There's something that's not well abstracted, right? And that's then about like sensors, thinking about the sensors that help us look at that coupling in modularity level, right? So I tried that a little bit with again, like more computational static analysis, you know, finding the what other files that get imported a lot by other files or stuff like that. And it's actually not that helpful. Like, it finds some of the hotspots but in this area with modularity I've had much better results with LLM sensors, LLM judges, right, that actually have really good prompting about what coupling and balanced coupling means, right? Let me just quickly look up. I don't want to botch the name, but I use this skill by Vlad Kononov, who wrote a book about balanced coupling, right? And I've had really, really good results, which shows when you have an expert, right, really good description about also, like trade-offs and semantic analysis of what that means, you can get some good results from that. It's not just a doing lots of stuff in one file. Inside of a file, when I feel confident in my test side, sometimes don't mind as much, although it is a little suspicious, and then I might go and look at that in particular. But across files, it's even more problematic, potentially, right? So can you walk us through a real world example of an honest in action? So I actually published a little YouTube video recently on an example, like my example application that I'm working on, where I'm trying to put a harness like that in there. And in that one, because I focus a lot on sensors, I don't have a lot of guides in there, but I would say typically what I see lots of teams do these days is like on the one hand half, this informational part of the guides, right? So almost like a knowledge base inside the code base that gives the general context of the basics of what you're working on, so that the agent becomes aware of that really quickly and doesn't have to like reconstruct that every time you start a session by looking at the code base. And then the other part is definitely some like coding conventions or pitfalls that are maybe in cloud MD or agents MD file, and then maybe a few skills that are about coding conventions in places, right? On top of that, there's of course that a whole space of spectrum specification during development, right? Where people then also use like workflows and stuff like that, which in a way is also extra guides, right? But I know that lots of people are building their own workflows in form of guides. First do the planning, then do the design, then do the, you know, all of those, all of those types of things. So that's also quite typical, but also a space that is very emerging and lots of different stuff happening, and there's some backlash to it already again about like how it's too much, right? With spectrum development. So that's on the guide side, right? On the sensor side, I haven't seen that as much yet, but like in my application that I've been using, I've set up like a set of sensors that happened during the coding agent session. So for example, the static code analysis we talked about, it's looking at the test coverage. I have mutation testing set up as well, although that's a bit resource intense, right? But mutation testing with the coverage actually tells me how good my regression level is, right? So there's a bunch of things happening in the session before I even do a commit. I should say I come very much from the tradition of trunk-based development, and you know, pushing to main as much as possible. So I'm very like controlling about a commit, and I always wanted to be perfect. So I know that some people are using much smaller commits, and then think more about the PR. I just wanted to give that as a caveat. But this exactly goes to like one of the things we have to do when we think about the guides and sensors is where to place them. Where do we want them to run? Because they have different costs in terms of how long they take to run, how much energy they use to run, how many tokens they use to run. So those are all things to consider of where we place them. During the session before we even integrate, during a PR review, or in the CI/CD pipeline, and then there's also one place in our path to production that is kind of like a repeated running of sensors. There's this article by an open AI team about harness engineering where they call this garbage collection. So they say they worked on a code base for five, six months, just having the agent touch all the code, and them just working on that harness, and they still saw technical debt compound. Probably also things like I experienced about the modularity and stuff like that. So they also have things running on a schedule. I don't know, they didn't share details about how often they do that. But in my application, I also have some skills that are like one is this modularity review. One is a security review that is based on our internal infosec guidelines at ThoughtWorks, and then there's one that checks kind of like the freshness of the dependencies and gives me recommendations of where I should replace libraries or something like that. And I just go in there, and I currently manually just run those once a week and see if there's anything new. You can of course then expand that even more, have the agent create tickets for the findings that it has, or even create pull requests for the findings that it has, right? So it all depends on your team processes and how you're maintaining the application, but you can already start by just having it create a report once a week and having a human look at it. It has definitely reduced my maintenance work on this application, which is a real life application with a very small user base, but you know, it needs some maintenance and it has definitely made it possible for me to do that with like half an hour of week or something like that. Okay, that's interesting to know. And are there any frameworks of patterns for building harnesses today? No, on the one hand, I think it's more like conceptual thing. So there's probably not, here's like the one technical thing that is the harness and at least not in this like expanded harness, you know, of course, for the base harness, there's the one technical thing that is the coding engine harness. But yeah, I've also been thinking about that. For example, you have guides and sensors that have to be consistent with each other, right? You might have a guide that describes, this is a very simple example that's probably not real in reality, but let's say a guy said you should have very low psychrometric complexity and then there's a sensor that actually checks the psychrometric complexity, right? I mean, this is very simple example, but just to say that the guides and sensors, they have to be in sync with each other. And you might have them all like splattered across the code base and not so I've also been wondering, is there a way to maybe package them together somehow or is there a way that the base harness can take some of the responsibility of running the sensors with some like plugins or something like that, right? I think there's definitely potential for more tooling in some of these things and more configurability. But overall, I think it will always stay more like a conceptual thing, like architecture or like what are the things that you have in place to increase your coding agents quality of results? So this comes before you actually do the like you run your Gita actions or anything on the main branch, right? So when as soon as you get a result from the coding agent is when you run these sensors as well. Like I said, you have to decide where you put which sensor, right? And I definitely think they are definitely the kind of low hanging fruit, quick hygiene type of sensors that also run really fast. Why not run them before you even create a commit? Like I see a lot of the base harnesses always assume there's already a PR or you're on a branch or something, right? But I want to have a lot more stuff that happens on my local change stiff, right? Because if you can do it after the commit, you can also do it before it, right? So again, maybe this comes from my history of trunk business development. But we don't want to like start pushing quality right? We want to keep it as far left as possible whenever we can, right? So especially the cheap stuff, let's just try to run it, you know, as soon as possible and not two days later when we have a PR review. And here is what I want to ask your question also in terms of when you run these tools for doing the static code analysis or security like CSM grip or tools like that. What happens is sometimes you'll get a finding where it'll tell you to go and fix it, but then the thing is that sometimes it might not really make sense to fix it in your particular project either because of it could break something else or it's really not that important. And there's almost a judgment that comes from a human to tell you to fix it, right? How does that work with the EIA agents? So this goes back to what I was talking about before I was asking it to make a judgment call in my self-correction guy, so to say, right? And so that again is, you know, it remains to be seen how much we trust the models to make this judgment call, right? We might trust it more with something like max lines per function than with like security thing, right? So I actually also do have some grip set up for my application. And I think in that guidance, I don't tell it to make a judgment call. I tell it to let me know. I don't quite remember. But in any case, it's a lot easier to do this like suppression, you know, like usually these linting tools, you can put like a comment in the code. And then in the comment, you can also say why you are suppressing it, right? So that also gives information for the future when you're doing this. So harnesses for me are all about improving how as a human, I can prioritize where to put my review. So always thinking about like, how can I triage that almost, right? And depending on the risk that I see in my use case, in this area of the application, and so on. But the thing that I actually find even more interesting than that, and I don't know yet where that is going to go, is what if you have sensors that contradict each other, right? Trade-offs are all over software delivery, right? So I have been like in my application watching out for these like, are there any like contradictions, trade-offs? What does that mean? The only small thing I've found maybe so far is that because my agent has been doing a lot of splitting things into smaller pieces because of, you know, it kept violating max lines per function, max lines per file kinds of things. So it puts some reasonable exceptions in there. But sometimes it just like breaks my react components down even smaller and smaller, right? And then suddenly I have a hierarchy of, I don't know how many levels of react components that contain each other, and that they all like suddenly pass through like eight or ten properties all the way down to the bottom. And most components don't even need that, right? So that's maybe the only example I've seen of a trade-off so far, where the, you know, it's very eager to break everything down into smaller pieces because that's what the sensor said. But what if I now switched on another sensor that tells it more about the reaction. component health and like not making it too granular. So that will be interesting to see when you switch on like lots and lots of sensors. Will it just go into overdrive and keep ping ponging between different judgment calls. Right, that's very interesting. So then how do you kind of build a trust in systems where agents are generating and also modifying so much of the code? Yeah, so that's kind of the goal of this, right? Like thinking about this like increasing trust in the agent and this is of course not the only thing, right? Like we were saying before the test suite is green, that might not actually mean anything, right? But it is a lot about probabilities and risk assessment, right? So I always think of it as probability impact and detectability. That's always like the formula of how you do risk assessment. So I think about how probably do I think it is that AI will do something wrong or will do it right. However, I want to think about it. And so that probability assessment is based on my experience with using the coding agent, my experience with using the model for how much do I know about the tool. So it's very like you can't just look it up in a table. It's very much this skill that we have to own because it's such a weird technology. But probability that it does something wrong might also be, oh, this is a very, very messy code base. So it's a lot higher probability that it will do something wrong than when it's like a very, very well-factor code base. And then for impact, it's all about the use case. Am I building a POC or a spike or is this like a super critical business flow that I'm working on? And then detectability is all about how easy will it be for me to see that it did something wrong. So what are my feedback loops? What do I have in place? And then when I look at all of those things, then I decide how much do I let it go unsupervised? How much review do I want to do? Do I want to look at every single line of code or just like a high level thing? Just check the sensors and I'm done. And yeah, to go back to the probability, right? Probability then is also a lot about how much confidence I have in my guides and sensors. How much visibility do I have into the things that I care about for this particular application and for this change that I'm doing? So in a sense, the trust gets built because of your trust and also your harness in a century. Yeah, yeah, yeah. We just now have to find out like how far can we push these harnesses? And again, it might depend on the use case, right? And some use cases I'm fine with like just a little linting, and maybe there's some like modularity review once a week. And in other use cases, it might just not be enough for me. And I really want to look at everything. Can multiple agents coordinate within a harness? So I was talking before about the coding harness itself is the base thing that does everything, right? And that coding harness might actually have the ability to spin off multiple agents. And then my expanded harness, like I can of course, you know, all of those agents can potentially access it or some of those agents might be part of my harness, my expanded harness. So like there might be a code review agent that is one of my sensors. So yeah, again, with the terminology, it's a little tricky right now. But I think we're getting there. It's getting a little better. I would love it if there was a better word for this expanded outer harness. But nobody has come up with one yet. So I think it would be helpful if we had a separate word for it. That outer part of the onion, basically, that we engineer. Yeah. And these separate code review agents are actually a very, very common sensor that people set up where they spin off another sub agent that has its fully owned context and no history of the conversation. And then with that quote unquote unbiased view, it looks at the code and reviews it. Sometimes people like to use a different model, even for that sub agent, right? And so that's like a very commonly used sensor that people put in place. In your article, you talk a little bit about the role of human in the software development life cycle and also the accountability which humans have to do things right, which agents might not have because they don't belong to an organization or an organization. Yeah, they definitely don't they are machines, right? They don't have accountability. So now we're placing so much of trust on these agents to do a lot of the work without the accountability. So how does this whole fit into the software development life cycle? Yeah, and also to add to that, sometimes like some of the anecdotes and stories you hear, it's also putting people in unfair position because some organizations on the one hand side put a lot of pressure on people to use coding agents and to become faster and more output and just, you know, you're being measured by that. But then it's when something goes wrong, then suddenly it's your fault. But when you put a lot of pressure on people, oh, now that you have AI, you have to be X percent faster, you have to create 50 PRs that we go whatever, right? Then you know, if that's what you're being measured on, people are going to cut corners and it's going to lead to more incidents. It's going to lead to more instability, right? Like Google does this doora report on software delivery performance. And now they're also focusing a lot on the AI assistant. They call it, I think AI assistant software delivery. And that is one of the factors that they have found so far in their data that instability goes up, right? So stability goes down. However, you want to put it. And yeah, there were some like prominent incidents over the past few months, where in the communication around it, you could start seeing some organizations having this reflex to throw people under the bus a little bit, right? And so I'm always torn because on the one hand, it's like, absolutely gay to me, the human has to be accountable, right? But because of the environment that we put the agents in and that we put people in, I feel for people for cutting corners, when you're only being measured by activity, by throughput and all of that. So it's a tough situation. I think it has to be done consistently. If you still expect accountability, like if you hold humans accountable for what's happening, you also have to give them the space, the environment and the incentives to be able to do that. That's true. So in this regard, I also wanted to ask you, from your perspective, how is the role of the software engineering change? Because of agents of agents and unsengineering, how does the whole thing change? Yeah, I mean, from the beginning of all of this hype starting, right? Like people have said, Oh, it's just we don't type the code anymore, right? I mean, that's what people mean these days when they say, Oh, all of our code is written by AI or 90% of our code is written by AI. They mean it's being typed by AI. Of course, a lot of it is also reasoning about and creating it. But the engineers sitting in front of the coding agent or like deciding what task they give it, how they describe, like a lot of the prompting that is being done is very technical has a lot of technical details, right? And this is particularly easy for experience software engineers, right? Because when we know what we need ultimately and what good looks like, we're also a lot better at prompting and saying what we need, right? So but as from the beginning, in this talk of like, Oh, the abstraction level goes up, right? But I don't think it goes up in the same way that went up with compilers and stuff like that. It's like a typical comparison that people do. Oh, it's like at some point at first, people didn't trust assembly code. And then at some point, they just trusted it and never read it again, right? But I don't think it's the same thing because a large language model is not a compiler. A compiler is repeatable deterministic to like very, very high nines. So a large language model is very semantic interpretative, probabilistic, all of those types of things. So I think it's a different type of abstraction level raising that will happen here. I also think that the details will matter less, especially when we find good ways to control the details even more with tools like linting and stuff like that. But then, you know, like I said, this modularity review, that's already where I came to the point where just having the data and the computational sensors was not enough anymore, you needed more semantic interpretation, which an LLM helps us with a little bit. But then we also maybe want to look at and still understand what's going on in our code base. So it's easier for us again in the future to tell the LLM what we need. So yeah, I think there's definitely some kind of raising of the abstraction level, but we don't know yet where that's going to sit might also depend on the domain. And then the other thing is this thinking and risk assessment that I talked about before. So I recently thought about the best quality analyst I ever worked with, who is actually a career changer from recruiting. So not a computer science graduate. She could sit with us developers and she got into coding a little bit and she could sit with us. She could read the code and she was the person on the team who understood the whole system inside out better than anybody else on the team. And she would know when we would do story kickoffs, she would say things like, Oh, you're changing something in the database. And then she would know exactly what to poke at what to test what the risk profile of that was, what that meant. And so this type of thinking in like, Oh, we're changing this. So that means that we have to test that quality to show these things. And maybe do we have sensors for this or whatever, right? So this type of risk assessment or also how much do I review based on probability impact detectability? That's something that will be a very important skill. And that often developers haven't honed that much. The fact that we need to have quality analysts on teams tells us that since so many teams got all we need a quality analyst, you know, it's like six developers sitting there and they also they need a quality analyst. So it tells us that it's not like a skill that so far we've always like widely developed. So that's another shift, I think, we'll have to make like you said before, how do I know when I can trust it? It depends. So I think that's a good skill, like looking at quality engineering, I mean, which we used to have before, but then we've all fused into the T shaped engineer, but I think love looks like this has to come up a bit in the T shape. To highlight that again, and quality assurance in is very, very much about risk assessment, where the critical path, like what actually matters, the testing pyramid, how will that change, right? Will we indeed have more acceptance tests? And then how do we feel about the risk of that, right? And so on. So it's very much this risk assessment and thinking and probabilities and being comfortable with that. Yeah, I think the quality angle is going to become all the more important when writing code is not going to be so tough. So yeah. And then now we're also like to determine quality, we actually have to describe what good looks like for our situation. Right. And that's also not something that we're historically always good at. Yes, yes. It's like, oh, it just feels more clean, you know? Yeah, metrics for that as well, yeah. But I'd like to end the show by asking you a little about what do you think about the future of harness engineering, adding more things to make the AI agents more predictable, right? Yeah, I mean, it's just like maybe recency bias, but I've been experimenting a lot with these sensors because I think they're still quite underused and there's also not a lot of tooling in that area. I just don't see the future as being like 50 markdown files in our code base. I mean, that can't be it, right? And then like I said before, in every markdown file, it's very very important. Do the following never do the following. I mean, that can't be it. Can we still call ourselves engineers? That's how we're doing stuff, I don't know. I mean, it will be part of that definitely, but yeah, so I'm like just like really interested in like this whole ecosystem and all these integrations into the base harness and how we can make that better and also balance it, right? It also cannot be just like throwing 100 tools at the agent and like 50 sensors that kind of overload it. Or we can think about, okay, if I have these sensors, do I need those guides anymore? How do we balance that? Yeah, and unfortunately, then we'll probably never have really, really good way to measure what's better and what's worse. So it will be about the feeling again, right? But in short, like I see a lot of tooling potential there still and a lot of things we still have to figure out about how to balance this. Like this whole idea of regulation, I really like it. Like a system that you try to regulate, that it doesn't get too much or too little or, you know, so I really like that image to think about harnesses. And it's also good way to test the models which are coming out in the market as well, right? If you have a good harness. If we know how to determine that it is good, then it's okay. Okay, okay, yeah, you're right. I mean, in the sense that it's all those moving pieces, right? Right. It's all of these moving pieces. The models change, the base harnesses change. I mean, they're all like churning out releases like crazy, right? And then our own harness changes, right? So there are so many moving pieces on the board. I mean, the ultimate measures we have are our software delivery performance, right? What is stability, what is throughput? And then the ultimate ultimate measure is user value, right? Like, is this actually what we're building? Are we just building more crap faster? Or is it actually bringing the user's value? Is it bringing us revenue? Is it bringing profit, right? I think building something of value is what is most important. And I think using all the tools we can to get to that state is what we should aim for here. Thank you. This has been a very great conversation. Where can people find you in cyberspace? Pre-github, is it? LinkedIn or email. Yeah, most of my writing I do on my colleague Martin Fowler's website. There's a series there exploring Genai and also some articles. I have a personal website, begeta.info, where I just always list all the podcasts, the YouTube conference talks, writing, it's just a list of content. Okay, great. I'll add that to our show notes. Thank you for coming on this show. Yeah, thanks for the conversation, Priyanka. This is Priyanka Rajman for Software Engineering Radio. Thanks for listening. Thanks for listening to S.E. Radio, an educational program brought to you by IEEE Software Magazine. For more about the podcasts, including other episodes, visit our website at se-radio.net. To provide feedback, you can comment on each episode on the website or reach us on LinkedIn, Facebook, Twitter, or through our Slack channel at seradio.slack.com. You can also email us at [email protected]. This and all other episodes of S.E. Radio's license under Creative Commons license 2.5. Thanks for listening.

Podcast Summary

Key Points:

  1. Harness engineering involves building systems that sit atop language models to orchestrate and guide coding agents, using tools like guides and sensors to improve code quality.
  2. Guides provide contextual instructions (e.g., coding standards, architecture rules) and are often written in markdown files, while sensors deliver real-time feedback through tools like static code analysis or test suites.
  3. Sensors enable self-correction, such as detecting high cyclomatic complexity or poor modularity, and allow AI agents to make judgment calls—like refactoring or suppressing warnings—based on human-defined thresholds.
  4. The effectiveness of harnesses depends on balance
  5. Trust in AI-generated code is built through risk assessment using probability, impact, and detectability, not just automated checks, emphasizing human oversight and domain expertise.
  6. Human accountability remains critical, especially when performance metrics pressure developers into cutting corners, leading to instability and incidents.
  7. As AI agents evolve, the role of software engineers shifts from writing code to defining quality, context, and risk—highlighting the growing need for risk assessment and quality analysis skills.
  8. The future of harness engineering lies in better tooling for observability, sensor integration, and feedback loops, with a focus on making AI behavior more predictable and aligned with real-world software goals.

Summary:

Harness engineering is a growing discipline focused on improving AI-powered coding agents by designing systems—called harnesses—that sit atop language models and use structured guidance and feedback mechanisms. These harnesses incorporate "guides" like context files and coding rules, and "sensors" such as static analysis tools, test suites, or LLM-based judgment systems that provide real-time feedback to ensure code quality, maintainability, and correctness. , on code complexity or modularity), and establishing trust through risk-based evaluation.

The future lies in enhanced observability, such as tracking agent actions and sensor feedback over time, and in integrating these systems into developer workflows to catch issues early—before commits or PRs. Human oversight remains essential due to the probabilistic and interpretive nature of AI models, and developers must evolve into strategic decision-makers who assess risk, define what "good" code looks like, and manage trade-offs. As AI takes over more coding tasks, the role of engineers expands from writing code to setting context, defining quality standards, and conducting critical risk assessments—emphasizing a shift toward more thoughtful, human-driven software engineering practices.

FAQs

A coding harness is a system that sits on top of a language model and orchestrates its actions, such as generating code or making tool calls. It includes a system prompt, guides, and sensors to direct and improve the model's output.

A coding agent is the instance of software that runs and performs tasks, while the harness is the underlying structure or framework that enables and controls the agent's behavior. The harness defines how the agent operates, including its tools and constraints.

Guides are instructions or context provided to the agent (e.g., in markdown files) to define what to do and what to avoid. Sensors provide real-time feedback, such as static code analysis or test coverage, to help the agent self-correct and improve its output.

Developers should begin with a vanilla harness to understand its default behavior and how it works out of the box. This helps build foundational knowledge before adding custom guides or sensors to tailor the agent to specific codebases.

Yes, AI agents can produce code with poor architectural decisions, such as high cyclomatic complexity or excessive coupling. This is why sensors like static analysis and code quality checks are essential to maintain code health.

Guides set expectations and context to increase the likelihood of good initial output, while sensors provide feedback during execution to detect and correct flaws, creating a self-improving loop.

Chat with AI

Loading...

Pro features

Go deeper with this episode

Unlock creator-grade tools that turn any transcript into show notes and subtitle files.