0Pricing
AI Agents · Lezione

Perché testare gli agenti è diverso

Non determinismo, costi degli LLM e motivi per cui i normali unit test non sono sufficienti

Perché testare gli agenti è diverso è una lezione AI Agents gratuita su CoddyKit. Questa è la lezione 1 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento AI Agents, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso AI Agents include 4 lezioni in totale.

Testare il software e testare gli agenti

Il software tradizionale è deterministico: fornendo lo stesso input si ottiene lo stesso output. I test unitari si basano su questa proprietà per verificare valori attesi esatti.

Gli agenti di IA mettono in discussione questa ipotesi. Lo stesso prompt può produrre output diversi a ogni esecuzione, rendendo insufficienti da soli gli approcci di test standard.

Non determinismo: stesso input, output diverso

Gli LLM sono probabilistici per natura. Il parametro temperature controlla la casualità: anche con temperature=0, gli output possono variare tra versioni del modello o a seguito di modifiche all'infrastruttura.

Ciò significa che un test dell'agente che oggi ha esito positivo potrebbe fallire domani senza alcuna modifica al codice.

import openai

client = openai.OpenAI(api_key='YOUR_API_KEY')

# Same prompt, potentially different outputs each run
for i in range(3):
    response = client.chat.completions.create(
        model='gpt-4o-mini',
        messages=[{'role': 'user', 'content': 'Name a planet.'}],
        temperature=0.9  # High randomness
    )
    print(f'Run {i+1}: {response.choices[0].message.content}')
# Run 1: Mars
# Run 2: Jupiter
# Run 3: Saturn

Il problema dei costi: le chiamate reali agli LLM sono costose

L'esecuzione di una suite di test che effettua chiamate API reali a OpenAI o Anthropic può costare diversi dollari a ogni esecuzione. Una pipeline CI che esegue 100 test × 10 iterazioni potrebbe costare centinaia di dollari al mese.

Per questo non è pratico eseguire i test degli agenti nello stesso modo dei test unitari: servono strategie per controllare i costi.

# A test that calls the real API costs tokens every run
# 100 tests x 500 tokens each x 10 CI runs/day = 500,000 tokens/day
# At $0.15/1M tokens (gpt-4o-mini): ~$0.075/day = ~$27/year for a tiny suite
# For gpt-4o: 15x more expensive = ~$400/year

# This is why mocking and recording API responses is essential
print('Real API calls in tests = expensive and slow')
print('Solution: Mock or record LLM responses in unit tests')
print('Reserve real calls for scheduled integration tests')

Il problema della latenza

Le chiamate reali alle API degli LLM richiedono in genere 2-20 secondi. Una suite con 50 test impiegherebbe da 100 a 1000 secondi. Questo riduce la produttività degli sviluppatori: un feedback rapido è un valore fondamentale dei test efficaci.

Mockare le chiamate agli LLM consente di eseguire i test in pochi millisecondi.

import time

# Simulating what a test suite looks like with real vs mocked calls
num_tests = 50

# Real API calls
real_time = num_tests * 5  # avg 5 seconds per call
print(f'With real API calls: {real_time}s = {real_time/60:.1f} minutes')

# Mocked calls
mock_time = num_tests * 0.001  # <1ms per mock
print(f'With mocked calls: {mock_time:.3f}s = nearly instant')

# Conclusion: mock in unit tests, use real calls in integration tests

Dipendenze esterne nei test degli agenti

Gli agenti spesso chiamano strumenti esterni: API di ricerca, database, file system e web scraper. Nei test, queste dipendenze possono:

  • Non essere disponibili (interruzione della rete, indisponibilità dell'API)
  • Restituire dati diversi a ogni esecuzione
  • Avere limiti di frequenza che bloccano le pipeline CI

Nei test unitari devono essere controllate o sostituite con mock.

# An agent might call multiple external services
# Each is a potential test failure point

def agent_pipeline(query: str) -> str:
    search_results = search_web(query)       # External: Tavily/Serper API
    documents = fetch_documents(search_results)  # External: HTTP calls
    answer = llm_summarize(documents)        # External: OpenAI API
    saved = database_store(answer)           # External: PostgreSQL
    return answer

# In unit tests: mock ALL of these
# In integration tests: use sandboxed versions of real services
print('Each external call is a test reliability risk')

Cosa presuppongono i test unitari standard

I framework standard per i test unitari, come pytest, presuppongono che:

  • I test siano rapidi (millisecondi)
  • I test siano deterministici
  • I test non abbiano effetti collaterali esterni
  • I test possano essere eseguiti in qualsiasi ordine

I test degli agenti violano tutte e quattro queste ipotesi, a meno che non vengano progettati esplicitamente per tenerne conto.

# Standard unit test — works perfectly for deterministic code
def add(a, b):
    return a + b

def test_add():
    assert add(2, 3) == 5  # Always passes — deterministic

# Agent 'unit test' that calls a real LLM — problematic
# def test_agent_answers_question():
#     response = agent.run('What is 2+2?')
#     assert response == '4'  # Might return 'The answer is 4' or 'Four'

print('Exact string matching fails for LLM outputs')
print('Need structural or semantic assertions instead')

La piramide dei test per gli agenti

Una strategia pratica di test per gli agenti segue una piramide:

  • Test unitari (numerosi e rapidi): testano singoli strumenti e funzioni con chiamate agli LLM sostituite da mock
  • Test di integrazione (meno numerosi e più lenti): testano la pipeline dell'agente end-to-end con servizi in sandbox
  • Test di valutazione (rari e costosi): valutano la qualità dell'output con chiamate reali agli LLM e una valutazione in stile umano

Asserzioni strutturali e semantiche

Invece di confrontare stringhe esatte, i test degli agenti dovrebbero usare asserzioni strutturali (l'agente ha chiamato lo strumento corretto?) o controlli semantici (l'output contiene il concetto pertinente?).

# Fragile: exact string match
# assert response.content == 'The capital of France is Paris.'

# Better: structural assertion
# assert response.tool_calls[0]['function']['name'] == 'search_web'

# Better: semantic check
def test_capital_in_response(response_text: str) -> bool:
    key_words = ['paris', 'france', 'capital']
    lower = response_text.lower()
    return all(word in lower for word in key_words)

response = 'Paris is the capital city of France.'
print(test_capital_in_response(response))  # True

Harness di valutazione e LLM-as-Judge

Per valutare la qualità, nel settore si usa LLM-as-Judge: si chiede a un secondo LLM di valutare l'output dell'agente. Framework come DeepEval e RAGAS automatizzano questo schema.

Questa tecnica è riservata alle costose esecuzioni di valutazione, non alla CI ordinaria.

import openai

client = openai.OpenAI(api_key='YOUR_API_KEY')

def llm_judge(question: str, answer: str) -> dict:
    prompt = f'Question: {question}\nAnswer: {answer}\nRate the answer 1-5 for accuracy. Reply with only a number.'
    response = client.chat.completions.create(
        model='gpt-4o-mini',
        messages=[{'role': 'user', 'content': prompt}]
    )
    score = int(response.choices[0].message.content.strip())
    return {'score': score, 'pass': score >= 4}

# result = llm_judge('What is the capital of France?', 'Paris')
# print(result)  # {'score': 5, 'pass': True}

Test di regressione per gli agenti

Quando aggiorna un prompt o modifica la logica dell'agente, i test di regressione verificano che il comportamento esistente non sia stato compromesso. Registri esempi di riferimento (input → struttura attesa) ed esegua automaticamente i test a ogni commit.

# golden_examples.py
GOLDEN_EXAMPLES = [
    {
        'input': 'Search for the weather in Paris',
        'expected_tool': 'get_weather',
        'expected_args': {'city': 'Paris'}
    },
    {
        'input': 'Calculate 15% tip on $45',
        'expected_tool': 'calculate',
        'expected_args': {'expression': '45 * 0.15'}
    }
]

def run_regressions(agent, examples: list) -> int:
    failures = 0
    for ex in examples:
        result = agent.plan(ex['input'])  # mocked LLM
        if result['tool'] != ex['expected_tool']:
            print(f'FAIL: expected {ex["expected_tool"]}, got {result["tool"]}')
            failures += 1
    return failures

# --- demo: a stub agent whose .plan() mimics an LLM's tool choice ---
class _StubAgent:
    def plan(self, text):
        if 'weather' in text.lower():
            return {'tool': 'get_weather'}
        if 'tip' in text.lower() or 'calculate' in text.lower():
            return {'tool': 'wrong_tool'}  # simulate a regression
        return {'tool': 'unknown'}

failures = run_regressions(_StubAgent(), GOLDEN_EXAMPLES)
print(f'{failures} of {len(GOLDEN_EXAMPLES)} golden examples failed')

Configurare un file di test di base per un agente

Ecco la struttura minima di un file di test pytest per un agente. Separa i test unitari rapidi (con mock) dai test di integrazione lenti (con chiamate reali), consentendo di eseguire solo ciò che serve.

# tests/test_agent.py
import pytest

# Fast unit tests — run on every commit
class TestAgentTools:
    def test_tool_returns_dict(self, mock_llm):
        result = my_tool(query='test')
        assert isinstance(result, dict)
        assert 'data' in result

    def test_agent_selects_correct_tool(self, mock_llm):
        response = agent.run('Search for Python tutorials')
        assert response['tool_used'] == 'web_search'

# Slow integration tests — run nightly or on release
@pytest.mark.integration
class TestAgentIntegration:
    def test_full_pipeline_with_real_api(self):
        # Uses real OpenAI + sandboxed services
        result = agent.run('Summarize the Python docs')
        assert len(result['answer']) > 50

Verifica delle conoscenze: perché i test degli agenti sono diversi

Verifichi la Sua comprensione delle sfide specifiche dei test degli agenti di IA.

Riepilogo: perché testare gli agenti è diverso

Testare gli agenti IA richiede un approccio diverso rispetto ai normali test unitari:

  • Non determinismo: lo stesso input può produrre output diversi ma validi
  • Costo: le chiamate reali agli LLM sono costose — nei test unitari le simuli
  • Latenza: le chiamate API reali richiedono secondi — i mock vengono eseguiti in millisecondi
  • Dipendenze esterne: nei test è necessario controllare tool e API
  • Asserzioni: utilizzi controlli strutturali e semantici, non il confronto esatto delle stringhe

Utilizzi una piramide dei test: molti test unitari economici con mock e un numero minore di test di integrazione costosi con chiamate reali.

Domande Frequenti

La lezione «Perché testare gli agenti è diverso» è gratuita?

Sì — il testo completo di «Perché testare gli agenti è diverso» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso AI Agents, passa a CoddyKit PRO. Il corso AI Agents include 4 lezioni in totale.

Cosa imparerò in «Perché testare gli agenti è diverso»?

Non determinismo, costi degli LLM e motivi per cui i normali unit test non sono sufficienti Eserciti AI Agents con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare AI Agents?

Non è richiesta alcuna esperienza precedente. AI Agents su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 1 di 4.

Quanto tempo richiede la lezione «Perché testare gli agenti è diverso»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione AI Agents?

Sì. Ogni lezione AI Agents include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Perché testare gli agenti è diverso
  2. Mock delle chiamate LLM nei test
  3. Test degli agenti basati su asserzioni
  4. Test di integrazione per le pipeline degli agenti
← Torna a AI Agents