It has been a while since I wrote the first part of this post. Sorry for the delay.
In the first part of my post about essential complexity I said that there would be a second part where I explained the approach to managing complexity on Agile teams. However, I also gave the answer in the first part. The answer is Test-Driven Development.
The diagram below shows the usual way that complexity is managed on software projects:

When we start building the solution we have certain ideas about what we are going to need to do and how we are going to solve upcoming problems. We build those ideas into the approach to our solution, but along the way we discover new problems and assumptions. So, we build those onto the solution we started with. By the time that we approach our first release we have created something that contains a certain amount of accidental complexity.
Our solution is represented by the black arrow in the diagram. The essential complexity is represented by the gray arrow. In order to make our solution perform well and respond to change we attempt to drive the complexity down through refactoring. Unfortunately, at this point the solution already contains too much complexity to refactor easily. This is the familiar situation of “legacy code.”
TDD recommends something radically different as represented by the following diagram:

We create a solution that is naively, terribly, overly simple. We know that this solution won’t solve all of our problems, but it solves the problem that we have immediately posed to it (As represented by the tests.) In order to arrive at a solution that contains our essential complexity we continue to add more and more tests that ask further questions of our system. Then we work diligently to ensure that the system is no more complex than necessary to continue to pass these tests. We use refactoring right from the beginning to achieve this.
Working in this way we are able to drive from a system that is too simple to one that is just complex enough. The real beauty comes from the realization that we can often get considerable business value from incomplete solutions. That is to say that our customers benefit when we deliver solutions that do not manage to tackle the essential complexity of the problem posed to us but merely a useful subset of it. Further, our overly simple solution, which has value to our customers, is very lightweight and easy to change. So, we can add features to it at a blistering rate, and continue to learn and get feedback.
There is another advantage to this approach. Our system is always tested, and therefore testable. Those tests provide some assurance that the features we have implemented still work. So, we are always able to make changes safely and quickly. The only bugs that such a system can produce are the result of tests that we forgot to write because we didn’t think of them. However, it is trivially simple to add those tests, and generally quite easy to add the minimum functionality needed to make them pass.
Wait a minute… that sounds just like what we said we do when we add a new feature. In fact, it is. Discovering bugs is just discovering essential complexities that we have yet to address adequately. If we have a lot of complexity to manage when we do that then it is difficult, but if the majority of our mistakes are a result of a solution that is too naively simple then it is almost trivially easy. This is the power of TDD.
[Update: I changed the size of the images so that they don't bork the whole page flow.]