Aller au contenu principal

Bien démarrer avec AG-UI

Prérequis

  1. Python 3.10 ou une version ultérieure est installé.
  2. Un fournisseur LLM est configuré pour iac-code. Consultez Authentification.
  3. Si la tâche accède à Alibaba Cloud, configurez des identifiants cloud ou fournissez des identifiants temporaires dans la requête.
  4. Vous disposez d’un chemin absolu vers un espace de travail accessible en lecture et écriture par iac-code.

Installez les dépendances AG-UI :

pip install "iac-code[agui]"

Pour développer depuis le dépôt source :

uv sync --extra agui

Option 1 : démarrer un noyau A2A local géré

Pour la configuration locale la plus simple, omettez --a2a-url :

iac-code agui --host 127.0.0.1 --port 41243

L’adaptateur choisit un port de bouclage disponible, démarre un processus enfant iac-code a2a et l’arrête à sa fermeture. L’enfant hérite de la configuration et de l’environnement d’exécution actuels.

Ce mode convient au développement local et à une gestion unifiée du cycle de vie. En production, utilisez l’option suivante si le superviseur doit gérer les deux services séparément.

Option 2 : se connecter à un noyau A2A indépendant

Démarrez d’abord le serveur A2A :

iac-code a2a --host 127.0.0.1 --port 41242 --thinking-exposure all

Puis démarrez l’adaptateur AG-UI :

iac-code agui \
--host 0.0.0.0 \
--port 41243 \
--a2a-url http://127.0.0.1:41242

Les services conservent des responsabilités et des ports distincts. A2A peut continuer à servir ses propres clients, tandis que l’adaptateur l’appelle uniquement par l’interface de bouclage.

--thinking-exposure all permet de convertir le raisonnement brut en événements standard REASONING_*. Ne l’activez que pour des clients de confiance. Conservez la valeur A2A par défaut, tool-trace, si le contenu du raisonnement ne doit pas être exposé.

Si le serveur A2A utilise un jeton bearer :

export IACCODE_A2A_HTTP_TOKEN="secret-a2a-local"
iac-code a2a --host 127.0.0.1 --port 41242

Fournissez le même jeton amont à l’adaptateur :

export IAC_CODE_AGUI_A2A_TOKEN="secret-a2a-local"
iac-code agui --port 41243 --a2a-url http://127.0.0.1:41242

Configuration YAML

Les paramètres statiques peuvent être enregistrés dans un fichier YAML :

agui-server.yml
host: 0.0.0.0
port: 41243
a2a-url: http://127.0.0.1:41242
interrupt-ttl: 540
state-dir: /var/lib/iac-code/agui
idle-shutdown: 0
debug: false
log-stdout: true

Démarrez l’adaptateur avec :

iac-code agui --config agui-server.yml

Les arguments CLI explicites remplacent le YAML. Injectez les valeurs sensibles, comme les jetons, par variables d’environnement plutôt que dans le fichier.

CLI / YAMLValeur par défautSignification
--host / host127.0.0.1Adresse d’écoute HTTP AG-UI
--port / port8000Port HTTP AG-UI ; les exemples de déploiement utilisent 41243
--a2a-url / a2a-urlvideURL A2A locale ; vide démarre un enfant géré
--interrupt-ttl / interrupt-ttl540Durée en secondes pendant laquelle une interruption peut être reprise
--state-dir / state-dir<config-dir>/aguiRépertoire d’état des threads AG-UI
--idle-shutdown / idle-shutdown0Arrêt après inactivité ; 0 le désactive
--debug / debugfalseJournalisation de débogage
--log-stdout / log-stdoutfalseDupliquer les journaux sur stdout

Variables d’environnement associées :

VariableRôle
IAC_CODE_AGUI_HOSTAdresse d’écoute AG-UI
IAC_CODE_AGUI_PORTPort AG-UI
IAC_CODE_AGUI_A2A_URLURL locale du service A2A amont
IAC_CODE_AGUI_A2A_TOKENJeton bearer du service A2A amont
IAC_CODE_AGUI_AUTH_TOKENJeton bearer protégeant le point d’accès AG-UI
IAC_CODE_AGUI_INTERRUPT_TTLDurée de vie des interruptions
IAC_CODE_AGUI_STATE_DIRRépertoire d’état des threads AG-UI
IAC_CODE_AGUI_ALLOWED_CWDSRacines d’espace de travail autorisées, séparées par le séparateur de chemins du système
IAC_CODE_CONFIG_DIRRacine de configuration d’iac-code et parent par défaut de l’état AG-UI

Vérification de l’état

curl http://127.0.0.1:41243/health

Exemple de réponse :

{
"status": "ok",
"protocol": "ag-ui",
"protocolPackageVersion": "0.1.20",
"executionKernel": "a2a-1.0",
"serverVersion": "version actuelle d’iac-code"
}

Utiliser le client JavaScript officiel

Installez la version vérifiée :

pnpm add @ag-ui/client@0.0.58

Cet exemple se connecte directement à iac-code agui avec le HttpAgent standard et fournit les propriétés d’exécution dans forwardedProps :

import { HttpAgent, randomUUID } from "@ag-ui/client";

const threadId = randomUUID();
const rosInvocationId = randomUUID();
const agent = new HttpAgent({
url: "http://127.0.0.1:41243/",
threadId,
// Si IAC_CODE_AGUI_AUTH_TOKEN est configuré :
// headers: { Authorization: `Bearer ${process.env.AG_UI_TOKEN}` },
});

const forwardedProps = {
iacCode: {
schemaVersion: 1,
rosInvocationId,
cwd: process.cwd(),
runMode: "normal",
preferredLanguage: "fr",
},
};

agent.addMessage({
id: randomUUID(),
role: "user",
content: "Crée un modèle VPC avec deux vSwitches.",
});

const subscriber = {
onTextMessageContentEvent({ event }) {
process.stdout.write(event.delta);
},
onToolCallStartEvent({ event }) {
console.log(`\n[outil] ${event.toolCallName}`);
},
onStepStartedEvent({ event }) {
console.log(`\n[étape] ${event.stepName}`);
},
onRunErrorEvent({ event }) {
console.error(`\n${event.code}: ${event.message}`);
},
};

await agent.runAgent({ forwardedProps }, subscriber);

Avec un jeton bearer, transmettez Authorization dans HttpAgent.headers. Une application web passe normalement par un backend de même origine ou un proxy inverse ; l’adaptateur n’ajoute pas de politique CORS.

Traiter les interruptions

Le client officiel conserve RUN_FINISHED.outcome.interrupts dans agent.pendingInterrupts. Construisez chaque réponse à partir de son responseSchema, puis envoyez-la dans une nouvelle exécution :

const responses = agent.pendingInterrupts.map((interrupt) => ({
interruptId: interrupt.id,
status: "resolved",
payload: { decision: "allow_once" },
}));

await agent.runAgent({ forwardedProps, resume: responses }, subscriber);

Ce payload ne s’applique qu’aux autorisations dont le schéma exige decision. Les questions et choix d’options ont leurs propres schémas.

Une reprise doit utiliser le threadId d’origine, un nouveau runId, conserver le rosInvocationId de l’exécution interrompue, répondre en une seule requête à toutes les interruptions en attente et respecter chaque responseSchema. Utilisez status: "cancelled" lorsque l’utilisateur abandonne.

Démarrer un Pipeline

Définissez runMode sur pipeline et choisissez éventuellement un Pipeline :

const forwardedProps = {
iacCode: {
schemaVersion: 1,
rosInvocationId: randomUUID(),
cwd: process.cwd(),
runMode: "pipeline",
pipelineName: "selling",
candidatePresentation: "rich",
},
};

Les clients devraient traiter STEP_*, TOOL_CALL_*, ACTIVITY_SNAPSHOT et CUSTOM. Un client générique qui ignore les événements personnalisés d’iac-code continue de traiter normalement tous les événements standard.

Espace de travail et identifiants temporaires

cwd n’est pas fixé au démarrage du serveur. Chaque requête doit fournir un chemin absolu sous une racine autorisée par IAC_CODE_AGUI_ALLOWED_CWDS ou IACCODE_A2A_ALLOWED_CWDS.

Le demandeur peut fournir, par requête, un modèle, une clé LLM et des identifiants Alibaba Cloud temporaires via forwardedProps.iacCode. L’adaptateur ne les écrit pas dans son état ; il les transmet au noyau A2A selon les règles habituelles de surcharge de requête.

Répertoire d’état

Disposition par défaut :

<IAC_CODE_CONFIG_DIR>/agui/
threads/
<threadId>.json

Chaque thread est écrit indépendamment et le démarrage ne parcourt pas l’historique. Les UUID normaux restent lisibles ; les identifiants dangereux sont encodés et les identifiants très longs utilisent une clé de fichier de longueur fixe. Le document JSON conserve et vérifie toujours le threadId original.

Ce répertoire contient uniquement les associations, interruptions et données d’idempotence de l’adaptateur. Il ne contient ni conversation ni identifiants de requête. Ne modifiez pas ces fichiers JSON manuellement.

Étapes suivantes