Aller au contenu

Agent de Strands Python

Générer un agent Strands Agent en Python pour créer des agents IA avec des outils, et optionnellement le déployer sur Amazon Bedrock AgentCore Runtime.

Strands est un framework Python léger et prêt pour la production permettant de créer des agents IA. Principales fonctionnalités :

  • Léger et personnalisable : Boucle d’agent simple qui reste discrète
  • Prêt pour la production : Observabilité complète, traçage et options de déploiement évolutives
  • Agnostique aux modèles et fournisseurs : Supporte de nombreux modèles de différents fournisseurs
  • Outils communautaires : Ensemble puissant d’outils contribués par la communauté
  • Support multi-agents : Techniques avancées comme les équipes d’agents et agents autonomes
  • Modes d’interaction flexibles : Support conversationnel, streaming et non-streaming

Vous pouvez générer un agent Strands en Python de deux manières :

  1. Installez le Nx Console VSCode Plugin si ce n'est pas déjà fait
  2. Ouvrez la console Nx dans VSCode
  3. Cliquez sur Generate (UI) dans la section "Common Nx Commands"
  4. Recherchez @aws/nx-plugin - py#strands-agent
  5. Remplissez les paramètres requis
    • Cliquez sur Generate
    Paramètre Type Par défaut Description
    project Requis string - The project to add the Strands Agent to
    computeType string BedrockAgentCoreRuntime The type of compute to host your Strands Agent.
    name string - The name of your Strands Agent (default: agent)
    iacProvider string Inherit The preferred IaC provider. By default this is inherited from your initial selection.

    Le générateur ajoutera les fichiers suivants à votre projet Python existant :

    • Répertoireyour-project/
      • Répertoireyour_module/
        • Répertoireagent/ (ou nom personnalisé si spécifié)
          • __init__.py Initialisation du package Python
          • agent.py Définition principale de l’agent avec des outils exemples
          • main.py Point d’entrée pour Bedrock AgentCore Runtime
          • agentcore_mcp_client.py Factory client utile pour invoquer des serveurs MCP hébergés sur Bedrock AgentCore Runtime
          • Dockerfile Point d’entrée pour héberger votre agent (exclu si computeType est None)
      • pyproject.toml Mis à jour avec les dépendances Strands
      • project.json Mis à jour avec les cibles de service de l’agent

    Ce générateur fournit de l’infrastructure as code basée sur votre iacProvider choisi. Il créera un projet dans packages/common qui inclut les constructions CDK ou modules Terraform pertinents.

    Le projet commun d’infrastructure as code est structuré comme suit :

    • Répertoirepackages/common/constructs
      • Répertoiresrc
        • Répertoireapp/ Constructions pour l’infrastructure spécifique à un projet/générateur
        • Répertoirecore/ Constructions génériques réutilisées par celles dans app
        • index.ts Point d’entrée exportant les constructions depuis app
      • project.json Cibles de build et configuration du projet

    Pour le déploiement de votre agent Strands, les fichiers suivants sont générés :

    • Répertoirepackages/common/constructs/src
      • Répertoireapp
        • Répertoireagents
          • Répertoire<project-name>
            • <project-name>.ts Construct CDK pour déployer votre agent
            • Dockerfile Fichier Docker transmis utilisé par le construct CDK

    Les outils sont des fonctions que l’agent IA peut appeler pour effectuer des actions. Le framework Strands utilise une approche basée sur des décorateurs pour définir les outils.

    Vous pouvez ajouter de nouveaux outils dans le fichier agent.py :

    from strands import Agent, tool
    @tool
    def calculate_sum(numbers: list[int]) -> int:
    """Calcule la somme d'une liste de nombres"""
    return sum(numbers)
    @tool
    def get_weather(city: str) -> str:
    """Obtient les informations météo d'une ville"""
    # Votre intégration d'API météo ici
    return f"Météo à {city} : Ensoleillé, 25°C"
    # Ajoutez les outils à votre agent
    agent = Agent(
    system_prompt="Vous êtes un assistant utile avec accès à divers outils.",
    tools=[calculate_sum, get_weather],
    )

    Le framework Strands gère automatiquement :

    • La validation des types via les annotations de type
    • La génération de schémas JSON pour l’appel d’outils
    • La gestion des erreurs et le formatage des réponses

    Strands fournit une collection d’outils prêts à l’emploi via le package strands-tools :

    from strands_tools import current_time, http_request, file_read
    agent = Agent(
    system_prompt="Vous êtes un assistant utile.",
    tools=[current_time, http_request, file_read],
    )

    Par défaut, les agents Strands utilisent Claude 4 Sonnet, mais vous pouvez personnaliser le fournisseur de modèle. Consultez la documentation Strands sur les fournisseurs de modèles pour les options de configuration :

    from strands import Agent
    from strands.models import BedrockModel
    # Créez un BedrockModel
    bedrock_model = BedrockModel(
    model_id="anthropic.claude-sonnet-4-20250514-v1:0",
    region_name="us-west-2",
    temperature=0.3,
    )
    agent = Agent(model=bedrock_model)

    Vous pouvez ajouter des outils depuis des serveurs MCP à votre agent Strands.

    Pour utiliser des serveurs MCP créés avec les générateurs py#mcp-server ou ts#mcp-server (ou d’autres hébergés sur Bedrock AgentCore Runtime), une factory client est générée pour vous dans agentcore_mcp_client.py.

    Vous pouvez mettre à jour votre méthode get_agent dans agent.py pour créer des clients MCP et ajouter des outils. L’exemple suivant montre comment faire cela avec l’authentification IAM (SigV4) :

    agent.py
    import os
    from contextlib import contextmanager
    import boto3
    from strands import Agent
    from .agentcore_mcp_client import AgentCoreMCPClient
    # Obtenez la région et les credentials
    region = os.environ["AWS_REGION"]
    boto_session = boto3.Session(region_name=region)
    credentials = boto_session.get_credentials()
    @contextmanager
    def get_agent(session_id: str):
    mcp_client = AgentCoreMCPClient.with_iam_auth(
    agent_runtime_arn=os.environ["MCP_AGENTCORE_RUNTIME_ARN"],
    credentials=credentials,
    region=region,
    session_id=session_id,
    )
    with mcp_client:
    mcp_tools = mcp_client.list_tools_sync()
    yield Agent(
    system_prompt="..."
    tools=[*mcp_tools],
    )

    Avec l’exemple d’authentification IAM ci-dessus, nous devons configurer deux éléments dans notre infrastructure. Premièrement, ajouter la variable d’environnement consommée par notre agent pour l’ARN du runtime AgentCore du serveur MCP, et deuxièmement accorder les permissions d’invocation à notre agent. Cela peut être réalisé comme suit :

    import { MyProjectAgent, MyProjectMcpServer } from ':my-scope/common-constructs';
    export class ExampleStack extends Stack {
    constructor(scope: Construct, id: string) {
    const mcpServer = new MyProjectMcpServer(this, 'MyProjectMcpServer');
    const agent = new MyProjectAgent(this, 'MyProjectAgent', {
    environmentVariables: {
    MCP_AGENTCORE_RUNTIME_ARN: mcpServer.agentCoreRuntime.agentRuntimeArn,
    },
    });
    mcpServer.agentCoreRuntime.grantInvoke(agent.agentCoreRuntime);
    }
    }

    Pour un guide plus détaillé sur l’écriture d’agents Strands, consultez la documentation Strands.

    Le générateur utilise FastAPI pour créer le serveur HTTP de votre agent Strands. FastAPI fournit un framework web moderne et rapide pour créer des API avec Python, avec documentation API automatique et validation de types.

    Le serveur généré inclut :

    • Configuration de l’application FastAPI avec middleware CORS
    • Middleware de gestion des erreurs
    • Génération du schéma OpenAPI
    • Point de terminaison de vérification de santé (/ping)
    • Point de terminaison d’invocation de l’agent (/invocations)

    Personnalisation des entrées et sorties d’invocation avec Pydantic

    Section intitulée « Personnalisation des entrées et sorties d’invocation avec Pydantic »

    Le point de terminaison d’invocation de l’agent utilise des modèles Pydantic pour définir et valider les schémas de requête et de réponse. Vous pouvez personnaliser ces modèles dans main.py pour correspondre aux besoins de votre agent.

    Le modèle InvokeInput par défaut accepte un prompt et un ID de session.

    from pydantic import BaseModel
    class InvokeInput(BaseModel):
    prompt: str
    session_id: str

    Vous pouvez étendre ce modèle pour inclure tous les champs supplémentaires dont votre agent a besoin.

    Pour les réponses en streaming, l’annotation de type de retour sur votre point de terminaison correspond au type de chaque valeur générée par votre fonction génératrice. Par défaut, l’agent génère des chaînes contenant le texte de réponse de l’agent tel qu’il est diffusé en continu depuis Strands :

    @app.post("/invocations", openapi_extra={"x-streaming": True})
    async def invoke(input: InvokeInput) -> str:
    """Point d'entrée pour l'invocation de l'agent"""
    return StreamingResponse(handle_invoke(input), media_type="text/event-stream")

    Vous pouvez définir un modèle Pydantic pour générer des données structurées à la place. Pour ce faire, vous devrez sérialiser les modèles pydantic générés par handle_invoke :

    from pydantic import BaseModel
    class StreamChunk(BaseModel):
    content: str
    timestamp: str
    token_count: int
    def handle_invoke(...):
    ...
    yield StreamChunk(content="xx", timestamp="yy", token_count=5)
    def serialize_stream(generator):
    async for output in generator:
    yield (output.model_dump_json() + "\n").encode("utf-8")
    @app.post("/invocations", openapi_extra={"x-streaming": True})
    async def invoke(input: InvokeInput) -> StreamChunk:
    return StreamingResponse(serialize_stream(handle_invoke(input)), media_type="application/json")

    Le générateur inclut une dépendance au SDK Python Bedrock AgentCore pour les constantes PingStatus. Si vous le souhaitez, il est simple d’utiliser BedrockAgentCoreApp au lieu de FastAPI, mais notez que la sécurité des types est perdue.

    Vous trouverez plus de détails sur les capacités du SDK dans la documentation ici.

    Le générateur configure une cible nommée <your-agent-name>-serve qui démarre votre agent Strands localement pour le développement et les tests.

    Terminal window
    pnpm nx run your-project:agent-serve

    Cette commande utilise uv run pour exécuter votre agent Strands via le SDK Python Bedrock AgentCore.

    Déploiement de votre agent Strands sur Bedrock AgentCore Runtime

    Section intitulée « Déploiement de votre agent Strands sur Bedrock AgentCore Runtime »

    Si vous avez sélectionné BedrockAgentCoreRuntime pour computeType, l’infrastructure CDK ou Terraform correspondante est générée, que vous pouvez utiliser pour déployer votre Strands Agent sur Amazon Bedrock AgentCore Runtime.

    Un construct CDK est généré pour votre agent, nommé en fonction du name que vous avez choisi lors de l’exécution du générateur, ou <ProjectName>Agent par défaut.

    Vous pouvez utiliser ce construct CDK dans une application CDK :

    import { MyProjectAgent } from ':my-scope/common-constructs';
    export class ExampleStack extends Stack {
    constructor(scope: Construct, id: string) {
    // Add the agent to your stack
    const agent = new MyProjectAgent(this, 'MyProjectAgent');
    // Grant permissions to invoke the relevant models in bedrock
    agent.agentCoreRuntime.addToRolePolicy(
    new PolicyStatement({
    actions: [
    'bedrock:InvokeModel',
    'bedrock:InvokeModelWithResponseStream',
    ],
    // You can scope the below down to the specific models you use
    resources: [
    'arn:aws:bedrock:*:*:foundation-model/*',
    'arn:aws:bedrock:*:*:inference-profile/*',
    ],
    }),
    );
    }
    }

    Par défaut, votre Strands Agent sera sécurisé à l’aide de l’authentification IAM, déployez-le simplement sans aucun argument :

    import { MyProjectAgent } from ':my-scope/common-constructs';
    export class ExampleStack extends Stack {
    constructor(scope: Construct, id: string) {
    new MyProjectAgent(this, 'MyProjectAgent');
    }
    }

    Vous pouvez accorder l’accès pour invoquer votre agent sur Bedrock AgentCore Runtime en utilisant la méthode grantInvoke, par exemple :

    import { MyProjectAgent } from ':my-scope/common-constructs';
    export class ExampleStack extends Stack {
    constructor(scope: Construct, id: string) {
    const agent = new MyProjectAgent(this, 'MyProjectAgent');
    const lambdaFunction = new Function(this, ...);
    agent.agentCoreRuntime.grantInvoke(lambdaFunction);
    }
    }

    Ce qui suit démontre comment configurer l’authentification Cognito pour votre agent.

    Pour configurer l’authentification JWT en utilisant Cognito, utilisez la méthode factory RuntimeAuthorizerConfiguration.usingCognito() :

    import { MyProjectAgent } from ':my-scope/common-constructs';
    import { RuntimeAuthorizerConfiguration } from '@aws-cdk/aws-bedrock-agentcore-alpha';
    export class ExampleStack extends Stack {
    constructor(scope: Construct, id: string) {
    const userPool = new UserPool(this, 'UserPool');
    const client = userPool.addClient('Client', {
    authFlows: {
    userPassword: true,
    },
    });
    new MyProjectAgent(this, 'MyProjectAgent', {
    authorizerConfiguration: RuntimeAuthorizerConfiguration.usingCognito(
    userPool,
    [client],
    ),
    });
    }
    }

    Alternativement, pour une authentification JWT personnalisée avec votre propre fournisseur OIDC, utilisez RuntimeAuthorizerConfiguration.usingJWT() :

    import { MyProjectAgent } from ':my-scope/common-constructs';
    import { RuntimeAuthorizerConfiguration } from '@aws-cdk/aws-bedrock-agentcore-alpha';
    export class ExampleStack extends Stack {
    constructor(scope: Construct, id: string) {
    new MyProjectAgent(this, 'MyProjectAgent', {
    authorizerConfiguration: RuntimeAuthorizerConfiguration.usingJWT(
    'https://example.com/.well-known/openid-configuration',
    ['client1', 'client2'], // Allowed Client IDs (optional)
    ['audience1'], // Allowed Audiences (optional)
    ),
    });
    }
    }

    Pour construire votre agent Strands pour Bedrock AgentCore Runtime, une cible bundle est ajoutée à votre projet, qui :

    • Exporte vos dépendances Python dans un fichier requirements.txt via uv export
    • Installe les dépendances pour la plateforme cible (aarch64-manylinux2014) via uv pip install

    Une cible docker spécifique à votre agent Strands est également ajoutée, qui :

    Par défaut, votre agent Strands sera sécurisé via l’authentification IAM. Déployez-le simplement sans arguments :

    import { MyProjectAgent } from ':my-scope/common-constructs';
    export class ExampleStack extends Stack {
    constructor(scope: Construct, id: string) {
    new MyProjectAgent(this, 'MyProjectAgent');
    }
    }

    Vous pouvez accorder l’accès à votre agent sur Bedrock AgentCore Runtime via la méthode grantInvoke, par exemple :

    import { MyProjectAgent } from ':my-scope/common-constructs';
    export class ExampleStack extends Stack {
    constructor(scope: Construct, id: string) {
    const agent = new MyProjectAgent(this, 'MyProjectAgent');
    const lambdaFunction = new Function(this, ...);
    agent.agentCoreRuntime.grantInvoke(lambdaFunction);
    }
    }

    L’exemple suivant montre comment configurer l’authentification Cognito pour votre agent.

    Pour configurer l’authentification JWT avec Cognito, utilisez la méthode factory RuntimeAuthorizerConfiguration.usingCognito() :

    import { MyProjectAgent } from ':my-scope/common-constructs';
    import { RuntimeAuthorizerConfiguration } from '@aws-cdk/aws-bedrock-agentcore-alpha';
    export class ExampleStack extends Stack {
    constructor(scope: Construct, id: string) {
    const userPool = new UserPool(this, 'UserPool');
    const client = userPool.addClient('Client', {
    authFlows: {
    userPassword: true,
    },
    });
    new MyProjectAgent(this, 'MyProjectAgent', {
    authorizerConfiguration: RuntimeAuthorizerConfiguration.usingCognito(
    userPool,
    [client],
    ),
    });
    }
    }

    Alternativement, pour une authentification JWT personnalisée avec votre propre fournisseur OIDC, utilisez RuntimeAuthorizerConfiguration.usingJWT() :

    import { MyProjectAgent } from ':my-scope/common-constructs';
    import { RuntimeAuthorizerConfiguration } from '@aws-cdk/aws-bedrock-agentcore-alpha';
    export class ExampleStack extends Stack {
    constructor(scope: Construct, id: string) {
    new MyProjectAgent(this, 'MyProjectAgent', {
    authorizerConfiguration: RuntimeAuthorizerConfiguration.usingJWT(
    'https://example.com/.well-known/openid-configuration',
    ['client1', 'client2'], // IDs clients autorisés (optionnel)
    ['audience1'], // Audiences autorisées (optionnel)
    ),
    });
    }
    }

    Votre agent est automatiquement configuré avec l’observabilité via AWS Distro for Open Telemetry (ADOT), via l’auto-instrumentation dans votre Dockerfile.

    Vous pouvez trouver les traces dans la console CloudWatch en sélectionnant “GenAI Observability”. Notez que pour voir les traces, vous devez activer Transaction Search.

    Pour plus de détails, consultez la documentation AgentCore sur l’observabilité.

    Pour invoquer un agent exécuté localement via la cible <your-agent-name>-serve, vous pouvez envoyer une simple requête POST à /invocations sur le port où votre agent local s’exécute. Par exemple, avec curl :

    Fenêtre de terminal
    curl -N -X POST http://localhost:8081/invocations \
    -d '{"prompt": "what is 3 + 5?", "session_id": "abcdefghijklmnopqrstuvwxyz0123456789"}' \
    -H "Content-Type: application/json"

    Pour invoquer votre Agent déployé sur Bedrock AgentCore Runtime, vous pouvez envoyer une requête POST au point de terminaison du plan de données Bedrock AgentCore Runtime avec votre ARN d’exécution encodé en URL.

    Vous pouvez obtenir l’ARN d’exécution depuis votre infrastructure comme suit :

    import { CfnOutput } from 'aws-cdk-lib';
    import { MyProjectAgent } from ':my-scope/common-constructs';
    export class ExampleStack extends Stack {
    constructor(scope: Construct, id: string) {
    const agent = new MyProjectAgent(this, 'MyProjectAgent');
    new CfnOutput(this, 'AgentArn', {
    value: agent.agentCoreRuntime.agentRuntimeArn,
    });
    }
    }

    L’ARN aura le format suivant : arn:aws:bedrock-agentcore:<region>:<account>:runtime/<agent-runtime-id>.

    Vous pouvez ensuite encoder l’ARN en URL en remplaçant : par %3A et / par %2F.

    L’URL du plan de données Bedrock AgentCore Runtime pour invoquer l’agent est la suivante :

    https://bedrock-agentcore.<region>.amazonaws.com/runtimes/<url-encoded-arn>/invocations

    La manière exacte d’invoquer cette URL dépend de la méthode d’authentification utilisée.

    Pour l’authentification IAM, la requête doit être signée avec AWS Signature Version 4 (SigV4).

    Fenêtre de terminal
    acurl <region> bedrock-agentcore -N -X POST \
    'https://bedrock
    -agentcore.<region>.amazonaws.com/runtimes/<url-encoded-arn>/invocations' \
    -d '{"prompt": "what is 3 + 5?", "session_id": "abcdefghijklmnopqrstuvwxyz0123456789"}' \
    -H 'Content-Type: application/json'
    Cliquez ici pour plus de détails sur la configuration de la commande acurl ci-dessus

    Pour l’authentification Cognito, passez le jeton d’accès Cognito dans l’en-tête Authorization :

    Fenêtre de terminal
    curl -N -X POST 'https://bedrock
    -agentcore.<region>.amazonaws.com/runtimes/<url-encoded-arn>/invocations' \
    -d '{"prompt": "what is 3 + 5?", "session_id": "abcdefghijklmnopqrstuvwxyz0123456789"}' \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer <access-token>"

    Vous pouvez obtenir le jeton d’accès en utilisant la commande cognito-idp admin-initiate-auth de l’AWS CLI, par exemple :

    Fenêtre de terminal
    aws cognito-idp admin-initiate-auth \
    --user-pool-id <user-pool-id> \
    --client-id <user-pool-client-id> \
    --auth-flow ADMIN_NO_SRP_AUTH \
    --auth-parameters USERNAME=<username>,PASSWORD=<password> \
    --region <region> \
    --query 'AuthenticationResult.AccessToken' \
    --output text