Six Design Patterns for Agentic LLM's

,

Introduction

Design patterns are pre thought-out solutions to common problems in software engineering. Anyone with an inclination for engineering will find design patterns enjoyable to merely think about - the factory method, the builder pattern.

These design patterns parcel up the insights of great engineers, and once in our mental repertoire, we can leverage them to solve difficult and abstract problems.

Recently, programmers have been given a new tool to play with - the Large Language Model.
Natural language programming calls for a complementary set of design patterns in order to empower elegant and robust solutions to even harder problems.

Many of these design patterns are predicated on the idea of ‘Agents’ - individual and autonomous instances of an LLM. Orchestrating many Agents in a sandbox is a complex problem with many degrees of freedom, thus motivating the need for these design patterns.

The Six Patterns

I. Looping

1
2
while (task_not_done): 
try_again()

Looping allows an LLM to break down a natural language goal into a set of subtasks, and then recursively execute on those tasks.

Looping is a fundamental design pattern since it transforms the LLM from a single-use token generator into an Agent capable of satisfying a goal. It is the pattern used by AutoGPT and Devin.ai .

Looping hopes to complete discrete tasks with indefinite levels of difficulty, by enforcing repetition until the goal is accomplished.

One limitation is the tendency for the Agent to get stuck in infinite loops - due to limited context window, the Agent may repeatedly attempt the same subtask.


II. The Reflection Pattern
In a nutshell, the reflection pattern is the classic “make it better” prompt. This pattern is based on the thesis that LLM’s rarely generate their best work the first time around - and we should never expect them to in the future.


III. [Persistence]
This is an extension of the Reflection Pattern. An example of the persistence pattern is an Agent writes unit tests and persists them to a codebase. At face value, this simple act seems inconsequential, however it accomplishes two important feats:

  1. Transmuting the stochastic into the deterministic. Converting the flux-like state of natural language into immutable code.
  2. Persisting its thought process into the far future

Through the act of writing a unit test, the LLM persists a piece of its own intellect as a piece of runnable code.

Currently, most of the output generated by Agents in production systems is not persisted back to the system (it is ephemeral). The answer is discarded as soon as it serves its purpose, meaning those Agents are effectively idempotent.

The Persistence pattern allows agentic systems to iteratively build up a separate system which exists independent of the Agents which created it.


IV. Tool use

Models, however intelligent, still need access to live, reliable information. As much as the world’s knowledge can theoretically be encoded and made available in model weights, a huge amount of the inputs models need change in real time.

Another way to make an agentic system larger than the sum of its parts is to grant the Agents agency over the surrounding Web (or even the physical world). This integration can be broken down into two sides:

  1. Pull: the ability to freely query data from the outside world.
    1. Integrations with communication channels like Slack
    2. Integrations with databases
    3. Integrations with platforms like Google Ads
  2. Push: the ability to push a change into the outside world.
    1. Agents that can write pull requests
    2. Agents that can call other Generative Agents (text to image, text to speech)*

In programming, command query separation principle states that every method should either change the state of the system (command), or return the state of the system (query).

Agents should be able to do both.


V. The Planning Pattern
The raw horsepower of the LLM - being able to, for example, write an entire essay from a single prompt - has led us to incorrect expectations where we have forgotten the general necessity of breaking down a problem into smaller tasks.

A student, given the task of writing an essay, does not immediately put pen to paper and write the essay without stopping. Just because LLM’s can write this way out of the box, doesn’t mean that it is an optimal way to use them.

The benefits of Chain of Thought Reasoning are well documented, so I will not go into them here.

In 2022, Andrej Kaparthy referred to System 1 and System 2 thinking in human cognition when he described the need for LLM’s that could ‘think slowly’. I believe that this is possible through the planning pattern.


VI. Multiagent collaboration

Multiagent collaboration is self-explanatory and best summed up by the following quote:

“It works… much better than you might think”.

This pattern borrows from the pattern of Ensemble Learning⁑ in traditional machine learning. The idea is that if you had one hard question to answer, would you feel more comfortable asking 1000 average people, or a single expert?

Often, the average⁂ of many weak models beats a single strong model.

Multi agent collaboration is the same general idea, but its implementation is different in nature.
For example, one might place Gemini, ChatGPT, and Anthropic Agents in a sandbox and let them ‘debate’ until an answer is resolved. This has the following characteristic differences:

  • Instead of aggregating independent ‘votes’ to get the final answer, a network of Agents to argues until they reach the final answer.
  • Thus, you are able to ‘spectate’ the decision making process - it is not a black box.

However, there are a few limitations:

  1. These ‘arguments’ must unfold in real time - there is no way to parallelize this process.
  2. The Agents themselves are themselves bottlenecked by the efficacy of natural language in communicating ideas; unlike the pure 1’s and 0’s which transfer packets of data over the internet, there is inevitable signal loss when one idea is transferred from Agent A to Agent B.

Nonetheless, we have to get used to delegating tasks to Agents and patiently waiting for a response.

Conclusion

Software is an abstraction of the if/else statement and the while loop. Similarly, the fundamental unit of natural language programming is next word prediction.

As a reminder, a system of Agents is already capable of creating video games. This emergent complexity is the product of many next-word-predictors. Like programming, we should reason from first principles about

Example:
![[Pasted image 20240819204119.png]]


Patterns II, IV, V and VI are a synthesis of Andrew Ng’s presentation at Sequoia.

* HuggingGPT: Solving AI Tasks with ChatGPT and its Friends in Hugging Face
⁑ Note: not actually known as a design pattern
⁂ You can also aggregate via the mode, weighted average, or even a meta classifier