[Intum Pomoc](https://intum.pl/pomoc.md) / [API](https://intum.pl/pomoc/noe/api.md)

# [Prompty Noe](https://intum.pl/pomoc/noe/api/prompty.md)

Prompty to szablony instrukcji dla AI: treść AI buttonów, systemowe prompty agentów i chatu.
Każdy prompt ma `code` (identyfikator, np. `workinfo_new`) i `content` (treść z placeholderami Liquid).
Prompt zapisany w bazie **nadpisuje** plik systemowy o tym samym `code` - dzięki temu użytkownik
może dostosować standardowy prompt pod siebie, nie ruszając kodu aplikacji.

**Autoryzacja:** `Authorization: Bearer TOKEN`
**Content-Type:** `application/json; charset=utf-8`

## API Endpoints

| Metoda | Ścieżka | Opis |
|--------|---------|------|
| GET | `/noe/prompts.json` | Lista promptów z bazy (bez systemowych z plików) |
| GET | `/noe/prompts/:id.json` | Pojedynczy prompt (`id` to UUID) |
| POST | `/noe/prompts.json` | Utworzenie prompta |
| PATCH | `/noe/prompts/:id.json` | Aktualizacja prompta |
| DELETE | `/noe/prompts/:id.json` | Usunięcie prompta (wraca systemowy z pliku, jeśli istnieje) |
| GET | `/noe/prompts/:id.md` | Surowa treść prompta (bez renderowania Liquid) |
| GET | `/noe/prompt/:code.md` | **Treść po kaskadzie**, z podstawionymi `TOKEN` i `https://app.intum.pl` |
| GET | `/noe/prompts/system/:code.md` | Treść systemowa z pliku, z pominięciem bazy |

`GET /noe/prompts.json` zwraca **gołą tablicę**, nie obiekt z kluczem `prompts`.

## Pola prompta

| Pole | Typ | Wymagane | Opis |
|------|-----|----------|------|
| `name` | string | tak | Nazwa widoczna na liście i w nagłówku modala AI |
| `code` | string | tak | Identyfikator, np. `workinfo_new`. Unikalny w ramach (konto, `scope`, `scope_id`) |
| `content` | text | tak | Treść prompta, Liquid (zob. niżej) |
| `kind` | string | tak | `"chat"` (rozmowa) albo `"agent"` (zadanie wykonawcze). Domyślnie `"chat"` |
| `scope` | string | nie | `"user"`, `"team"`, `"department"`, `"account"`. Domyślnie `"account"` |
| `scope_id` | bigint | nie | ID użytkownika / zespołu / działu. Dla `scope: "account"` zostaw puste |
| `ai_placeholder` | string | nie | Podpowiedź w polu tekstowym modala AI. Ląduje w `fields.ai_placeholder` |

Zasady:

- pole `token` nie jest zwracane przez API (nadawane automatycznie przy tworzeniu)
- `scope_id` uzupełnia się samo dla `scope: "user"` (bieżący użytkownik), gdy go nie podasz
- żeby **przesłonić prompt systemowy**, utwórz rekord z tym samym `code`, jaki ma plik
  w `app/src/noe/prompts/` - kaskada wybierze wersję z bazy

## Kaskada rozwiązywania prompta

`GET /noe/prompt/:code.md` szuka treści w kolejności:

1. `scope: "user"` + `scope_id` = bieżący użytkownik
2. `scope: "team"` + zespół użytkownika
3. `scope: "department"` + dział użytkownika
4. `scope: "account"`
5. plik `app/src/noe/prompts/:code.agent.md` albo `:code.md`

Pierwszy znaleziony wygrywa. Dodatkowo, jeśli istnieje prompt o kodzie `:code_extra`,
jego treść zostaje **dopisana na końcu** jako "Dodatkowe instrukcje" - to sposób na
uzupełnienie systemowego prompta bez kopiowania go w całości.

## Liquid w treści

| Zmienna | Skąd | Opis |
|---------|------|------|
| `TOKEN` | automatycznie | Token API bieżącego użytkownika |
| `https://app.intum.pl` | automatycznie | URL konta, np. `https://firma.intum.com` |
| `{{date}}` | automatycznie | Data z parametru `date`, domyślnie dziś |
| dowolna inna | `env` w AI buttonie | Np. `{{prompt_id}}`, `{{client_id}}` |

Filtr `prompt_url` buduje link do innego prompta:

```
Instrukcje API: https://app.intum.pl/noe/prompt/workinfo_api.md
```

Filtr `api_block` wstawia komplet nagłówków dla agenta - zamiast wypisywać je ręcznie
w każdym prompcie, wystarczy jedna linia na końcu treści:

```
Instrukcje API: https://app.intum.pl/noe/prompt/workinfo_api.md
Zasady API: https://app.intum.pl/noe/prompt/common_api.md
Host: https://app.intum.pl
Authorization: Bearer TOKEN
```

rozwija się do:

```
Instrukcje API: https://firma.intum.com/noe/prompt/workinfo_api.md
Zasady API: https://firma.intum.com/noe/prompt/common_api.md
Host: https://firma.intum.com
Authorization: Bearer <token uzytkownika>
```

Kilka instrukcji naraz podajesz po przecinku
(`Instrukcje API: https://app.intum.pl/noe/prompt/kb_knowledge_base_api.md
Instrukcje API: https://app.intum.pl/noe/prompt/kb_entry_api.md
Zasady API: https://app.intum.pl/noe/prompt/common_api.md
Host: https://app.intum.pl
Authorization: Bearer TOKEN`), a gdy prompt nie ma osobnej
instrukcji API - `Zasady API: https://app.intum.pl/noe/prompt/common_api.md
Host: https://app.intum.pl
Authorization: Bearer TOKEN` (zostana same zasady, host i token).

Warunek na obecność zmiennej (kontekst listy vs pojedynczego rekordu):

```
{% if prompt_id != blank %}Pracuję nad promptem {{prompt_id}}.
{% else %}Pracuję nad listą promptów.
{% endif %}
```

Plik systemowy może zaczynać się blokiem `---` z `name: Nazwa` (i opcjonalnie `placeholder:`),
który staje się nazwą prompta i nie trafia do treści wysyłanej do modelu.

## Format requestu

### POST - własna wersja systemowego prompta

```
POST /noe/prompts.json
Authorization: Bearer TOKEN
Content-Type: application/json; charset=utf-8
```

```json
{
  "prompt": {
    "name": "Wypełnij timesheet",
    "code": "workinfo_new",
    "kind": "agent",
    "scope": "user",
    "content": "Wypełnij mój timesheet za {{date}}.\n\nAuthorization: Bearer TOKEN\nHost: https://app.intum.pl"
  }
}
```

Odpowiedź: `201 Created` z pełnym obiektem prompta (`id` to UUID).

### PATCH - zmiana samej treści

```json
{ "prompt": { "content": "Nowa treść..." } }
```

Odpowiedź: `200 OK`. Nie musisz wysyłać pozostałych pól.

### Błąd walidacji (422 Unprocessable Content)

```json
{ "code": ["zostało już zajęte"] }
```

Najczęstsza przyczyna: prompt o tym `code` już istnieje w tym samym `scope`/`scope_id`.
Zamiast tworzyć nowy, pobierz istniejący (`GET /noe/prompts.json?code=workinfo_new`) i zrób PATCH.

## Wyszukiwanie i filtrowanie

| Parametr | Opis |
|----------|------|
| `q` | Szuka w `name` i `code` |
| `code`, `kind`, `scope` | Filtr po dokładnej wartości |
| `order_by` | `id`, `created_at`, `updated_at`, `name`, `code` (sufiks `_desc` odwraca) |

```
GET /noe/prompts.json?scope=user&kind=agent&order_by=updated_at_desc
```

## Zasady pracy

- **Nie usuwaj cudzych promptów** - przed DELETE sprawdź `scope`/`scope_id` i `created_by_id`
- **Zachowaj placeholdery** przy edycji treści: wycięcie `TOKEN` albo `https://app.intum.pl`
  z prompta agentowego zepsuje AI button (agent straci dostęp do API)
- **Nie wstawiaj prawdziwego tokena** do `content` - zawsze `TOKEN`, bo treść
  prompta jest widoczna dla innych użytkowników konta
- **Zmieniasz systemowy prompt?** Nie edytuj pliku - utwórz rekord z tym samym `code`
  i `scope: "user"`, żeby zmiana dotyczyła tylko Ciebie
- Treść pisz w **Markdown**, zwięźle - to instrukcja dla modelu, nie dokumentacja