Great International Developer Summit (GIDS)

The Intersection of Architecture and AI - Neal Ford

1:02:00 · 21 Apr 2026 – 24 Apr 2026 · YouTube

About this talk

This talk explores the intersection of software architecture and artificial intelligence, focusing on the complexities introduced by generative AI in software development. The speaker, alongside co-author Mark Richards, draws from their work on a book discussing how to establish architectural guardrails when both human developers and AI agents are involved in building code. They highlight the necessity of defining architecture effectively so that it accommodates agents while ensuring their outputs align with architectural goals. The discussion includes nine intersections within the software development ecosystem that influence architecture, such as engineering practices, integration architecture, and data topologies. Key insights address the limitations of generative AI in capturing architectural capabilities, the importance of deterministic guardrails, and the challenges of using agents for coding tasks. The speaker emphasizes the need for architects to continually refine constraints and governance in the context of non-deterministic code generation.

Full transcript

Uh today I want to talk about the intersection of software architecture and AI. Uh it is uh required that every talk uh be about AI apparently this year and so my talk is no different. But this is a subject about how do you constrain agents who are building your software myself and Mark Richards, who many of you are familiar with, my co-author, we've actually been thinking about

this problem for a couple of years. Which is interesting because agents haven't been building software for a couple of years, but we've been thinking about this because we've been working on this book and I'm going to be showing you some of the highlights from this book as we go along today. Architecture as code because when we started writing this book, it was about how do you define

architecture so that human developers can fit and do the right thing from an architecture standpoint, but now we have humans and agents building code, but it turns out the guardrails still need to be there regardless of who's creating that code and as it turns out, you have to be more careful about the guardrails you create for agents than you do for humans. Let's talk a little bit

about that. So, what Mark and I did was identify nine different parts of the software development ecosystem that intersect and influence software architecture. Software architecture is unique in that it touches so many different parts of the ecosystem and I will briefly touch on each of these in my keynote and then do a slightly deeper dive uh on these in the talk I'm doing tomorrow called architecture as

code, but those nine areas are architecture and implementation. Obviously, to implement an architecture, you have to write code, and there's a an intersection there. But also around things like engineering practices. Like how do you use version control? I'll talk about a concrete example I recently had of how do you keep two agents from cheating in a mono repo? Cuz it happens. We'll show you exactly how to

prevent that from happening. Even things like team topologies have an impact on architecture, a measurable impact, and you can define those relationships with code. Integration architecture, the enterprise. In fact, we have an entire role called enterprise architect who's responsible for this intersection, but you can also quantify that intersection in code. Generative AI, of course, which is going to be mostly the focus of my talk this morning.

Infrastructure and infrastructure code along with architecture as code. Data and data topologies, and finally, how do you build concrete feedback loops with the business environment? Are we building the right architecture for the business that we're in? But let's first talk about this intersection of architecture and generative AI because that's going to inform all the rest of the intersections that I talk about. So, let's talk about three

different ways that we can think about AI as an architect. First, can we just replace architects with generative AI? And the answer is no, but I'll explain why as we go through. Then, can we use it as a coder? Turns out we can, and there's some nice ways to do that. And finally, of course, agentic AI. What is the role of architect if you have agents building

code? And in fact there are two aspects of this that are interesting. One, agents building code that you then compile and execute, or agents that are working on your behalf, autonomous or semi-autonomous agents doing things like, you know, negotiating prices or arbitrage or something like Which is still a lot more speculative. We're going to focus more on the coding generation agents here. But I want to talk

about this to start with. Uh first, let's talk about can you just replace your architects with GenAI? And the answer is no. And the reason for at least partially comes from here. And this is I want to bring this up early because this is going to inform a lot of the things that we talk about this morning. This really important split that we talked about in this

book, and I've talked about it a bunch of my other books, which is when you are doing structural design as a software architect, you have to think about two different things. One of them is the problem domain. I've got a problem, and I'm going to write some software to solve that problem. That is your problem domain, and that of course is going to influence the decisions you

make as an architect of how to design that system. But you also have to think about what we've long called architecture characteristics, but are really about the capabilities of the system. That's where the illity thing comes from. We're describing capabilities that it needs to have to be successful outside of behavior. And this is a really useful split as a software architect, because the behavior is one thing,

but then capabilities are completely different set of things to think about. And in fact it's important to think about these two things because of uh the difference in the way that these two things can evolve. So, let's talk for a second about this concept from the design world of emergent design. What emergent design says is that if you think you're going to end up with a lorry,

you shouldn't start with a lorry. Instead, you should start with something simpler like a roller skate and then go to a unicycle and then a bicycle and then a motorcycle and then a car and then a lorry. Letting the behavior that you need emerge over time. This is the essence of And this, of course, makes good sense because you're learning more about the problem space as you

build more of the solution and you want to be able to adapt as you make those changes. So, this is that idea of the emergent design and this is very much what we're often doing with agents. Oh, here's something that works. Now, add some more onto that. Oh, this works and add some more onto it. So, this is very much that behavioral flow with agents as we're

building software. The same is not true about architecture. Cuz architecture is about capabilities, not about behavior. And if you look at the capabilities of a roller skate and the capabilities of a lorry, they have almost nothing in common in terms of weight distribution and balance and capabilities of any kind you can imagine. So, you can't emerge architecture. You have to start over at some point and rebuild.

This is that key difference between an emergent design but an evolutionary architecture. An evolutionary architecture requires you to rebuild at some point from the ground up to support better capabilities. In other words, I can't take a fundamentally non-scalable system and then just make it scalable without changing anything else because it takes a lot of effort to do that. And the reason for that is behavioral uh behavior

is something you can build incrementally but capabilities is something that requires more planning and a lot more diligence. And this split is really useful for our conversation this morning. Capabilities versus behavior because it turns out that LLMs and agentic coding are great but terrible at capabilities. And it's not even that they're bad at taking some capabilities into account, we're just not telling them to take those capabilities

into account when we're telling it how to build software. When a person when a human developer builds software, they take things like scalability and security into account. We have to be able to instruct agents to be able to do that as well. That's about trade-off analysis and about uh controlling capabilities. GenAI as a developer. GenAI is great for this both for coding assistance and also building code

because you can ask it questions like how do I configure Kubernetes, but you understand how LLMs work. What happens when you make that query is that it goes off and creates vectors and tries to match against similar things within this huge corpus of knowledge it has. And for something like Kubernetes, there're going to be a lot of really close matches and you're going to get a pretty

good answer back. Same is true for some other mundane coding task like regular expression, that problem has been solved thousands and hundreds of thousands of times and so there's a great corpus that it can pattern match on to find the solution to Now, when you try to do this as an architect, now you're in a completely different problem space because the problem you're trying to solve has

not already been solved thousands of times. you have to give it a lot of nuance. You've got to give it a lot of context to be able to make a an architectural level decision because you have to take all those things into account and then you ask it, "Well, what are the tradeoffs here?" Well, it's going to go and search, but it's not going to find really

good matches like it did before because this is not a problem that's been solved hundreds or thousands of times, but it will give you an answer back with the exact same level of confidence that it gave you for the thing it knew exactly what the answer was. And I don't know if that's going to be true or not as an architect. One of the things that we're

fighting with here, still and will be in the near term, is this context. This is one of those missed opportunities. I heard one of my colleagues say this and I can't unhear this now. Uh we call this a context window, but we should have called it attention span cuz that's really what it is is the attention span of the LLM and if you tell it too much,

it loses its train of thought and it loses its attention span. But at least now we're fighting with this idea of a context window, which suggests that we want to be able to convey really important information to the LLM in as little space as possible in terms of context. Now, hold on to that thought for just a second because it's going to come up again here in

just a minute. One of the things it is good for as an architect is for crazy idea generation. This is a famous quote by Pablo Picasso, the artist who said, "Computers are useless. They can only give you answers." His idea, of course, being that what he really wanted was something that could give you questions, which is a much more interesting thing as far as an artist is

concerned. Picasso would have loved generative AI. Because computers always give you deterministic answers. You never worry about whether your spreadsheet is hallucinating or not when it comes up with a sum. You trust that spreadsheet, and if you didn't, it'd be really chaotic. But LLMs hallucinate. This is a feature, not a bug. They won't always hallucinate because that's where their creativity comes from is from their ability to

hallucinate. So, you can't get rid of one thing without getting rid of the other one. And so, this is great for It gives you really bad answers very often, but it's really great for questions you might not have thought of. What if questions about Here's my design. Give me 10 things that I should think about in this design, and probably eight of those will be, "Yeah, I

thought about that." One of them will be ridiculous, and one of them will be, "Oh, yeah, I haven't thought about Do not trust the answers. We've done a lot of sort of informal testing on this, when you ask to architecture questions to LLMs, they tend to produce very complex answers and have to be coerced into creating actual simple, elegant solutions to problems. This is a problem that's

getting better and better all the time, but it is still a bit of a problem that when you use gen AI to produce code, it will tend towards boiling the ocean in terms of complexity, it doesn't take into account architecture characteristics unless you tell it to, and it also tends toward great complexity and boiling the ocean. But again, this is only because we've told it not to.

And I'll give you an example here in a few minutes of where a solution that was created by agents with no particular architectural constraints, but then we decided, well, we want to open source this code and we need to control the quality more. When we constrained the LLM, it started producing better quality, less complex code, and I'll show you exactly the kind of metrics you can use

to uh drive that. This is getting better all the time about the brute force approach, but it is still there a little bit. So, another interesting use we have in is to use gen AI as an interpolator. Not as an interpreter or compiler or transpiler or anything like that, but as let me explain why that's interesting and start talking about agentic AI, which is the the third

way this has had a big impact on architecture. Over the last year or so, we've seen this massive gain in the functionality of agents to be able to produce code, and in fact, we've seen this sort of evolution from uh prompting towards this idea of context engineering. Uh has various terms, but we've seen this evolution from the simple idea of phrasing and wording of instructions to system

architecture and data flow, from single input and output turns to multiple multiple turn sessions and long-term memory that context window keeps getting better and better from a single specific response to making sure that the multitude of responses we have don't have things like hallucinations in them. The analogies of writing a letter to a recipient versus running the entire household and so much more broader in terms of

capabilities and When I put my architect's view on this, the two of these things that [snorts] that call out the most to are system architecture and data flow, obviously that has the word architecture in it, but also ensuring consistency and and eliminating hallucinations when you generate code. What we're seeing here, in my opinion, is the evolution of abstraction. And we've seen this over and over again. This

is just sort of an extreme version of that because when I first started writing code, languages that required you to do your own memory management were still popular. C++, I was talking chatting with someone recently. My very first book was a platform called Delphi, which was written on based on object Pascal back in 1995 and that was a language that required you to do your own memory

management. So, you had to learn how to do that and you had to be careful about it because it was a bad error if you got it wrong. But then languages like Java and the .NET platform came came along and that just disappeared. Still happening. Fact, the JVM is still choosing a memory allocation algorithm behind the scenes, but I don't care about that unless I have really

highly specialized needs. That's just an invisible part of the ecosystem to me. This keeps happening over and over again where things that are really important decisions just become subsumed by abstraction layers that just make those details melt away. And that's exactly what we're seeing now with agentic coding is another level of abstraction that says, "Well, what if the behavior of my code how abstract can I be

from that to not even care what it looks like anymore?" I'm going to talk about that in just a second as well, in this new idea of uh how long something should live. But, I want to go back to this distinction I made earlier between capabilities and behavior. the way that this is unlike the previous levels of abstraction that we've seen is that we've now added non-determinism

into the mix. The garbage collector in the JVM is never non-deterministic. It is always deterministic. And we talk about when we talk about abstractions, we talk about leaky abstractions, which are abstractions that don't match perfectly. And sometimes they leak, but they always leak in deterministic ways. When you're talking about agentic code if I generate this code today and tomorrow and the next day, it may produce the

same code, but then next Tuesday it may hallucinate and create something completely different. It's a feature, not a bug. These things are non-deterministic, which means that anytime if you're trying to build real software, you have something non-deterministic in the mix, you have to put deterministic guardrails around it to make sure that it hasn't gone rogue and started hallucinating and doing something crazy. And that, I believe, is

going to become your new job. Is not caring so much about the code inside some unit of work, and I'll talk about what that unit of agentic regeneration should be in my architecture's code talk, but rather what kind of guardrails are sufficient to give me confidence to execute that code without knowing all the details of what's going on inside. I believe that this is going to become

our new job, writing deterministic guardrails around non-deterministic code But, there actually two phases of this. Because I need to, if I'm using agents to build code, I need to wire these architectural guardrails into my context window. And there are ways to do this in virtually all the agentic platforms now. This would be skills in Claude code. This would be a root context and other tools where the

root context has higher priority than the things further down in the hierarchy for agentic code That's where this idea of architecture definition language, that's our ADL, is wired into your agent to constrain the way it produces code. And I'll show you an example of one of those kind of constraints toward code quality here in just a second. So, we want to be able to wire that into

our agents. But, we also want guardrails to make sure that it did the right thing. And it didn't find a way to cheat. Which is an interesting concern that we have to think about here. let me talk about the cheating for just a second and then I'll come back to this ADL versus concrete fitness functions business. This is, I think, a really important perspective to pick up

uh that I haven't seen many people talking about in the generative AI world. So, I'm going to introduce it to you, uh the Dreyfus model of knowledge acquisition. This was created for the nursing industry in the United States back in the 1970s, I believe. Cuz it turns out nursing and software development are very similar skills in terms of trying to learn to be a nurse or software

developer because you can go to school and learn all the things about being a nurse, but you actually have to do it for real to really understand it. It's like an apprenticeship kind of deal, just like software development is one of those. And they did a bunch of studies about how nurses learn things and the stages of knowledge. And it turns out this applies to any sort

of knowledge field and it applies particularly to software developers. And has a new perspective now in our modern world. So, let's talk about the Dreyfus model. This has been around for a while. There's a Wikipedia page on this. So, there are five levels to the Dreyfus model. Beginner or novice, this is sometimes called Beginners are just following recipes. They don't know why the recipes work, but they

understand enough to apply a recipe and if it breaks, they don't know how to fix it because, "Hey, I'm just following a recipe and I don't understand why it works." Advanced beginners have done recipes dozens or hundreds of times. They still don't have a deep understanding, but if one of the recipes breaks, they can sort of improvise and say, "Well, okay, this one broke, but you know,

I did another similar recipe before and and let me try to substitute these steps here. Okay, I can get this to work and move on. And so, limited improvisation because of previous experience with recipes. Competent developers, nurses, knowledge workers understand at least one level of abstraction below where they're working and understand how and why things work. Proficient means they understand things deeply and in fact can build

recipes for beginners, advanced beginners. And experts know it so well, they can't even explain it to you anymore. It's sort of become part of their muscle memory. When airline pilots, when they react to something in a flight simulator and they say, "Okay, why did you do that?" They go, "I don't know. It just sort of happens now because it's just so baked into my brain." The reason

this scale is really useful for us is because until now and at least in the near term agents and LLMs are perpetual advanced They're not thinking through the problem. They're looking for recipes to apply. The latest way you can trip up virtually every single one of the LLMs is give it a word problem that says, "Bob picked five mangoes, Susie picked three mangoes. Two of them were

smaller than the others. How many mangoes do we have total?" They all get tricked by the smaller thing. It's irrelevant to the number of mangoes, but it's pattern matching. It's not reasoning. And that's what they haven't plugged into the things yet. That's what they're working on now. But what they're doing is getting better and better at applying recipes to solve problems. And this is a really hard

barrier to overcome. And in fact, what's going to have to happen is other kinds of artificial intelligence, machine learning, reasoning models, etc. are going to have to be wedded with the pattern matching and recipe ability of LLMs to make that next advance forward. That's why you're seeing in my opinion a little bit of a dip in the capabilities of LLMs because we've reached more or less the

limit of how far you can push advanced beginners to get things done. That's really important. Because advanced beginners don't really understand why things work and will use some crazy recipes to get out of problems they're having a hard time solving. So, come back to this in a second, but I want to go back for just a second and talk about this business this idea of an architecture

definition language, but also concrete fitness functions. And this is the other thing that I alluded to here that LLMs are useful for and that's GenAI as an interpolator. And this idea of an architecture definition language. So, I'll show you an example in just a minute. Defining a set of components like this and the dependencies between those components. You would do this as an architect for a group

of human developers, but also a bunch of agents because So, the real question now becomes and we'll bring this up later how long is this code that I'm producing going to last? If it's 6 months, then I don't really care what it looks like. It can be a bunch of slop. Who cares as long as it works? But if I'm building the foundation for something that I

want to build on for years, I need good components. I need dependency management. I need complexity to be under control. I need all those things. And so, what we defined is a language, a pseudo code that helps you describe software architectures. Here's part of Uh there's I'll I'll show you some examples of it in just a second. We're not the only ones who are doing this. Calm

is a language created by the financial services industry that helps infrastructure in a consistent way. So, this is basically architecture as code for that infrastructure intersection that I was talking about before, those intersections. Software, this is for the the infrastructure intersection. So, we're not the only ones creating this architecture as code language like this. Here is how we're using this. So, here's the example at the bottom

of some of our architecture definition language where we're defining what domains we want within the system that we're producing. Now, it's useful to do this for human developers because what this gives you is a feedback loop in case somebody creates a new component that you weren't expecting. As an architect, I'm responsible for the components, the dependencies, and all those things that happen, and I want to know

when those things change. But, this is even more critical for When you produce code, I only want these because I want to control dependencies in my ecosystem for my controlled code, so that's what our architecture as code It is pseudo code, and that's really beneficial because pseudo code takes up less context. So, we really like pseudo code for this for a couple of reasons. One, it takes

up the fewest tokens in your context window, and that's a precious resource because the more these things you layer in there, you have to fit that wall the other context. The other thing is pseudo code gives the LLM fewer opportunities to hallucinate. Every pronoun you put in markdown gives your LLM an opportunity to go hallucinate and invent some crazy stuff, and so the fewer words you have,

the fewer branches it can take as it's reasoning through the language that you have. we wire this into the agentic generation, but here's the GenAI's interpolator business, we also can take that and hand it to the generation part of an LLM and say, "Okay, take that and produce a concrete fitness function for in one of these platforms." Java, .NET, Python, Golang, TypeScript, all these are concrete fitness

function libraries that you wire into your continuous build, your deployment pipeline. This is concrete deterministic code that you wire in to the back end of your code generation. This is this idea of uh trust, but verify. And this is where we come back to this picture is critically important. The ADL to get it to produce the right things, but then concrete fitness to make sure that it

did. I mentioned that LLMs are recipe finders. And they will find recipes that humans won't. For example, let's say you put a constraint on an LLM that says, "Okay, you've got to produce code of this certain code quality within these components." And it tries and fails and tries and fails. And And part of the constraint is you have to pass all these unit tests as One of

the recipes it will eventually find is the way to pass a unit test is just replace the assertion with assert true. Success. Okay, we're good. We can move on to the next thing. That's a legitimate recipe to get a unit test to pass, but it's not the right solution to get it to pass. And so, that's why I say you have to have even stricter guardrails for

agentic generation because they are recipe finders. They will find recipes that a human would never pick because they realize that's a really bad idea, but we're just looking for recipes here because remember, it's not reasoning through. It's just looking for a recipe to solve a problem. So now that begs the question, as an architect, how can I create the most succinct, unambiguous foundational rules for developers, either

person or machine, and that's definition language comes in. So for system architecture and data flow concerns, you define capabilities as foundational constraints for your Excuse me. These get wired into your specifications to say, and some of the keywords we use are always do this, never do this, never comment out assertions in unit test to make unit test pass, rules like that that get cooked into your agents.

And then we build build fitness functions for deterministic tasks on the back end to make sure that the recipes that it has applied has been something that is not cheating. This gives us objective definitions for architecture characteristics. This is how you explain your architecture to agents. It's through this architecture as code a pseudo code. I'll give you some concrete examples of this in a second. And as

I said, pseudo code is nice because it uses the least context, so it takes up the least of your attention span, um and it ensures quality guardrails as your agents produce code. As I said, agents don't want to produce bad code, but if you don't tell them not to produce bad code, then they'll produce bad code. So you have to tell them the rules for what good

code looks like. The other thing we have to do is ensure consistency about uh around hallucinations. And the way we get consistency is with objective definitions. Wrap deterministic wrappers around non-deterministic code. This is the way that we make sure that, okay, the past five times it regenerated that code, it did it successfully. This time it didn't. Let's go ahead and try again. And this [clears throat] is

uh the way that you get feedback for either humans or machines, are we creating the right things? So, the last bit about agents here, what should the regeneration scope for agents be? Should it be a single function? Or should it be the entire system? This is one of the things that drives me crazy about all the bubbles that I've seen throughout my career, but it seems really

acute in this particular bubble, that as soon as some bubble comes along, everybody says, "Oh, let's throw everything out the window that we already know about software development, because it's a brand new world where none of the old rules apply." And that's not true. There are really good objective ways to think about this question, but everything I see online is just crazy wild speculation about, well, it's

a brand new world. How could you possibly objectively think about this? Well, of course you can. So, the idea that we sort of latched onto in the world is, well, the proper scope for agentic generation are microservices. I think it's the term micro that appeals to everybody, because micro is small, and I want the scope of agentic regeneration to be small, and so, oh, those seem to

match, and so, if you're doing um tech word bingo, those two things sort of go together. But let's talk about that as a scope for regeneration. So, for behavior, we still need domain level testing. That's unit tests and functional tests, etc. That's the deterministic guardrails over the behavior of our system. But for capabilities, what we really need is something that defines the scope for a set of

capabilities. And we already have a definition for that. It is this concept of an architectural quantum. We define this originally in the first edition of evolutionary architectures. We've been using this in every one of our books since then, and this is the definitional scope for agentic regeneration because this is the definition from an architectural standpoint for the scope for a set of architecture Those capabilities that we're

talking Notice that's why this is the perfect scope of agentic of agentic regeneration because I have to control both capabilities and behavior. Well, I need the scope of the capabilities because that's going to be a unique set of deterministic tests. Well, that's what an architectural quantum is. This mostly matches with microservices, the reason I bring this up is because, okay, microservices and agentic regeneration, this is the

scope business, but the other important aspect that nobody's paying attention to is this. An architectural quantum also defines five different types of architectural coupling. And everybody that's talking about microservices as this A the scope of agentic regeneration are ignoring the impact of these five kinds of coupling that we've known about in distributed architectures for really long time. So, if you're going to use microservices for your agent

degree generation, you need to think about the scope of architecture characteristics and also these five types of coupling. I'll talk about these briefly here. I'll talk about these more in my architectures code session, but these are the five types of coupling: static, dynamic, transactional, temporal, and contract coupling. Quick examples of each of these. These are the things you have to build guardrails for, by the way. If

I'm using agents to produce microservices, I need concrete guardrails to check all five of these kind of couplings to make sure that agents haven't created couplings that I don't want in my distributed architecture. Static coupling refers to how things are wired together. So, if two services share a component, they are statically coupled together in a microservices architecture because a change in that shared component will require both

of them to change. This is also the relationship between the code and the database is statically coupled in a microservices architecture, so that's static coupling. And the way you deterministically check that are with these fitness function libraries that I was talking about before. Dynamic coupling has to do with how things call each other. Two services that call each other dynamically have different impact on your architecture than

two that call each other asynchronously. And so, you have to watch out for synchronous coupling in architectures like this. And to check those things, you need monitors or observability in your architecture to be able to see how things are communicating with each Temporal coupling is about startup dependencies. This is really only useful for caches. Caches are used a lot in microservices as a substitute for views. I

need to see data that I don't own, and so I'll cache it, and there's a startup dependency there that's both static and dynamic, but then it goes away quickly. So, this one's of limited applicability. Contract coupling is when two different services share the same contract. A change to that contract will cause both of them to change, and so this is a form of static and dynamic coupling,

but it's a combination of those things. The way we typically check against those and build fitness functions for them are contract testing libraries like consumer-driven contracts, which are common in the microservices And then finally, the killer ones is transactional coupling. That is actually the subject of my next talk that I'm going to be doing in here an hour after the next session. This is the trickiest one

of all to check for because it has the most impact in your architecture, and it is the one most likely to rear its head if you're just naively using agents to build microservices for you. All of those things have to be taken into account, and that's part of the concrete guardrails that you can wire into your ecosystem. So, that's this idea of how GenAI impacts architectures code.

Now, I want to give you some concrete examples of the things I've been talking about. I'm making the pitch here that as architects, we need ways to constrain agents and humans when they build code. What do those constraints look like? That's what I'm going to do for the rest of the talk is show you some samples from those different intersections. And the first of these is architecture

and implementation, that intersection, which is an obvious one, and we have two different ways of validating this, structural alignment and constraint alignments. So, as an architect, I build domains, and then I design components to go within domains, subdomains, dependencies between components, etc. That's part of what an a software architect does as part of their job. Of course, in a language like Java, that reifies into an actual

directory structure somewhere where each of these things is a container ship in a directory structure. But then, you hand this over to a team of or a bunch of agents and say, "Okay, build me code." This is what they produce. Like, wait a minute. Where did uh ticket assignment go? I had a ticket assignment component, but it got eaten somewhere. And what is this uh customer registration

disappeared, too. And what is that thing? Oh, well, that was a remote team, and we thought it'd be easier to keep their code separate if we just put that in a sub package of our other stuff. Well, when you do that, you're creating a new component, which means you're messing up component dependencies and a bunch of Agents do this kind of stuff all the time. So, what

I actually have here is Not what I had planned, but this is what I ended up with. This is the dysfunction in the architecture of many systems, whether produced by humans or by agents. Um this is what this idea of architecture as code is about is aligning these two things. And so, now I can actually define what I want, and this doesn't match any of those things.

So, part of the reason I designed the thing on the left was because I wanted agility, reliability, adaptability, extensibility, etc. And the one on the right doesn't exhibit any of those characteristics. So, that's this idea of architecture as code with bool constraints and then produce those constraints to uh uh produce concrete fitness functions. So, for example, I can define domains here. Here are the domains I want

you to produce and assert that classes are only contained within sub domains within those domains. What I'm doing here is building a hierarchy of directory I pass this to generative AI to produce that fitness function for me and here it is in Java. I could also do this in .NET or Python or any of these other supported platforms. This is the concrete deterministic check. Even though I

put in ADL in my agent only use these components, at some point it may cheat and create a new one and so there's the deterministic check to make sure you haven't done that. Here's the same kind of test in the .NET world. And it's really nice the reasons I'll show you in a second to be able to use pseudo code for this. So let's talk about constraints.

I want to build a layered architecture. Part of the goal of a layered architecture separation of concerns. And so uh one of those constraints might be things like uh open and close layers. Where I want to determine which layers can be left open or not. And so now I can define the relationship between these layers and say presentation has no dependencies on services or persistence. This controls

who can see what in my layered architecture and there in fact is a test that validates that for me. Same for uh the .NET world, same kind of test. But here's the more interesting one. One of the constraints I also want to put in this layered architecture is to say only the persistence layer should have database logic in it. This is also the kind of thing you

need to tell agents because agents will realize, "Oh, it's really convenient for the reporting module of this system to have the presentation layer talk directly to the database." But we know that's a bad idea as an architect because now I don't have separation of concerns anymore. I want to be able to build and say the persistence layer is the only one that's allowed to talk to the

database. So, here's something that restricts database access, defines the layers, only layer that contains database logic. Now, when we first started down this path, we put very specific code there. The second part of that assertion, we said, "Do not let it access any of these specific classes in the Java world." But, the problem with that is many, many architects are working in cross-platform systems. They don't just

have a Java system, they have a Java system and two .NET systems and four Python systems, and I want to be able to write rules that are generic and not platform-specific. And it turns out that's really nice to be vague like that, because that second L in LLM is your friend. Because when I tell it to produce Java code that does that, it goes through and picks

up every one of the Java classes that allow you to connect to a database and puts them specifically there. But, when I have it do this in the .NET world, it picks up the .NET interfaces that allow you to connect to the The intent was in my architecture definition language, don't let any talk to the database, the LLM took care of the details of filling in the

actual classes or interfaces that allow me to do that. So, that's a nice bit of using it as an interpolator to see what it can produce. Okay, that's pretty obvious. We have literally have tools to check that intersection between architecture and But what about architecture and data? This is a tricky problem in a lot of distributed architectures. So, let's talk about this intersection and a bunch of

data fitness functions that we can write. We can actually control all sorts of things in an ecosystem like this. We know about eventual consistency, which is really about data consistency. But you know, we can also have eventual referential integrity and eventual cascading deletes. It turns out we can have eventual all the things that we get in a relational database if we just code them in the correct

way. And I'll show you exactly how to do that. So, the architect goes to a product owner and says, "You know, I've decided we need to split the database into two domain databases for better fault tolerance, change control, and scalability." This is the common kind of decision an architect makes. And so, the product owner says, "Great. Make sure we don't lose any trouble tickets and both domains

have the same data." That's a trivial problem if I'm in a single relational database. It's a lot trickier if I've split across multiple domain databases. Where is this information documented? And most people when I ask this correctly say in a spreadsheet somewhere that we don't know where, but I'm sure it's in a spreadsheet somewhere. And more importantly, how do you verify that this is true? As an

architect, I make this confident assertion, but how can I make sure that that's true? Well, we can make sure that's true by First of all, documenting it in something like ADL. Tickets must be consistent between But this is not something we can just hand to an LLM and say, "Okay, produce a fitness function for me because there is no fitness function library to do this." And so,

we have to write our own code to And here's an example of that. I have my customer quantum over here, my ticket processing quantum over there. I have those two databases. I want to make sure that the customer information is consistent between those two databases. So, I'm going to write a fitness function that takes a hash of all ticket keys there, number of tickets that are pending

in the queue there, and a hash of all and write a fitness function that says, "When P is equal to zero, in other words, no pending messages, assert that the two hashes are equal to one another." I'm now validating across my databases data consistency and I have foreign key references correct. Really nice if you have humans building this as a way to govern that. But, what if

each of these two quanta here are being generated by agents? I really want to know that I have data consistency and referential integrity because as they generate code, they may change something that breaks that. I need a deterministic test to make sure that all of that thing all of those things are true. That's an example of data consistency. Here's an example of referential integrity. You can do

the same kind of thing looking at customer keys and customer foreign keys, and we queued up the zero, assert that those hashes are equal to one another. So, you can build the sort of eventual behavior uh even at the data level in uh So, let's talk about engineering There are a bunch of engineering practices that fall under um architecture as code including things like um version control,

controlling version control access. I'll actually show an example of that in my architecture as code session that I'm doing uh tomorrow. Um but I want to talk about code quality for a second. There are deterministic ways of learning what good code is that are metrics driven. I won't spend a lot of time describing abstractness, instability, and normalized distance to the main sequence. I'll leave that as homework

But I'll let you know that uh normalized distance to the main sequence is the number one metric for finding AI slop. Um because what normalized distance to the main sequence does is it when you take abstractness and instability and compare them to each other, where that little ball falls, if it's near that main sequence line, it's pretty good code. It's a balance between reuse and um abstractness.

Things that go too far up the upper right-hand corner are the zone of uselessness. But the zone of pain down here is where LLM generated code lives. That zone of pain means big giant methods, not enough abstraction, not enough code reuse. That is the default mode for LLM code >> [clears throat] >> And so this is the example of metrics tool. Um this is um Independent, the

.NET tool that produces This is a great example of the kind of constraint you can wire into your agents because the example I was giving you I thought I had a slide that said that. I guess not. The example I gave you working on a project that has this this agentic consensus protocol and the first version of it we built was literally what is I don't care

what the code inside is doing because it was a proof of concept. But now it needs to be high enough quality code to actually open source. And we started running some of these metrics on it and they scored poorly. And so we wired with ADL into the spec produce code that has normalized distance to main sequence below 0.3 and sure enough it started producing much higher quality

code. Agents can produce good code. You just have to know how to tell them how to produce good code. Takes more iterations to create that but it did in fact fix those problems in the code base by regenerating it and building these constraints into that generation. Here's of ADL using this pseudo code make sure that all components in this code base have a normalized distance to the

main sequence less than this value. This is a way of wiring this into agentic code generation to make sure it's producing reasonably good code. This of course gets you away from this tidal wave of functioning but terrible code. LLMs will produce bad code if you let them but as you constrain agents they will produce higher and higher quality code. As I mentioned before there's an entire category

of the intersection of architecture in the enterprise called enterprise architects. they have had a very bureaucratic role in a lot of organizations and one of the things they are responsible for are things like enterprise governance. These are the strategies for what kind of tools and platforms etc. We're using in our organization. And there are a bunch of these as controls technology stacks and architecture and approaches methodologies

etc. So there are a bunch of these that are extent. Um And a bunch of different approaches for primary one being these days more of a distributed kind of approach. This durable interface strategy where I don't really care what happens inside. What I care about are the ways these things call one another. So consumer driven contracts having agents produce things and care less and less about things

like technology choices. I want to come back to this in just a second but I want to take a quick trip over to the infrastructure world for just a second. I mentioned calm before. This is a way of specifying network resources in a consistent way across the entire distributed architecture. This uses JSON so they actually have a formal language spec. Which we do not we don't want

ours to be a formal language spec. We would be really loose but this has an actual language spec that lets you define how things relate to one another within an architecture. They're building a bunch of rules etc. around this and so this is the other ongoing way handling this but I wanted to get to here so I can talk about who executes this code. I showed you

that data fitness function before. This says when the queue drops to zero check these two databases against one another. But who's calling that code? Well, increasingly, who's calling it is a service mesh. If you're running microservices, you have a service mesh that runs, and that really turns it into a governance mesh. And in fact, now we can start talking about what the cool kids are calling an

agentic mesh. And there are two aspects of this, which is how do you productionize the AI stuff, but the other is the sort of agentic context of how do you build things within agentic context, what do agents need to understand about architecture, non-deterministic generation, and that foundational context we were talking about before. These are the two pillars of what we're talking about in the the architectures code

world. That brings me the other piece of the ecosystem that exists, MCP, model context protocol. This is obviously useful for agent to agent communication as a way of agents for discovering capabilities for other agents. The model part of this being the the tool side is the one most often used When we go back to this example I showed this is the short version, the simpler version of

the customer service and the ticket service. And I talked about this fitness function when Q is at zero, assert that TC is an element of C. But now, who calls this? We are now referring to this scope right here as a governance context. And the problem we've often had as enterprise architects, I really as an enterprise architect, I want all of my projects to exhibit good data

The problem though is I would really want to write a fitness function like that, but I have to know a lot of the details about how that project is implemented to be able to do that. And I don't want to have to know that. As enterprise architects, I don't want to know all those details because inevitably that's going to change. They're going to add another database. It's

going to break my fitness function. This is that uh governance context. And the problem is when from a long way away you try to write governance, it breaks because it becomes brittle because you have to know too many implementation details. That's where MCP as a protocol comes along. Forget about the agent part of MCP. This is just fantastic from an integration architecture standpoint because now at that

governance context, I can build an MCP server. And one of the tools that it exposes is validate referential integrity. It knows within the governance context that when that queue hits zero, assert membership from one to the other. And as enterprise architects, I can call that MCP server and say validate referential integrity, and it can come back and say yes. Then one day, yeah, I can have an

agent acting as an enterprise architect referential integrity for this project, and it can validate that, make sure that it's working correctly. But inevitably, when that project changes and adds a third database, I still want to check The call from above doesn't change, but the implementation details change. And this is why that governance context is a useful idea, just like a bounded context is in domain-driven design. This

is really useful for governing things because that is the scope of governance, particularly if you're having things like agents build parts of your architecture, you need a good scope for governing those things, and that's exactly what that represents. Going back to the example I was just giving you about these enterprise architecture governance standards, we now have a way that enterprise architects can in fact govern those strategies

much more directly by putting MCP servers there and exposing things like software bill materials to enterprise architects and other useful information at the the enterprise architectural level that may be useful for security constraints or other interesting things like that. All right, so let's wrap things up. To summarize what I've been talking about today, the really great resource for solved problems using gen AI as an architect, but

it's a terrible resource for trusted solutions, and it's a really terrible solution for things that have never been built before, but really good for gap analysis. Have I missed something? And a lot of times it will come up with something that you have missed. LLMs make great fitness function code generators. That's this interpolation idea, but watch out for maximal complexity rather than simplicity. That gets better and

better all the time, but it's still something to watch out for. The mundane but necessary real-world impact on architects is we have to think about productionalizing AI, but the bigger problem we have is building guardrails and foundational context for agents. I think this is mostly what our world is going to become in the near term is learning how to build really good guardrails, learning the kind of

recipes that LLMs are going to use to cheat, and then putting guardrails around those things, and then rinse and repeat, and rinse and repeat, and rinse and repeat. I think that's what our job is going to look like at least in the near term. And we are building a lot of resources for this in Architecture's code, which should be out this year. So, I hope uh all

of you can get a copy of it. Thank you very much for coming. Hope you enjoyed it. >> [music]