🇬🇧 English version
Voir aussi : Retour à l'index
Limites et contraintes connues
InMemoryUnitOfWorkn'a par conception aucune étape de persistance durable : les agrégats vivent dans les repositories in-memory etSaveChangesAsyncse réduit au dispatch (réel et ordonné) des événements de domaine. Un adapter durable remplacerait cet adapter dans son ensemble — il n'y a plus de promesse de migration EF dans le code.- Persistance d'état d'exécution (R3.8) : par défaut, les états d'exécution de crew (
ICrewExecutionStateManager) sont in-memory only (pas de reprise après crash). La persistance durable est opt-in : enregistrer un state store de checkpointing (AddOrkeonCheckpointing/AddOrkeonSqliteCheckpointing/AddOrkeonPostgresCheckpointing) et activerAddCrewExecutionStatePersistence(...)(ou la sectionOrkeon:ExecutionState:Persistence). Une fois activée, les états sont persistés à chaque transition et rechargés/réutilisés après redémarrage — voir Sous-systèmes opt-in. Limites v1 : métadonnées persistées en chaînes invariantes,ToolsUsednon persisté. - Le framework cible .NET 10 — version courante
1.0.0-rc.4(définie danssrc/Directory.Build.props). .NET 11 (GA le 10 novembre 2026) n'est pas encore une cible :ci.ymlconstruit et teste la solution avec le SDK 11.x (canal preview, non bloquant jusqu'à la GA) en guise d'alerte précoce, et les deux dotnet tools (orkeon,orkeon-repl) acceptent un runtime majeur plus récent (RollForward=Major) pour qu'une machine n'ayant que .NET 11 puisse les exécuter. Le target framework,global.jsonet les images de base des conteneurs bougent le jour de la GA, pas avant. - Le périmètre fonctionnel est gelé à 16 fournisseurs LLM (quatorze vendeurs et deux agrégateurs — OpenRouter et Mammouth AI, l'unique exception motivée au gel, intégrés documentation d'abord et en attente de leur première campagne), 79 outils intégrés et 6 stores de mémoire tant que de vrais utilisateurs n'en demandent pas davantage : un mainteneur unique porte toute la surface, et chaque ajout est un coût permanent. Pas de 17ᵉ fournisseur : les endpoints qui parlent le dialecte OpenAI n'ont pas besoin de fournisseur (pointez
Orkeon:Llm:BaseUrldessus) ; les outils s'écrivent en scripts.ork.tsou en plugins. La règle et ce qui reste bienvenu sont dans CONTRIBUTING.fr.md. LlmConfig.ApiKeySecretNameest réservée, pas résolue. Le framework ne transforme jamais un nom de secret en clé d'API : chaque garde de fournisseur et chaque chemin de requête litLlmConfig.ApiKey, donc une config ne portant queApiKeySecretNameest non configurée et tout appel répond qu'une clé d'API est requise. Les fabriques*WithSecret(WithDefaultModelSecret,Gpt35TurboWithSecret,ClaudeWithSecret) enregistrent le nom, rien de plus. Un hôte qui garde ses clés dans un coffre résout le nom lui-même et affecte le résultat ÃApiKey; les chemins supportés pour la fournir sont le fichier de settings (Llm:ApiKey) et l'environnement (ORKEON_Llm__ApiKey).ApiKeyportait un attribut[Obsolete]qui orientait les appelants versApiKeySecretNamejusqu'à la rc.3 ; il a été retiré parce qu'il désignait un chemin inexistant.- Le streaming LLM est uniforme à la frontière du framework : les 16 providers héritent du lecteur de streaming SSE/NDJSON de
HttpLlmProviderBase(IStreamingLlmProvider).SupportsStreamingn'est pas untrueinconditionnel : il suit le fait que le provider soit réellement utilisable (une clé d'API quand le fournisseur en exige une, plus l'endpoint de ressource pour Azure), si bien qu'un provider non configuré déclarefalseet que tout appelant qui teste la capacité prend le chemin tamponné — celui qui rend la réponse explicite « API key is required » — au lieu d'une branche SSE qui se terminerait sans le moindre chunk. L'exception restante par provider est le/api/chatd'Ollama (voir l'entrée Ollama ci-dessous) FlowEngineet le système de Flows (steps séquentiels, parallèles, décisionnels) existent en infrastructure mais constituent un système d'orchestration alternatif distinct des Crews- Défauts DI délibérément minimaux —
IAgentPlanner(plan fixe 4 étapes),ITaskDelegator(refuse la délégation),IKnowledgeStore(in-memory, non persistant ; sonSearchAsyncignore la requête) etIAgentExecutionServicesont des remplaçants qui s'annoncent chacun par un Warning unique nommant la remédiation ; rien n'appelle un LLM ni ne persiste implicitement. Inventaire complet et gestes de remplacement : Comportements par défaut - Les outils custom doivent implémenter
IBaseToolou hériter deToolBase<TReq,TRes>. Le chargement de plugins au runtime existe (opt-inAddOrkeonPlugins(...)— découverte par répertoire,AssemblyLoadContextcollectables isolés, voir Plugins) ; limites v1 : les assemblies chargées s'exécutent en pleine confiance (pas de sandbox), et il n'y a ni manifeste de plugin ni hot-reload - Plusieurs sous-systèmes (A2A, monitoring backend, NIST, DLP, rate-limiting d'outils, rotation de clés, benchmarking, validation multi-modale, hooks de kickoff, sous-système RAG depuis RAG-01/C6 —
AddOrkeonRag+AddOrkeonRagToolsdepuis RAG-02, plus les opt-ins RAGAddOrkeonOnnxRerankerdepuis RAG-04 et le transportAddOrkeonRagWebFallbackdepuis RAG-06) sont opt-in : ils ne sont plus enregistrés parAddOrkeonInfrastructure()/AddOrkeonApplication()et s'activent par leur extension dédiée — voir Sous-systèmes opt-in - A2A — la persistance des tâches est opt-in (PUB-08) : enregistrez un state store de checkpointing plus
AddOrkeonA2ATaskPersistence(), etGET /a2a/tasks/{id}répond200avec le cycle de vie enregistré (404pour un id inconnu) tandis queDELETEenregistre l'annulation (404pour un id inconnu ; l'annulation reste consultative — le travail en cours n'est pas interrompu). Sans l'opt-in,GETcontinue de renvoyer un501explicite plutôt que de fabriquer un état. Les écarts plus larges vis-à -vis de la spec v1.0 (bindings, push notifications, cycle de vie à 9 états,A2A-Version) sont inventoriés dans la matrice de conformité A2A. - A2A mTLS —
A2AClientcharge le certificat client (A2ASecurityOptions.ClientCertificatePath) et applique toujours la validation complète du certificat serveur — il n'existe délibérément aucun opt-out « accepter n'importe quel certificat » ; un serveur auto-signé ou de dev local épingle sa CA viaTrustedCertificateAuthorities. Côté serveur, quandRequireMutualTls = true,A2AServern'accepte que les certificats clients qui chaînent vers l'une desTrustedCertificateAuthoritiesou correspondent à une empreinte épinglée deTrustedClientCertificateThumbprints(403 sinon) et refuse de démarrer si aucune ancre de confiance n'est configurée (fail-closed). La révocation n'est pas vérifiée (CA privées sans endpoints CRL/OCSP supposées). L'épinglage CA côté client ne couvre que la chaîne inconnue — un mismatch de nom d'hôte n'est jamais contourné. Les requêtes sans schéma d'authentification autorisé sont rejetées (401) quandAllowedAuthSchemesest défini. La terminaison TLS mutuelle réelle requiert un binding HTTPS deHttpListener(réservation HTTP.sys / certificat serveur) configuré au niveau de l'hôte ; l'endpoint de découverte/.well-known/agent.jsonreste public. - La sélection sémantique d'agents (
OrkeonApplicationOptions.AgentSelectionStrategy = Embedding) hérite depuis RAG-02/C5 de la chaîne de résolution d'embeddings réelle : leSimpleEmbeddingServicebasé sur un hachage a été supprimé, et l'IEmbeddingServicepar défaut adapte le portIEmbeddingProvider(BGE local siAddOrkeonLocalEmbeddings()est enregistré → provider distant viaOrkeon:Embeddings→ échec expliciteInvalidOperationExceptionau premier usage, message actionnable). Plus aucun repli non sémantique silencieux : sans embedding provider, la stratégieEmbeddingéchoue bruyamment — configurer un provider, ou préférer la stratégieSkill(correspondance lexicale, sans dépendance) ou le défautFirstFit(premier agent disponible) - Corrigé depuis RAG-01, rebasé en RAG-02 — le chemin RAG ne se dégrade plus silencieusement : le pipeline d'ingestion (
Orkeon.Rag) embedde les chunks à l'ingestion et le document store cherche par similarité vectorielle scorée (les scores survivent de bout en bout jusqu'ÃScoredChunk), et le portIEmbeddingProviderse résout BGE local (siAddOrkeonLocalEmbeddings()est enregistré) → provider distant viaOrkeon:Embeddings→ échec explicite (InvalidOperationExceptionau premier usage, message actionnable).HashBasedEmbeddingProviderest un double de test uniquement — plus jamais résolu implicitement - Tool calling natif — Ollama (levé en LLM-07) :
OllamaLlmProvideratteint désormais/api/chat— et est câblé avec la stratégie native OpenAI — dès que la conversation déclare des outils, rejoue des appels d'outils, ou transporte une image. Il remet en forme la réponse d'Ollama (message.tool_callsavecargumentsen objet JSON, sans tableauchoices) dans le corps OpenAI que lit l'unique parser du framework (choices[0].message.tool_calls,argumentsen chaîne JSON), et assigne des ids d'appel positionnels puisqu'Ollama n'en émet pas. Limites restantes : tout le reste — conversations simples, génération mono-prompt, streaming — passe encore par/api/generate(le streaming NDJSON et lagrammarGBNF n'existent que là ), donc le protocole texte de repli reste aux commandes pour les modèles sans support des tools ; le streaming de/api/chatn'est pas implémenté, un appel streamé garde donc le chemin prompt-complétion ; et les images doivent être fournies en octets, puisqu'Ollama prend des payloads base64 nus et ne télécharge jamais une URL distante. - Profils RAG
adaptive/corrective— les nœuds dépendant d'un LLM se dégradent hors ligne : depuis RAG-06 la route Adaptive-RAGIterativedélègue au pipeline graphecorrective(le repli documenté RAG-05 versqualityest levé ; l'étaperoutetracedelegate=correctiveetRagTrace.Routeporte la décision). Limites honnêtes restantes : le classifieur de complexité par défaut est l'heuristique déterministe ; le classifieurllmrequiert unIChatClientenregistré (sans lui, repli sur l'heuristique avec avertissement) ; et sans vrai LLM le graphe correctif ne peut pas combler un fossé de vocabulaire — en évaluation--offlinele stub extractif alimenterewrite_query/evaluate/check_groundedness: le parseur tolérant du grader pêche des mots de grade dans les passages recopiés (verdicts pseudo-aléatoires ; le repli du vérificateur d'ancrage reste sûrementgrounded), et une réécriture déclenchée dégénère en le préfixe fixe du stub — une seule probe dénuée de sens partagée par tous les cas — donc les chiffrescorrectiveoffline mesurent les garde-fous de la boucle plus cette dégradation, pas la qualité de réécriture, et peuvent tomber sousquality(tableau mesuré et analyse dansexamples/rag/eval/README.md; le mécanisme de bout en bout — verdict de l'évaluateur → réécriture → citation récupérée sur le cas seedé q-007 — est prouvé parCorrectiveRagMechanismSlowTestsavec un LLM scripté, étiqueté comme tel). Même note offline qu'avant pour les transformers de requête LLM (multi-query/rag-fusion/hyde) : le chemin mesuré offline estQueryTransform.Mode=none+ routage heuristique. - Les profils RAG
balanced/quality/adaptiveexigent les paquets du reranker ONNX : leurs presets activent l'étage de rerank cross-encoder, et le résolveur de profils échoue explicitement à la première requête (InvalidOperationExceptionactionnable) quandOrkeon.Rag.Onnx+Orkeon.Rag.Onnx.Modelne sont pas référencés et qu'AddOrkeonOnnxReranker()n'est pas enregistré.fast(le défaut) etcorrective(le graphe corrige en bouclant, pas d'étage de rerank linéaire) fonctionnent sans les paquets ONNX.adaptiveen a besoin car sa routeSingleShotdélègue Ãbalanced. - Runtime natif ONNX — les suites qui le chargent : deux suites de tests chargent la bibliothèque native ONNX Runtime —
tests/tools/Orkeon.Tools.Embeddings.Local.Tests(embeddings BGE-micro-v2 locaux) ettests/rag/Orkeon.Rag.Onnx.Tests(reranker cross-encoder ms-marco) — et exigent donc une plateforme où cette bibliothèque se charge. Jusqu'au 2026-09-07 cette entrée décrivait aussi un SIGSEGV (code 139) qui emportait le processus après le passage des tests Embeddings.Local, le qualifiait d'artefact de teardown du runtime natif (PUB-17 / SONAR-14), et faisait tolérer exactement cette forme parci.ymletpublish.yml. Ce n'était pas un artefact de teardown.Dispose_Releases_EmbedderappelaitEmbedBatchAsyncsur un provider libéré, et le provider — qui posait un drapeau_disposedqu'il ne relisait jamais — déréférençait la session native libérée : un comportement indéfini, qui apparaissait tantôt comme uneOnnxRuntimeExceptionfantaisiste sur un tas encore chaud, tantôt comme un SIGSEGV tuant le processus sur un tas sali, parfois avant même qu'un seul résultat ait été rapporté. La tolérance ne pouvait pas davantage l'attraper, puisque la comptabilité qu'elle comparait venait du processus crashé lui-même.LocalEmbeddingProviderlève désormaisObjectDisposedExceptiondepuisEmbedBatchAsyncetDimensions; la suite exécute ses 11 tests et sort en 0 (17 exécutions d'affilée), les deux étapes CI sont redevenues de simplesdotnet test, etintegration.ymln'écarte plus le projet. Les deux suites ont par ailleurs été mesurées vertes dans un conteneur le 2026-09-07 : la consigne antérieure de ne les lancer que sur une machine hôte ou en CI est abandonnée. Orkeon.Tools.Embeddings.Localrepose sur une pré-release d'un amont archivé — l'opt-in d'embeddings locaux on-device est bâti surSmartComponents.LocalEmbeddings 0.1.0-preview10148(épinglé dansDirectory.Packages.props), qui est la seule version existante : l'amont n'a jamais publié de version stable, et le dépôt visé par leprojectUrldu paquet (dotnet-smartcomponents/smartcomponents) est archivé — le code a déménagé versdotnet/smartcomponents, qui ne livre toujours pas de 1.0. Attendre un amont stable n'est pas un plan. Le volet licence est tranché et documenté (MIT pour le wrapper comme pour les poids BGE-micro-v2 embarqués, provenance établie à la main dansTHIRD-PARTY-NOTICES.mdsections 1-2) ; ce qui reste est une contrainte de packaging : NuGet refuse de packager un paquet stable qui dépend d'une pré-release (NU5104). Une1.0.0stable d'Orkeon ne peut donc pas porter cette dépendance dans son paquet principal — c'est exactement pour cela que cet opt-in est livré comme paquetOrkeon.Tools.Embeddings.Localà part plutôt que fondu dans le parapluieOrkeon(PUB-25). Conséquence pour un consommateur : référencer cet opt-in fait entrer une dépendance pré-release dans votre propre graphe, et si vous publiez ensuite un paquet stable qui en dépend, vous heurtezNU5104à votre tour. Échappatoires, de la moins coûteuse à la plus coûteuse : (a) ne pas référencer l'opt-in — le portIEmbeddingProviderrésout alors un provider distant depuisOrkeon:Embeddings(voir l'entrée sélection sémantique d'agents ci-dessus) ; (b) implémenterIEmbeddingProvidersur votre propre pile d'embeddings ; (c) vendorer le wrapper d'inférence amont (MIT, donc autorisé) dans une assembly que vous contrôlez et retirer la référence de paquet. Décision (2026-09-11) : la préversion est assumée, pas vendorisée.Orkeon.Tools.Embeddings.Localsera livré en1.0.0stable dépendant deSmartComponents.LocalEmbeddings 0.1.0-preview10148;NU5104est réduit au silence dans ce seul projet de packaging (l'ombrelle,Orkeon.Toolset la CLI ne portent jamais la dépendance), un pack stable de toute la ligne réussit, et le README dit en une ligne quel opt-in reste sur une préversion et pourquoi. Vendoriser le wrapper d'inférence (issue (c)) reste possible pour un consommateur qui exige un graphe entièrement stable ; cela ne vaut pas une seconde copie d'un wrapper MIT pour le framework lui-même. Les dotnet toolsorkeon/orkeon-replet les installeurs ne sont pas concernés parNU5104— un paquet tool est self-contained et c'est sa propre version que NuGet contrôle.- Le repli web RAG est un double opt-in, désactivé par défaut : le nœud
web_fallbackdu graphe correctif ne s'exécute que quand les deux interrupteurs sont activés —Orkeon:Rag:Corrective:WebFallback(politique : le graphe a-t-il le droit de sortir du store local) etOrkeon:Rag:WebFallback(transport : endpoint SearxNG,AddOrkeonRagWebFallbackn'enregistre le retriever que si activé avec un endpoint non vide). Chaque page téléchargée est filtrée parPromptInjectionDocumentValidatoravant d'entrer dans le working set (les pagesRejectedn'entrent jamais ;Suspicioussuit la politique configurée) — voir Sécurité - MCP — client/serveur dual-era depuis PUB-07 : le client sonde avec
server/discoveret parle la révision moderne stateless (2026-07-28—_metapar requête, renégociation de version surUnsupportedProtocolVersionError) ou retombe sur le handshakeinitializelegacy (2025-11-25,2025-06-18,2024-11-05;2025-03-26est exclue à dessein — seule révision qui impose le batching JSON-RPC, que cette implémentation ne parle pas) ; le serveur sert les deux ères simultanément. Limites assumées de la surface moderne : pas desubscriptions/listen(notifications poussées par le serveur), pas de requêtes multi-aller-retour (un résultatinput_requiredremonte comme erreur d'outil), pas d'autorisation MCP (OAuth) ; le transport HTTP est le mode réponse JSON du Streamable HTTP — en-têtes modernes envoyés et corps SSE déballé jusqu'à son message final, mais les flux à l'initiative du serveur ne sont pas consommés. L'interop contre les serveurs de référence (MCP Inspector) n'a pas encore tourné — suivie dans la note de clôture de PUB-07. - LanceDB —
LanceDbMemoryProvidercible désormais un serveur LanceDB Cloud/Enterprise distant (protocole Lance REST Namespace, payloads Arrow IPC) ; il n'existe plus de store JSON local. Limites de l'API distante (détails dans Système de mémoire) :SearchAsyncexige un index FTS surcontent(créé automatiquement à la création de la table, sinon l'erreur serveur est propagée — jamais simulée localement) ;HybridSearchAsyncémet deux requêtes serveur (classements_distance/_scorecôté serveur) et fusionne localement les deux listes classées, comme les rerankers des SDK officiels ; l'API delete ne renvoyant pas de compteur,DeleteAsync/UpdateAsyncfont une requête d'existence préalable pour préserver leur contrat booléen ; la conversion score =1 − _distancen'est pertinente que pour la métriquecosine(défaut) spawn_agentn'est enregistré par aucune racine de composition livrée — la classe (SpawnAgentTool, self-spawn sous budget du mode autonome) est livrée dansOrkeon.Infrastructure, mais niorkeon runni le REPL ne la mettent dans le registre de tools ; un hôte qui veut le self-spawn l'enregistre explicitement avec unIAgentFactory. Voirdocs/fr/tools/inventory.mdetdocs/fr/orchestration/autonomous.md.- Les espaces de noms de mounts par exécution ne sont entrés que par
orkeon-host—IFileSystemScope/AsyncLocalFileSystemScope(Domain) donnent à un flux d'exécution son propreFileSystemRegistry, etFileSystemServiceconsulte cette surcharge ambiante à chaque opération : deux crews dans le même processus peuvent donc adresser chacun son/outputsur des dossiers physiques différents — le rejet des chemins virtuels en double est par instance, jamais global.orkeon-hostest la seule racine de composition livrée qui entre un namespace, par crew hébergé, depuisOrkeon:Host:Crews:*:Mounts(CrewRunner). Tous les autres points d'entrée —orkeon run,orkeon forge,orkeon rag— tournent sur le registre de boot, un jeu de mounts plat par processus dont les chemins virtuels doivent être globalement uniques : d'où le fait qu'ils réservent leurs racines contre le fichier de settings au lieu de les cloisonner, et que l'hôte renomme encore les crews auxquels il n'accorde aucun mount (/crews,/crews-1, …). Un hôte qui veut son propre namespace le compose avecScopedMountComposition.ForExecution: entrer dans un scope remplace le jeu de boot au lieu de fusionner avec lui, donc la composition reporte les mounts de boot et laisse ceux de l'exécution les masquer aux chemins qu'ils revendiquent — les abandonner emporte/llm-logset/sandboxavec le run, et emporte la racine depuis laquelle le runner charge le crew. Un second portail, process-global, subsiste dans tous les cas — les racines autorisées d'IPathValidatorsont figées au boot, donc un dossier accordé hors de la racine du workspace résout dans le namespace puis se fait refuser par le validateur ;PathSecurity:AdditionalAllowedDirectoriesest l'endroit où un opérateur l'élargit. Voir Conformité VFS.