Lab 06: Python SDK - Podstawy integracji z agentem
Opis
W tym laboratorium nauczymy się komunikować z agentem używając Python SDK. Będziemy budować kod małymi kawałkami - każdy krok to kilka linijek kodu które dodasz, uruchomisz i zrozumiesz przed dodaniem kolejnego kawałka.
Ważne: NIE tworzymy agenta w kodzie. Użyjemy istniejącego agenta z Lab 05 (KRS-Agent) lub Lab 06 (NewsAgent).
Pełna dokumentacja:
Przygotowanie środowiska
Krok 1: Przygotuj katalog roboczy
Wejdź do terminala gdzie tworzyłeś katalogu w zadaniu 01 na starcie szkolenia. Powinieneś widzieć tam coś podobnego:
(venv) PS C:\workshop>
Ważne: Wszystkie kolejne kroki wykonuj z aktywowanym venv! Twój prompt powinien pokazać (venv).
Krok 2: Instalacja pakietów SDK
Zainstaluj tylko dwa pakiety:
pip install azure-ai-projects azure-identity
Co instalujemy:
azure-ai-projects- SDK do komunikacji z Azure AI Foundry Agentsazure-identity- Uwierzytelnianie (ChainedTokenCredential, EnvironmentCredential, AzureCliCredential)
Czas instalacji: ~30 sekund
Krok 3: Znajdź Project Endpoint w portalu
- Przejdź do Azure AI Foundry Portal
- Wybierz swój projekt
- Na stronie Overview znajdź Azure AI Foundry project endpoint
- Skopiuj endpoint
Format endpoint:
https://<resource-name>.services.ai.azure.com/api/projects/<project-name>
Przykład:
https://my-ai-foundry.services.ai.azure.com/api/projects/my-workshop-project
Tip: Endpoint jest w sekcji Overview na górze strony projektu, nie w Project settings.
Krok 4: Znajdź Agent ID w portalu
- W Azure AI Foundry Portal → Agents
- Kliknij na KRS-Agent (z Lab 05) lub NewsAgent (z Lab 06)
- W prawym panelu zobacz Agent ID - długi string zaczynający się od
asst_... - Skopiuj ten ID
Przykład Agent ID:
asst_abc123XYZ456def789
Krok 5: Konfiguracja uwierzytelniania
Na warsztatach używamy Azure CLI do uwierzytelnienia (najprostszy sposób dla local development).
Sposób 1: Azure CLI (warsztaty, local development)
az login
Otworzy się przeglądarka - zaloguj się tym samym kontem co w Azure AI Foundry Portal.
💡 Już zalogowany w Lab 01? Jeśli wykonałeś
az loginw Lab 01: Setup środowiska, nie musisz nic robić - jesteś już zalogowany! Możesz przejść do następnego punktu.
Sposób 2: Service Principal (produkcja, on-prem Kubernetes)
ℹ️ Na warsztatach NIE używamy: To jest informacja jak uruchomić kod w środowisku produkcyjnym (np. on-prem Kubernetes, CI/CD).
W środowisku produkcyjnym (np. klaster Kubernetes on-premises) tworzysz Service Principal i ustawiasz zmienne środowiskowe:
Linux/macOS:
export AZURE_TENANT_ID="your-tenant-id"
export AZURE_CLIENT_ID="your-client-id"
export AZURE_CLIENT_SECRET="your-client-secret"
Windows PowerShell:
$env:AZURE_TENANT_ID="your-tenant-id"
$env:AZURE_CLIENT_ID="your-client-id"
$env:AZURE_CLIENT_SECRET="your-client-secret"
Jak to działa?
SDK użyje ChainedTokenCredential który próbuje uwierzytelnienie w kolejności:
- EnvironmentCredential - sprawdza zmienne środowiskowe (Service Principal)
- AzureCliCredential - sprawdza czy jesteś zalogowany przez
az login
Jeśli pierwsze się nie uda, przechodzi do drugiego. Wystarczy jeden działający sposób.
Dokumentacja: Credential chains - Microsoft Learn
Budowanie skryptu krok po kroku
Teraz zbudujemy skrypt małymi kawałkami. Każdy krok:
- Dodasz kod
- Uruchomisz skrypt
- Zobaczysz wynik
- Zrozumiesz co się stało
- Przejdziesz do kolejnego kroku
Krok 1: Utworzenie pliku i podstawowy import
Otwórz Visual Studio Code (wpisz w terminalu w katalogu roboczym code .)
Utwórz plik agent_client.py w swoim katalogu roboczym (z aktywowanym venv!):
#!/usr/bin/env python3
"""
Podstawowa komunikacja z agentem przez SDK
"""
from azure.ai.projects import AIProjectClient
from azure.identity import ChainedTokenCredential, EnvironmentCredential, AzureCliCredential
import json
print("✓ Importy załadowane")
Uruchom:
python agent_client.py
Oczekiwany wynik:
✓ Importy załadowane
Co się stało: Sprawdziliśmy że pakiety są zainstalowane poprawnie.
Krok 2: Utworzenie klienta
Dodaj do pliku agent_client.py (pod importami):
# Project endpoint z Overview (zastąp swoim!)
PROJECT_ENDPOINT = "YOUR_PROJECT_ENDPOINT_HERE"
# ChainedTokenCredential: Service Principal → Azure CLI
print("🔧 Tworzenie credential...")
credential = ChainedTokenCredential(
EnvironmentCredential(), # Próbuje AZURE_CLIENT_ID/SECRET/TENANT_ID
AzureCliCredential() # Próbuje az login
)
# (Opcjonalne) Jeżeli masz rozszyfrowywanie ruchu na proxy (SSL interception),
# możesz wyłączyć weryfikowanie certyfikatu:
# from azure.core.pipeline.transport import RequestsTransport
# transport = RequestsTransport(connection_verify=False)
# Utworzenie klienta
print("🔧 Tworzenie klienta...")
project_client = AIProjectClient(
endpoint=PROJECT_ENDPOINT,
credential=credential
# transport=transport # Odkomentuj jeżeli używasz proxy
)
print("✓ Klient utworzony")
Zastąp YOUR_PROJECT_ENDPOINT_HERE swoim endpointem z Kroku 3 przygotowania (Overview).
Uruchom:
python agent_client.py
Oczekiwany wynik:
🔧 Tworzenie credential...
🔧 Tworzenie klienta...
✓ Klient utworzony
Co się stało:
- Utworzyliśmy
ChainedTokenCredentialktóry próbuje uwierzytelnienia w kolejności:- EnvironmentCredential (Service Principal ze zmiennych środowiskowych)
- AzureCliCredential (
az login)
- Utworzyliśmy klienta
AIProjectClientz endpointem i credential - Klient jest gotowy do komunikacji z projektem
Który credential został użyty?
- Jeśli masz zmienne środowiskowe (
AZURE_CLIENT_ID,AZURE_CLIENT_SECRET,AZURE_TENANT_ID) → użyje EnvironmentCredential - Jeśli nie ma zmiennych ale jesteś zalogowany przez
az login→ użyje AzureCliCredential - Jeśli żaden nie działa → błąd uwierzytelnienia
Tip: ChainedTokenCredential próbuje w kolejności i używa pierwszego który zadziała.
Krok 3: Listowanie agentów (weryfikacja połączenia)
Dodaj kolejny kawałek kodu:
# Listowanie agentów w projekcie
print("\n📋 Listowanie agentów...")
agents = project_client.agents.list_agents()
print("✓ Agenci w projekcie:")
for agent in agents:
print(f" - {agent.name} (ID: {agent.id})")
print(f" Model: {agent.model}")
Uruchom:
python agent_client.py
Oczekiwany wynik:
📋 Listowanie agentów...
✓ Agenty w projekcie:
- KRS-Agent (ID: asst_abc123...)
Model: gpt-4.1-mini
- NewsAgent (ID: asst_xyz789...)
Model: gpt-4.1-mini
Co się stało:
- Wywołaliśmy
list_agents()- pobraliśmy listę wszystkich agentów w projekcie - Widzimy agentów utworzonych w Lab 05 i Lab 06
- Każdy agent ma swoją nazwę, ID i model
Znajdź Agent ID którego użyjesz (np. KRS-Agent).
Krok 4: Utworzenie thread (wątku konwersacji)
Dodaj kod:
# ID agenta z którym będziemy rozmawiać (zastąp swoim!)
AGENT_ID = "YOUR_AGENT_ID_HERE"
# Utworzenie thread (wątku konwersacji)
print(f"\n💬 Tworzenie thread dla agenta {AGENT_ID}...")
thread = project_client.agents.threads.create()
print("✓ Thread utworzony")
print(f" Thread ID: {thread.id}")
Zastąp YOUR_AGENT_ID_HERE Agent ID z poprzedniego kroku (np. KRS-Agent).
Uruchom:
python agent_client.py
Oczekiwany wynik:
💬 Tworzenie thread dla agenta asst_abc123...
✓ Thread utworzony
Thread ID: thread_xyz456...
Co się stało:
- Utworzyliśmy thread = wątek konwersacji
- Thread to kontener na wiadomości między userem a agentem
- Thread ID będzie używany we wszystkich kolejnych operacjach
- Thread żyje dopóki go nie skasujemy - możesz wrócić do niego później
Wyjaśnienie: Thread ≠ wątek programistyczny. To kontekst konwersacji - wszystkie wiadomości w jednym threadzie są widoczne dla agenta.
Krok 5: Dodanie wiadomości użytkownika
Dodaj kod:
# Dodanie wiadomości użytkownika
print("\n📝 Dodawanie wiadomości użytkownika...")
message = project_client.agents.messages.create(
thread_id=thread.id,
role="user",
content="Podaj dane firmy KRS 0000028860"
)
print("✓ Wiadomość dodana")
print(f" Message ID: {message.id}")
print(f" Content: {message.content[0].text.value}")
Uruchom:
python agent_client.py
Oczekiwany wynik:
📝 Dodawanie wiadomości użytkownika...
✓ Wiadomość dodana
Message ID: msg_abc123...
Content: Podaj dane firmy KRS 0000028860
Co się stało:
- Dodaliśmy wiadomość do thread z rolą
user - Wiadomość jest zapisana w threadzie ale agent jej jeszcze nie widział
- Agent odpowie dopiero jak uruchomimy run
Ważne: Dodanie message NIE wywołuje agenta! To tylko zapisanie wiadomości w threadzie. Agent odpowie w następnym kroku.
Krok 6: Uruchomienie agenta (run)
Dodaj kod:
# Uruchomienie agenta (run)
print("\n▶️ Uruchamianie agenta...")
run = project_client.agents.runs.create_and_process(
thread_id=thread.id,
agent_id=AGENT_ID
)
print("✓ Run zakończony")
print(f" Run ID: {run.id}")
print(f" Status: {run.status}")
Uruchom:
python agent_client.py
Oczekiwany wynik:
▶️ Uruchamianie agenta...
✓ Run zakończony
Run ID: run_xyz789...
Status: completed
To może potrwać 5-15 sekund! Agent:
- Odczytuje wiadomość z threadu
- Analizuje pytanie
- Wywołuje KRS API tool (jeśli używasz KRS-Agent)
- Generuje odpowiedź
- Zapisuje odpowiedź w threadzie
Co się stało:
- Wywołaliśmy
create_and_process_run()- to wygodna metoda która:- Utworzyła run (wywołanie agenta)
- Poczekała aż agent skończy (polling)
- Zwróciła wynik
- Status
completed= agent odpowiedział pomyślnie - Odpowiedź agenta jest zapisana w threadzie
Wyjaśnienie:
create_and_process_run()blokuje wykonanie dopóki agent nie skończy. Jest teżcreate_run()+ manual polling - do tego wrócimy później.
Krok 7: Odczytanie odpowiedzi agenta
Dodaj kod:
# Odczytanie wiadomości z threadu
print("\n📨 Odczytywanie wiadomości...")
messages = project_client.agents.messages.list(thread_id=thread.id)
print("✓ Konwersacja:")
print("-" * 60)
for msg in messages:
role = "User" if msg.role == "user" else "Agent"
content = msg.content[0].text.value if msg.content else "(brak treści)"
print(f"\n{role}:")
print(content)
print("-" * 60)
Uruchom:
python agent_client.py
Oczekiwany wynik:
📨 Odczytywanie wiadomości...
✓ Konwersacja:
------------------------------------------------------------
User:
Podaj dane firmy KRS 0000028860
Agent:
Oto dane firmy z KRS 0000028860:
**Nazwa:** ORLEN Spółka Akcyjna
**Siedziba:** Płock, ul. Chemików 7, 09-411
**NIP:** 7740001454
**REGON:** 610188201
...
------------------------------------------------------------
Co się stało:
- Wywołaliśmy
list_messages()- pobraliśmy wszystkie wiadomości z threadu - Wiadomości są w kolejności od najnowszej do najstarszej
- Widzimy zarówno pytanie usera jak i odpowiedź agenta
- Agent wywołał KRS API tool i zwrócił dane firmy
Krok 8: Szczegóły run (tokeny i tool calls)
Dodaj kod:
# Szczegóły run
print("\n🔍 Szczegóły run:")
print(f" Model: {run.model}")
if run.usage:
print(f" Tokeny:")
print(f" - Prompt: {run.usage.prompt_tokens}")
print(f" - Completion: {run.usage.completion_tokens}")
print(f" - Total: {run.usage.total_tokens}")
# Tool calls
print("\n🔧 Tool calls:")
run_steps = project_client.agents.run_steps.list(
thread_id=thread.id,
run_id=run.id
)
for step in run_steps:
if step.type == "tool_calls":
for tool_call in step.step_details.tool_calls:
print(f"\n ━━━ Tool Type: {tool_call.type} ━━━")
print(f" Tool Call ID: {tool_call.id}")
# Konwertuj do dict żeby łatwiej dostać się do danych
tool_dict = tool_call.as_dict() if hasattr(tool_call, 'as_dict') else {}
# Dla typu 'openapi' dane są w kluczu 'function'
func_data = tool_dict.get('function', {})
if func_data:
# Nazwa funkcji/operacji
name = func_data.get('name', 'unknown')
print(f" Function/Operation: {name}")
# Arguments - pretty print JSON z wcięciami
arguments = func_data.get('arguments', '')
if arguments:
print(f"\n 📥 Arguments:")
try:
args = json.loads(arguments)
args_json = json.dumps(args, ensure_ascii=False, indent=2)
for line in args_json.split('\n'):
print(f" {line}")
except:
print(f" {arguments}")
# Output - zwiększony limit do 1500 znaków
output = func_data.get('output', '')
if output:
print(f"\n 📤 Output:")
output_str = str(output)
max_length = 1500
if len(output_str) > max_length:
output_str = output_str[:max_length] + f"\n ... (skrócono, pełna długość: {len(output_str)} znaków)"
# Multi-line output z wcięciem
for line in output_str.split('\n'):
print(f" {line}")
else:
print(f"\n 📤 Output: (brak)")
else:
print(f" ⚠️ Brak danych funkcji w tool_call")
Uruchom:
python agent_client.py
Oczekiwany wynik:
🔍 Szczegóły run:
Model: gpt-4.1-mini
Tokeny:
- Prompt: 20561
- Completion: 856
- Total: 21417
🔧 Tool calls:
━━━ Tool Type: openapi ━━━
Tool Call ID: call_abc123xyz456
Function/Operation: krs_api_getKrsOdpisAktualny
📥 Arguments:
{
"krs": "0000028860",
"rejestr": "P"
}
📤 Output:
{'odpis': {'rodzaj': 'Aktualny', 'naglowekA': {'rejestr': 'RejP',
'numerKRS': '0000028860', 'dataCzasOdpisu': '13.11.2025 14:34:58',
'stanZDnia': '31.10.2025', 'dataRejestracjiWKRS': '19.07.2001',
'numerOstatniegoWpisu': 201, 'dataOstatniegoWpisu': '31.10.2025',
...
... (skrócono, pełna długość: 45234 znaków)
Co się stało:
run.usagepokazuje ile tokenów zostało zużytych (ważne dla kosztów!)run_steps.list()pokazuje kroki wykonania - widzimy szczegóły tool calls:- Tool type:
openapi(narzędzie OpenAPI) - Tool Call ID: Unikalny identyfikator wywołania
- Function/Operation:
krs_api_getKrsOdpisAktualny- nazwa operacji z OpenAPI spec - Arguments: Parametry przekazane do API w sformatowanym JSON (z wcięciami dla czytelności)
- Output: Odpowiedź z API (pierwsze 1500 znaków, całość może mieć dziesiątki tysięcy znaków)
- Tool type:
- Kod używa
tool_call.as_dict()żeby dostać się do danych funkcji dla typuopenapi - JSON w arguments jest formatowany używając
json.loads()ijson.dumps(indent=2) - To narzędzie OpenAPI (KRS API) dodane w Lab 04
Tip: Run steps to świetne narzędzie do debugowania - widzisz dokładnie jakie argumenty agent przekazał do narzędzia i co narzędzie zwróciło!
Krok 9: Zarządzanie threads (referencja)
Po zakończeniu pracy z agentem, warto wiedzieć jak zarządzać threads. NIE dodawaj tego kodu do swojego skryptu - to tylko informacja referencyjna.
Listowanie wszystkich threads
# Pobranie wszystkich threads w projekcie
threads = project_client.agents.threads.list()
print("📋 Wszystkie threads:")
for thread in threads:
print(f" - Thread ID: {thread.id}")
print(f" Created: {thread.created_at}")
Kiedy używać:
- Chcesz zobaczyć wszystkie konwersacje w projekcie
- Debugujesz problemy z threads
- Sprzątasz stare threads
Usuwanie thread
# Usunięcie konkretnego thread
project_client.agents.threads.delete(thread_id=thread.id)
print("✓ Thread usunięty")
Kiedy używać:
- Development: Po każdym teście (oszczędność zasobów)
- Production: Gdy konwersacja się zakończyła i nie potrzebujesz historii
- Nigdy: Gdy chcesz zachować historię dla audytu lub kontynuacji
Ważne: Threads żyją dopóki ich nie skasujesz. W development zawsze kasuj thread’y po użyciu. W produkcji decyduj na podstawie business requirements.
Thread lifecycle:
create → add messages → runs → ... → delete (opcjonalnie)
↓
reuse (multi-turn conversation)
Kluczowe koncepty
ChainedTokenCredential vs DefaultAzureCredential
W tym labie używamy ChainedTokenCredential dla pełnej kontroli nad uwierzytelnianiem:
from azure.identity import ChainedTokenCredential, EnvironmentCredential, AzureCliCredential
credential = ChainedTokenCredential(
EnvironmentCredential(), # Service Principal (AZURE_CLIENT_ID/SECRET/TENANT_ID)
AzureCliCredential() # Azure CLI (az login)
)
Zalety ChainedTokenCredential:
- ✅ Pełna kontrola nad kolejnością credentials
- ✅ Optymalna wydajność (tylko credentials których używasz)
- ✅ Łatwiejsze debugowanie (wiesz dokładnie co próbuje)
- ✅ Jasna logika (najpierw Service Principal, potem Azure CLI)
DefaultAzureCredential (alternatywa):
from azure.identity import DefaultAzureCredential
credential = DefaultAzureCredential()
- Prekonfigurowany łańcuch ~10 credentials
- Łatwiejszy dla początkujących (zero konfiguracji)
- Może być wolniejszy (próbuje credentials które nie są potrzebne)
- Trudniejsze debugowanie błędów uwierzytelnienia
Nasza kolejność w ChainedTokenCredential:
- EnvironmentCredential - zmienne środowiskowe (
AZURE_CLIENT_ID,AZURE_CLIENT_SECRET,AZURE_TENANT_ID)- Dla: produkcja, CI/CD, Service Principal
- Najszybszy (brak zewnętrznych wywołań)
- AzureCliCredential -
az login- Dla: local development
- Wygodny dla developerów
Dla produkcji w Azure: Dodaj ManagedIdentityCredential na początku łańcucha:
credential = ChainedTokenCredential(
ManagedIdentityCredential(), # Azure Managed Identity (App Service, VM, AKS)
EnvironmentCredential(),
AzureCliCredential()
)
Więcej informacji: Credential chains - Microsoft Docs
Thread lifecycle
create_thread() → add messages → create_run → ... → delete_thread()
Kiedy tworzyć nowy thread:
- Nowa sesja czatu
- Zmiana kontekstu konwersacji
- User wybrał “Reset” w UI
Kiedy reużywać thread:
- Multi-turn conversation (follow-up questions)
- User kontynuuje rozmowę
- Chcesz zachować historię
Run statuses
| Status | Znaczenie | Co robić |
|---|---|---|
queued |
Czeka na wykonanie | Poczekaj |
in_progress |
Agent pracuje | Poczekaj |
requires_action |
Wymaga approval (MCP) | Wyślij approval |
completed |
✓ Sukces | Odczytaj odpowiedź |
failed |
✗ Błąd | Sprawdź run.last_error |
cancelled |
User anulował | - |
expired |
Timeout (default 10 min) | Retry |
Message roles
user- Wiadomości od end-useraassistant- Odpowiedzi agentasystem- Wewnętrzne (nie pokazywane userowi)
Praktyka: Dodatkowe zadania
Zadanie 1: Multi-turn conversation
Zmodyfikuj skrypt aby zadać dwa pytania w tym samym threadzie:
- “Podaj dane firmy KRS 0000028860”
- “Jaki jest adres tej firmy?”
Cel: Agent powinien zrozumieć że “tej firmy” odnosi się do Orlen S.A. z pierwszego pytania.
Hint (kliknij aby zobaczyć)
```python # Pierwsze pytanie (już masz) message1 = project_client.agents.messages.create(...) run1 = project_client.agents.runs.create_and_process(...) # Drugie pytanie (ten sam thread!) message2 = project_client.agents.messages.create( thread_id=thread.id, # TEN SAM thread role="user", content="Jaki jest adres tej firmy?" ) run2 = project_client.agents.runs.create_and_process( thread_id=thread.id, agent_id=AGENT_ID ) ```Zadanie 2: Error handling
Co się stanie jak podasz nieprawidłowy KRS?
Przetestuj:
content="Podaj dane firmy KRS 9999999999" # Nieprawidłowy KRS
Cel: Sprawdź run.status i run.last_error jeśli status = failed.
Zadanie 3: NewsAgent z Bing Search
Jeśli masz NewsAgent (Lab 06), przetestuj pytanie wymagające Bing Search:
content="Jakie są najnowsze wiadomości o AI?"
Sprawdź w run steps czy agent wywołał bing_grounding.
Troubleshooting
Problem: “EnvironmentCredential authentication unavailable”
Przyczyna: ChainedTokenCredential próbował EnvironmentCredential ale nie ma zmiennych środowiskowych Service Principal.
To jest OK! ChainedTokenCredential próbuje kolejno:
- EnvironmentCredential - jeśli nie ma zmiennych, przechodzi dalej
- AzureCliCredential - używa
az login
Rozwiązanie: Jeśli widzisz ten warning ale skrypt działa - wszystko jest OK. Używa AzureCliCredential.
Jeśli chcesz usunąć warning, ustaw zmienne środowiskowe Service Principal (jeśli je masz):
export AZURE_TENANT_ID="your-tenant-id"
export AZURE_CLIENT_ID="your-client-id"
export AZURE_CLIENT_SECRET="your-client-secret"
Problem: “ChainedTokenCredential failed to retrieve a token”
Przyczyna: Wszystkie credentials w łańcuchu failed (brak ani Service Principal ani az login).
Rozwiązanie:
# Sprawdź czy jesteś zalogowany
az account show
# Jeśli nie, zaloguj się
az login
# Uruchom skrypt ponownie
python agent_client.py
Problem: “Unauthorized” lub “AuthenticationError”
Przyczyna: Jesteś zalogowany ale nie masz dostępu do projektu.
Rozwiązanie:
- Sprawdź czy używasz właściwego account:
az account show - Jeśli to niewłaściwy account, zmień:
az login --tenant YOUR_TENANT_ID - Sprawdź czy masz rolę Azure AI Developer lub Azure AI User w projekcie (poproś prowadzącego)
Problem: Agent ID not found
Przyczyna: Nieprawidłowy Agent ID lub agent w innym projekcie.
Rozwiązanie:
- Sprawdź Agent ID w portalu
- Upewnij się że używasz właściwego connection stringa (projekt z tym agentem)
Problem: “Thread not found”
Przyczyna: Próbujesz użyć usuniętego threadu.
Rozwiązanie:
- Usuń linię
delete_thread()jeśli chcesz używać threadu później - Lub zapisz thread ID przed usunięciem
Podsumowanie
W tym labie nauczyliśmy się:
✅ Setup: Instalacja SDK, znalezienie connection string i Agent ID
✅ Client: Utworzenie AIProjectClient z DefaultAzureCredential
✅ Listowanie agentów: Weryfikacja połączenia
✅ Thread: Utworzenie wątku konwersacji
✅ Message: Dodanie wiadomości użytkownika
✅ Run: Uruchomienie agenta i polling
✅ Response: Odczytanie odpowiedzi z threadu
✅ Details: Tokeny i tool calls w run steps
✅ Cleanup: Usuwanie thread
Kluczowe wnioski:
- Budowaliśmy kod małymi kawałkami - każdy krok osobno
- NIE tworzyliśmy agenta w kodzie - użyliśmy istniejącego
- Thread = kontener na wiadomości, reużywalny
- Run = pojedyncze wywołanie agenta, może trwać kilka sekund
- Run steps = debugging tool - widzimy co agent zrobił
Next step: Lab 08 - Structured Output z Pydantic