Le premier cas de support construisait chaque brique à la main. Ici, on refait le même agent sur la stack managée AWS : récupération par Knowledge Bases, raisonnement Bedrock, sécurité par Guardrails, état dans DynamoDB, déploiement sur AgentCore Runtime. On garde l’orchestration LangGraph au centre — c’est elle qui rend le tout contrôlable.

C’est la mise en pratique de tous les deep-dives AWS, assemblés en un système déployable.

L’architecture managée

Le graphe reste le RAG agentique : l’agent décide quand interroger la base. Mais chaque brique est désormais un service AWS.

Fig.01 · Boucle agentique
sinon → STOP tool_calls ToolMessage START modèle llm.invoke() outils ToolNode END
L'agent (Claude via Bedrock) décide d'appeler l'outil de recherche — adossé à une Knowledge Base managée — ou de répondre. Guardrails et DynamoDB encadrent le tout.
BriqueService AWS
Récupération (RAG)Bedrock Knowledge Bases (hybride, reranking inclus)
RaisonnementBedrock Converse API (Claude)
SécuritéBedrock Guardrails (PII, sujets, ancrage)
Persistance / mémoireDynamoDB (checkpointer)
OrchestrationLangGraph
Exécution / hébergementAgentCore Runtime
ObservabilitéLangFuse + CloudWatch

Construire l’agent, étape par étape

Provisionner la Knowledge Base

On crée une Knowledge Base pointant vers un bucket S3 (la documentation), avec OpenSearch Serverless en backend. Cela se fait en IaC (CDK/Terraform) ou en console ; on retient l’knowledgeBaseId. L’ingestion, le chunking, les embeddings et l’index hybride sont gérés par AWS — c’est tout l’intérêt.

# La Knowledge Base est provisionnée hors application (IaC). On ne garde que son id.
KB_ID = "KB123456"        # identifiant de la Knowledge Base
REGION = "eu-west-1"

Exposer la récupération managée comme outil

On branche la Knowledge Base via AmazonKnowledgeBasesRetriever, en mode hybride, et on l’expose comme outil — l’agent décide quand chercher.

from langchain_aws import AmazonKnowledgeBasesRetriever
from langchain_core.tools import tool

retriever = AmazonKnowledgeBasesRetriever(
    knowledge_base_id=KB_ID, region_name=REGION,
    retrieval_config={"vectorSearchConfiguration": {
        "numberOfResults": 5, "overrideSearchType": "HYBRID"}},
)

@tool
def base_de_connaissances(requete: str) -> str:
    """Recherche dans la base de connaissances produit (Bedrock Knowledge Base)."""
    docs = retriever.invoke(requete)
    if not docs:
        return "AUCUN_RESULTAT"
    return "\n\n---\n\n".join(
        f"[{d.metadata.get('source_metadata', {}).get('x-amz-bedrock-kb-source-uri', 'doc')}]\n"
        f"{d.page_content}" for d in docs)

Le modèle Bedrock, protégé par un Guardrail

Le raisonnement est confié à Claude via la Converse API, avec un Guardrail attaché : PII caviardée, sujets interdits, vérification d’ancrage — appliqués à chaque appel (cf. Guardrails en profondeur).

from langchain_aws import ChatBedrockConverse

modele = ChatBedrockConverse(
    model="eu.anthropic.claude-sonnet-4-5-20250929-v1:0",
    region_name=REGION,
    temperature=0.1,
    guardrail_config={"guardrailIdentifier": "abcd1234",
                      "guardrailVersion": "1", "trace": "enabled"},
)

Câbler l’escalade

Comme dans le cas d’origine, « escalader » est un outil concret — ici, il crée un ticket (par exemple via une Lambda exposée).

@tool
def escalader(motif: str, resume: str) -> str:
    """Transfère la demande à un humain (hors base, réclamation, action sur le compte)."""
    ticket_id = creer_ticket_helpdesk(motif, resume)   # Lambda / API interne
    return f"Demande transférée à un conseiller (ticket {ticket_id})."

Assembler l’agent avec persistance DynamoDB

On assemble l’agent ReAct et on lui donne un checkpointer DynamoDB : l’état survit aux redéploiements, et le human-in-the-loop devient possible (cf. archi de production).

from langgraph.prebuilt import create_react_agent
from langgraph_checkpoint_aws.saver import BedrockSessionSaver

SYSTEME = """Tu es l'assistant de support de niveau 1 de DEEP-5.
- Réponds UNIQUEMENT à partir des documents de `base_de_connaissances`, cite la source.
- Hors périmètre, réclamation ou action sur le compte : appelle `escalader`.
- N'invente jamais. Réponds en français, concis et actionnable."""

checkpointer = BedrockSessionSaver(region_name=REGION)
agent = create_react_agent(
    modele, [base_de_connaissances, escalader],
    prompt=SYSTEME, checkpointer=checkpointer,
)

Déployer sur AgentCore Runtime

On emballe l’agent derrière le contrat d’entrée d’AgentCore Runtime : exécution serverless, isolée, à sessions longues, sans gérer de conteneurs.

from langfuse.langchain import CallbackHandler
_handler = CallbackHandler()

def handler(requete: dict) -> dict:
    """Point d'entrée invoqué par AgentCore Runtime pour chaque requête."""
    res = agent.invoke(
        {"messages": [{"role": "user", "content": requete["prompt"]}]},
        config={
            "callbacks": [_handler],
            "configurable": {"thread_id": requete["session_id"]},
            "recursion_limit": 8,
            "metadata": {"langfuse_session_id": requete["session_id"],
                         "langfuse_tags": ["support-aws"]},
        },
    )
    return {"reponse": res["messages"][-1].content}

Lire la trace : managé, mais transparent

Déléguer à AWS ne doit pas créer une boîte noire. La trace LangFuse montre l’arbre complet — y compris l’appel à la Knowledge Base et l’intervention éventuelle du Guardrail (grâce à trace: enabled).

Fig.02 · Trace d'une réponse
TRACE · agent.invoke() 2.4 s · $0.0031 GENERATION · décision gpt-4o-mini · 412 tok SPAN · chercher_doc() 84 ms GENERATION · réponse finale 356 tok
Décision, appel à la Knowledge Base managée, génération — et, le cas échéant, l'intervention du Guardrail. Le managé reste observable.

Évaluer : le managé doit prouver sa qualité

Le pipeline d’évaluation ne change pas : un dataset de questions réelles (dont des pièges hors périmètre attendant une escalade), un LLM-juge de fidélité, et une non-régression en CI. On y ajoute un contrôle propre à l’AWS : vérifier que le Guardrail intervient bien sur les cas sensibles (PII, sujets interdits) sans sur-bloquer les cas légitimes.

Bonnes pratiques & pièges

Bonnes pratiques
  • Déléguez la récupération à Knowledge Bases (hybride, reranking) ; gardez LangGraph pour le flux.
  • Attachez un Guardrail à l'inférence pour PII, déni de sujets et ancrage — entrée et sortie.
  • Persistez l'état dans DynamoDB : durabilité, HITL, reprise après redéploiement.
  • Déployez sur AgentCore Runtime : serverless, isolé, sessions longues, sans conteneurs.
  • Double observabilité : LangFuse (agentique) + CloudWatch (audit Bedrock/Guardrail).
  • Évaluez la fidélité ET le bon déclenchement du Guardrail sur un dataset à pièges.
Pièges à éviter
  • Tout-managé sans observabilité : on perd la visibilité sur les décisions de l'agent.
  • Régler le Guardrail trop strict : sur-blocage de demandes légitimes, UX dégradée.
  • Garder l'état en mémoire : pas de reprise, pas de HITL durable sur AgentCore.
  • Oublier de citer les sources de la Knowledge Base : on perd la vérifiabilité.
  • Croire que Knowledge Bases + Guardrails suffisent : le flux (escalade, refus) reste votre logique.

Ce qu’il faut retenir

  • Le même agent de support, porté sur la stack managée AWS : Knowledge Bases (RAG), Bedrock (raisonnement), Guardrails (sécurité), DynamoDB (état), AgentCore (exécution).
  • LangGraph reste au centre : c’est le flux (décision, escalade, refus) qui demeure votre valeur — le managé porte l’infra, pas la logique.
  • La double observabilité (LangFuse + CloudWatch) empêche le tout-managé de devenir une boîte noire.
  • L’évaluation vaut aussi pour le managé : fidélité et bon déclenchement des Guardrails, sur un dataset à pièges.

Vous avez désormais le même cas en version artisanale et en version 100 % AWS managée : de quoi choisir, pour chaque projet, le bon curseur entre contrôle et délégation.

#cas-pratique#aws#bedrock#knowledge-bases#agentcore