Lab 09: Connected Agents - Orkiestracja multi-agent
Opis
W tym laboratorium poznasz architekturę multi-agent z głównym agentem jako orchestratorem delegującym zadania do wyspecjalizowanych sub-agentów. Zbudujesz system, gdzie jeden agent koordynuje pracę innych agentów, z których każdy ma swoją specjalizację.
Co zbudujesz:
- Orchestrator Agent - główny koordynator (bez własnych tools)
- KRS Agent - specjalista od Krajowego Rejestru Sądowego (reużycie z Lab 04)
- Company API Agent - specjalista od lokalnej bazy firm (NOWY)
Use case: Użytkownik podaje numer KRS firmy → Orchestrator pobiera dane z rejestru (KRS Agent) → zapisuje firmę do lokalnej bazy (Company API Agent) → potwierdza operację.
Wprowadzenie: Dlaczego multi-agent?
Problem pojedynczego agenta
Kiedy agent ma zbyt wiele odpowiedzialności:
- ❌ Trudny w utrzymaniu (długie instructions)
- ❌ Ciężko testować (wiele tools w jednym miejscu)
- ❌ Brak reusability (nie można użyć części logiki w innym kontekście)
- ❌ Context overload (za dużo informacji w jednym prompcie)
Rozwiązanie: Connected Agents
Connected Agents to pattern gdzie:
- ✅ Main Agent (Orchestrator): Koordynuje pracę, nie ma własnych tools
- ✅ Sub-Agents: Wyspecjalizowani agenci, każdy odpowiada za jedną domenę
- ✅ Separation of Concerns: Jasny podział odpowiedzialności
- ✅ Reusability: Sub-agentów można użyć w różnych orchestratorach
Korzyści:
- Modularność (każdy sub-agent = osobny komponent)
- Łatwiejsze testowanie (test każdego sub-agenta osobno)
- Reużywalność (ten sam KRS Agent w różnych scenariuszach)
- Przejrzystość (clara responsibility boundaries)
Architektura systemu
graph TD
User[👤 User] --> Orch[🎯 Orchestrator Agent<br/>GPT-4.1-mini<br/>Coordinator - no tools]
Orch -->|"Delegates:<br/>Get company from KRS"| KRS[🏢 KRS Agent<br/>GPT-4.1-mini<br/>Registry specialist]
Orch -->|"Delegates:<br/>Save/retrieve companies"| API[💾 Company API Agent<br/>GPT-4.1-mini<br/>Database specialist]
KRS -->|Uses| KRSAPI[🔌 KRS API<br/>API Management<br/>External registry]
API -->|Uses| CompanyAPI[🔌 Company API<br/>API Management<br/>Internal database]
KRS -->|Returns data| Orch
API -->|Returns data| Orch
Orch -->|Final response| User
style Orch fill:#4A90E2,stroke:#2E5C8A,color:#fff
style KRS fill:#50C878,stroke:#2E7D4E,color:#fff
style API fill:#9B59B6,stroke:#6C3483,color:#fff
style User fill:#E8E8E8,stroke:#666,color:#333
style KRSAPI fill:#F39C12,stroke:#C87F0A,color:#fff
style CompanyAPI fill:#F39C12,stroke:#C87F0A,color:#fff
Komponenty systemu
1. Orchestrator Agent (Main Agent)
- Model: GPT-4.1-mini
- Rola: Koordynacja i routing zapytań użytkownika
- Tools: TYLKO ConnectedAgentTool (nie ma własnych API tools!)
- Odpowiedzialność: Zrozumienie intencji użytkownika i delegacja do odpowiedniego sub-agenta
2. KRS Agent (Sub-Agent)
- Model: GPT-4.1-mini
- Rola: Specjalista od Krajowego Rejestru Sądowego
- Tools: OpenAPI Tool → KRS API (getKrsOdpisAktualny)
- Odpowiedzialność: Pobieranie danych firm z rejestru KRS
3. Company API Agent (Sub-Agent)
- Model: GPT-4.1-mini
- Rola: Specjalista od lokalnej bazy firm
- Tools: OpenAPI Tool → Company API (GET/POST/PATCH/DELETE /companies)
- Odpowiedzialność: Zarządzanie firmami w lokalnej bazie danych
Company API - Nasza lokalna baza firm
Company API to REST API na Azure API Management które zarządza lokalną bazą danych firm.
Endpoints
| Method | Endpoint | Operacja | Opis |
|---|---|---|---|
| GET | /companies |
get-companies |
Lista wszystkich firm w bazie |
| POST | /companies |
post-companies |
Dodaj nową firmę (ID auto-generated) |
| GET | /companies/{id} |
get-companies-id |
Pobierz firmę po ID |
| PUT | /companies/{id} |
put-companies-id |
Upsert - utwórz lub zastąp firmę |
| PATCH | /companies/{id} |
patch-companies-id |
Aktualizuj wybrane pola firmy |
| DELETE | /companies/{id} |
delete-companies-id |
Usuń firmę po ID |
Schema firmy
{
"id": "string",
"nazwa": "string",
"nip": "string",
"krs": "string",
"regon": "string",
"adres": "string"
}
Authentication
Company API używa API Management subscription key:
- Header:
Ocp-Apim-Subscription-Key: <your-key> - Query param:
subscription-key=<your-key>
Teoria: Jak działają Connected Agents?
Delegation Flow
sequenceDiagram
participant U as 👤 User
participant O as Orchestrator Agent
participant K as KRS Agent
participant A as Company API Agent
participant KAPI as KRS API
participant CAPI as Company API
U->>O: "Dodaj firmę PKN ORLEN (KRS 0000028860) do bazy"
Note over O: 1. Analyzes request<br/>2. Decides to delegate<br/>3. Plans workflow
O->>K: "Retrieve company data for KRS 0000028860"
activate K
K->>KAPI: GET /odpis-aktualny?krs=0000028860&rejestr=P
KAPI-->>K: Returns company data
K-->>O: {"nazwa": "PKN ORLEN S.A.", "nip": "7740001454", ...}
deactivate K
Note over O: Receives data from KRS Agent<br/>Prepares delegation to Company API Agent
O->>A: "Save company to database with data: {...}"
activate A
A->>CAPI: POST /companies<br/>Body: {"nazwa": "PKN ORLEN S.A.", ...}
CAPI-->>A: {"id": "1", "nazwa": "PKN ORLEN S.A.", ...}
A-->>O: "Company saved successfully with ID: 1"
deactivate A
Note over O: Synthesizes results<br/>from both sub-agents
O-->>U: "✅ Firma PKN ORLEN S.A. została pobrana z KRS<br/>i zapisana do bazy z ID: 1"
Kluczowe koncepty
1. Delegation (Delegacja)
- Main Agent NIE wykonuje zadań sam
- Main Agent DELEGUJE zadania do sub-agentów
- Sub-agenci zwracają wyniki do Main Agent
- Main Agent kompiluje wyniki i prezentuje użytkownikowi
2. ConnectedAgentTool
- Specjalny typ tool w Azure AI Foundry
- Pozwala jednemu agentowi wywołać drugiego agenta
- Składnia:
{"type": "connected_agent", "connected_agent_id": "sub_agent_id"}
3. Separation of Concerns
- Każdy sub-agent odpowiada za jedną domenę
- Sub-agenci nie wiedzą o sobie nawzajem
- Orchestrator nie ma własnych API tools (tylko ConnectedAgentTool)
Limitations (Ograniczenia)
| Ograniczenie | Opis | Obejście |
|---|---|---|
| Max depth = 2 | Sub-agent NIE może mieć własnych connected agents | Spłaszcz architekturę - usuń poziomy |
| No citations passthrough | Citations z sub-agentów nie są przekazywane do main agent | Prompt engineering: poproś sub-agenta o załączenie źródeł w tekście |
| No function calling | Local Python functions nie działają jako tools w sub-agentach | Użyj OpenAPI Tool lub Azure Functions |
| Performance | Każda delegacja = dodatkowy round-trip | Trade-off: modularność vs latency |
| Debugging | Odpowiedzi sub-agentów widoczne TYLKO dla main agent | Thread logs są kluczowe - sprawdzaj je regularnie |
Ważne: Sub-agent nie może mieć własnych connected agents. Maksymalny depth to 2 poziomy:
- ✅ OK: Main Agent → Sub-Agent
- ❌ BŁĄD: Main Agent → Sub-Agent → Sub-Sub-Agent
Przygotowanie środowiska
Krok 1: Export OpenAPI spec dla Company API
Musisz wyeksportować OpenAPI specification z API Management:
- Azure Portal → API Management → APIs
- Wybierz Company API
- Kliknij Export (górny pasek)
- Wybierz OpenAPI v3 (JSON) ⚠️ Ważne: JSON, nie YAML!
- Zapisz plik lokalnie jako
company-api.json
Dlaczego JSON? Azure AI Foundry lepiej obsługuje OpenAPI w formacie JSON przy tworzeniu connections.
Krok 2: Utworzenie Connection dla Company API
Connection przechowuje credentials centralnie - możesz reużywać w wielu agentach.
- W Azure AI Foundry Portal, kliknij More (menu u góry)
- Management center → Project (Twój projekt)
- Connected resources → + New connection
- Wybierz Custom keys
- Configuration:
- Connection name:
company-api-connection - Przewiń w dół do sekcji Connection key
- Credentials (dodaj DWA klucze):
- Pierwszy klucz:
- Key:
Ocp-Apim-Subscription-Key - Value: Wklej subscription key otrzymany od prowadzącego (z Azure Portal → APIM → Subscriptions)
- Is secret: Zaznacz (checkbox)
- Key:
- Kliknij + Add key i dodaj drugi:
- Key:
subscription-key - Value: Ten sam subscription key co powyżej
- Is secret: Zaznacz (checkbox)
- Key:
- Pierwszy klucz:
- Connection name:
- Create
Tip: Ten sam subscription key co do KRS API - możesz reużyć
krs-apim-connection-<INICJAŁ>z Lab 04 jeśli chcesz!
Lab Część 1: Utworzenie Sub-Agentów
Krok 1: KRS Agent (reużycie z Lab 04)
Option A: Reużyj istniejącego KRS Agent z Lab 04
- Jeśli masz już działającego KRS Agent z Lab 04 - użyj go
- Skopiuj jego Agent ID (będzie potrzebny później)
- Przejdź do Kroku 2
Option B: Utwórz nowego KRS Agent
- AI Foundry Portal → Twój Project → Agents (lewy panel)
- + Create agent
Konfiguracja:
| Pole | Wartość |
|---|---|
| Name | krs_agent |
| Description | Retrieves company data from Polish National Court Register (KRS) based on KRS number |
| Model | gpt-4.1-mini-<INICJAŁ> |
| Instructions | Zobacz poniżej ⬇️ |
Instructions dla KRS Agent:
Jesteś wyspecjalizowanym agentem do pobierania danych z Krajowego Rejestru Sądowego (KRS).
TWOJE ZADANIE:
- Pobierz aktualny odpis firmy z KRS na podstawie numeru KRS
- Zwróć strukturalne dane firmy (nazwa, NIP, REGON, adres, KRS)
NARZĘDZIE:
- getKrsOdpisAktualny - pobiera dane z KRS API
PARAMETRY:
- krs: numer KRS (10 cyfr, format: 0000123456)
- rejestr: ZAWSZE używaj "P" (rejestr przedsiębiorców)
ZASADY:
1. Wywołaj getKrsOdpisAktualny z numerem KRS i rejestr="P"
2. Wyciągnij najważniejsze pola: nazwa, NIP, REGON, adres siedziby, numer KRS
3. Zwróć dane w formacie JSON lub ustrukturyzowanym tekście
4. Jeśli API zwróci 404 - powiedz że firma nie znaleziona
5. NIE WYMYŚLAJ danych - używaj TYLKO informacji z API
FORMAT ODPOWIEDZI:
Zwróć dane w czytelnym formacie:
- Nazwa: [nazwa firmy]
- NIP: [nip]
- KRS: [krs]
- REGON: [regon]
- Adres: [pełny adres]
- Tools → + Add tool → OpenAPI
- Connection: Wybierz KRS API connection (z Lab 04)
- Import: Wybierz OpenAPI spec dla KRS API
- Add
-
Create agent
- Test KRS Agent:
- Nowy thread → Pytanie:
"Pobierz dane firmy KRS 0000028860" - Oczekiwana odpowiedź: Dane PKN ORLEN S.A. (nazwa, NIP, adres, etc.)
- ✅ Jeśli działa - KRS Agent gotowy!
- Nowy thread → Pytanie:
Zapisz Agent ID:
- Kliknij na agenta w liście → Skopiuj Agent ID (np.
asst_abc123xyz) - Będzie potrzebny w Kroku 4
Krok 2: Company API Agent (NOWY)
Teraz utworzymy nowego sub-agenta do zarządzania lokalną bazą firm.
- AI Foundry Portal → Agents → + Create agent
Konfiguracja:
| Pole | Wartość |
|---|---|
| Name | company_api_agent |
| Description | Manages local company database - saves, retrieves, updates, and deletes company records |
| Model | gpt-4.1-mini-<INICJAŁ> |
| Instructions | Zobacz poniżej ⬇️ |
Instructions dla Company API Agent:
Jesteś wyspecjalizowanym agentem do zarządzania lokalną bazą danych firm.
TWOJE ZADANIE:
- Zapisywanie firm do bazy danych
- Odczytywanie firm z bazy danych
- Aktualizacja i usuwanie firm
NARZĘDZIA (Company API):
- get-companies: Lista wszystkich firm w bazie
- post-companies: Dodaj nową firmę (ID generowane automatycznie)
- get-companies-id: Pobierz firmę po ID
- patch-companies-id: Aktualizuj wybrane pola firmy
- delete-companies-id: Usuń firmę po ID
ZASADY:
1. Gdy dostajesz prośbę "zapisz firmę" - użyj post-companies
2. Dane firmy MUSZĄ zawierać: nazwa, nip, krs, regon, adres
3. Gdy dostajesz prośbę "jakie firmy w bazie" - użyj get-companies
4. Przy aktualizacji użyj patch-companies-id (potrzebujesz ID firmy)
5. Zwracaj przyjazne komunikaty o sukcesie/błędzie
FORMAT DANYCH dla POST/PATCH:
{
"nazwa": "nazwa firmy",
"nip": "1234567890",
"krs": "0000123456",
"regon": "123456789",
"adres": "ul. Przykładowa 1, 00-001 Warszawa"
}
KOMUNIKATY:
- Po zapisie: "Firma [nazwa] została zapisana do bazy z ID: [id]"
- Po liście: "W bazie znajduje się [N] firm: [lista nazw]"
- Po aktualizacji: "Firma [nazwa] została zaktualizowana"
- Po usunięciu: "Firma z ID [id] została usunięta"
- Actions → Add action → OpenAPI 3.0 specification tool
- Tool details:
- Name:
company_api(bez spacji) - Description:
Manages local company database - saves, retrieves, updates, and deletes company records
- Name:
- OpenAPI spec:
- Otwórz plik
company-api.json(wyeksportowany w Kroku 1 przygotowania) w edytorze tekstowym - Skopiuj całą jego zawartość
- Wklej zawartość JSON do pola tekstowego w portalu
- Otwórz plik
- Authentication:
- Type: Connection
- Connection: Wybierz company-api-connection (utworzony w Kroku 2 przygotowania)
-
Add
-
Create agent
- Test Company API Agent:
Test 1: Lista firm (pusta baza)
- Pytanie:
"Jakie firmy są w bazie?" - Oczekiwana odpowiedź:
"W bazie znajduje się 0 firm"lub podobna
Test 2: Dodanie firmy ręcznie
- Pytanie:
```
Dodaj firmę do bazy:
- Nazwa: Test Sp. z o.o.
- NIP: 1234567890
- KRS: 0000111111
- REGON: 123456789
- Adres: ul. Testowa 1, 00-001 Warszawa ```
- Oczekiwana odpowiedź:
"Firma Test Sp. z o.o. została zapisana do bazy z ID: 1"
Test 3: Lista firm (po dodaniu)
- Pytanie:
"Jakie firmy są w bazie?" - Oczekiwana odpowiedź:
"W bazie znajduje się 1 firma: Test Sp. z o.o."
✅ Jeśli wszystkie testy przeszły - Company API Agent gotowy!
Zapisz Agent ID:
- Skopiuj Agent ID dla
company_api_agent - Będzie potrzebny w następnej części
Lab Część 2: Utworzenie Orchestrator Agent
Teraz utworzymy głównego agenta, który będzie koordynował pracę KRS Agent i Company API Agent.
Krok 3: Utworzenie Orchestrator Agent
- AI Foundry Portal → Agents → + Create agent
Konfiguracja:
| Pole | Wartość |
|---|---|
| Name | orchestrator_agent |
| Description | Main coordinator that delegates tasks to specialized sub-agents (KRS and Company API) |
| Model | gpt-4.1-mini |
| Instructions | Zobacz poniżej ⬇️ |
Instructions dla Orchestrator Agent:
Jesteś głównym agentem koordynującym pracę wyspecjalizowanych sub-agentów.
TWOJE SUB-AGENCI:
1. **krs_agent** - pobiera dane firm z Krajowego Rejestru Sądowego (KRS)
2. **company_api_agent** - zarządza lokalną bazą danych firm (dodawanie, odczyt, aktualizacja, usuwanie)
TWOJA ROLA:
Analizujesz zapytania użytkownika i DELEGUJ zadania do odpowiednich sub-agentów.
NIE wykonuj zadań samodzielnie - ZAWSZE deleguj do sub-agentów.
SCENARIUSZE:
**Scenariusz 1: Dodanie firmy po numerze KRS**
Użytkownik: "Dodaj firmę KRS 0000028860 do bazy"
Flow:
1. Deleguj do krs_agent → pobierz dane z KRS (podaj numer KRS)
2. Poczekaj na odpowiedź z danymi firmy
3. Deleguj do company_api_agent → zapisz firmę do bazy używając danych z KRS
4. Podsumuj: "Firma [nazwa] została pobrana z KRS i zapisana do lokalnej bazy z ID: [id]"
**Scenariusz 2: Listowanie firm**
Użytkownik: "Jakie firmy mam w bazie?"
Flow:
1. Deleguj do company_api_agent → pobierz listę firm (get-companies)
2. Pokaż użytkownikowi listę w czytelnym formacie (tabela lub lista punktowana)
**Scenariusz 3: Sprawdzenie firmy bez zapisywania**
Użytkownik: "Sprawdź firmę KRS 0000028860"
Flow:
1. Deleguj do krs_agent → pobierz dane z KRS
2. Pokaż użytkownikowi dane BEZ wywoływania company_api_agent (nie zapisuj do bazy)
**Scenariusz 4: Aktualizacja firmy w bazie**
Użytkownik: "Zaktualizuj adres firmy ID 1 na 'ul. Nowa 10, 00-001 Warszawa'"
Flow:
1. Deleguj do company_api_agent → patch-companies-id z nowym adresem (podaj ID i nowe dane)
2. Podsumuj: "Adres firmy został zaktualizowany"
**Scenariusz 5: Usunięcie firmy**
Użytkownik: "Usuń firmę ID 1"
Flow:
1. Deleguj do company_api_agent → delete-companies-id (podaj ID)
2. Podsumuj: "Firma z ID 1 została usunięta z bazy"
**Scenariusz 6: Multi-step (kilka firm)**
Użytkownik: "Dodaj 3 firmy: KRS 0000028860, KRS 0000033427, KRS 0000011288"
Flow:
1. Dla każdego numeru KRS wykonaj Scenariusz 1:
- krs_agent → pobierz dane
- company_api_agent → zapisz do bazy
2. Podsumuj: "Dodałem 3 firmy do bazy: [lista nazw z ID]"
ZASADY DELEGACJI:
- Zapytania o KRS (numery KRS, odpisy, dane z rejestru) → krs_agent
- Operacje na bazie (zapis, lista, aktualizacja, usuwanie) → company_api_agent
- NIE wykonuj zadań samodzielnie - ZAWSZE deleguj do sub-agentów
- Czekaj na odpowiedź sub-agenta przed kolejnym krokiem
- Kompiluj odpowiedzi sub-agentów w finalną odpowiedź dla użytkownika
KOMUNIKACJA Z UŻYTKOWNIKIEM:
- Bądź przyjazny i opisuj co robisz: "Pobieram dane z KRS... Zapisuję do bazy..."
- Pokazuj podsumowania: "Znalazłem firmę X w KRS i zapisałem do bazy z ID Y"
- Formatuj odpowiedzi używając Markdown:
- Nagłówki: ### Wyniki
- Listy: - Firma 1, - Firma 2
- Tabele dla wielu firm
- Jeśli sub-agent zwróci błąd (np. firma nie znaleziona w KRS) - poinformuj użytkownika wyraźnie
ERROR HANDLING:
- Jeśli krs_agent zwróci "firma nie znaleziona" → Powiedz użytkownikowi i NIE próbuj zapisywać do bazy
- Jeśli company_api_agent zwróci błąd (np. 404, 400) → Wyjaśnij problem użytkownikowi
- Jeśli brak numeru KRS w zapytaniu → Poproś użytkownika o podanie numeru KRS
- Tools → ⚠️ NIE dodawaj żadnych OpenAPI tools!
- Orchestrator nie ma własnych API tools
- Ma tylko Connected Agent tools (następny krok)
- Create agent
Krok 4: Dodanie Connected Agents do Orchestratora
Teraz podłączymy KRS Agent i Company API Agent jako tools Orchestratora.
- Otwórz Orchestrator Agent (agent
orchestrator_agent) - Tools → + Add tool → Connected Agent
Dodanie KRS Agent:
| Pole | Wartość |
|---|---|
| Connected Agent | Wybierz krs_agent z listy (lub wklej Agent ID) |
| Name | krs_agent ⚠️ Ważne: dokładnie ta nazwa! |
| Description | Retrieves company data from Polish National Court Register (KRS) based on KRS number. Use when user asks for company data from KRS registry. |
Kliknij Add
- Tools → + Add tool → Connected Agent (drugi sub-agent)
Dodanie Company API Agent:
| Pole | Wartość |
|---|---|
| Connected Agent | Wybierz company_api_agent z listy (lub wklej Agent ID) |
| Name | company_api_agent ⚠️ Ważne: dokładnie ta nazwa! |
| Description | Manages local company database - saves, retrieves, updates, and deletes company records. Use when user wants to save companies to database, list companies, or modify database. |
Kliknij Add
- Save agent (jeśli są niezapisane zmiany)
Dlaczego nazwa i opis są ważne?
- Name: Model używa nazwy do wywołania tool (musi pasować do nazwy w instructions!)
- Description: Model decyduje KIEDY użyć tool na podstawie description (musi być konkretny!)
Sprawdzenie:
- Orchestrator Agent powinien mieć 2 tools typu Connected Agent:
- ✅
krs_agent - ✅
company_api_agent
- ✅
- 0 tools typu OpenAPI (Orchestrator nie ma własnych API tools)
Krok 5: Test podstawowego flow
Teraz przetestujemy czy cała orkiestracja działa.
Test: Dodanie firmy z KRS do bazy
- Otwórz Orchestrator Agent
- Nowy thread
- Pytanie:
Dodaj firmę PKN ORLEN (KRS 0000028860) do mojej bazy danych
Oczekiwany flow:
flowchart LR
U[User Query] --> O[Orchestrator<br/>analyzes]
O -->|"Get data for<br/>KRS 0000028860"| K[KRS Agent]
K -->|KRS API call| K2[Returns:<br/>PKN ORLEN data]
K2 --> O
O -->|"Save company<br/>with data"| C[Company API<br/>Agent]
C -->|POST /companies| C2[Returns:<br/>ID: 1]
C2 --> O
O --> R[Final response<br/>to user]
style O fill:#4A90E2,color:#fff
style K fill:#50C878,color:#fff
style C fill:#9B59B6,color:#fff
Oczekiwana odpowiedź (przykład):
Pobieram dane firmy z KRS...
✅ Znalazłem firmę w rejestrze KRS:
- Nazwa: PKN ORLEN S.A.
- NIP: 7740001454
- KRS: 0000028860
- REGON: 610188201
- Adres: ul. Chemików 7, 09-411 Płock
Zapisuję firmę do lokalnej bazy danych...
✅ Firma PKN ORLEN S.A. została zapisana do bazy z ID: 1
Co sprawdzić w Thread logs:
- Delegacja do krs_agent:
- Log:
Calling connected agent: krs_agent - Tool call:
getKrsOdpisAktualnyz parametrami{krs: "0000028860", rejestr: "P"}
- Log:
- Odpowiedź krs_agent:
- Widoczna TYLKO dla orchestratora (nie dla użytkownika bezpośrednio)
- Zawiera dane PKN ORLEN
- Delegacja do company_api_agent:
- Log:
Calling connected agent: company_api_agent - Tool call:
post-companiesz body zawierającym dane PKN ORLEN
- Log:
- Odpowiedź company_api_agent:
- Zawiera ID zapisanej firmy (np. “1”)
- Final response:
- Orchestrator kompiluje odpowiedzi sub-agentów
- Zwraca podsumowanie użytkownikowi
✅ Jeśli test przeszedł - Twój system multi-agent działa!
Lab Część 3: Testowanie scenariuszy
Teraz przetestujemy różne scenariusze użycia naszego systemu multi-agent.
Scenariusz 1: Dodanie firmy po numerze KRS ✅ (już przetestowany)
Input:
Dodaj firmę PKN ORLEN (KRS 0000028860) do bazy
Expected flow:
- Orchestrator → krs_agent (pobierz dane)
- Orchestrator → company_api_agent (zapisz do bazy)
- Orchestrator → user (potwierdzenie)
Success criteria:
- ✅ Firma pobrana z KRS
- ✅ Firma zapisana w Company API z ID
- ✅ Użytkownik otrzymał potwierdzenie
Scenariusz 2: Listowanie firm w bazie
Input:
Jakie firmy mam w mojej bazie danych?
Expected flow:
- Orchestrator → company_api_agent (GET /companies)
- Orchestrator → user (sformatowana lista)
Expected response (przykład):
### Firmy w bazie danych
W bazie znajduje się 1 firma:
| ID | Nazwa | NIP | KRS | Adres |
|----|-------|-----|-----|-------|
| 1 | PKN ORLEN S.A. | 7740001454 | 0000028860 | ul. Chemików 7, 09-411 Płock |
Success criteria:
- ✅ Lista wyświetlona w czytelnym formacie
- ✅ Wszystkie firmy z bazy pokazane
Scenariusz 3: Sprawdzenie firmy bez zapisywania
Input:
Sprawdź dane firmy KRS 0000033427 ale NIE zapisuj do bazy
Expected flow:
- Orchestrator → krs_agent (pobierz dane)
- Orchestrator → user (dane firmy BEZ wywoływania company_api_agent)
Expected response (przykład):
Dane firmy z rejestru KRS:
- Nazwa: MICROSOFT SP. Z O.O.
- NIP: 5260250995
- KRS: 0000033427
- REGON: 012072970
- Adres: ul. Postępu 18, 02-676 Warszawa
Firma NIE została zapisana do bazy (zgodnie z Twoją prośbą).
Success criteria:
- ✅ Dane z KRS pobrane
- ✅ Company API Agent NIE został wywołany
- ✅ Brak nowego rekordu w bazie
Scenariusz 4: Multi-step (dodanie wielu firm)
Input:
Dodaj do bazy 3 firmy:
1. KRS 0000028860 (PKN ORLEN)
2. KRS 0000033427 (Microsoft)
3. KRS 0000011288 (Samsung)
Expected flow:
- Loop 3x:
- Orchestrator → krs_agent (firma 1)
- Orchestrator → company_api_agent (zapis 1)
- Orchestrator → krs_agent (firma 2)
- Orchestrator → company_api_agent (zapis 2)
- Orchestrator → krs_agent (firma 3)
- Orchestrator → company_api_agent (zapis 3)
- Orchestrator → user (podsumowanie)
Expected response (przykład):
Dodałem 3 firmy do bazy danych:
1. ✅ PKN ORLEN S.A. (KRS: 0000028860) - ID: 1
2. ✅ MICROSOFT SP. Z O.O. (KRS: 0000033427) - ID: 2
3. ✅ SAMSUNG ELECTRONICS POLSKA SP. Z O.O. (KRS: 0000011288) - ID: 3
Wszystkie firmy zostały pomyślnie dodane do bazy.
Success criteria:
- ✅ 3 firmy pobrane z KRS
- ✅ 3 firmy zapisane w bazie (3 nowe ID)
- ✅ Podsumowanie ze wszystkimi firmami
Scenariusz 5: Error handling (nieprawidłowy numer KRS)
Input:
Dodaj firmę KRS 9999999999 do bazy
Expected flow:
- Orchestrator → krs_agent (pobierz dane)
- krs_agent → KRS API zwraca 404
- krs_agent → orchestrator (“firma nie znaleziona”)
- Orchestrator → user (błąd, BEZ wywoływania company_api_agent)
Expected response (przykład):
❌ Nie mogę dodać firmy do bazy.
Sprawdziłem rejestr KRS i firma o numerze KRS 9999999999 nie została znaleziona.
Możliwe przyczyny:
- Nieprawidłowy numer KRS
- Firma nie istnieje w rejestrze
- Firma została wykreślona
Proszę sprawdź numer KRS i spróbuj ponownie.
Success criteria:
- ✅ Błąd wykryty przez krs_agent
- ✅ Company API Agent NIE został wywołany
- ✅ Użytkownik otrzymał jasny komunikat o błędzie
Scenariusz 6: Aktualizacja danych firmy
Input:
Zaktualizuj adres firmy ID 1 na: ul. Nowa 100, 00-001 Warszawa
Expected flow:
- Orchestrator → company_api_agent (PATCH /companies/1)
- Orchestrator → user (potwierdzenie)
Expected response (przykład):
✅ Adres firmy z ID 1 został zaktualizowany.
Nowy adres: ul. Nowa 100, 00-001 Warszawa
Success criteria:
- ✅ PATCH request wysłany z nowymi danymi
- ✅ Firma zaktualizowana w bazie
- ✅ Potwierdzenie dla użytkownika
Scenariusz 7: Usunięcie firmy
Input:
Usuń firmę ID 1 z bazy
Expected flow:
- Orchestrator → company_api_agent (DELETE /companies/1)
- Orchestrator → user (potwierdzenie)
Expected response (przykład):
✅ Firma z ID 1 została usunięta z bazy danych.
Success criteria:
- ✅ DELETE request wysłany
- ✅ Firma usunięta z bazy
- ✅ Ponowne wywołanie GET /companies nie zwraca tej firmy
Lab Część 4: Observability i Debugging
Thread Logs - śledzenie delegacji
Thread logs to kluczowe narzędzie do debugowania Connected Agents.
Jak sprawdzić Thread logs:
Otwórz thread z interakcją z Orchestratorem
Co szukać w logach:
1. Main Agent Decision
└─ "Analyzing user request..."
└─ "Deciding to call connected agent: krs_agent"
2. Connected Agent Call
└─ Tool: connected_agent
└─ Arguments: {agent_id: "asst_abc...", query: "..."}
3. Sub-Agent Execution (może być widoczny lub nie)
└─ Tool: getKrsOdpisAktualny
└─ Arguments: {krs: "0000028860", rejestr: "P"}
└─ Response: {data from KRS API}
4. Sub-Agent Response (widoczny TYLKO dla main agent)
└─ "Firma PKN ORLEN S.A., NIP: 7740001454, ..."
5. Main Agent Compilation
└─ "Received data from krs_agent"
└─ "Now calling company_api_agent to save data"
6. Another Connected Agent Call
└─ Tool: connected_agent
└─ Arguments: {agent_id: "asst_xyz...", query: "..."}
7. Final Response to User
└─ "Firma PKN ORLEN S.A. została zapisana z ID: 1"
Kluczowe punkty:
- Connected agent calls: Szukaj “connected_agent” tool w logach
- Sub-agent responses: Mogą być widoczne w “intermediate steps” (nie zawsze)
- Final compilation: Main agent łączy wyniki sub-agentów
Jak debugować typowe problemy
Problem 1: Orchestrator wykonuje zadanie sam (nie deleguje)
Symptom:
- Orchestrator próbuje sam odpowiedzieć bez wywoływania sub-agentów
- Brak “connected agent call” w thread logs
Diagnoza:
- Sprawdź instructions Orchestratora - czy jasno mówią “ZAWSZE deleguj”?
- Sprawdź description Connected Agent tools - czy są konkretne?
Fix:
- Popraw instructions - dodaj więcej scenariuszy z explicit delegation
- Popraw descriptions - bądź konkretny kiedy użyć każdego sub-agenta
Problem 2: Sub-agent nie jest wywoływany
Symptom:
- Thread logs pokazują że Orchestrator “zdecydował się delegować” ale brak wywołania
- Błąd: “Tool not found” lub podobny
Diagnoza:
- Sprawdź czy nazwa tool w instructions pasuje do nazwy w Connected Agent tool
- Instructions:
krs_agent→ Tool name:krs_agent✅ - Instructions:
KRS_Agent→ Tool name:krs_agent❌ (wielkość liter!)
- Instructions:
Fix:
- Upewnij się że nazwa w instructions == nazwa w tool definition
- Użyj snake_case konsekwentnie
Problem 3: Sub-agent zwraca błąd 401/403
Symptom:
- Sub-agent wywołuje API tool ale dostaje 401 Unauthorized lub 403 Forbidden
Diagnoza:
- Sprawdź Connection dla tego API - czy subscription key jest poprawny?
- Sprawdź w Azure Portal APIM → Subscriptions czy key jest aktywny
Fix:
- Zaktualizuj Connection z poprawnym subscription key
- Lub regeneruj key w APIM i zaktualizuj Connection
Problem 4: Orchestrator “zapomina” o wcześniejszych delegacjach
Symptom:
- Orchestrator deleguje do krs_agent ✅
- Dostaje odpowiedź ✅
- Ale potem nie wywołuje company_api_agent (zapomina o danych)
Diagnoza:
- Instructions mogą być zbyt ogólne
- Model nie rozumie że ma wykonać multi-step workflow
Fix:
- W instructions dodaj explicit multi-step scenarios:
```
Scenariusz 1: Dodaj firmę
- NAJPIERW deleguj do krs_agent
- POCZEKAJ na odpowiedź
- POTEM deleguj do company_api_agent z danymi z kroku 1 ```
Flowchart: Debugging Decision Tree
flowchart TD
Start([Problem with<br/>Connected Agents]) --> Check{What is<br/>the issue?}
Check -->|Sub-agent not called| Desc[Check tool<br/>description]
Check -->|Wrong sub-agent called| Instr[Check orchestrator<br/>instructions]
Check -->|API error 401/403| Auth[Check API<br/>connection]
Check -->|Agent does task itself| Deleg[Check delegation<br/>instructions]
Desc --> DescFix[Make description<br/>more specific]
Instr --> InstrFix[Add scenario<br/>examples]
Auth --> AuthFix[Update subscription<br/>key in connection]
Deleg --> DelegFix[Add explicit<br/>'ALWAYS delegate']
DescFix --> Test[Test again]
InstrFix --> Test
AuthFix --> Test
DelegFix --> Test
Test --> Works{Works?}
Works -->|Yes| Success([✅ Fixed!])
Works -->|No| Logs[Check thread logs<br/>for more details]
Logs --> Start
style Start fill:#E8E8E8,stroke:#666
style Success fill:#50C878,stroke:#2E7D4E,color:#fff
style Check fill:#4A90E2,stroke:#2E5C8A,color:#fff
style Test fill:#F39C12,stroke:#C87F0A,color:#fff
Best Practices
Kiedy używać Connected Agents?
✅ Używaj Connected Agents gdy:
| Scenariusz | Dlaczego multi-agent? |
|---|---|
| Wiele domen | KRS + Company DB + Accounting = 3 oddzielne sub-agenty zamiast jednego “monolitu” |
| Reużywalność | Ten sam KRS Agent w różnych orchestratorach (HR, Finance, Legal) |
| Testowanie | Łatwiej testować każdy sub-agent osobno niż jeden duży agent |
| Separation of concerns | Jasny podział odpowiedzialności - każdy agent robi jedną rzecz dobrze |
| Długie instructions | Jeśli instructions przekraczają 2000 słów - czas na podział |
❌ NIE używaj Connected Agents gdy:
| Scenariusz | Lepsze rozwiązanie |
|---|---|
| Proste zadanie | Single agent z 1-2 tools wystarczy |
| Depth > 2 | Spłaszcz architekturę - connected agents mają max depth = 2 |
| Latency critical | Każda delegacja = round-trip, single agent jest szybszy |
| Need citations | Sub-agenci nie przekazują citations - prompt engineering ma ograniczenia |
Separation of Concerns
Zasada: Każdy sub-agent odpowiada za jedną domenę.
Dobre przykłady:
- ✅ KRS Agent: TYLKO KRS API
- ✅ Company API Agent: TYLKO Company database
- ✅ Email Agent: TYLKO wysyłanie emaili
- ✅ Search Agent: TYLKO wyszukiwanie w dokumentach
Złe przykłady:
- ❌ “Universal Agent”: KRS + Company DB + Email + Search (za dużo)
- ❌ “Data Agent”: KRS + Tax Office + Court Records (3 różne API w jednym)
Reguła:
Jeśli sub-agent potrzebuje więcej niż 3 tools typu OpenAPI - prawdopodobnie robi za dużo.
Naming Conventions
Agent names:
- Format:
{domain}_{role}w snake_case - Przykłady:
- ✅
krs_agent - ✅
company_api_agent - ✅
email_sender_agent - ❌
Agent1(nie mówi co robi) - ❌
KRS-Agent(kebab-case może powodować problemy)
- ✅
Tool names (Connected Agent):
- MUSZĄ pasować do nazwy użytej w instructions
- Przykład:
Instructions: "Deleguj do krs_agent..." Tool name: "krs_agent" ✅
Descriptions:
- Bądź konkretny - model decyduje na podstawie description
- Dobre:
"Retrieves company data from Polish KRS registry based on KRS number" - Złe:
"Gets data"(zbyt ogólne)
Error Handling Patterns
Pattern 1: Sub-agent przekazuje błąd w tekście
Sub-agent instructions:
Jeśli API zwróci 404:
- Zwróć: "ERROR: Firma nie znaleziona w KRS"
Orchestrator instructions:
Jeśli sub-agent zwróci "ERROR:..." - poinformuj użytkownika i ZATRZYMAJ workflow
Pattern 2: Orchestrator waliduje przed delegacją
Jeśli użytkownik nie podał numeru KRS:
- NIE deleguj do krs_agent
- Poproś użytkownika o numer KRS
Pattern 3: Retry logic
Jeśli krs_agent zwróci timeout:
1. Spróbuj ponownie (max 2 razy)
2. Jeśli nadal błąd - poinformuj użytkownika
Limitations (Ograniczenia)
1. Maximum Depth = 2
Ograniczenie:
- Sub-agent NIE może mieć własnych connected agents
- Maksymalna głębokość to 2 poziomy
Diagram:
✅ DOZWOLONE (Depth = 2):
Main Agent
├─ Sub-Agent 1
└─ Sub-Agent 2
❌ NIEDOZWOLONE (Depth = 3):
Main Agent
└─ Sub-Agent 1
└─ Sub-Sub-Agent ← BŁĄD!
Błąd:
Assistant Tool Call Depth Error: Sub-agent cannot have connected agents
Obejście:
- Spłaszcz architekturę - usuń poziomy
- Sub-Sub-Agent zrób Sub-Agent (sibling zamiast child)
2. Citations nie są przekazywane
Ograniczenie:
- Sub-agent używa Bing Search → zwraca citations
- Main agent NIE otrzyma citations w odpowiedzi
- User nie zobaczy źródeł
Przykład:
Sub-Agent (z Bing Search):
"Według Microsoft.com, Azure AI Foundry..." [citation: microsoft.com]
Main Agent otrzyma:
"Według Microsoft.com, Azure AI Foundry..." (BEZ citation object)
Obejście (partial):
- Prompt engineering: poproś sub-agenta o załączenie źródeł w tekście
Instructions dla sub-agenta: "Jeśli używasz Bing Search - ZAWSZE podaj źródła w formacie: [Źródło: URL]" - Ale: variability (czasami działa, czasami nie)
3. Function Calling Tool nie działa
Ograniczenie:
- Local Python functions (Function Calling tool) NIE działają w connected agents
- Tylko OpenAPI Tool i Azure Functions działają
Przykład problemu:
# NIE ZADZIAŁA w sub-agencie:
def my_custom_function(data):
return process(data)
# Tool definition:
{"type": "function", "function": my_custom_function} ❌
Obejście:
- Zamiast local function → użyj OpenAPI Tool (API endpoint)
- Lub: Azure Functions (serverless HTTP endpoint)
4. Performance - Round-trip Latency
Ograniczenie:
- Każda delegacja = dodatkowy round-trip do API
- Multi-step workflow może być wolniejszy niż single agent
Przykład:
Single Agent (1 hop):
User → Agent (KRS + DB tools) → User
Czas: ~3-5 sekund
Multi-Agent (3 hops):
User → Orchestrator → KRS Agent → Orchestrator → Company API Agent → Orchestrator → User
Czas: ~8-12 sekund
Trade-off:
- ✅ Modularność i reużywalność
- ❌ Wyższa latency
Kiedy to problem:
- Real-time applications (chatbots, live support)
- High-volume scenarios (setki requestów/min)
Kiedy OK:
- Batch processing
- Back-office workflows
- Quality > speed
5. Debugging - Limited Visibility
Ograniczenie:
- Odpowiedzi sub-agentów są widoczne TYLKO dla main agent
- User nie widzi bezpośrednio co zwrócił sub-agent
- Thread logs są kluczowe (ale czasami incomplete)
Obejście:
- Main agent powinien “opowiadać” co robi:
Instructions: "Opisuj każdy krok: 'Deleguje do krs_agent...', 'Otrzymałem dane...', 'Teraz zapisuję do bazy...'" - Sprawdzaj Thread logs regularnie podczas developmentu
Podsumowanie
Co poznaliśmy w Lab 09:
✅ Connected Agents architecture:
- Main Agent (Orchestrator) + Sub-Agents (specjaliści)
- Delegation flow: User → Orchestrator → Sub-Agent → Tools → Orchestrator → User
✅ Praktyczna implementacja:
- 3 agentów: Orchestrator + KRS Agent + Company API Agent
- ConnectedAgentTool jako sposób na wywoływanie sub-agentów
- 7 scenariuszy testowych (podstawowy flow, lista, multi-step, error handling)
✅ Best Practices:
- Separation of concerns: każdy sub-agent = jedna domena
- Naming conventions: snake_case, konkretne descriptions
- Error handling: sub-agenci przekazują błędy w strukturalny sposób
✅ Limitations:
- Max depth = 2 (no sub-sub-agents)
- Citations nie są przekazywane
- Function calling tool nie działa
- Performance: każda delegacja = round-trip
Kiedy używać Connected Agents?
Używaj gdy:
- Masz wiele wyraźnie oddzielonych domen (KRS, DB, Email, etc.)
- Chcesz reużywać sub-agentów w różnych kontekstach
- System jest złożony i single agent byłby “overloaded”
NIE używaj gdy:
- Zadanie jest proste (1-2 tools wystarczą w single agent)
- Potrzebujesz depth > 2 (sub-sub-agents)
- Latency jest krytyczna