# Po co stronie agent, który ją obsługuje

Notatka, 2026-10-27

Uważam, że strona bez wersji dla asystentów AI traci ponad połowę swojej wartości, a za kilka lat straci znacznie więcej. To moja teza i nie mam na nią badań. Z niej wzięła się ta strona: asystent może ją przeczytać, odpowiedzieć komuś na pytanie o to, co tu jest, i umówić ze mną rozmowę. Jak to działa w środku, opisałem w [osobnym wpisie](https://majlo.dev/blog/strona-dla-agentow). Tutaj jest o tym, po co mi to było i co nie wyszło.

## Skąd pomysł

Sam często szukam przez ChatGPT albo Claude'a. Kiedy strona nie jest przygotowana pod asystenta, robi się kłopot. Część treści bywa schowana za JavaScriptem, którego prosty czat nie uruchamia, więc po prostu jej nie widzi. Zauważyłem to przy geoportalu, kiedy szukałem danych o działce. Nie wszystko dało się odczytać wprost (chyba chodziło o ukształtowanie terenu, nie pamiętam dokładnie) i asystent musiał kombinować przez inne źródła.

Do tego ludzie coraz częściej wysyłają po coś agenta, zamiast klikać sami. Są już gotowe produkty do tego: Muse od Mety, Grok Bot od xAI, Gemini Spark od Google, dots od OpenAI i Claude Duet od Anthropic, który pokazano 21 października. Są też narzędzia dla programistów, jak Claude Code i Codex. Nie wierzę, że z tego kierunku jest odwrót. Programiści też prawie nie piszą już kodu ręcznie, bo robią to za nich agenci, i nikt do tego nie wróci.

Wyszukiwanie zmienia się tak samo. Kiedy ktoś szuka firmy, która coś robi, najpierw pyta ChatGPT. Google przestawiło wyszukiwarkę na AI, bo inaczej straciłoby ludzi właśnie na rzecz ChatGPT. Strona, której asystent nie umie przeczytać, w takim świecie po prostu nie istnieje.

Chciałem więc, żeby ktoś, kto chce ze mną pogadać, mógł wysłać na stronę asystenta. Niech przeczyta wszystko, opowie, co tu jest, i da odnośnik do mnie.

## Po co czat na stronie, skoro ludzie mają asystentów

Czat jest dla tych, którzy trafili tu bez asystenta, np. z filmu na YouTube albo z linku od znajomego. Mogą zapytać o coś wprost, zamiast szukać po blogu i poradnikach, i umówić rozmowę. Ktoś równie dobrze przeczyta to wszystko przez ChatGPT, ale ten czat to moje spojrzenie na sprawę, więc go dodałem.

Napędza go Ollama, czyli program, który udostępnia modele AI pod jednym adresem. Wybrałem ją z prostych powodów. Ma darmowe tokeny, a strona stoi na tej samej maszynie (VPS-ie), więc łączy się z nią bez żadnego klucza API. Ollama jest uwierzytelniona wcześniej i osobno, niezależnie od aplikacji. Model to Gemma 4 z 31 miliardami parametrów od Google. Jak na tak mały model jest według mnie bardzo dobry do rozmowy, choć nie do kodowania.

Model działa w chmurze Ollamy, więc nie obciąża mojego serwera. Najchętniej postawiłbym go u siebie, ale na moim VPS-ie odpowiadałby zbyt wolno. Jest też druga przeszkoda, gdy model ładuje się lokalnie: kilka rozmów naraz. Model załadowany do pamięci karty graficznej (albo zwykłej pamięci RAM, jeśli liczy procesor) potrzebuje obok miejsca na samą rozmowę, czyli kontekst. Żeby jeden model obsługiwał kilka rozmów jednocześnie, każda musi mieć swój kontekst zarezerwowany z góry. llama.cpp pozwala ustawić, ile takich równoległych rozmów jest naraz w pamięci. Przy hostingu w chmurze tego problemu nie mam.

## Co mi się nie udało

Najdłużej walczyłem o to, żeby wszystko działało też w zwykłym czacie, w przeglądarce. Poszły na to trzy wieczory debugowania. Z Codexem i Claude Code poszło dobrze od początku: sprawdzały terminy i rezerwowały bez problemu. Chciałem tego samego w ChatGPT w przeglądarce: piszę „umów mnie z Miłoszem”, a on umawia, bez żadnego klikania z mojej strony.

Tak się nie stało. Zwykły czat potrafi odczytywać strony, czyli wysyłać zapytania GET. W API zbudowanym według zasad REST każde zapytanie ma metodę. GET pobiera dane i niczego nie zmienia, a POST, PUT i DELETE tworzą, zmieniają albo usuwają. Rezerwacja to zapis, więc normalnie jest to POST z danymi w treści zapytania (`POST /api/v1/bookings`). Najpierw szukałem błędu u siebie, w endpoincie. Dopiero po kilku próbach okazało się, że to ograniczenie czata: takiego POST nie wyśle. Wynika to z moich testów, a o przyczynę zapytałem też samego czata, który zna swoją dokumentację: tak jest skonfigurowany.

Spróbowałem obejścia. Dodałem `GET /api/v1/book`, który robi to samo co POST, ale dane przyjmuje w adresie:

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

Każdy wolny termin ma gotowy `booking_link`. Asystent dopisuje do niego imię, e-mail i temat, a po zgodzie osoby otwiera adres. To łamie konwencję, bo GET tu coś zapisuje. Dlatego rezerwacja jest wstępna: blokuje termin na 30 minut i dopiero kliknięcie w mailu ją potwierdza. Ponowne otwarcie tego samego adresu nie robi drugiej rezerwacji, tylko zwraca `already_pending`.

W przeglądarkowym ChatGPT to i tak nie wystarczyło. Przy takim adresie pokazuje ostrzeżenie „Check this link is safe”, więc ostatnie kliknięcie robi człowiek. Dołożyłem dwa wyjścia awaryjne. Jeśli narzędzie blokuje adres z parametrami, asystent daje osobie gotowy link. Jeśli nie umie pobrać terminów, zapisuje jej dane po znaku `#` w adresie formularza (`/booking#name=…&email=…&topic=…`), a osoba wybiera już tylko godzinę.

Zostało więc tak: czat przeprowadza z osobą krótki wywiad, przygotowuje link z jej danymi i pokazuje przycisk, który trzeba kliknąć samemu. Pełnej rezerwacji bez ręki człowieka nie dostałem. Dołożyłem co mogłem, żeby było wygodnie: czat na stronie bez tych ograniczeń, gotowe polecenie do wklejenia i instrukcję krok po kroku.

Te ograniczenia stawiają dostawcy, nie ja. Podejrzewam, że środowiska typu Dots czy Gemini Spark załatwiłyby to bez problemu, ale nie mam do nich dostępu, więc to tylko przypuszczenie.

## Co zrobiłbym inaczej

Nic. Wiedziałem, co chcę zbudować, jak to ma działać i jaki ma być efekt, więc nie odkrywałem koła na nowo. Cel zrealizowałem, a to, co nie wyszło, leży po stronie dostawców. Więcej pracy widzę teraz w marketingu niż w technice, bo ktoś musi się o tej stronie dowiedzieć. Dobrze się przy tym bawię, bo nagrywam swoje przemyślenia, a z nich powstaje blog.

## Słowniczek

- **JavaScript**: Język programowania, dzięki któremu strona w przeglądarce reaguje na kliknięcia i zmienia się bez przeładowania.
- **agent**: Program oparty na modelu AI, który sam wykonuje zadania, np. szuka informacji, klika i zapisuje.
- **Muse**: Osobisty agent AI firmy Meta, który działa na własnym komputerze w chmurze, z własną przeglądarką.
- **Grok Bot**: Agent AI firmy xAI. Można tworzyć kilka nazwanych botów, każdy z osobną pamięcią.
- **Gemini Spark**: Agent AI od Google, który działa w chmurze całą dobę i np. pilnuje poczty i kalendarza.
- **dots**: Agent AI firmy OpenAI działający w ChatGPT, który ma własny komputer w chmurze i pracuje całą dobę.
- **Claude Duet**: Aplikacja z agentem AI firmy Anthropic, który sam podpowiada, co zrobić, np. układa terminy spotkań.
- **Claude Code**: Program firmy Anthropic, w którym asystent Claude pracuje na plikach i kodzie na twoim komputerze.
- **Codex**: Asystent AI firmy OpenAI, który pracuje na plikach na twoim komputerze: czyta je, zmienia i uruchamia programy.
- **Ollama**: Program, który uruchamia modele AI i udostępnia je innym programom pod jednym adresem.
- **VPS**: Wynajęty w sieci komputer, na którym działa strona, bez potrzeby trzymania go w domu.
- **API**: Interfejs, przez który jeden program prosi inny o dane albo o wykonanie czynności.
- **Gemma 4**: Model AI od Google, którego pliki można pobrać i uruchomić na własnym komputerze.
- **parametrów**: Liczby, w których model AI zapisuje to, czego się nauczył. Im ich więcej, tym model zwykle większy.
- **kontekst**: Pamięć rozmowy, w której model trzyma to, co już zostało napisane. Zajmuje miejsce w pamięci komputera.
- **llama.cpp**: Program do uruchamiania modeli AI na zwykłych komputerach. Pozwala ustawić, ile rozmów model obsługuje naraz.
- **REST**: Zasady, według których programy rozmawiają przez internet. Jedne zapytania pobierają dane, inne je zmieniają.
- **endpoint**: Adres w API, pod którym program przyjmuje jedno konkretne zapytanie, np. `/api/v1/bookings` do rezerwacji.
