Lab 11: Wdrażanie agenta z kodu (Create/Update)

Opis

W tym laboratorium nauczymy się automatyzować tworzenie i aktualizację agentów używając Python SDK. Będziemy budować skrypt małymi kawałkami - każdy krok to kilka linijek kodu które dodasz, uruchomisz i zrozumiesz przed dodaniem kolejnego kawałka.

Co zbudujemy:

  • Skrypt który ładuje instrukcje agenta z pliku Markdown
  • Skrypt który ładuje OpenAPI spec z pliku JSON
  • Pattern create-or-update - sprawdza czy agent istnieje i tworzy lub aktualizuje
  • Referencjonowanie connection utworzonego w portalu
  • Konfiguracja przez zmienne środowiskowe

Zalety tego podejścia:

  • ✅ Infrastructure as Code - wersjonowanie agentów w git
  • ✅ Powtarzalność - łatwo odtworzyć agenta w różnych środowiskach
  • ✅ CI/CD ready - możliwość automatyzacji deploymentu
  • ✅ Prawdziwy update - agent ID się nie zmienia
  • ✅ Separacja concerns - instructions i spec w osobnych plikach

Przygotowanie

Krok 1: Wymagania

Virtual environment:

Użyj tego samego venv co w poprzednich labach. Jeśli masz aktywny venv - zostań w nim. Jeśli nie:

# Przejdź do katalogu roboczego z Lab 06
cd c:\workshop  # lub twój katalog roboczy

# Aktywuj venv
source venv/bin/activate  # Linux/Mac
# lub
venv\Scripts\activate.bat  # Windows

Zainstaluj dodatkowy pakiet:

pip install python-dotenv

💡 Pakiety z Lab 06: Pakiety azure-ai-projects i azure-identity już masz zainstalowane z Lab 06, więc teraz tylko dodajemy python-dotenv do obsługi plików .env.

Connection w portalu:

WAŻNE: Connection MUSI być utworzony ręcznie w portalu PRZED rozpoczęciem labu!

Jeśli masz już connection z Lab 04 (krs-apim-connection-<INICJAŁ>) - użyj go.

Jeśli nie, utwórz zgodnie z instrukcjami Lab 04:

  • AI Portal (ai.azure.com) → Twój projekt → Management center → Connected resources → + New connection
  • Custom keys
  • Nazwa: krs-apim-connection-<INICJAŁ>
  • Dodaj 2 klucze (oba z tym samym API subscription key)

Azure authentication:

Jeśli wykonałeś Lab 06: Python SDK Basics, masz już skonfigurowane uwierzytelnienie!

💡 Zobacz Lab 06: Szczegółowe instrukcje uwierzytelniania znajdziesz w Lab 06 → Krok 5: Konfiguracja uwierzytelniania. Nie musisz ponownie logować się jeśli już jesteś zalogowany (az login z Lab 01 nadal działa).

Krok 2: Przygotuj pliki konfiguracyjne

Otwórz Visual Studio Code przez wpisanie code . w katalogu gdzie masz venv

Utwórz plik .env:

Zawartość .env:

# Project Endpoint - z Portal → Overview
PROJECT_ENDPOINT="https://ai-xxx.services.ai.azure.com/api/projects/your-project"

# Model deployment - z Portal → Models + endpoints → Name
MODEL_DEPLOYMENT_NAME="gpt-4.1-mini"

# Connection name - z Portal → Management center → Connected resources
CONNECTION_NAME="krs-apim-connection-<INICJAŁ>"

Gdzie znaleźć te wartości:

Zmienna Lokalizacja w portalu
PROJECT_ENDPOINT Overview → sekcja “Azure AI Foundry project endpoint”
MODEL_DEPLOYMENT_NAME Models + endpoints → kolumna “Name” (nie “Model name”!)
CONNECTION_NAME Management center → Connected resources → kolumna “Name”

Tip: Nigdy nie commituj .env do git! Dodaj do .gitignore.

Krok 3: Przygotuj plik z instrukcjami agenta

Utwórz plik krs_agent_instructions.md:

Utwórz plik krs_agent_instructions.md

Zawartość krs_agent_instructions.md:

# KRS Agent Instructions

Jesteś asystentem pomagającym sprawdzać dane firm w Krajowym Rejestrze Sądowym.

## Twoje narzędzie

- **getKrsOdpisAktualny** - pobiera aktualny odpis z KRS

## Parametry

- **krs**: numer KRS (10 cyfr, np. 0000123456)
- **rejestr**: ZAWSZE używaj "P" (rejestr przedsiębiorców)

## Proces działania

Gdy użytkownik poda numer KRS:

1. Wywołaj getKrsOdpisAktualny z parametrem rejestr="P"
2. Przedstaw dane w czytelny sposób używając formatowania Markdown
3. Jeśli API zwróci 404 - powiedz że firma nie znaleziona

## ZASADY

- ZAWSZE używaj narzędzia - nie wymyślaj danych!
- Odpowiadaj TYLKO na pytania dotyczące danych z KRS
- Formatuj odpowiedzi używając Markdown (nagłówki, listy, pogrubienia)

Dlaczego osobny plik? Łatwiej edytować, wersjonować w git, reużywać w wielu skryptach.

Krok 4: Pobierz OpenAPI spec dla KRS API

Z Azure Portal (eksport z APIM):

  1. Portal Azure → API Management → APIs → KRS API
  2. Kliknij (trzy kropki obok nazwy API)
  3. ExportOpenAPI v3 (JSON)
  4. Zapisz jako krs-api.json w katalogu roboczym

Weryfikacja pliku:

type krs-api.json #CMD
Get-Content krs-api.json #PowerShell

Powinieneś zobaczyć JSON z:

  • "openapi": "3.0.1"
  • "title": "KRS API - Krajowy Rejestr Sądowy"
  • "paths": { ... }
  • "operationId": "getKrsOdpisAktualny"

Ważne: Używaj formatu JSON, nie YAML!


Budowanie skryptu krok po kroku

Teraz zbudujemy skrypt małymi kawałkami. Każdy krok:

  1. Dodasz kod
  2. Uruchomisz skrypt
  3. Zobaczysz wynik
  4. Zrozumiesz co się stało
  5. Przejdziesz do kolejnego kroku

Krok 1: Utworzenie pliku i podstawowe importy

Utwórz plik create_agent.py w swoim katalogu roboczym (z aktywowanym venv!):

#!/usr/bin/env python3
"""
Lab 11: Create or Update Agent - Step by step
"""

import os
import json
from pathlib import Path
from azure.ai.projects import AIProjectClient
from azure.identity import DefaultAzureCredential
from azure.ai.agents.models import (
    OpenApiTool,
    OpenApiConnectionAuthDetails,
    OpenApiConnectionSecurityScheme
)
from dotenv import load_dotenv

print("✓ Importy załadowane")

Uruchom:

python create_agent.py

Oczekiwany wynik:

✓ Importy załadowane

Co się stało: Sprawdziliśmy że pakiety są zainstalowane poprawnie.


Krok 2: Załadowanie zmiennych środowiskowych

Dodaj do pliku create_agent.py (pod importami):

# Załaduj zmienne z .env
print("\n🔧 Ładowanie konfiguracji z .env...")
load_dotenv()

PROJECT_ENDPOINT = os.getenv("PROJECT_ENDPOINT")
MODEL_DEPLOYMENT_NAME = os.getenv("MODEL_DEPLOYMENT_NAME")
CONNECTION_NAME = os.getenv("CONNECTION_NAME")

print(f"   PROJECT_ENDPOINT: {PROJECT_ENDPOINT}")
print(f"   MODEL_DEPLOYMENT_NAME: {MODEL_DEPLOYMENT_NAME}")
print(f"   CONNECTION_NAME: {CONNECTION_NAME}")

# Walidacja
if not PROJECT_ENDPOINT or not MODEL_DEPLOYMENT_NAME or not CONNECTION_NAME:
    print("\n❌ BŁĄD: Brakuje zmiennych środowiskowych w .env!")
    exit(1)

print("✓ Konfiguracja załadowana")

Uruchom:

python create_agent.py

Oczekiwany wynik:

✓ Importy załadowane

🔧 Ładowanie konfiguracji z .env...
   PROJECT_ENDPOINT: https://ai-xxx.services.ai.azure.com/...
   MODEL_DEPLOYMENT_NAME: gpt-4.1-mini
   CONNECTION_NAME: krs-apim-connection-<INICJAŁ>
✓ Konfiguracja załadowana

Co się stało:

  • load_dotenv() załadował zmienne z pliku .env
  • os.getenv() odczytał wartości zmiennych
  • Walidacja sprawdziła czy wszystkie wymagane zmienne są ustawione
  • Jeśli brakuje którejkolwiek - skrypt kończy się błędem

Tip: Walidacja na początku = fail fast. Lepiej błąd na starcie niż w połowie wykonania.


Krok 3: Wczytanie instrukcji z pliku

Dodaj kolejny kawałek kodu:

# Wczytaj instrukcje agenta z pliku Markdown
print("\n📄 Wczytywanie instrukcji z pliku...")

instructions_file = Path("krs_agent_instructions.md")

if not instructions_file.exists():
    print(f"❌ BŁĄD: Nie znaleziono pliku {instructions_file}")
    exit(1)

with open(instructions_file, 'r', encoding='utf-8') as f:
    instructions = f.read()

print(f"✓ Załadowano {len(instructions)} znaków z {instructions_file}")

Uruchom:

python create_agent.py

Oczekiwany wynik:

✓ Importy załadowane

🔧 Ładowanie konfiguracji z .env...
   ...
✓ Konfiguracja załadowana

📄 Wczytywanie instrukcji z pliku...
✓ Załadowano 1234 znaków z krs_agent_instructions.md

Co się stało:

  • Path("krs_agent_instructions.md") - obiekt reprezentujący ścieżkę do pliku
  • .exists() - sprawdza czy plik istnieje
  • open(..., 'r', encoding='utf-8') - otwiera plik do odczytu z UTF-8
  • .read() - wczytuje całą zawartość pliku do zmiennej instructions

Dlaczego UTF-8? Polskie znaki (ą, ę, ł) wymagają UTF-8. Bez tego mogą się źle wyświetlać.


Krok 4: Wczytanie OpenAPI spec z JSON

Dodaj kolejny kawałek:

# Wczytaj OpenAPI spec z pliku JSON
print("\n📄 Wczytywanie OpenAPI spec z pliku...")

openapi_file = Path("krs-api.json")

if not openapi_file.exists():
    print(f"❌ BŁĄD: Nie znaleziono pliku {openapi_file}")
    exit(1)

with open(openapi_file, 'r', encoding='utf-8') as f:
    openapi_spec = json.load(f)

print(f"✓ Załadowano OpenAPI spec")
print(f"   API Title: {openapi_spec.get('info', {}).get('title')}")
print(f"   API Version: {openapi_spec.get('info', {}).get('version')}")

# Policz operacje
operations = []
for path, methods in openapi_spec.get('paths', {}).items():
    for method in ['get', 'post', 'put', 'delete', 'patch']:
        if method in methods:
            op_id = methods[method].get('operationId', 'unknown')
            operations.append(op_id)
            print(f"   Operacja: {op_id}")

print(f"✓ Znaleziono {len(operations)} operacji")

Uruchom:

python create_agent.py

Oczekiwany wynik:

...
📄 Wczytywanie OpenAPI spec z pliku...
✓ Załadowano OpenAPI spec
   API Title: KRS API - Krajowy Rejestr Sądowy
   API Version: 1.0
   Operacja: getKrsOdpisAktualny
✓ Znaleziono 1 operacji

Co się stało:

  • json.load(f) - parsuje JSON do słownika Python
  • .get('info', {}) - bezpieczny dostęp do kluczy (zwraca {} jeśli nie ma ‘info’)
  • Iteracja po pathsmethods - liczy dostępne operacje
  • operationId - wymagane dla każdej operacji w OpenAPI

Tip: operationId jest używane przez agenta do wywołania funkcji. Musi być unikalne!


Krok 5: Utworzenie klienta Azure AI

Dodaj kolejny kawałek:

# Utwórz klienta Azure AI Project
print("\n🔧 Inicjalizacja klienta Azure AI...")

try:
    credential = DefaultAzureCredential()

    # (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)

    project_client = AIProjectClient(
        endpoint=PROJECT_ENDPOINT,
        credential=credential
        # transport=transport  # Odkomentuj jeżeli używasz proxy
    )
    print("✓ Klient utworzony pomyślnie")
except Exception as e:
    print(f"❌ BŁĄD: {e}")
    print("\n💡 Upewnij się że jesteś zalogowany:")
    print("   - Uruchom: az login")
    print("   - Lub ustaw: AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET")
    exit(1)

Uruchom:

python create_agent.py

Oczekiwany wynik:

...
🔧 Inicjalizacja klienta Azure AI...
✓ Klient utworzony pomyślnie

Co się stało:

  • DefaultAzureCredential() - próbuje uwierzytelnienia w kolejności:
    1. Zmienne środowiskowe (Service Principal)
    2. Managed Identity (jeśli na Azure VM)
    3. Azure CLI (az login)
    4. Interactive browser login
  • AIProjectClient - klient do komunikacji z Azure AI Foundry
  • Używa pierwszego credential który zadziała

Jeśli błąd uwierzytelnienia:

# Zaloguj się przez Azure CLI
az login

# Sprawdź
az account show

Krok 6: Utworzenie OpenAPI tool z connection

Dodaj kolejny kawałek:

# Utwórz OpenAPI tool z connection-based authentication
print(f"\n🔌 Tworzenie OpenAPI tool...")
print(f"   Connection: {CONNECTION_NAME}")

try:
    # Obiekt autentykacji
    auth = OpenApiConnectionAuthDetails(
        security_scheme=OpenApiConnectionSecurityScheme(
            connection_id=CONNECTION_NAME
        )
    )

    # Obiekt OpenAPI tool
    openapi_tool = OpenApiTool(
        name="krs_api",
        spec=openapi_spec,
        description="Retrieves company data from Polish National Court Register (KRS)",
        auth=auth
    )

    print("✓ OpenAPI tool utworzony")
    print(f"   Nazwa: krs_api")
    print(f"   Auth: Connection ({CONNECTION_NAME})")
except Exception as e:
    print(f"❌ BŁĄD: {e}")
    print(f"\n💡 Sprawdź czy connection '{CONNECTION_NAME}' istnieje w portalu:")
    print("   Portal → Management center → Connected resources")
    exit(1)

Uruchom:

python create_agent.py

Oczekiwany wynik:

...
🔌 Tworzenie OpenAPI tool...
   Connection: krs-apim-connection-<INICJAŁ>
✓ OpenAPI tool utworzony
   Nazwa: krs_api
   Auth: Connection (krs-apim-connection-<INICJAŁ>)

Co się stało:

  • OpenApiConnectionAuthDetails - typ autentykacji przez connection
  • connection_id - nazwa connection z portalu (nie ID projektu!)
  • OpenApiTool - opakowuje OpenAPI spec + auth
    • name - używane w wywołaniach agenta
    • spec - słownik z OpenAPI (wczytany wcześniej)
    • description - pomaga agentowi zdecydować kiedy użyć tool
    • auth - obiekt z credentials

Ważne: Connection musi istnieć w portalu PRZED uruchomieniem skryptu!


Krok 7: Sprawdzenie czy agent już istnieje

Dodaj kolejny kawałek:

# Sprawdź czy agent już istnieje
print("\n🔍 Sprawdzanie czy agent istnieje...")

agent_name = "KRS-Agent-FromCode"

try:
    agents_list = project_client.agents.list_agents()
    agents = list(agents_list)
    print(f"✓ Znaleziono {len(agents)} agentów w projekcie")
except Exception as e:
    print(f"❌ BŁĄD przy listowaniu agentów: {e}")
    exit(1)

# Szukaj agenta po nazwie
existing_agent = None
for agent in agents:
    if agent.name == agent_name:
        existing_agent = agent
        print(f"✓ Agent '{agent_name}' istnieje (ID: {agent.id})")
        break

if not existing_agent:
    print(f"   Agent '{agent_name}' nie istnieje - zostanie utworzony")

Uruchom:

python create_agent.py

Oczekiwany wynik (pierwszy raz - agent nie istnieje):

...
🔍 Sprawdzanie czy agent istnieje...
✓ Znaleziono 2 agentów w projekcie
   Agent 'KRS-Agent-FromCode' nie istnieje - zostanie utworzony

Co się stało:

  • list_agents() - pobiera listę wszystkich agentów w projekcie
  • list() - konwertuje iterator na listę (żeby móc iterować)
  • Pętla for agent in agents - sprawdza każdego agenta
  • Porównanie agent.name == agent_name - szuka po nazwie
  • Jeśli znajdzie - zapisuje do existing_agent

Tip: Wyszukiwanie po nazwie, nie ID. Nazwa jest bardziej czytelna i stabilna.


Krok 8: Create lub Update agenta

Dodaj ostatni kawałek - serce skryptu:

# CREATE lub UPDATE agenta
print(f"\n🤖 {'Aktualizacja' if existing_agent else 'Tworzenie'} agenta...")

try:
    if existing_agent:
        # UPDATE - agent już istnieje
        print(f"   Istniejący agent ID: {existing_agent.id}")
        print(f"   Istniejący model: {existing_agent.model}")

        final_agent = project_client.agents.update_agent(
            agent_id=existing_agent.id,
            model=MODEL_DEPLOYMENT_NAME,
            name=agent_name,
            instructions=instructions,
            tools=openapi_tool.definitions
        )

        print("✅ Agent zaktualizowany!")
        print(f"   Agent ID: {final_agent.id} (ten sam)")
        print(f"   Nowy model: {final_agent.model}")
        print(f"   Instructions: zaktualizowane")
        print(f"   Tools: zaktualizowane")

    else:
        # CREATE - agent nie istnieje
        final_agent = project_client.agents.create_agent(
            model=MODEL_DEPLOYMENT_NAME,
            name=agent_name,
            instructions=instructions,
            tools=openapi_tool.definitions
        )

        print("✅ Agent utworzony!")
        print(f"   Agent ID: {final_agent.id}")
        print(f"   Model: {final_agent.model}")

except Exception as e:
    print(f"❌ BŁĄD: {e}")
    exit(1)

Uruchom:

python create_agent.py

Oczekiwany wynik (pierwszy raz - CREATE):

...
🤖 Tworzenie agenta...
✅ Agent utworzony!
   Agent ID: asst_abc123xyz456
   Model: gpt-4.1-mini

Uruchom DRUGI raz (bez zmian):

python create_agent.py

Oczekiwany wynik (drugi raz - UPDATE):

...
🔍 Sprawdzanie czy agent istnieje...
✓ Znaleziono 3 agentów w projekcie
✓ Agent 'KRS-Agent-FromCode' istnieje (ID: asst_abc123xyz456)

🤖 Aktualizacja agenta...
   Istniejący agent ID: asst_abc123xyz456
   Istniejący model: gpt-4.1-mini
✅ Agent zaktualizowany!
   Agent ID: asst_abc123xyz456 (ten sam)
   Nowy model: gpt-4.1-mini
   Instructions: zaktualizowane
   Tools: zaktualizowane

Co się stało:

  • if existing_agent: - decyduje czy UPDATE czy CREATE
  • UPDATE path:
    • update_agent() - aktualizuje istniejącego agenta
    • agent_id - ID agenta do aktualizacji
    • Wszystkie parametry (model, instructions, tools) - nowe wartości
    • Agent ID się NIE zmienia - threads dalej działają!
  • CREATE path:
    • create_agent() - tworzy nowego agenta
    • Nowy agent dostaje nowy ID
  • openapi_tool.definitions - liczba mnoga! (nie .definition)

Kluczowa różnica: UPDATE zachowuje Agent ID - wszystkie istniejące threads i runs dalej działają!


Krok 9: Podsumowanie i next steps

Dodaj na końcu pliku:

# Podsumowanie
print("\n" + "=" * 60)
print("✨ Gotowe!")
print("=" * 60)
print(f"\n📊 Szczegóły agenta:")
print(f"   Nazwa: {final_agent.name}")
print(f"   ID: {final_agent.id}")
print(f"   Model: {final_agent.model}")

if existing_agent:
    print(f"\n💡 Co się stało:")
    print(f"   ✅ Agent został ZAKTUALIZOWANY")
    print(f"   - Instructions z: {instructions_file}")
    print(f"   - OpenAPI spec z: {openapi_file}")
    print(f"   - Model: {MODEL_DEPLOYMENT_NAME}")
else:
    print(f"\n💡 Co się stało:")
    print(f"   ✅ Agent został UTWORZONY")
    print(f"   - Instructions z: {instructions_file}")
    print(f"   - OpenAPI spec z: {openapi_file}")
    print(f"   - Model: {MODEL_DEPLOYMENT_NAME}")

print(f"\n🎯 Następne kroki:")
print(f"   1. Portal: https://ai.azure.com")
print(f"   2. Agents → My agents → {final_agent.name}")
print(f"   3. Test w Playground!")
print(f"\n   Pytanie testowe: 'Sprawdź firmę KRS 0000028860'\n")

Uruchom pełny skrypt:

python create_agent.py

Pełny output:

✓ Importy załadowane

🔧 Ładowanie konfiguracji z .env...
   PROJECT_ENDPOINT: https://ai-xxx.services.ai.azure.com/...
   MODEL_DEPLOYMENT_NAME: gpt-4.1-mini
   CONNECTION_NAME: krs-apim-connection-<INICJAŁ>
✓ Konfiguracja załadowana

📄 Wczytywanie instrukcji z pliku...
✓ Załadowano 1234 znaków z krs_agent_instructions.md

📄 Wczytywanie OpenAPI spec z pliku...
✓ Załadowano OpenAPI spec
   API Title: KRS API - Krajowy Rejestr Sądowy
   API Version: 1.0
   Operacja: getKrsOdpisAktualny
✓ Znaleziono 1 operacji

🔧 Inicjalizacja klienta Azure AI...
✓ Klient utworzony pomyślnie

🔌 Tworzenie OpenAPI tool...
   Connection: krs-apim-connection-<INICJAŁ>
✓ OpenAPI tool utworzony
   Nazwa: krs_api
   Auth: Connection (krs-apim-connection-<INICJAŁ>)

🔍 Sprawdzanie czy agent istnieje...
✓ Znaleziono 3 agentów w projekcie
✓ Agent 'KRS-Agent-FromCode' istnieje (ID: asst_abc123xyz456)

🤖 Aktualizacja agenta...
   Istniejący agent ID: asst_abc123xyz456
   Istniejący model: gpt-4.1-mini
✅ Agent zaktualizowany!
   Agent ID: asst_abc123xyz456 (ten sam)
   Nowy model: gpt-4.1-mini
   Instructions: zaktualizowane
   Tools: zaktualizowane

============================================================
✨ Gotowe!
============================================================

📊 Szczegóły agenta:
   Nazwa: KRS-Agent-FromCode
   ID: asst_abc123xyz456
   Model: gpt-4.1-mini

💡 Co się stało:
   ✅ Agent został ZAKTUALIZOWANY
   - Instructions z: krs_agent_instructions.md
   - OpenAPI spec z: krs-api.json
   - Model: gpt-4.1-mini

🎯 Następne kroki:
   1. Portal: https://ai.azure.com
   2. Agents → My agents → KRS-Agent-FromCode
   3. Test w Playground!

   Pytanie testowe: 'Sprawdź firmę KRS 0000028860'

Test agenta w portalu

Krok 1: Otwórz Portal

  1. Przejdź do Azure AI Foundry Portal
  2. Wybierz swój projekt
  3. AgentsMy agents
  4. Znajdź KRS-Agent-FromCode
  5. Kliknij na niego

Krok 2: Sprawdź konfigurację

W prawym panelu sprawdź:

  • Model: gpt-4.1-mini
  • Instructions: Powinny być załadowane z krs_agent_instructions.md
  • Actions: Powinien być krs_api (OpenAPI tool)

Krok 3: Test w Playground

W Playground wpisz:

Sprawdź dane firmy o numerze KRS 0000028860

Oczekiwany wynik:

  • Agent wywoła getKrsOdpisAktualny
  • Parametry: krs=0000028860, rejestr=P
  • Pobierze dane PKN ORLEN S.A.
  • Wyświetli dane w formacie Markdown

Workflow: Edycja i aktualizacja

Scenariusz 1: Zmiana instrukcji agenta

  1. Otwórz plik krs_agent_instructions.md i zmień jego instrukcję (Dodaj, usuń, zmień)

  2. Uruchom skrypt ```bash

    1. Uruchom skrypt - automatyczny UPDATE

    python create_agent.py

2. Agent zaktualizowany! Ten sam ID!


### Scenariusz 2: Zmiana modelu

1. Otwórz plik `.env` i zmień model na `gpt-4o`

2. Uruchom skrypt.
```bash

python create_agent.py

3. Sprawdź w portalu czy się zmienił

Scenariusz 3: Aktualizacja OpenAPI spec

  1. Wyeksportuj nowy spec z APIM (Portal → APIM → Export → JSON)

  2. Nadpisz nim plik krs-api.json

  3. Uruchom skrypt
    python create_agent.py
    
  4. Sprawdź w portalu czy agent używa nowego spec!

Kluczowe koncepty

Pattern Create-or-Update

if existing_agent:
    # UPDATE - zachowuje Agent ID
    agent = client.agents.update_agent(
        agent_id=existing_agent.id,
        ...
    )
else:
    # CREATE - nowy Agent ID
    agent = client.agents.create_agent(
        ...
    )

Zalety:

  • Idempotentność - wielokrotne uruchomienie = ten sam rezultat
  • Stabilny Agent ID - threads dalej działają
  • CI/CD ready - automatyczny deployment
  • Rollback - git checkout old-version + uruchom skrypt

OpenAPI Tool z Connection

# 1. Connection auth object
auth = OpenApiConnectionAuthDetails(
    security_scheme=OpenApiConnectionSecurityScheme(
        connection_id="krs-apim-connection-<INICJAŁ>"  # Nazwa z portalu
    )
)

# 2. OpenAPI tool
tool = OpenApiTool(
    name="krs_api",          # Nazwa dla agenta
    spec=openapi_spec,        # Słownik z JSON
    description="...",        # Opis dla agenta
    auth=auth                 # Connection z portalu
)

# 3. W create/update agenta
agent = client.agents.create_agent(
    tools=tool.definitions    # LICZBA MNOGA!
)

Connection musi:

  • Być utworzony w portalu PRZED uruchomieniem
  • Mieć dokładnie tę samą nazwę co connection_id
  • Zawierać API keys (Ocp-Apim-Subscription-Key, subscription-key)

Infrastructure as Code

Project/
├── .env                          # Config (NIE commituj do git!)
├── .gitignore                    # Dodaj: .env
├── krs_agent_instructions.md     # Instructions (GIT)
├── krs-api.json                  # OpenAPI spec (GIT)
└── create_agent.py               # Skrypt (GIT)

Workflow:

# 1. Zmień plik
git diff krs_agent_instructions.md

# 2. Commit
git add krs_agent_instructions.md
git commit -m "Update KRS agent instructions"

# 3. Deploy
python create_agent.py

# 4. Verify w portalu

Troubleshooting

Problem 1: ModuleNotFoundError

Błąd:

ModuleNotFoundError: No module named 'azure.ai.projects'

Rozwiązanie:

# Sprawdź czy venv aktywowany
which python  # powinno pokazać ścieżkę do venv

# Jeśli nie
source venv/bin/activate  # Linux/Mac
venv\Scripts\activate.bat  # Windows

# Zainstaluj pakiety
pip install azure-ai-projects azure-identity python-dotenv

Problem 2: Authentication failed

Błąd:

❌ BŁĄD: DefaultAzureCredential failed to retrieve a token

Rozwiązanie:

# Azure CLI
az login
az account show

# Service Principal
export AZURE_TENANT_ID="..."
export AZURE_CLIENT_ID="..."
export AZURE_CLIENT_SECRET="..."

Problem 3: Connection not found

Błąd:

❌ BŁĄD przy tworzeniu OpenAPI tool: Connection 'krs-apim-connection-<INICJAŁ>' not found

Rozwiązanie:

  1. Portal → Management center → Connected resources
  2. Sprawdź czy connection istnieje
  3. Sprawdź dokładną nazwę (case sensitive!)
  4. Jeśli nie ma - utwórz (Lab 04)
  5. Zaktualizuj CONNECTION_NAME w .env

Problem 4: File not found

Błąd:

❌ BŁĄD: Nie znaleziono pliku krs_agent_instructions.md

Rozwiązanie:

# Sprawdź gdzie jesteś
pwd

# Sprawdź co jest w katalogu
ls -la

# Plik musi być w tym samym katalogu co skrypt
# Lub podaj pełną ścieżkę w Path(...)

Problem 5: JSON decode error

Błąd:

json.decoder.JSONDecodeError: Expecting value: line 1 column 1

Rozwiązanie:

# Sprawdź zawartość pliku
cat krs-api.json | head

# Upewnij się że to JSON, nie YAML
# Pierwszy znak powinien być {

# Wyeksportuj ponownie z APIM w formacie JSON

Problem 6: Model deployment not found

Błąd:

❌ BŁĄD: Model deployment 'gpt-4.1-mini' not found

Rozwiązanie:

  1. Portal → Models + endpoints
  2. Sprawdź kolumnę Name (nie “Model name”!)
  3. Skopiuj dokładną nazwę
  4. Wklej do MODEL_DEPLOYMENT_NAME w .env
  5. Jeśli nie ma - wdróż model (Lab 03)

CI/CD Integration

GitHub Actions przykład

.github/workflows/deploy-agent.yml:

name: Deploy KRS Agent

on:
  push:
    branches: [main]
    paths:
      - 'krs_agent_instructions.md'
      - 'krs-api.json'
      - 'create_agent.py'

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Setup Python
        uses: actions/setup-python@v4
        with:
          python-version: '3.12'

      - name: Install dependencies
        run: |
          pip install azure-ai-projects azure-identity python-dotenv

      - name: Deploy agent
        env:
          PROJECT_ENDPOINT: $
          MODEL_DEPLOYMENT_NAME: $
          CONNECTION_NAME: $
          AZURE_TENANT_ID: $
          AZURE_CLIENT_ID: $
          AZURE_CLIENT_SECRET: $
        run: |
          python create_agent.py

Konfiguracja GitHub Secrets:

  1. Repo → Settings → Secrets and variables → Actions
  2. Dodaj secrets:
    • PROJECT_ENDPOINT
    • MODEL_DEPLOYMENT_NAME
    • CONNECTION_NAME
    • AZURE_TENANT_ID
    • AZURE_CLIENT_ID
    • AZURE_CLIENT_SECRET

Workflow:

# 1. Zmień instructions
git add krs_agent_instructions.md
git commit -m "Update instructions"
git push

# 2. GitHub Action automatycznie:
#    - Pobiera kod
#    - Instaluje dependencies
#    - Uruchamia create_agent.py
#    - Agent zaktualizowany!

Best Practices

1. Wersjonowanie

# Commituj konfigurację, NIE credentials
git add krs_agent_instructions.md
git add krs-api.json
git add create_agent.py
git add .env.example  # Template bez wartości

# NIE commituj
# .env - zawiera credentials!

2. Separacja środowisk

# Różne .env dla środowisk
.env.dev
.env.staging
.env.prod

# W skrypcie
env_file = ".env.prod" if os.getenv("ENV") == "prod" else ".env.dev"
load_dotenv(env_file)

3. Testowanie

# Na końcu skryptu dodaj smoke test
print("\n🧪 Test agenta...")

thread = project_client.agents.threads.create()
message = project_client.agents.messages.create(
    thread_id=thread.id,
    role="user",
    content="Test: sprawdź KRS 0000028860"
)

run = project_client.agents.runs.create(
    thread_id=thread.id,
    agent_id=final_agent.id
)

# Poll for completion...
# Verify response contains expected data
print("✅ Test passed!")

4. Dokumentacja w kodzie

# Dobre komentarze wyjaśniają DLACZEGO, nie CO
# DOBRZE:
# Używamy connection dla bezpieczeństwa - API key w portalu, nie w kodzie
auth = OpenApiConnectionAuthDetails(...)

# ŹLE:
# Tworzymy auth
auth = OpenApiConnectionAuthDetails(...)

Podsumowanie

W tym labie nauczyłeś się:

Budować skrypt małymi kawałkami - każdy krok testowany osobno ✅ Pattern Create-or-Update - idempotentne deployementy ✅ Ładować config z plików - instructions (MD), OpenAPI spec (JSON) ✅ Używać update_agent() - zachowuje Agent ID ✅ Connection-based auth - bezpieczne credentials ✅ Infrastructure as Code - wszystko w git ✅ CI/CD ready - automatyczny deployment

Następne kroki:

  • Dostosuj skrypt do swoich agentów
  • Dodaj testy automatyczne
  • Zintegruj z CI/CD
  • Dodaj więcej agentów (multi-agent deployment)

Dokumentacja:

results matching ""

    No results matching ""