Agent Skills
Agent Skills to pliki markdown z frontmatterem YAML, które żyją w
saiku-home/skills/. Launcher skanuje je leniwie przy każdym żądaniu i
wstrzykuje katalog do system promptu LLM, więc każda tura
AI Ask — MDX lub Ossie — może
skierować do przepływu autorstwa administratora zamiast improwizować.
Mała funkcja, nieproporcjonalna wartość: pozwala operatorom skodyfikować kanoniczne pytania swojego zespołu („rollup dla zarządu z tego kwartału”, „kohorta churn”, „raport porównania sklepów”) bez posiadania kolejnego narzędzia. Skill żyje w repo, wersjonuje się z modelem semantycznym i przechodzi code review jak wszystko inne.
Dostarczone w saiku v4.7 jako saiku#1426.
Dwie ścieżki wywołania
Format pliku
---name: weekly-foodmart-rollupdescription: | Weekly revenue rollup for the FoodMart Sales cube: total Store Sales by Product Family for the last 7 days, compared to the prior 7 days. Flags any family with a >20% swing.cube: unknown_foodmart/FoodMart/FoodMart/Sales---
## Steps
1. Query total `[Measures].[Store Sales]` and `[Measures].[Unit Sales]` broken down by `[Product].[Product Family]` for the last 7 days (`[Time].[Weekly].[Week].&[latest]`).
2. Query the same shape for the prior 7 days (`[Time].[Weekly].[Week].&[latest - 1]`).
3. Present the result as a two-column table with a `Δ vs prior` percentage column derived per family.
4. Highlight any Product Family whose `Δ vs prior` swings by more than 20% in either direction.Frontmatter
| Pole | Wymagane | Typ | Uwagi |
|---|---|---|---|
name | tak | string | kebab-case, [a-z][a-z0-9-]{0,63}. Używane jako slug slash. |
description | tak | string | Jedna linia lub blok scalar. Pokazywane w /ai/skills i prompcie LLM. |
cube | nie | string | Referencja connection/catalog/schema/cubeName. Ogranicza skill. |
Nieznane klucze najwyższego poziomu są odrzucane. Literówka
(descripton) ujawnia się jako ustrukturyzowany błąd UNKNOWN_FIELD —
nigdy jako cichy bezimienny skill.
Ciało
Wszystko po zamykającej granicy --- to ciało. Markdown jest zalecany,
ale niewymagany; ciało jest traktowane jako nieprzezroczysty tekst i
wklejane dosłownie do promptu LLM przy dopasowaniu polecenia slash. Trzymaj
je zwięzłe — LLM musi przeczytać cały plik.
Polecenie slash
-
Użytkownik (lub widżet DimSum w twoim imieniu) wysyła ask zaczynający się od
/:Okno terminala curl -sS -X POST -H 'Content-Type: application/json' \-u admin:admin \http://localhost:8080/saiku/api/ai/ask \-d @- <<'EOF'{"question": "/weekly-foodmart-rollup for Q4 instead of this week","cube": {"connectionName":"unknown_foodmart","catalog":"FoodMart","schema":"FoodMart","cubeName":"Sales"}}EOF -
Usługa parsuje slash i wyszukuje
weekly-foodmart-rollupw katalogu. -
Trafienie → ask wysłany do LLM to:
Skill: weekly-foodmart-rollup## Steps1. Query total [Measures].[Store Sales] ……User follow-up: for Q4 instead of this week -
LLM uruchamia kroki, stosuje kontynuację („Q4 instead of this week”) do filtra czasu i emituje
AiQueryRequestjak zwykle. -
Pudło → ask podróżuje niezmieniony. LLM widzi go jako zwykły prompt z wiodącym ukośnikiem. Nic się nie psuje.
Język naturalny
Katalog ląduje w system prompcie LLM jako:
Available skills (admin-authored workflows). When the user's questionclosely matches one of these — or when the message starts with`/<skill-name>` — use the skill's steps to structure your responseinstead of freewheeling:- /weekly-foodmart-rollup: Weekly revenue rollup for the FoodMart Sales cube…- /store-comp-report: Store-level comp vs same period last year…- /churn-cohort: 30/60/90 day churn cohort split by acquisition channel…Model kieruje samodzielnie. Jeśli użytkownik pyta „jak sklepy wypadły
w porównaniu z zeszłym rokiem?”, matcher języka naturalnego wybiera
/store-comp-report; użytkownik nigdy nie widzi decyzji o kierowaniu.
Powierzchnia REST
Wszystkie trzy endpointy siedzą pod standardową ścieżką bazową AI Ask.
GET /rest/saiku/api/ai/skills
Katalog — zwarte podsumowania {name, description, cube}.
curl -sS -u admin:admin \ http://localhost:8080/saiku/api/ai/skills | jq{ "skills": [ { "name": "weekly-foodmart-rollup", "description": "Weekly revenue rollup for the FoodMart Sales cube: total Store Sales …", "cube": "unknown_foodmart/FoodMart/FoodMart/Sales" } ]}GET /rest/saiku/api/ai/skills?errors=true
Ten sam kształt, plus tablica errors[] listująca każdy plik, który nie
sparsował się w tym skanie. Każdy wpis niesie stabilny kod maszynowy,
więc operatorzy naprawiają zły frontmatter bez czytania logów serwera.
{ "skills": [ /* … */ ], "errors": [ { "path": "broken.md", "code": "MISSING_FRONTMATTER", "message": "expected leading `---` YAML frontmatter block" } ]}Stabilne kody błędów:
| Kod | Kiedy |
|---|---|
EMPTY_SKILL | Plik jest pusty lub całkowicie białe znaki. |
MISSING_FRONTMATTER | Brak wiodącej granicy ---. |
EMPTY_BODY | Frontmatter sparsowany, ale brak markdown po zamykającej granicy. |
MALFORMED_YAML | Parser YAML odrzucił frontmatter. |
MISSING_FIELD | Wymagane pole (name / description) nieobecne. |
BLANK_FIELD | Wymagane pole obecne, ale puste / same białe znaki. |
TYPE_MISMATCH | Pole obecne, ale zły typ (name: 42). |
INVALID_NAME | name nie pasuje do [a-z][a-z0-9-]{0,63}. |
UNKNOWN_FIELD | Frontmatter zawiera pole spoza schemy. |
DUPLICATE_NAME | Dwa pliki skilli zadeklarowały tę samą name. |
IO_ERROR | Nie udało się odczytać pliku (poziom systemu plików). |
GET /rest/saiku/api/ai/skills/{name}
Pełne ciało jednego skilla — surowy markdown. Przydatne dla menu slash w UI, które podglądasz przepływ, zanim użytkownik naciśnie wyślij.
POST /rest/saiku/api/ai/skills/refresh
Wymuś ponowny skan (omija sprawdzenie sygnatury mtime). Zwraca świeże liczniki, więc operatorzy mogą na oko ocenić przeładowanie.
curl -sS -u admin:admin -X POST \ http://localhost:8080/saiku/api/ai/skills/refresh{ "skills": 4, "errors": 0 }Dołączony przykład
Świeże instalacje Saiku umieszczają działający przykład przy pierwszym starcie — zobacz weekly-foodmart-rollup.md. Operatorzy dodają własne obok; zasiany jest idempotentny (ląduje tylko, gdy plik docelowy jeszcze nie istnieje).
Jak działa skan
- Podkatalogi są przechodzone rekurencyjnie.
- Pliki nie-
.mdsą ignorowane (błąkający sięREADME.txtnie zawiesi skanu). - Zepsute pliki nie kładą katalogu —
ParseExceptionna jednym pliku pozostawia pozostałe nienaruszone. - Duplikaty na
nameprodukują błądDUPLICATE_NAMEna drugim pliku do załadowania; pierwszy wygrywa.
Ask-i Ossie też je podchwytują
Katalog skilli to pojedynczy magazyn per-launcher serwowany pod
/rest/saiku/api/ai/skills. Każdy skill, którego pole cube: nazywa
referencję Ossie (np. pharma/Pharma/Pharma/Sales), jest naturalnie
ograniczony przez tę referencję, gdy kierowany przez
/ai/ossie/ask. MDX i Ossie
dzielą ten sam prymityw.