A propos Compétences Expérience Services Blog Contact

Reconstruis-le pour le comprendre : des protocoles réseau aux agents LLM Rebuild it to understand it: from network protocols to LLM agents

TL;DR : tu ne comprends vraiment un système qu'en le reconstruisant. J'ai recodé TCP à l'école, puis le protocole DNS, puis Modbus, à chaque fois pour comprendre de l'intérieur. Un collègue vient de vivre ça avec les LLM. Il a écrit un petit agent en Go, et il a enfin compris le tooling et la fenêtre de contexte. Un LLM n'est qu'un système de plus à démystifier. Reconstruis-en une version minuscule, et tu passes d'utilisateur à ingénieur.

Pour les devs qui veulent maîtriser les LLM, pas seulement les utiliser.

Un collègue, un agent en Go, un déclic

Cette semaine, j'aide un collègue à monter en compétence sur les LLM. Je lui explique les concepts. Le contexte, les tokens, les outils. Un token est un petit morceau de texte que le modèle lit et compte. Il écoute, mais quelque chose ne clique pas.

Puis il revient, tout content. Il a écrit une petite CLI en Go. Une simple boucle de chat qui appelle un modèle et exécute ses outils. Et là, il comprend. Le tooling, la fenêtre de contexte, la boucle. Pas parce que je lui ai expliqué. Parce qu'il l'a reconstruit.

Ce déclic, je le connais par cœur. Je l'ai vécu plusieurs fois, sur d'autres sujets. Toujours la même méthode. Pour comprendre un truc, je le reconstruis.

On ne comprend un système qu'en le reconstruisant

Lire une doc te donne une carte. Reconstruire te donne le terrain. Ce n'est pas pareil. La carte dit « il y a une rivière ici ». Le terrain te fait sentir le courant.

Quand tu réécris un système, tu ne peux plus tricher. Chaque octet doit être à sa place. Chaque cas limite te tombe dessus. Tu ne crois plus comprendre. Tu comprends, ou ton code ne marche pas.

Ce n'est pas un exercice d'école. C'est l'inverse. Tu reconstruis pour agir mieux ensuite. Déboguer plus vite. Détourner l'outil. Bâtir ce qu'aucune lib toute faite ne te donne.

TCP en C : la première fois

La toute première fois, c'était à l'école, en C. J'ai recodé des morceaux de TCP et d'UDP. Le fameux handshake en trois temps. Et le parsing des en-têtes, champ par champ.

TCP ouvre une connexion en trois messages. SYN, SYN-ACK, ACK. Avant, c'était une phrase dans un cours. Après, c'était des octets que je posais moi-même dans un paquet.

Je n'ai rien inventé. Le protocole existait déjà depuis quarante ans. Mais le refaire a changé ma vision du réseau. Depuis, une capture réseau n'est plus un mystère. C'est un format que j'ai déjà écrit à la main.

DNS : recoder le protocole pour détourner ses sous-domaines

Plus tard, je m'attaque au DNS. Le DNS traduit un nom comme jrobineau.com en adresse IP. Je l'ai réécrit moi-même, en Go. Le header, les questions, les réponses, octet par octet.

En le reconstruisant, tu tombes sur un détail que la doc survole. Un nom de domaine est une suite de labels. Chaque label est précédé de sa longueur. « www », c'est un 3, puis w, w, w.

Et là, une idée arrive. Si je contrôle les labels, je contrôle des octets. Je peux glisser mes propres données dans un sous-domaine. C'est le principe de l'exfiltration DNS, dans un cadre de sécurité autorisé.

Mon serveur reçoit la requête, parse le nom, et récupère les données cachées dedans. J'ai même géré la compression des noms, un coin tordu du protocole. Aucune lib clé en main ne m'aurait montré ça. Le reconstruire, si.

Modbus : reconstruire pour savoir qui a le bug

Sur une mission avec du matériel industriel, on parlait Modbus. Modbus est un vieux protocole qui pilote automates et capteurs. La lib qu'on utilisait était mauvaise. Beaucoup de bugs, beaucoup de comportements bizarres.

Impossible de savoir d'où venait le mal. Du protocole ? De la lib ? De notre code ? Alors j'ai fait la seule chose qui tranche. J'ai recodé Modbus moi-même, en Go.

Verdict : le protocole était sain. Le coupable, c'était la lib. Et une fois le protocole reconstruit, le vrai bénéfice est arrivé. Je pouvais bâtir des outils autour, à ma façon.

J'en ai tiré une petite lib Go avec une API à la Gin. Tu déclares un handler par plage de registres. Tu ajoutes des middlewares de log et de recovery. Un protocole industriel de 1979, avec le confort d'un framework web. Ça, c'est détourner la connaissance à son besoin.

Un LLM, c'est un système de plus à reconstruire

Reviens aux LLM. En 2026, on nous vend l'IA comme une magie. Une boîte noire à qui on parle. Et on reste utilisateur, un peu passif, un peu à sa merci.

Mais un agent LLM n'a rien de magique. C'est une boucle. Tu envoies des messages au modèle. Il répond, parfois en réclamant un outil. Tu exécutes l'outil. Tu renvoies le résultat. Et tu recommences.

La fenêtre de contexte, c'est tout ce que le modèle voit à cet instant. Ta boucle décide quoi mettre dedans, et quoi jeter. Le modèle ne se souvient de rien. C'est toi qui lui redonnes le passé à chaque tour.

Voici la boucle entière, en Go. Enlève le vernis, il ne reste que ça.

func runAgent(ctx context.Context, client LLM, tools map[string]Tool, goal string) (string, error) {
	// La fenetre de contexte, c'est cette liste. Toi seul la remplis.
	msgs := []Message{{Role: "user", Content: goal}}

	for {
		// 1. Tu envoies tout le contexte au modele.
		reply, err := client.Complete(ctx, msgs, tools)
		if err != nil {
			return "", err
		}
		msgs = append(msgs, reply)

		// 2. Pas d'outil demande ? Le modele a fini, tu sors.
		if len(reply.ToolCalls) == 0 {
			return reply.Content, nil
		}

		// 3. Tu executes chaque outil toi-meme, pas le modele.
		for _, call := range reply.ToolCalls {
			out := tools[call.Name].Run(ctx, call.Args)
			// 4. Tu renvoies le resultat dans le contexte. On reboucle.
			msgs = append(msgs, Message{Role: "tool", Content: out})
		}
	}
}

Une fois que tu as écrit ça, la peur tombe. Un « agent », c'est cette boucle plus quelques bons outils. Le tool calling, c'est juste le modèle qui te dit quelle fonction appeler. Rien de plus.

Reconstruire, oui, mais pas tout, pas pour toujours

Le but n'est pas de tout réécrire à vie. Je ne mets pas ma pile TCP maison en production. J'utilise celle du système, et j'ai raison de le faire.

Tu reconstruis une fois, pour comprendre. Ensuite tu fais confiance, parce que tu sais ce qu'il y a dans la boîte. C'est une confiance gagnée, pas une confiance aveugle.

Reconstruis quand l'enjeu est fort. Un protocole au cœur de ton produit. Un outil que tu vas déboguer souvent. Une techno neuve, comme les LLM, où tout le monde reste en surface. C'est là que comprendre paie.

La checklist pour apprendre une techno en la reconstruisant

La prochaine techno qui t'impressionne, ne te contente pas de l'utiliser. Reconstruis-en un bout.

  • Vise le cœur, pas le confort. La boucle d'agent, pas toute l'API du fournisseur
  • Fais-le en petit. Une CLI, un fichier, un après-midi suffisent souvent
  • Écris le format à la main une fois. Les octets t'apprennent ce que la doc cache
  • Cherche le détail qui débloque. Les labels DNS, la boucle du contexte
  • Casse-le exprès. Tu vois vite où sont les limites et les pièges
  • Une lib te déçoit ? Reconstruis pour savoir qui porte vraiment le bug
  • Une fois compris, détourne. Bâtis l'outil que les libs toutes faites ne donnent pas
  • Puis lâche ta version jouet. Reprends la lib de prod, avec un vrai modèle mental

Ce qu'il faut retenir

Le mojo du dev n'a pas bougé. Utiliser un outil sans le comprendre, c'est rester à sa merci. Le reconstruire, même en jouet, c'est reprendre la main.

TCP, DNS, Modbus, un agent LLM. À chaque fois, la même méthode. Reconstruis pour comprendre. Comprends pour détourner. Les LLM sont juste le prochain système sur la liste.

Tu formes une équipe aux LLM, ou tu veux du backend Go qui tient la route ? C'est mon métier. Écris-moi. On ne subit pas les outils. On les comprend.

TL;DR: you only truly understand a system once you rebuild it. I recoded TCP at school, then the DNS protocol, then Modbus, each time to understand it from the inside. A colleague just went through this with LLMs. He wrote a small agent in Go, and he finally understood tooling and the context window. An LLM is just one more system to demystify. Rebuild a tiny version, and you move from user to engineer.

For developers who want to master LLMs, not just use them.

A colleague, a Go agent, a click

This week, I am helping a colleague level up on LLMs. I explain the concepts. Context, tokens, tools. A token is a small piece of text the model reads and counts. He listens, but something does not click.

Then he comes back, delighted. He wrote a small CLI in Go. A plain chat loop that calls a model and runs its tools. And now he gets it. The tooling, the context window, the loop. Not because I explained it. Because he rebuilt it.

I know that click by heart. I have felt it many times, on other topics. Always the same method. To understand something, I rebuild it.

You only understand a system by rebuilding it

Reading the docs gives you a map. Rebuilding gives you the terrain. They are not the same. The map says "there is a river here". The terrain lets you feel the current.

When you rewrite a system, you can no longer bluff. Every byte has to sit in the right place. Every edge case lands on you. You do not think you understand. You understand, or your code fails.

This is not an academic exercise. It is the opposite. You rebuild to act better afterward. To debug faster. To bend the tool. To build what no off-the-shelf library gives you.

TCP in C: the first time

The very first time was at school, in C. I recoded pieces of TCP and UDP. The famous three-step handshake. And header parsing, field by field.

TCP opens a connection in three messages. SYN, SYN-ACK, ACK. Before, that was one line in a lecture. After, it was bytes I placed into a packet myself.

I invented nothing. The protocol had existed for forty years. But redoing it changed how I see the network. Since then, a packet capture is no mystery. It is a format I have written by hand.

DNS: recode the protocol to bend its subdomains

Later, I took on DNS. DNS turns a name like jrobineau.com into an IP address. I rewrote it myself, in Go. The header, the questions, the answers, byte by byte.

Rebuilding it, you hit a detail the docs gloss over. A domain name is a series of labels. Each label is prefixed by its length. "www" is a 3, then w, w, w.

And then an idea shows up. If I control the labels, I control bytes. I can slip my own data into a subdomain. That is the principle of DNS exfiltration, in an authorized security context.

My server receives the query, parses the name, and recovers the data hidden inside. I even handled name compression, a nasty corner of the protocol. No ready-made library would have shown me that. Rebuilding it did.

Modbus: rebuild it to find who owns the bug

On a job with industrial hardware, we spoke Modbus. Modbus is an old protocol that drives controllers and sensors. The library we used was bad. Many bugs, much strange behavior.

There was no way to tell where the pain came from. The protocol? The library? Our code? So I did the one thing that settles it. I recoded Modbus myself, in Go.

The verdict: the protocol was fine. The culprit was the library. And once the protocol was rebuilt, the real payoff arrived. I could build tools around it, my way.

I turned it into a small Go library with a Gin-like API. You declare a handler per register range. You add logging and recovery middleware. A 1979 industrial protocol, with the comfort of a web framework. That is bending knowledge to your need.

An LLM is one more system to rebuild

Back to LLMs. In 2026, AI is sold as magic. A black box you talk to. And you stay a user, a bit passive, a bit at its mercy.

But an LLM agent is not magic. It is a loop. You send messages to the model. It replies, sometimes asking for a tool. You run the tool. You send the result back. And you start again.

The context window is everything the model sees right now. Your loop decides what goes in, and what to drop. The model remembers nothing. You are the one who feeds it the past on every turn.

Here is the whole loop, in Go. Strip the varnish, and only this is left.

func runAgent(ctx context.Context, client LLM, tools map[string]Tool, goal string) (string, error) {
	// The context window is this list. You alone fill it.
	msgs := []Message{{Role: "user", Content: goal}}

	for {
		// 1. You send the whole context to the model.
		reply, err := client.Complete(ctx, msgs, tools)
		if err != nil {
			return "", err
		}
		msgs = append(msgs, reply)

		// 2. No tool requested? The model is done, you return.
		if len(reply.ToolCalls) == 0 {
			return reply.Content, nil
		}

		// 3. You run each tool yourself, not the model.
		for _, call := range reply.ToolCalls {
			out := tools[call.Name].Run(ctx, call.Args)
			// 4. You feed the result back into the context. Loop again.
			msgs = append(msgs, Message{Role: "tool", Content: out})
		}
	}
}

Once you have written this, the fear fades. An "agent" is this loop plus a few good tools. Tool calling is just the model telling you which function to call. Nothing more.

Rebuild, yes, but not everything, not forever

The goal is not to rewrite everything for life. I do not ship my own TCP stack to production. I use the system's, and I am right to.

You rebuild once, to understand. Then you trust, because you know what is in the box. It is earned trust, not blind trust.

Rebuild when the stakes are high. A protocol at the core of your product. A tool you will debug often. A new tech, like LLMs, where everyone stays on the surface. That is where understanding pays.

The checklist for learning a tech by rebuilding it

The next tech that impresses you, do not just use it. Rebuild a piece of it.

  • Aim at the core, not the comfort. The agent loop, not the whole vendor API
  • Keep it small. A CLI, one file, an afternoon are often enough
  • Write the format by hand once. The bytes teach what the docs hide
  • Hunt for the unlocking detail. DNS labels, the context loop
  • Break it on purpose. You quickly see the limits and the traps
  • A library lets you down? Rebuild to learn who really owns the bug
  • Once you get it, bend it. Build the tool no ready-made library gives you
  • Then drop your toy version. Go back to the production library, with a real mental model

What to remember

The dev mojo has not changed. Using a tool without understanding it means staying at its mercy. Rebuilding it, even as a toy, takes back control.

TCP, DNS, Modbus, an LLM agent. Every time, the same method. Rebuild to understand. Understand to bend. LLMs are simply the next system on the list.

Training a team on LLMs, or want Go backend that holds up? That is what I do. Write to me. We do not suffer our tools. We understand them.