/images/portrait.jpg

Simone Vellei

👨 Senior Backend Developer at Cybus | ☁️ Cloud Adept | 🐧Linux/IoT Expert | 🏝️ Full-remote Addicted

Designing multi-agent architectures in Go

In the previous article, we built a capable agent with multiple tools with real capabilities (Python, HTTP, time). It worked.

But there’s a problem with that design.

As you add more tools, the agent needs to:

  • Track all tool definitions
  • Reason about which tool to use
  • Handle all execution contexts
  • Maintain one giant conversation history

This doesn’t scale well.

In this article, we’re going to refactor it into something much more powerful:

Building a stateful multi-tool agent in Go

In the previous article, we built a minimal agent:

  • One tool
  • In-memory conversation
  • A clean reasoning loop

Now we’re going to level it up.

This version introduces two major upgrades:

  1. Persistent memory across sessions
  2. Multiple tools with different capabilities

We are still using go-openai as our client library, compatible with OpenAI and ollama.

But now the agent feels much closer to something you’d actually deploy.

What’s new in this version?

Compared to the previous article, this main.go adds:

How to build an AI agent from scratch in Go

Hi, I’m Simone Vellei, you might remember me from such Go-and-AI adventures as “Leveraging Go and Redis for Efficient Retrieval Augmented Generation” and “Empowering Go: unveiling the synergy of AI and Q&A pipelines

I’m the creator of LinGoose, an open-source framework built to make developing AI-powered applications in Go clean, modular, and production-friendly. I built it because I love Go’s simplicity and performance, and I wanted the same elegance when working with large language models.

UMBRA - Secure, fragmented, redundant storage for the privacy conscious

Over the winter holidays, I built Umbra — a command-line tool that takes a different approach to storing sensitive files. The core idea? Use anonymous paste services — the kind typically used for sharing code snippets or logs — as a distributed storage backend for encrypted file fragments.

The Core Idea

Services like termbin, clbin, and paste.c-net.org are designed for quickly sharing text snippets anonymously — no accounts, no tracking, just paste and get a URL. But what if you could use these ephemeral, anonymous paste bins as a storage layer for sensitive files?

NATS as broker for my home server

One of my childhood memories is tied to my aunt’s habit of making pizza dough. It was her favorite way to relax. This might seem normal, except that she was a baker by profession. How ironic, isn’t it? The very job that could be a source of stress became her way to unwind. The funny thing is, after becoming a software developer, I found myself in the exact same situation. I love to code, but sometimes I need to do it to relax. And that’s exactly what happened when I started to develop my home server.

Running NATS on a FreeBSD Jail

Last few months I played with FreeBSD and my Rock64 embedded boards [1] [2]. I really enjoyed the experience and I wanted to go to the next level and experiment with FreeBSD jails. I was surprised how easy (and logical) it was to create and manage an isolated environment. I also noticed that the low level commands have been wrapped into a more user friendly interfaces (like bastille) making the whole experience more enjoyable. To have a real example of a microservice running on a jail, I decided to try with NATS.