Claude Agents SDK: subagenci, skills, hooks i pamięć projektu (przewodnik z realnymi plikami)
Damian GębalaAutorClaude Agents SDK to biblioteka, która daje Ci ten sam silnik agentowy, który napędza Claude Code, tylko sterowany z kodu zamiast z terminala. Subagenci, skills i hooki działają tak samo, ale opisujesz je plikami w repozytorium i regułami w konfiguracji. Poniżej konkretne pliki: co w nich jest, gdzie leżą i która różnica między nimi najczęściej się myli.
Czym jest Claude Agents SDK i kiedy warto po niego sięgnąć
Oficjalna nazwa brzmi Claude Agent SDK. Nazwa Claude Code SDK, którą spotkasz w starszych materiałach, to ta sama biblioteka przed zmianą - Anthropic przemianowała ją, gdy okazało się, że z niej korzystają nie tylko skrypty wewnątrz Claude Code. Jeśli widzisz obie nazwy w artykułach sprzed końca 2025 roku, to nie szukasz różnicy w funkcjach.
SDK jest warstwą programistyczną nad Claude Code. W praktyce oznacza to, że SDK uruchamia binarny Claude Code i rozmawia z nim, a nie że budujesz agenta od zera na API. Stąd też dwa praktyczne wnioski: dostajesz gotową pętlę agenta, narzędzia i zarządzanie kontekstem, ale jednocześnie jesteś przywiązany do tego, jak działa Claude Code. Aktualizacja Claude Code potrafi zmienić zachowanie bez zmiany w Twoim kodzie. Jeśli porównujesz to z podejściem bez SDK, co realnie da się zbudować bez linijki kodu pokazuje, gdzie ta granica leży.
Oficjalnie są dwa warianty: Python (pip install claude-agent-sdk) i TypeScript (npm install @anthropic-ai/claude-agent-sdk). Dla innych języków dokumentacja nie przewiduje biblioteki - zostaje wywołanie CLI przez -p z --output-format json.
Wersja SDK idzie w parze z wersją dołączonego Claude Code: jeśli funkcja wymaga Claude Code 2.1.191, potrzebujesz SDK o tej samej lub wyższej łatce. Binarny Claude Code dołącza się do SDK jako zależność opcjonalna dla danej platformy, więc w większości przypadków osobna instalacja Claude Code nie jest potrzebna. Gdyby jednak menedżer pakietów zignorował zależności opcjonalne, dostaniesz błąd Native CLI binary for <platform>-<arch> not found - wtedy wskazujesz zewnętrzny binarny przez pathToClaudeCodeExecutable.
Najmniejszy działający przykład w TypeScript wygląda tak:
import { query } from "@anthropic-ai/claude-agent-sdk";
for await (const message of query({
prompt: "Pomóż mi zrefaktorować moduł logowania",
})) {
if ("result" in message) console.log(message.result);
}
Zwróć uwagę na kształt wywołania: query() przyjmuje obiekt z prompt i opcjonalnym options, a zwraca obiekt rozszerzający AsyncGenerator. Ten sam kształt masz w Pythonie, tylko opcje podajesz jako ClaudeAgentOptions, a wiadomości filtrujesz przez isinstance zamiast sprawdzać message.type.
Uwaga na różnicę konwencji, bo potrafi zaskoczyć: w Pythonie nazwy opcji są w snake_case (setting_sources, allowed_tools), a w TypeScript camelCase (settingSources, allowedTools). Wyjątkiem są nazwy wielowyrzazowe w definicji subagenta - tam Python celowo zostawia camelCase, żeby pasowało do formatu wymiany z Claude Code.
Struktura repozytorium: gdzie leży co
Cała konfiguracja siedzi w katalogu .claude/. Układ wygląda tak i warto go znać na pamięć, bo każdy element artykułu poniżej wpisuje się w jedno z tych miejsc:
moj-projekt/
├── CLAUDE.md # instrukcje dla projektu
├── .claude/
│ ├── settings.json # hooki, uprawnienia, konfiguracja
│ ├── agents/ # subagenci jako pliki .md
│ │ └── code-reviewer.md
│ ├── skills/ # skills jako katalogi z SKILL.md
│ │ └── pdf-processing/
│ │ ├── SKILL.md
│ │ └── scripts/
│ └── rules/ # dodatkowe reguły ładowane zawsze
└── src/
Dokumentacja opisuje trzy warstwy ustawień i warto wiedzieć, która gdzie leży, bo źle ustawiony poziom oznacza, że hook zadziała tylko u Ciebie na laptopie albo tylko w jednym repozytorium.
- User -
~/.claude/. Twoje skills, agenci isettings.json, wspólne dla wszystkich projektów. Nie commitujesz tego do repo. - Project -
<cwd>/.claude/. To, co commitujesz: hooki, skills, subagenci, reguły.settings.jsoni hooki z tego poziomu możesz dać zespołowi. - Local -
<cwd>/.claude/settings.local.jsoniCLAUDE.local.md. Ustawienia tylko dla siebie, Git je ignoruje.
Kluczowa opcja to settingSources (w Pythonie setting_sources), która decyduje, które z tych warstw SDK wczyta. Jeśli jej nie podasz, działa ["user", "project", "local"] - czyli dokładnie to samo, co czyta CLI. Pusta lista [] zostawia agenta wyłącznie z tym, co przekazałeś programowo. To jest wygodny sposób na produkcyjne uruchomienie, w którym nie chcesz, żeby zachowanie zależało od plików, których nie kontrolujesz.
Zwróć uwagę na jedną asymetrię: settingSources steruje wczytywaniem plików ustawień, ale pamięć auto i plik ~/.claude.json czytane są niezależnie od tej opcji.
Subagenci: osobny kontekst dla osobnego zadania
Subagent to osobna instancja agenta, którą główny agent wywołuje przez narzędzie Agent. Jeśli nie masz jeszcze podstaw, pętla agenta krok po kroku wyjaśnia, skąd biorą się te dodatkowe instancje. Definiujesz go na jeden z trzech sposobów: programowo przez parametr agents, plikiem markdown w .claude/agents/ albo korzystasz z wbudowanego agenta ogólnego przeznaczenia, który Claude odpala nawet wtedy, gdy nie zdefiniujesz żadnego.
Definicja programowa ma dwa pola obowiązkowe: description (opis, kiedy używać tego agenta) i prompt (jego rola i zachowanie, czyli system prompt). Reszta jest opcjonalna i warto z niej korzystać świadomie, bo to ona realnie ogranicza agenta.
for await (const message of query({
prompt: "Przejrzyj moduł logowania pod kątem bezpieczeństwa",
options: {
allowedTools: ["Read", "Grep", "Glob", "Agent"],
agents: {
"code-reviewer": {
description:
"Ekspert od przeglądu kodu. Używaj przy review jakości, bezpieczeństwa i utrzymywalności.",
prompt: `Jesteś specjalistą od przeglądu kodu z doświadczeniem
w bezpieczeństwie, wydajności i dobrych praktykach.
Podczas przeglądu:
- Wykrywaj podatności
- Sprawdzaj problemy wydajnościowe
- Weryfikuj zgodność ze standardami
- Podawaj konkretne propozycje poprawek`,
tools: ["Read", "Grep", "Glob"],
model: "sonnet"
}
}
}
})) {
if ("result" in message) console.log(message.result);
}
Definicje plikowe w .claude/agents/ mają pierwszeństwo nad plikowymi tylko w drugą stronę: to, co podasz programowo, wygrywa z plikiem o tej samej nazwie. Praktyczna konsekwencja jest taka, że warto trzymać jedno podejście - pliki dla zespołu, programowo dla parametrów zależnych od runtime.
Izolacja kontekstu to główna korzyść, ale ma cenę, o której trzeba wiedzieć z wyprzedzeniem. Subagent startuje z pustym kontekstem (chyba że jest forkiem). Jedyne, co przekazujesz z rodzica, to prompt narzędzia Agent - czyli musisz w nim jawnie podać ścieżki do plików, komunikaty błędów i decyzje, które subagent ma znać. Z powrotem rodzic dostaje tylko finalną wiadomość subagenta, więc zadanie trzeba zdefiniować tak, by wynik sam w sobie był zrozumiały bez kontekstu rozmowy.
Subagent dostaje własny system prompt, definicje narzędzi i projektowy CLAUDE.md (o ile settingSources na to pozwala). Nie dostaje historii rozmowy rodzica, jego wyników narzędzi ani wstępnie załadowanej treści skills, chyba że wymienisz je wprost w skills.
Pozostałe pola AgentDefinition, które realnie zmieniają zachowanie: tools (lista dozwolonych narzędzi - pominięcie dziedziczy wszystkie), disallowedTools (też przyjmuje wzorce MCP w stylu mcp__*), model (alias sonnet, opus, haiku, inherit albo pełny identyfikator modelu), maxTurns (limit tur, po którym wynik wraca oznaczony jako częściowy), background, effort i permissionMode.
Ograniczanie narzędzi działa twardo: narzędzie, które pominiesz, po prostu nie istnieje w sesji subagenta. Nie ma pytania o zgodę ani błędu - Claude po prostu pracuje bez niego. To jest najlepsza linia obrony przed atakami opisanymi przy prompt injection w promptach subagentów, które warto mieć na liście zagrożeń.
Dwie rzeczy, które łatwo przeoczyć. Po pierwsze, subagenci działają w tle domyślnie - wywołanie Agent bez run_in_background odpala subagenta w tle, a Claude ustawia false, dopiero gdy potrzebuje wyniku przed dalszym krokiem. Po drugie, subagenci chodzą równolegle, więc dwa zadania na tym samym pliku to wyścig, nie optymalizacja.
Skills: instrukcja, która ładuje się sama, gdy pasuje
Skill to katalog z plikiem SKILL.md, który opisuje procedurę do wykonania. Kluczowe jest to, że nie musisz go wywoływać - Claude decyduje sam, na podstawie opisu, czy pasuje do prośby.
Frontmatter ma dwa wymagane pola i tylko dwa: name (maksymalnie 64 znaki, tylko małe litery, cyfry i myślniki, bez słów zastrzeżonych "anthropic" i "claude") oraz description (maksymalnie 1024 znaki, musi mówić zarówno co skill robi, jak i kiedy go używać).
---
name: pdf-processing
description: Wyciągaj tekst i tabele z plików PDF, wypełniaj formularze, łącz dokumenty. Używaj przy pracy z plikami PDF i gdy użytkownik wspomina o PDF-ach, formularzach lub ekstrakcji danych.
---
# Przetwarzanie PDF
## Szybki start
Użyj pdfplumber do wyciągania tekstu z PDF-ów:
import pdfplumber
with pdfplumber.open("dokument.pdf") as pdf:
tekst = pdf.pages[0].extract_text()
Zaawansowane wypełnianie formularzy znajdziesz w FORMS.md.
Mechanizm nazywa się progressive disclosure i polega na trzech poziomach ładowania, które decydują o koszcie tokenów:
- Poziom 1 - metadane. Frontmatter wczytywany przy starcie do system promptu. ~100 tokenów na skill. Dopóki skill nie zostanie wywołany, w kontekście siedzi tylko jego nazwa i opis, co pozwala trzymać w repo dziesiątki skilli bez kary za kontekst.
- Poziom 2 - instrukcje. Body
SKILL.mdponiżej 5 tys. tokenów, wczytywany dopiero, gdy opis pasuje do prośby. - Poziom 3 - zasoby i skrypty. Dodatkowe pliki markdown i skrypty, do których Claude sięga tylko wtedy, gdy instrukcja je wskazuje. Kod skryptu nigdy nie wchodzi do kontekstu - wchodzi tylko to, co skrypt zwróci.
W praktyce to trzeci poziom odróżnia dobry skill od złego. Jeśli opisujesz procedurę, która wykonuje powtarzalne operacje na plikach, przenieś ją do skryptu w scripts/. Claude odczyta plik, ale nie wczyta kilkuset linii Pythona do kontekstu.
W Claude Code skille leżą w ~/.claude/skills/ (osobiste) albo .claude/skills/ (projektowe), a zespołowi udostępnisz je przez pluginy albo przez version control. Praktyczny przykład własnego serwera MCP podłączonego do Claude Code pokazuje, jak samodzielnie napisać serwer MCP w Pythonie. Jedna rzecz, o której warto wiedzieć od razu: własne skille nie synchronizują się między powierzchniami. To, co wgrasz na claude.ai, nie pojawi się w API, a to, co wgrasz przez API, nie pojawi się w Claude Code. Każdą powierzchnię obsługujesz osobno.
Dokumentacja przewiduje też wtyki, których jeszcze nie ma w stabilnym SDK - między innymi allowed-tools we frontmatter. Jeśli piszesz skille dzisiaj, opieraj się na name i description, a dodatkowe pola traktuj jako zapas na przyszłość.
Hooki: automatyczne reguły przy konkretnych zdarzeniach
Hook to akcja, która odpala się automatycznie przy określonym zdarzeniu w sesji Claude Code. Dokumentacja definiuje go szeroko - to komenda shellowa, endpoint HTTP, wywołanie narzędzia MCP, prompt do modelu albo subagent. Każde zdarzenie odpala te same hooki niezależnie od tego, czy pracujesz w terminalu, w rozszerzeniu IDE, w aplikacji desktopowej czy w sesji chmurowej.
Hooki rozwiązują trzy klasy problemów. Po pierwsze, eliminują powtarzalne kroki ręczne - formatter po każdej zmianie pliku, automatyczne akceptowanie testów. Po drugie, egzekwują reguły projektu bez udziału człowieka - blokują niebezpieczne komendy, sprawdzają ścieżki. Po trzecie, wstrzykują dynamiczny kontekst bez Twojej interwencji, na przykład SessionStart dokłada aktualny git status, a UserPromptSubmit dopisuje priorytety sprintu do każdej prośby.
Konfiguracja ma trzy poziomy: zdarzenie, grupa matcherów, handler. W praktyce wygląda to tak:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"if": "Bash(rm *)",
"command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/block-rm.sh",
"args": []
}
]
}
]
}
}
A skrypt blokujący jest zwykłym bashem czytającym JSON ze standardowego wejścia:
#!/bin/bash
# .claude/hooks/block-rm.sh
COMMAND=$(jq -r '.tool_input.command')
if echo " $COMMAND " | grep -q 'rm -rf' ; then
jq -n '{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "deny",
permissionDecisionReason: "Destructive command blocked by hook"
}
}'
else
Tu jest pułapka, o którą potyka się każdy: exit code 0 bez wyjścia oznacza brak decyzji, a nie zgodę. Zgoda jest wtedy, gdy hook nic nie blokuje. Blokowanie robisz albo przez permissionDecision: "deny" w JSON-ie, albo przez exit code 2, wtedy stderr staje się komunikatem błędu i akcja zostaje uniemożliwiona.
Skąd skrypt wie, co się dzieje? Każdy hook dostaje przez stdin JSON ze wspólnymi polami: session_id, transcript_path, cwd, permission_mode i hook_event_name. Hooki związane z narzędziami dostają dodatkowo tool_name i tool_input. Hooki odpalają też wewnątrz subagentów, a wejście zawiera wtedy agent_id i agent_type.
Matchery filtrują, które narzędzia odpalają hook, i mają trzy tryby. "*" albo pusty string dopasowuje wszystko. Zestaw liter, cyfr, podkreśleń, myślników, spacji, przecinka i pionowej kreski jest traktowany jako dokładny string albo lista dokładnych stringów rozdzielona | lub przecinkiem - Edit|Write dopasuje oba narzędzia. Wszystko inne to niezakotwiony regex JavaScriptu, testowany przez RegExp.prototype.test, czyli dopasowanie w dowolnym miejscu wartości: Edit.* pasuje i na Edit, i na NotebookEdit. Jeśli chcesz dopasować cały string, owinąć wzorzec w ^ i $.
Dokumentacja wymienia 33 zdarzenia, ale matcher działa tylko przy części z nich - przy PreToolUse, PostToolUse, PostToolUseFailure, PermissionRequest i PermissionDenied. Dodanie matchera do zdarzenia bez takiego wsparcia jest po cichu ignorowane, więc łatwo stracić godziny na szukanie błędu w filterze, który nigdy nie był czytany.
Wszystkie pasujące hooki odpalają równolegle. Ten sam handler zdefiniowany w kilku plikach ustawień wykona się raz. Warto też wiedzieć, że wpisy hooków między poziomami ustawień się scalają, zamiast nadpisywać - ustawienia projektu dokładają swoje hooki, nie zamiast Twoich. Starsze materiały piszą o pierwszeństwie ustawień projektu nad użytkownika; dokumentacja mówi o scalaniu. W praktyce wygrywa to, co dokumentacja opisuje.
Pamięć projektu: CLAUDE.md i to, co agent czyta sam
CLAUDE.md to plik tekstowy, w którym piszesz instrukcje projektu - jak uruchomić testy, jaki jest styl kodu, czego nie ruszać. Claude czyta go automatycznie, bez wskazywania ścieżki w prompcie.
Umiejscowienie pliku decyduje o zasięgu. <cwd>/CLAUDE.md albo <cwd>/.claude/CLAUDE.md to instrukcje projektu, ładowane gdy settingSources zawiera "project". CLAUDE.md w katalogach nadrzędnych wczytuje się na starcie sesji. CLAUDE.md w podkatalogach cwd ładuje się na żądanie, gdy agent czyta plik w tym poddrzewie - to najwygodniejszy sposób na opisanie modułu w sposób zrozumiały tylko przy nim. ~/.claude/CLAUDE.md to Twoje instrukcje na wszystkie projekty, a CLAUDE.local.md wariant lokalny, którego nie commitujesz.
Dokumentacja ma jeszcze .claude/rules/*.md - dodatkowe reguły ładowane z tego samego poziomu co CLAUDE.md. Praktyczny podział wygląda tak: CLAUDE.md trzymaj krótki i ogólny, a reguły specyficzne dla domeny wywal osobno. Szersze spojrzenie na to, ile plików pamięci realnie zużywa kontekst i jak liczyć limity, znajdziesz we porównaniu pamięci projektu w Claude i ChatGPT.
Jedna zasada z dokumentacji jest warta zapamiętania: każda włączona funkcja dokłada się do context window agenta. To nie liczba, tylko zasada - im więcej włączysz, tym mniej realnie zostaje na właściwą pracę. Rozdzielenie instrukcji na warstwy działa w drugą stronę: subagent z omitClaudeMd (opcja dostępna w TypeScript od SDK v0.3.271) startuje bez plików CLAUDE.md, co jest sensowne przy zadaniach wąskich, typu „przejrzyj ten plik i wypisz nazwy funkcji".
Sesje zapisują się lokalnie w ~/.claude/projects/<encoded-cwd>/ jako pliki .jsonl, gdzie nazwa katalogu to absolutna ścieżka robocza z każdym znakiem niealfanumerycznym zamienionym na myślnik. Ścieżki dłuższe niż 200 znaków są obcinane i dostają hash, więc przy szukaniu konkretnej sesji dopasuj pierwsze 200 znaków nazwy przekonwertowanej. W TypeScript kontynuację daje resume, forkSession albo persistSession; w Pythonie ClaudeSDKClient. Sesje są lokalne dla maszyny - na innym hoście albo przenosisz plik .jsonl przed wywołaniem resume, albo podpinasz własny adapter magazynu sesji.
Kiedy subagent, kiedy skill, kiedy hook
Te trzy mechanizmy rozwiązują różne problemy i mylenie ich jest najczęstszym powodem nadmiarowej pracy. Krótka reguła: skill odpowiada na pytanie 'jak to się robi', subagent na pytanie 'kto to robi', hook na pytanie 'co ma się stać automatycznie'. Jak ustawić granice, żeby agent nie działał na pełnej swobodzie, opisałem przy czterech poziomach autonomii agenta.
- Skill, gdy procedura jest powtarzalna, ale wykonywana w głównym kontekście. Wdrożenie integracji, formatowanie odpowiedzi, szablon raportu. Opis w frontmatter decyduje, czy Claude sięgnie po instrukcję.
- Subagent, gdy zadanie jest obszerne i chcesz odciążyć główny kontekst. Przeszukanie całego repo, przegląd kodu, migracja. Zyskujesz izolację kontekstu i możliwość ograniczenia narzędzi; płacisz za to ręcznym przekazaniem kontekstu w prompcie.
- Hook, gdy reguła ma obowiązywać zawsze, bez pytania do modelu. Blokowanie
rm -rf, formatowanie po edycji, wstrzyknięciegit status. Nie pytaj modelu, co ma robić z.env- powiedz mu to hookiem.
Jest jeszcze opcja, której nie warto pominąć przy planowaniu struktury repo: pluginy. Pozwalają spakować skills, agentów, hooki i serwery MCP w jeden katalog z manifestem .claude-plugin/plugin.json i udostępnić to całej firmie jednym poleceniem. Manifest jest opcjonalny - bez niego komponenty są wykrywane z układu katalogu, a skille z pluginu są przestrzenione nazwą w formacie /nazwa-pluginu:nazwa-skilla, żeby nie kolidowały z Twoimi własnymi.
Co się dzieje z kosztem, gdy agent zaczyna się zapętlać
Najczęstszy problem produkcyjny nie brzmi „nie działa", tylko „działa za drogo". Jedno z zespołów produkcyjnych opisało to tak: przed dodaniem zabezpieczeń agent wykonywał średnio 47 wywołań narzędzi na nieudane żądanie i palił $0.41 tokenów na przebieg. Po wprowadzeniu trzech prostych guardrails ta sama ścieżka przerywała się po 3 wywołaniach i $0.02 - spadek o 95 procent na pojedynczym żądaniu.
Trzy guardraile, które możesz zaimplementować w weekend:
MAX_TOOL_CALLS = 12- twardy limit wywołań narzędzi w jednym przebiegu.TOKEN_BUDGET_MULTIPLIER = 2.0- mnożnik budżetu tokenów.- Wykrywanie powtórzenia tych samych argumentów - przerwij, gdy ten sam blok z tymi samymi argumentami wraca drugi raz.
Ten sam zespół opisuje dwa wdrożenia, gdzie podział na wiele agentów obniżył rachunek. Router ze specjalistą zamiast jednego agenta: $462 do $276 miesięcznie przy 18 tys. dokumentów, czyli 40 procent mniej. Podział dużego promptu na bazę plus regionalne skille: mediana tokenów wejściowych na żądanie spadła z 4650 do 1780, a miesięczny koszt tego agenta z $940 do $412.
Przy czterech agentach w workflow koordynacja zjadała 42 procent tokenów i $2.14 na przebieg. Po poprawce handoffów: 17 procent koordynacji, 96 tys. tokenów zamiast 184 tys. i $1.02 zamiast $2.14. Wniosek z tych liczb brzmi: wydatnie jest nie tyle samo liczba agentów, co ilość wymiany między nimi.
Jeśli pracujesz na podobnym wdrożeniu, macierz porównująca frameworki - LangGraph, OpenAI Agents SDK, Claude SDK, CrewAI, Dify, n8n - pomoże ci zdecydować, czy potrzebujesz czegoś z tej listy, czy wystarczy Claude Code z plikami w repo. Opisałem kryteria, których używam przy takich wyborach: kto utrzymuje kod po pół roku, koszt przy dziesięciu tysiącach zadań i czy da się przenieść logikę do n8n, gdy zlecenie się zmieni.
Trzy rzeczy, które psują konfigurację najczęściej
Kilka błędów powtarza się przy wdrożeniach opisanych w dokumentacji i w praktyce. Po pierwsze, matcher na ścieżce regex bez kotwic - Edit.* przepuszcza NotebookEdit, a nie zdaje sobie z tego sprawy, dopóki hook nie zacznie blokować za dużo. Po drugie, dodanie matchera do zdarzenia, które go nie obsługuje - zostaje zignorowane po cichu. Po trzecie, agent typu wszystko-w-jednym bez maxTurns: brak limitu tur oznacza, że przy niepowodzeniu agent krąży, a Ty płacisz za każdą turę.
Warto też pamiętać o różnicy narzędzia: w blokach tool_use nazywa się "Agent", ale na liście system:init pojawia się jako "Task". Przed Claude Code v2.1.63 w tool_use też nazywało się "Task", więc jeśli piszesz kod wykrywający wywołanie subagenta, dopasuj obie wartości - inaczej po aktualizacji SDK przestaniesz widzieć swoich subagentów.
Jeśli chcesz przejść od czytania do wdrożenia, zacznij od jednego procesu, który realnie zjada czas w Twoim tygodniu, i sprawdź, czy da się go domknąć tymi plikami. Konfiguracja jest w tym podejściu nudna: kilka plików w repo, reguły w settings.json i jeden skrypt blokujący. Napisz do mnie - odpowiadam zwykle tego samego dnia - jeśli chcesz przejrzeć swoją strukturę przed wdrożeniem.