# Why a website needs an agent to serve it

Note, 2026-10-27

I think a website without a version for AI assistants loses more than half of its value, and in a few years it will lose far more. That's my thesis and I have no research behind it. This site came out of it: an assistant can read it, answer a visitor's question about what's here, and book a call with me. How it works inside is in a [separate post](https://majlo.dev/en/blog/strona-dla-agentow). This one is about why I wanted it and what didn't work.

## Where the idea came from

I often search through ChatGPT or Claude myself. When a site isn't prepared for an assistant, there's trouble. Some content sits behind JavaScript, which a simple chat doesn't run, so it just doesn't see it. I noticed it with the Polish land registry geoportal while looking up data about a plot. Not everything could be read directly (I think it was the terrain shape, I don't remember exactly) and the assistant had to work around it through other sources.

On top of that, people increasingly send an agent instead of clicking around themselves. There are ready products for it: Muse from Meta, Grok Bot from xAI, Gemini Spark from Google, dots from OpenAI and Claude Duet from Anthropic, shown on 21 October. There are also tools for developers, such as Claude Code and Codex. I don't believe there's a way back from this. Programmers also hardly write code by hand anymore, because agents do it for them, and nobody will go back to that.

Search is changing the same way. When someone looks for a company that does something, they ask ChatGPT first. Google moved its search to AI because otherwise it would lose people to ChatGPT. In that world a page an assistant can't read simply doesn't exist.

So I wanted someone who'd like to talk to me to be able to send an assistant to the site. Let it read everything, tell them what's here, and give them a link to me.

## Why a chat on the site when people have assistants

The chat is for those who got here without an assistant, e.g. from a YouTube video or a link from a friend. They can ask about something directly instead of searching the blog and guides, and book a call. Someone could just as well read all of this through ChatGPT, but this chat is my take on it, so I added it.

It runs on Ollama, a program that serves AI models at a single address. I picked it for simple reasons. It has free tokens, and the site lives on the same machine (a VPS), so it connects without any API key. Ollama is signed in beforehand and separately, independent of the app. The model is Google's Gemma 4 with 31 billion parameters. For such a small model I think it's very good at conversation, though not at coding.

The model runs in Ollama's cloud, so it doesn't load my server. I'd rather host it myself, but on my VPS it would answer too slowly. There's a second obstacle when a model is loaded locally: several conversations at once. A model loaded into graphics card memory (or ordinary RAM, if a processor does the work) needs room next to it for the conversation itself, the context. For one model to serve several conversations at once, each needs its own context reserved up front. llama.cpp lets you set how many of these parallel conversations sit in memory at once. With cloud hosting I don't have this problem.

## What didn't work

I fought longest to make everything work in a regular chat in the browser too. It took three evenings of debugging. With Codex and Claude Code it went well from the start: they checked slots and booked with no trouble. I wanted the same in ChatGPT in the browser: I write "book me with Miłosz" and it books, with no clicking on my side.

That didn't happen. A regular chat can read pages, meaning it sends GET requests. In an API built on REST principles every request has a method. GET fetches data and changes nothing, while POST, PUT and DELETE create, change or delete. A booking is a write, so normally it's a POST with the details in the request body (`POST /api/v1/bookings`). First I looked for a bug on my side, in the endpoint. Only after several attempts did it turn out to be a limit of the chat: it won't send such a POST. That comes from my tests, and I also asked the chat itself why, since it knows its own documentation: it's configured that way.

I tried a workaround. I added `GET /api/v1/book`, which does the same as the POST but takes the details in the address:

```
https://majlo.dev/api/v1/book?slot_start=…&timezone=…&name=…&email=…&topic=…
```

Every free slot has a ready `booking_link`. The assistant appends the name, email and topic to it and, with the person's consent, opens the address. That breaks the convention, because here GET writes something. So the booking is provisional: it holds the slot for 30 minutes and only a click in the email confirms it. Opening the same address again doesn't make a second booking, it returns `already_pending`.

In the browser version of ChatGPT that still wasn't enough. With such an address it shows a "Check this link is safe" warning, so the last click is made by a human. I added two fallbacks. If the tool blocks an address with parameters, the assistant gives the person the complete link. If it can't fetch slots at all, it saves the person's details after the `#` in the form's address (`/booking#name=…&email=…&topic=…`) and they only pick a time.

So it stayed like this: the chat runs a short interview with the person, prepares a link with their details and shows a button they have to click themselves. I didn't get a full booking with no human hand. I added what I could to make it comfortable: a chat on the site without these limits, a ready-made prompt to paste, and step-by-step instructions.

The providers set these limits, I didn't. I suspect agent environments like Dots or Gemini Spark would handle it with no problem, but I don't have access to them, so that's only a guess.

## What I'd do differently

Nothing. I knew what I wanted to build, how it should work and what the end result should be, so I didn't reinvent the wheel. I reached the goal, and what didn't work is on the providers' side. These days I see more work in marketing than in the technology, because someone has to find out the site exists. I enjoy it, because I record my thoughts and the blog is made from them.

## Glossary

- **JavaScript**: A programming language that makes a web page react to clicks and change without reloading.
- **agent**: A program built on an AI model that carries out tasks on its own, e.g. searches for information, clicks and saves.
- **Muse**: Meta's personal AI agent, which works on its own computer in the cloud, with its own browser.
- **Grok Bot**: An AI agent from xAI. You can create several named bots, each with its own memory.
- **Gemini Spark**: An AI agent from Google that runs in the cloud around the clock and, for example, watches your email and calendar.
- **dots**: An AI agent from OpenAI that lives in ChatGPT, has its own computer in the cloud and works around the clock.
- **Claude Duet**: An app with an AI agent from Anthropic that suggests what to do on its own, e.g. plans meeting times.
- **Claude Code**: Anthropic's program in which the Claude assistant works on files and code on your computer.
- **Codex**: OpenAI's AI assistant that works on files on your computer: it reads and changes them and runs programs.
- **Ollama**: A program that runs AI models and makes them available to other programs at a single address.
- **VPS**: A computer rented online where the website runs, so you don't have to keep one at home.
- **API**: An interface through which one program asks another for data or to do something.
- **Gemma 4**: An AI model from Google whose files you can download and run on your own computer.
- **parameters**: The numbers in which an AI model stores what it has learned. The more there are, the bigger the model usually is.
- **context**: The conversation's memory, where the model keeps what has already been written. It takes up space in the computer's memory.
- **llama.cpp**: A program for running AI models on ordinary computers. It lets you set how many conversations a model handles at once.
- **REST**: Rules by which programs talk over the internet. Some requests fetch data, others change it.
- **endpoint**: An address in an API where a program accepts one specific kind of request, e.g. `/api/v1/bookings` for bookings.
