Vai al contenuto

Definire un agente e utilizzarla

Traduzione automatica dell'originale francese.

Tre oggetti da posizionare, nell'ordine indicato. Nessuno è facoltativo: saltare il secondo crea un agente il cui utilizzo non è imputabile a nessuno.

flowchart TD
    e["1 · Équipe<br/>budget commun, un projet"] --> c["2 · Clé virtuelle<br/>une par agent = imputation"]
    c --> a["3 · Agent<br/>carte + limites + contrat"]
    a --> u["Consommation<br/>script · workflow · chat · autre agent"]

1. Il team

Gestisce il budget di un progetto e raggruppa le sue chiavi. Un singolo agente non ha bisogno di un team; due agenti dello stesso progetto, se — altrimenti i loro budget non si sommano.

curl -sX POST "$PROXY/team/new" -H "Authorization: Bearer $CLE_ADMIN" \
  -H 'Content-Type: application/json' \
  -d '{"team_alias":"<projet>","max_budget":0.5,"budget_duration":"1d"}'

2. La chiave virtuale — una per agente

È l'intero meccanismo di imputazione. Senza di essa, tutti spendono sotto lo stesso nome e il pannello di controllo mostra numeri che non rispondono a nessuna domanda.

curl -sX POST "$PROXY/key/generate" -H "Authorization: Bearer $CLE_ADMIN" \
  -H 'Content-Type: application/json' \
  -d '{"key_alias":"<projet>-<agent>","team_id":"<id>",
       "models":["<alias1>","<alias2>"],
       "max_budget":0.5,"budget_duration":"1d",
       "metadata":{"role":"agent-projet","agent":"<agent>"}}'

La chiave viene salvata nel portafoglio, immediatamente, mai in un file del repository: vedere Salvare un segreto dal portafoglio.

Un budget taglia

Una volta raggiunto, la chiave viene rifiutata. Per un agente di base, a cui nessuno presta attenzione, questo fornisce un servizio inutilizzabile, con un lavoro che si esaurisce. È necessario calibrare al di sopra del picco misurato, e configurare l'avviso di budget (Configurare una notifica).

3. L'agente

curl -sX POST "$PROXY/v1/agents" -H "Authorization: Bearer $CLE_ADMIN" \
  -H 'Content-Type: application/json' -d '{
    "agent_name": "<nom>",
    "agent_card_params": {
      "protocolVersion": "0.3",
      "name": "<Nom affiché>",
      "description": "<ce qu'"'"'il fait, et ce qu'"'"'il ne fera jamais>",
      "url": "http://<hôte>:<port>/a2a/<nom>",
      "version": "1.0.0",
      "defaultInputModes": ["text/plain"],
      "defaultOutputModes": ["text/markdown"],
      "skills": [{
        "id": "<verbe>", "name": "<verbe — ce qu'"'"'il établit>",
        "description": "<ce que cette compétence rend, et ce qu'"'"'elle ne rend pas>",
        "tags": ["<axe>"], "examples": ["<appel typique>"]
      }]
    },
    "object_permission": { "models": ["<alias1>","<alias2>"] },
    "rpm_limit": 6
  }'
Campo Ciò che decide
agent_name L'identificatore stabile. È questo che viene associato, mai l'agent_id: un agente ricreato dall'interfaccia utente cambia l'ID e mantiene il suo nome
agent_card_params La scheda A2A fornita agli chiamanti — nome, descrizione, competenze, formati
agent_card_params.url Dove il proxy digiterà. Se non c'è nulla dietro, la scheda mente
object_permission.models L'elenco dei modelli. Un secondo livello di protezione, distinto da quello della chiave
rpm_limit, tpm_limit Il tasso. session_* limita una conversazione, non l'intero agente

Utilizzare l'agente

Quattro modalità, dalla più universale a quella più specifica.

A. Come un modello normale — il percorso che serve il 90% dei casi

curl -sX POST "$PROXY/v1/chat/completions" -H "Authorization: Bearer $CLE" \
  -H 'Content-Type: application/json' \
  -d '{"model":"a2a/<nom>","messages":[{"role":"user","content":"<consigne>"}]}'

Il proxy riconosce il prefisso a2a/, risolve l'agente nel suo registro, lo traduce in message/send e traduce nuovamente la risposta. Tutto ciò che comunica già con un modello comunica ora con l'agente: l'interfaccia di chat lo vede nella sua lista, il motore dei workflow lo vede anche, e uno script di tre righe non ha nulla di speciale da fare.

Con una riserva che non è teorica: questa risoluzione legge il registro in memoria del proxy. Dopo un riavvio, fallisce per tutti finché gli agenti non sono stati riapplicati – vedi l'incidente n. 4.

B. In A2A, per un cliente che conosce il protocollo

curl -s "$PROXY/a2a/<id>/.well-known/agent-card.json" -H "Authorization: Bearer $CLE"

curl -sX POST "$PROXY/a2a/<id>/message/send" -H "Authorization: Bearer $CLE" \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":"1","method":"message/send","params":{"message":{
       "role":"user","parts":[{"kind":"text","text":"<consigne>"}],"messageId":"<uuid>"}}}'

Da utilizzare quando si vuole il ciclo di attività – un lavoro che dura, un monitoraggio dello stato, artefatti forniti lungo il percorso.

C. Da uno script di sistema, senza passare per A2A

Questo è il caso di un agente che è un programma da riga di comando su una macchina, non un server. Lo script legge la sua definizione nel registro, quindi avvia l'eseguibile stesso:

agent, provenance, contrat = charge(AGENT_DE_SECOURS)   # GET /v1/agents
print(f"définition : {provenance}")                      # litellm | cache | code

Tre cose da rispettare, e tutte sono costose da riscoprire:

  1. La lettura avviene con la chiave dell'agente stesso. Il registro risponde a una chiave ordinaria: non è necessario che una chiave di amministrazione sia presente sulla macchina che esegue.
  2. Una cache locale e la provenienza visualizzata. Un agente che gira su una copia di sicurezza produce la stessa uscita, nello stesso momento, allo stesso costo: questa riga è l'unica differenza visibile tra "aggiornato" e "proxy silenzioso da tre giorni".
  3. Un'etichetta di imputazione sulla chiamata x-litellm-tags, altrimenti la spesa è attribuibile alla chiave ma non al lavoro.

D. Tra agenti

Un agente registrato può chiamare un altro agente utilizzando la stessa chiave. È qui che object_permission.agents serve: definire chi può chiamare chi.

Gli errori, tutti misurati

1. L'interfaccia di amministrazione sovrascrive litellm_params

Il modulo riscrive questo campo utilizzando solo i suoi campi. Qualsiasi dato che viene memorizzato in esso – un contratto di esecuzione, metadati interni – scompare al primo utente che apre l'agente e lo salva. Senza messaggi, senza tracce, a parte in updated_by.

Misurato: 21 campi posizionati alle 07:52, eliminati alle 08:13 dello stesso giorno. La mappa, i limiti e l'elenco dei modelli, invece, erano intatti.

Da ricordare: ciò che deve durare va nella mappa. Ciò che viene memorizzato in litellm_params necessita di una fonte esterna e di un'azione che lo ripristini.

2. La mappa elimina ciò che non conosce, restituendo 200

capabilities.extensions – il punto normativo per i metadati interni – viene filtrato al momento dell'inserimento. Solo streaming, pushNotifications e stateTransitionHistory sopravvivono. La creazione ha successo, la mappa torna incompleta, ma non viene segnalato alcun errore.

3. L'operazione di lettura non è valida

Rileggere una mappa e poi restituirla così com'è fallisce con il codice 422, sui campi di sicurezza che il proxy ha creato autonomamente. Basta rimuovere questi campi dal corpo: verranno ripristinati. Tutte le operazioni di lettura / modifica / riscrittura devono eliminarli.

4. Il registro vive in memoria: un riavvio del proxy lo svuota

L'elenco degli agenti non viene controllato dalla base all'avvio: contiene solo gli agenti creati o modificati dopo l'avvio del processo. Dopo un riavvio, esistono ancora, e possono essere raggiunti tramite il loro identificativo, ma l'elenco è vuoto, e soprattutto a2a/<nom> smette di funzionare: la risoluzione legge lo stesso registro. Tutto ciò che consumava l'agente come modello si interrompe, senza alcun avviso, mentre il proxy rimane healthy e i modelli rispondono.

Misurato due volte nella stessa ora, il 13 settembre 2026, su sei agenti.

Tre azioni, in questo ordine: conservare l'identificativo di ogni agente nella sua definizione (quando l'elenco è dimenticato, è l'unico riferimento rimasto); far sì che la condizione sia controllata invece di segnalare "assente", il che potrebbe tentare una creazione e rendere "già esistente"; e riapplicare – un semplice scambio di dati lo riporta nel registro.

Il riavvio si automatizza senza rischi, perché il conflitto è falso: la base e la fonte dicono la stessa cosa, non c'è nulla da risolvere. Ma solo in questo caso – non appena si verifica una discrepanza di un'altra natura, si prevede e non si interviene, altrimenti si sovrascriverebbe il lavoro di qualcun altro.

5. Una modifica parziale sostituisce

Un PATCH non fonde: i campi mancanti del corpo vengono persi. È sempre necessario restituire l'oggetto completo. E un contratto incompleto si comporta esattamente come un contratto completo, poiché ciò che manca ricade sui valori predefiniti del codice – da cui l'importanza di un consumatore che annuncia ciò che ha effettivamente letto.

Controlli

# La définition telle que le registre la sert, et rien d'autre
curl -s "$PROXY/v1/agents" -H "Authorization: Bearer $CLE" | jq '.[] | {agent_name, rpm_limit}'

# Ce que l'exécutant a réellement chargé, à son dernier run
<commande de l'agent> 2>&1 >/dev/null | head -1

# Qui a modifié l'agent en dernier — un humain dans l'UI s'y voit
curl -s "$PROXY/v1/agents/<id>" -H "Authorization: Bearer $CLE_ADMIN" \
  | jq '{updated_at, updated_by}'

Dernière vérification de cette page : 2026-09-13