AgentInterface
L'interface AgentInterface définit un agent IA capable d'accomplir des tâches complexes impliquant potentiellement plusieurs appels LLM, des boucles de raisonnement ou l'orchestration de sous-systèmes.
À la différence d'un AiToolInterface (fonction simple appelée par le LLM), un agent est invoqué directement par l'application pour accomplir un objectif de haut niveau.
Namespace
ArnaudMoncondhuy\SynapseCore\Contract\AgentInterface
Contrat complet
use ArnaudMoncondhuy\SynapseCore\Agent\Input;
use ArnaudMoncondhuy\SynapseCore\Agent\Output;
interface AgentInterface
{
public function getName(): string;
public function getLabel(): string;
public function getDescription(): string;
public function call(Input $input, array $options = []): Output;
}
Méthodes
| Méthode | Rôle |
|---|---|
getName(): string |
Identifiant unique de l'agent (recommandé : snake_case, ex : 'preset_validator'). |
getLabel(): string |
Libellé court lisible (affiché dans l'admin). AbstractAgent fournit une implémentation par défaut (snake_case → Title Case). |
getDescription(): string |
Description en langage naturel — utilisée dans l'admin et pour l'auto-documentation. |
call(Input, array): Output |
Exécute la logique de l'agent. Retourne un Output structuré (réponse texte, données, usage, debugId, ...). |
Alignement symfony/ai (vocabulaire uniquement, pas de migration)
Les noms call(), Input et Output sont volontairement alignés sur Symfony\AI\Agent\AgentInterface / Symfony\AI\Agent\Input / Symfony\AI\Agent\Output.
Pas de migration prévue
C'est un alignement de vocabulaire, pas un chemin de migration. symfony/ai est encore en développement et aucune adoption n'est planifiée. L'intérêt est de ne pas construire une "deuxième réalité" qui serait douloureuse à rapprocher plus tard si le jour vient. Une réévaluation éventuelle n'est pas attendue avant au moins un an, et même à ce moment-là rien n'est décidé.
Écarts assumés :
getLabel()etgetDescription()sont des ajouts Synapse (utiles pour l'admin UI), absents desymfony/ai.- Le contexte d'exécution (
AgentContext: traçabilité, profondeur, budget) est transporté via$options['context'], pas en paramètre typé. Cela garde la signaturecall()call-compatible mot pour mot avecsymfony/ai.
AgentInterface vs SynapseAgent
AgentInterface est le contrat PHP pour les agents "code" (classes fournies par le bundle ou l'application hôte, découvertes par auto-configuration DI). SynapseAgent est l'entité Doctrine pour les agents "config" (système prompt, preset, ton, outils configurés depuis l'admin). Les deux mondes sont unifiés derrière le même contrat via AgentResolver et la classe d'adaptation ConfiguredAgent.
Cas d'usage typiques
- Analyse multi-documents complexe
- Validation d'un preset par simulation (
PresetValidatorAgent— exemple interne du bundle) - Génération de rapports structurés après plusieurs étapes de réflexion
- Orchestration de sous-agents (via
AgentResolver+AgentContext::createChild(), dans la limite desynapse.agents.max_depth)
Exemple : Agent d'analyse de document
La façon recommandée est d'étendre AbstractAgent (qui garantit l'AgentContext et fournit buildAskOptions()) :
namespace App\Agent;
use ArnaudMoncondhuy\SynapseCore\Agent\AbstractAgent;
use ArnaudMoncondhuy\SynapseCore\Agent\AgentContext;
use ArnaudMoncondhuy\SynapseCore\Agent\Input;
use ArnaudMoncondhuy\SynapseCore\Agent\Output;
use ArnaudMoncondhuy\SynapseCore\Engine\ChatService;
final class DocumentAnalyzerAgent extends AbstractAgent
{
public function __construct(private readonly ChatService $chatService) {}
public function getName(): string
{
return 'document_analyzer';
}
public function getDescription(): string
{
return 'Analyse un document et en extrait les points clés, les risques et les actions suggérées.';
}
public function getSystemPrompt(): string
{
return 'Analyse le document fourni et retourne : '
. '1) les points clés 2) les risques 3) les actions suggérées.';
}
protected function execute(Input $input, AgentContext $context): Output
{
$result = $this->chatService->ask(
$input->getMessage(),
$this->buildAskOptions(['stateless' => true]),
$input->getAttachments(),
);
return Output::fromChatServiceResult($result);
}
}
Exécution programmatique depuis l'application hôte
use ArnaudMoncondhuy\SynapseCore\Agent\AgentResolver;
use ArnaudMoncondhuy\SynapseCore\Agent\Input;
public function __construct(private readonly AgentResolver $agents) {}
public function analyze(string $document): array
{
$context = $this->agents->createRootContext(userId: 'user-42', origin: 'direct');
$agent = $this->agents->resolve('document_analyzer', $context);
$output = $agent->call(
Input::ofMessage($document),
['context' => $context],
);
return $output->getData();
}
Enregistrement automatique
Rien à déclarer côté hôte : toute classe qui implémente AgentInterface et qui se trouve dans les services auto-découverts (src/ par défaut sous services.yaml) est taggée automatiquement synapse.agent via registerForAutoconfiguration() du bundle. Le CodeAgentRegistry la prend en compte, et AgentResolver::resolve($name) sait la retourner.
Voir le guide Custom Agents pour un exemple complet.
Voir aussi
- Custom Agents (host-side) — premier agent code en 20 lignes
- AbstractAgent — classe de base recommandée
- Agents via l'admin — agents configurés sans code
- Contrôle d'accès aux agents — restreindre l'accès par rôle