Jak przygotować jeden produkt B2B do sprzedaży przez agenty AI

Case study wdrożeniowy: jak przygotować jeden produkt B2B do sprzedaży przez agenty AI

Produkt: folia stretch ręczna transparentna 50 cm, 23 µm, 3,3 kg brutto (PakShop, Warszawa)

Materiał pokazowy SalesBot.pl. Dane produktu za stroną pakshop.pl (stan na 09.07.2026). Wartości logistyczne oznaczone jako „przykładowe” służą ilustracji metody — w realnym wdrożeniu pobiera się je z ERP/cennika klienta.


Dlaczego akurat ten produkt

Bo jest „nudny” i typowy — dokładnie taki, jaki kupują agenty B2B masowo i bez emocji. Folia stretch to towar transakcyjny, powtarzalny, o niskiej wartości jednostkowej i wysokim wolumenie (tzw. tail spend), czyli pierwsza kategoria, którą działy zakupów oddają agentom. Jeśli ten SKU nie jest czytelny dla maszyny, wypada z porównania, zanim ktokolwiek spojrzy na cenę.


Krok 1. Punkt wyjścia — jak dziś widzi tę stronę agent (Stan 0)

Strona jest dobra dla człowieka: ma opis, parametry w formie listy, cenę, adres odbioru, telefon. Ale dla agenta kupującego to ściana z kilkoma krytycznymi blokadami:

Co widzi człowiekCo widzi (albo czego nie widzi) agent
„Cena orientacyjna: 32,00 zł netto / rolka”Cena niewiążąca — strona wprost zastrzega, że „nie stanowi oferty handlowej w rozumieniu Kodeksu Cywilnego”. Agent nie może na niej oprzeć decyzji zakupowej.
„Dostępna od ręki”Brak maszynowego stanu magazynowego (ile sztuk, do kiedy gwarantowane). „Od ręki” to nie liczba.
Formularz zapytania (RFQ)Formularz wymaga JavaScriptu („włącz obsługę JavaScript”) — agent bez wykonywania JS nie złoży zapytania. Ścieżka akcji urwana.
Parametry: 50 cm, 23 µm, 3,3 kgParametry są w tekście/liście, ale bez schema.org/JSON-LD, bez SKU, bez GTIN, bez jednostek maszynowych. Trudne do jednoznacznego sparsowania i porównania.
„Dostawa za dodatkową opłatą”TCO niepoliczalne: brak progów kurier/paleta, kosztu dostawy, wagi netto folii i wydajności (m²). Agent optymalizujący koszt całkowity nie ma z czego liczyć.
Brak feedu (JSONL / Merchant Center), brak endpointu MCP, brak llms.txt. Produkt nie istnieje w kanałach, którymi agent się porusza.

Diagnoza: produkt jest na etapie findable dla ludzi, ale nie executable dla agentów. W świecie agentowym „findable” daje bycie rozważanym, dopiero „executable” daje bycie wybranym.


Krok 2. Symulacja — zadanie dla agenta kupującego dziś

Zadanie od kupca: „Kup 50 rolek folii stretch ręcznej, min. 50 cm / 23 µm, do magazynu w Warszawie. Dostawa lub odbiór w 48 h. Budżet do 40 zł netto/rolka. Zwróć TCO i termin gwarancji ceny.”

Przebieg na Stanie 0:

  1. Agent znajduje stronę w wyszukiwaniu (SEO jest OK).
  2. Odczytuje cenę 32 zł netto — ale wykrywa zastrzeżenie „nie oferta handlowa” → oznacza pozycję jako niepewną.
  3. Chce potwierdzić dostępność 50 szt. i termin → brak danych maszynowych.
  4. Próbuje złożyć RFQ → formularz za JS, akcja niemożliwa bez człowieka.
  5. Nie może policzyć TCO (dostawa nieokreślona).
  6. Wynik: agent zwraca „cena orientacyjna, wymaga kontaktu ręcznego” i przechodzi do konkurencji, która oddaje wiążącą ofertę maszynowo. PakShop wypada z shortlisty mimo dobrej ceny.

To jest dokładnie ten scenariusz, w którym dobra oferta przegrywa z gorszą, ale czytelną dla maszyny.


Krok 3. Wdrożenie warstwa po warstwie

Warstwa 1 — porządek danych i atrybuty (fundament)

Uzupełniamy i strukturyzujemy dane tego SKU. Kluczowe braki do dodania:

  • Identyfikatory: SKU (np. FSR-50-23-T), GTIN (jeśli jest), MPN.
  • Jednostki maszynowe: szerokość 500 mm, grubość 23 µm, waga brutto 3,3 kg — plus brakujące, a krytyczne dla TCO: waga netto folii (bez gilzy), wydajność (m² lub mb na rolce), liczba rolek w kartonie/na palecie.
  • Ceny per kontekst: cena katalogowa vs progi ilościowe (np. od 1 palety), cena kontraktowa per klient.
  • TCO/logistyka jako dane, nie PDF: próg darmowej dostawy, próg kurier→paleta (np. maks. rolek w paczce kurierskiej), waga gabarytowa, strefa dostawy, koszt odbioru własnego = 0.
  • Warunki: termin ważności oferty (guaranteed_until), termin realizacji (lead time), forma płatności B2B (przelew/faktura), status merchant of record.

Warstwa 2 — odkrywalność (schema.org / feed / llms.txt)

Dodajemy do strony JSON-LD Product + Offer, żeby maszyna czytała parametry i cenę jednoznacznie:

{
  "@context": "https://schema.org/",
  "@type": "Product",
  "name": "Folia stretch ręczna transparentna 50 cm, 23 µm",
  "sku": "PAKSHOP-FSR-50-23-T",
  "mpn": "FSR-50-23-T",
  "brand": { "@type": "Brand", "name": "PakShop" },
  "category": "Folia stretch ręczna",
  "image": "https://pakshop.pl/wp-content/uploads/2026/07/Folia-reczna-PakShop-1024x1024.jpg",
  "url": "https://pakshop.pl/folia-stretch-transparentna-50-cm-33-kg-warszawa-pakshop/",
  "description": "Transparentna folia stretch do pakowania ręcznego paczek, kartonów i palet. Szerokość 50 cm, grubość 23 µm, waga brutto rolki 3,3 kg.",
  "additionalProperty": [
    { "@type": "PropertyValue", "name": "Szerokość", "value": 500, "unitCode": "MMT", "unitText": "mm" },
    { "@type": "PropertyValue", "name": "Grubość", "value": 23, "unitCode": "4H", "unitText": "µm" },
    { "@type": "PropertyValue", "name": "Waga brutto rolki", "value": 3.3, "unitCode": "KGM", "unitText": "kg" },
    { "@type": "PropertyValue", "name": "Waga netto folii", "value": 2.5, "unitCode": "KGM", "unitText": "kg", "description": "wartość przykładowa — uzupełnić z danych producenta" },
    { "@type": "PropertyValue", "name": "Kolor", "value": "transparentny" },
    { "@type": "PropertyValue", "name": "Typ", "value": "ręczna" }
  ],
  "offers": {
    "@type": "Offer",
    "priceCurrency": "PLN",
    "price": 32.00,
    "priceSpecification": {
      "@type": "UnitPriceSpecification",
      "price": 32.00,
      "priceCurrency": "PLN",
      "valueAddedTaxIncluded": false,
      "referenceQuantity": { "@type": "QuantitativeValue", "value": 1, "unitText": "rolka" }
    },
    "priceValidUntil": "2026-07-31",
    "availability": "https://schema.org/InStock",
    "inventoryLevel": { "@type": "QuantitativeValue", "value": 480, "unitText": "rolka" },
    "areaServed": { "@type": "City", "name": "Warszawa" },
    "availableAtOrFrom": {
      "@type": "Place",
      "name": "PakShop Warszawa-Wawer",
      "address": {
        "@type": "PostalAddress",
        "streetAddress": "ul. Ochocza 2",
        "postalCode": "04-942",
        "addressLocality": "Warszawa",
        "addressCountry": "PL"
      }
    },
    "seller": { "@type": "Organization", "name": "PakShop", "url": "https://pakshop.pl" }
  }
}

Do tego:

  • llms.txt w katalogu głównym, wskazujący kartę produktu i kartę kategorii „folia stretch ręczna” jako strony autorytatywne.
  • Feed (JSONL) z tym SKU dla kanałów agentowych, aktualizowany z ERP (stan + cena).
  • robots.txt przepuszcza GPTBot, ClaudeBot, PerplexityBot, Google-Extended; treść renderowana serwerowo (bez blokady JS na kluczowych danych).

Warstwa 3 — wykonywalność (serwer MCP)

To jest serce wdrożenia: serwer MCP, który wystawia realne akcje na żywych danych z ERP (Comarch/Symfonia/Subiekt/SAP). Agent odpytuje narzędzia zamiast scrapować stronę:

{
  "server": "pakshop-commerce",
  "tools": [
    {
      "name": "search_products",
      "description": "Wyszukuje produkty po parametrach (typ, szerokość, grubość, kolor).",
      "input_schema": {
        "type": "object",
        "properties": {
          "query": { "type": "string" },
          "width_mm": { "type": "integer" },
          "thickness_um": { "type": "integer" }
        }
      }
    },
    {
      "name": "get_offer",
      "description": "Zwraca WIĄŻĄCĄ ofertę dla SKU i ilości, z ceną per klient, TCO i terminem gwarancji.",
      "input_schema": {
        "type": "object",
        "required": ["sku", "quantity", "delivery_postal_code"],
        "properties": {
          "sku": { "type": "string" },
          "quantity": { "type": "integer" },
          "delivery_postal_code": { "type": "string" },
          "client_tax_id": { "type": "string", "description": "NIP — dla cen kontraktowych" }
        }
      }
    },
    {
      "name": "check_availability",
      "description": "Zwraca stan magazynowy i najbliższy termin realizacji dla ilości.",
      "input_schema": {
        "type": "object",
        "required": ["sku", "quantity"],
        "properties": {
          "sku": { "type": "string" },
          "quantity": { "type": "integer" }
        }
      }
    },
    {
      "name": "create_rfq",
      "description": "Tworzy zapytanie ofertowe / rezerwację; zwraca numer i status.",
      "input_schema": {
        "type": "object",
        "required": ["sku", "quantity", "buyer_tax_id", "delivery"],
        "properties": {
          "sku": { "type": "string" },
          "quantity": { "type": "integer" },
          "buyer_tax_id": { "type": "string" },
          "delivery": { "type": "object" },
          "needed_by": { "type": "string", "format": "date-time" }
        }
      }
    }
  ]
}

Zasady bezpieczeństwa od pierwszego dnia: least privilege, tokeny o wąskim zakresie z TTL, RBAC, whitelisting i audit logging. Agent dostaje get_offer i check_availability (read), a create_rfq z ograniczeniami — nigdy klucza systemowego do całego ERP.

Warstwa 4 — transakcyjność i zgodność (PL/UE)

  • Wiążąca oferta zamiast „ceny orientacyjnej”. To rozwiązuje problem prawny ze Stanu 0: get_offer zwraca ofertę z guaranteed_until, którą można świadomie skonstruować jako ofertę w rozumieniu KC (lub jako zaproszenie z jasnym mechanizmem potwierdzenia) — decyzja biznesowo-prawna, ale maszynowo jednoznaczna.
  • Płatność B2B zgodna z PSD2/SCA. W B2B naturalne są przelew/faktura z terminem, a nie karta — to omija część barier SCA dla płatności autonomicznych i pasuje do procesu akceptacji po stronie kupca.
  • Merchant of record zostaje PakShop — relacja z klientem i faktura po stronie sprzedawcy, agent jest tylko pełnomocnikiem kupującego.

Krok 4. Konkretny artefakt — odpowiedź, którą dostaje agent

Tak wygląda wiążąca odpowiedź z get_offer dla scenariusza „50 rolek, dostawa 04-xxx Warszawa” (wartości logistyczne przykładowe):

{
  "sku": "PAKSHOP-FSR-50-23-T",
  "product": "Folia stretch ręczna transparentna 50 cm / 23 µm",
  "quantity": 50,
  "unit": "rolka",
  "pricing": {
    "unit_net_pln": 32.00,
    "line_net_pln": 1600.00,
    "currency": "PLN",
    "vat_rate": 0.23,
    "guaranteed_until": "2026-07-19T23:59:59+02:00"
  },
  "availability": {
    "in_stock": true,
    "on_hand_qty": 480,
    "ready_to_ship": true
  },
  "tco": {
    "delivery_mode": "kurier",
    "delivery_threshold_note": "powyżej 33 rolek → paleta; poniżej → kurier (wartości przykładowe)",
    "delivery_net_pln": 60.00,
    "pickup_option": { "available": true, "cost_pln": 0, "location": "Warszawa-Wawer, ul. Ochocza 2" },
    "landed_unit_net_pln": 33.20,
    "landed_total_net_pln": 1660.00
  },
  "logistics": {
    "lead_time_hours": 24,
    "delivery_area": "Warszawa",
    "rolls_per_pallet": 33
  },
  "terms": {
    "payment": "przelew / faktura VAT, termin 14 dni",
    "merchant_of_record": "PakShop",
    "binding": true
  },
  "rfq_endpoint": "mcp://pakshop-commerce/create_rfq"
}

Zwróć uwagę na to, co się zmieniło względem Stanu 0: cena jest wiążąca i datowana, TCO policzone (koszt jednostkowy z dostawą = 33,20 zł, wciąż poniżej budżetu 40 zł), stan liczbowy, a ścieżka RFQ wykonywalna maszynowo.


Krok 5. Ten sam scenariusz po wdrożeniu (Stan 3)

  1. Agent odpytuje search_products(width_mm=500, thickness_um=23) → trafia na SKU.
  2. check_availability(sku, 50) → 480 szt. na stanie, realizacja 24 h. ✅
  3. get_offer(sku, 50, "04-942", client_tax_id) → wiążąca cena, guaranteed_until, TCO 33,20 zł/rolka. ✅ (poniżej budżetu)
  4. create_rfq(...) → numer zapytania + status „zarezerwowano do 2026-07-19″.
  5. Wynik: PakShop wchodzi na shortlist i wygrywa — ma najniższe TCO i jest jedynym dostawcą, u którego agent domknął ścieżkę bez człowieka.

Efekt wdrożenia (co mierzymy)

  • Widoczność w shortlistach agentów — z „pomijany” (cena niewiążąca, akcja urwana) do „wybierany”. Strony na „Stanie 0″ bywają pomijane w agentowych shortlistach istotnie częściej niż przygotowane.
  • Czas odpowiedzi na RFQ — z godzin pracy handlowca do sekund (agent ↔ MCP).
  • Błędy transakcyjne — spadek dzięki jednoznacznym danym (cena, jednostki, stan) zamiast parsowania tekstu.
  • Przewaga TCO — policzalny koszt całkowity wygrywa u agentów optymalizujących koszt, nawet gdy cena jednostkowa nie jest najniższa.
  • Kontrola — PakShop zostaje merchant of record, zachowuje relację z klientem i fakturowanie.

Mapa wdrożenia dla jednego SKU (skrót operacyjny)

  1. Uzupełnij atrybuty (SKU/GTIN, waga netto, wydajność, rolki/paleta, progi dostawy).
  2. Dodaj JSON-LD Product+Offer na kartę produktu; dodaj llms.txt; przepuść crawlery AI; usuń zależność kluczowych danych i RFQ od JS.
  3. Postaw serwer MCP na katalog/stan/cenę (read-only), spięty z ERP.
  4. Dołóż get_offer z guaranteed_until i TCO oraz create_rfq.
  5. Ustal warunki B2B (płatność przelew/faktura, PSD2/SCA, merchant of record).
  6. Przetestuj „oczami agenta” (ChatGPT/Claude/Perplexity/Gemini + własny agent) na realnym zadaniu zakupowym i zmierz, gdzie się wykłada.
  7. Skaluj wzorzec na całą kategorię „folia stretch”, potem na resztę katalogu.

Uwaga: to nie jest greenfield

PakShop ma już elementy tej układanki (m.in. „agent-ready Click & Buy” dla owijarki, PakBot, publikowane Case RFQ). Ten case pokazuje, jak domknąć brakujące warstwy na pojedynczym, typowym SKU — bo skala bierze się z powtórzenia tego wzorca, nie z jednorazowego wielkiego projektu.


Opracowano dla SalesBot.pl. Standardy: schema.org / JSON-LD · MCP (Linux Foundation) · ACP/UCP (warstwa handlowa) · AP2 (płatności). Wartości logistyczne przykładowe — w realnym wdrożeniu z ERP klienta.


synthosa.pl * kontakt@synthosa.pl


Synthosa