Skip to content

Python Strands Agent

Generate a Python Strands Agent for building AI agents with tools, and optionally deploy it to Amazon Bedrock AgentCore Runtime. By default, the generator uses FastAPI to expose an HTTP server. Alternatively, you can choose the Agent-to-Agent (A2A) protocol for interoperability with other A2A-compatible agents, or the AG-UI protocol for direct frontend integration via CopilotKit.

Strands is a lightweight, production-ready Python framework for building AI agents. Key features include:

  • Lightweight and customizable: Simple agent loop that gets out of your way
  • Production ready: Full observability, tracing, and deployment options for scale
  • Model and provider agnostic: Supports many different models from various providers
  • Community-driven tools: Powerful set of community-contributed tools
  • Multi-agent support: Advanced techniques like agent teams and autonomous agents
  • Flexible interaction modes: Conversational, streaming, and non-streaming support

You can generate a Python Strands Agent in two ways:

  1. Install the Nx Console VSCode Plugin if you haven't already
  2. Open the Nx Console in VSCode
  3. Click Generate (UI) in the "Common Nx Commands" section
  4. Search for @aws/nx-plugin - py#strands-agent
  5. Fill in the required parameters
    • Click Generate
    Parameter Type Default Description
    project Required 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)
    auth string IAM The method used to authenticate with your Strands Agent. Choose between IAM (default) or Cognito.
    protocol string HTTP The server protocol for your Strands Agent. HTTP exposes a FastAPI HTTP server. A2A exposes an Agent-to-Agent protocol server. AG-UI exposes an Agent-User Interaction protocol server for direct frontend integration.
    iacProvider string Inherit The preferred IaC provider. By default this is inherited from your initial selection.

    The generator will add the following files to your existing Python project. The files generated depend on the chosen protocol:

    • Directoryyour-project/
      • Directoryyour_module/
        • Directoryagent/ (or custom name if specified)
          • __init__.py Python package initialization
          • init.py FastAPI application setup with CORS and error handling middleware
          • agent.py Main agent definition with sample tools
          • main.py FastAPI entry point for Bedrock AgentCore Runtime
          • Dockerfile Entry point for hosting your agent (excluded when computeType is set to None)
      • pyproject.toml Updated with Strands dependencies
      • project.json Updated with agent serve targets

    When protocol is set to A2A, the entry point uses the Strands A2A Server instead of FastAPI:

    • Directoryyour-project/
      • Directoryyour_module/
        • Directoryagent/ (or custom name if specified)
          • __init__.py Python package initialization
          • agent.py Main agent definition with sample tools
          • main.py A2A server entry point
          • Dockerfile Entry point for hosting your agent (excluded when computeType is set to None)
      • pyproject.toml Updated with Strands dependencies
      • project.json Updated with agent serve targets

    When protocol is set to AG-UI, the entry point uses the ag-ui-strands integration, which exposes your agent via the AG-UI protocol for direct frontend integration with CopilotKit:

    • Directoryyour-project/
      • Directoryyour_module/
        • Directoryagent/ (or custom name if specified)
          • __init__.py Python package initialization
          • agent.py Main agent definition with sample tools
          • main.py AG-UI server entry point using ag-ui-strands
          • Dockerfile Entry point for hosting your agent (excluded when computeType is set to None)
      • pyproject.toml Updated with Strands and AG-UI dependencies
      • project.json Updated with agent serve targets

    Since this generator vends infrastructure as code based on your chosen iacProvider, it will create a project in packages/common which includes the relevant CDK constructs or Terraform modules.

    The common infrastructure as code project is structured as follows:

    • Directorypackages/common/constructs
      • Directorysrc
        • Directoryapp/ Constructs for infrastructure specific to a project/generator
        • Directorycore/ Generic constructs which are reused by constructs in app
        • index.ts Entry point exporting constructs from app
      • project.json Project build targets and configuration

    For deploying your Strands Agent, the following files are generated:

    • Directorypackages/common/constructs/src
      • Directoryapp
        • Directoryagents
          • Directory<project-name>
            • <project-name>.ts CDK construct for deploying your agent

    Tools are functions that the AI agent can call to perform actions. The Strands framework uses a simple decorator-based approach for defining tools.

    You can add new tools in the agent.py file:

    from strands import Agent, tool
    @tool
    def calculate_sum(numbers: list[int]) -> int:
    """Calculate the sum of a list of numbers"""
    return sum(numbers)
    @tool
    def get_weather(city: str) -> str:
    """Get weather information for a city"""
    # Your weather API integration here
    return f"Weather in {city}: Sunny, 25°C"
    # Add tools to your agent
    agent = Agent(
    system_prompt="You are a helpful assistant with access to various tools.",
    tools=[calculate_sum, get_weather],
    )

    The Strands framework automatically handles:

    • Type validation based on your function’s type hints
    • JSON schema generation for tool calling
    • Error handling and response formatting

    Strands provides a collection of pre-built tools through the strands-tools package:

    from strands_tools import current_time, http_request, file_read
    agent = Agent(
    system_prompt="You are a helpful assistant.",
    tools=[current_time, http_request, file_read],
    )

    By default, Strands agents use Claude 4 Sonnet, but you can customize the model provider. See the Strands documentation on model providers for configuration options:

    from strands import Agent
    from strands.models import BedrockModel
    # Create a 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)

    You can add tools from MCP servers to your Strands agent.

    For consuming MCP Servers which you have created using the py#mcp-server or ts#mcp-server generators you can make use of the connection generator.

    1. Install the Nx Console VSCode Plugin if you haven't already
    2. Open the Nx Console in VSCode
    3. Click Generate (UI) in the "Common Nx Commands" section
    4. Search for @aws/nx-plugin - connection
    5. Fill in the required parameters
      • Click Generate

      Refer to the connection generator guide for details about how the connection is set up.

      For other MCP servers, please refer to the Strands Documentation.

      For a more in-depth guide to writing Strands agents, refer to the Strands documentation.

      Your agent’s server protocol determines how it communicates. All options are served by FastAPI — the entry point differs:

      • HTTP (default): A standard FastAPI server with a custom /invocations endpoint, CORS, and streaming. Best for custom client integrations.
      • A2A: The Strands A2A Server mounted onto a FastAPI app. Best when your agent needs to be discoverable and invokable by other A2A-compatible agents.
      • AG-UI: The ag-ui-strands integration, which exposes the AG-UI protocol over SSE. Best for direct frontend integration with CopilotKit in a React website.

      All protocols expose /ping for the AgentCore runtime health check contract. A2A agents listen on port 9000; HTTP and AG-UI agents listen on port 8080. The generated Dockerfile and infrastructure are configured for you.

      The generated HTTP server includes:

      • FastAPI application setup with CORS middleware
      • Error handling middleware
      • OpenAPI schema generation
      • Health check endpoint (/ping)
      • Agent invocation endpoint (/invocations)

      Customizing Invoke Inputs and Outputs with Pydantic

      Section titled “Customizing Invoke Inputs and Outputs with Pydantic”

      The agent’s invocation endpoint uses Pydantic models to define and validate the request and response schemas. You can customize these models in main.py to match your agent’s requirements.

      The default InvokeInput model accepts a message.

      from pydantic import BaseModel
      class InvokeInput(BaseModel):
      message: str

      You can extend this model to include any additional fields your agent needs.

      The session ID is extracted from the x-amzn-bedrock-agentcore-runtime-session-id HTTP header, consistent with the Bedrock AgentCore Runtime session contract. If the header is not provided, a random UUID is generated as a fallback.

      For streaming responses, the generator provides JsonStreamingResponse which automatically serializes Pydantic models to JSON Lines format (application/jsonl). This format is compatible with OpenAPI 3.2’s streaming specification and works seamlessly with the generated TypeScript client.

      By default, the agent yields StreamChunk objects containing the agent’s response text:

      class StreamChunk(BaseModel):
      content: str

      You can customise the StreamChunk model to suit your needs:

      from pydantic import BaseModel
      class StreamChunk(BaseModel):
      content: str
      timestamp: str
      token_count: int

      There is an open feature request for native support in FastAPI.

      The generator includes a dependency on the Bedrock AgentCore Python SDK for the PingStatus constants. If desired, it is straightforward to use BedrockAgentCoreApp instead of FastAPI, however note that type-safety is lost.

      You can find more details about the SDK’s capabilities in the documentation here.

      When protocol=A2A, the generated main.py mounts A2AServer.to_fastapi_app() onto a parent FastAPI app that also exposes /ping. When deployed to AgentCore, the entry point resolves the runtime’s public ARN from AppConfig and advertises it in the agent card.

      Most users will not need to modify this file — edit agent.py to change tools or the system prompt. The A2A server populates the agent card (/.well-known/agent-card.json) from the Agent constructor’s name and description.

      When protocol=AG-UI, the generated main.py wraps your Strands Agent in an ag_ui_strands.StrandsAgent and creates a FastAPI app via create_strands_app(). The resulting app exposes a single POST endpoint that streams AG-UI events over Server-Sent Events (SSE), as well as /ping for the AgentCore runtime health check.

      Most users will not need to modify this file — edit agent.py to change tools or the system prompt.

      The generator configures a target named <your-agent-name>-serve, which starts your Strands Agent locally for development and testing.

      Terminal window
      pnpm nx agent-serve your-project

      This command uses uv run to execute your Strands Agent using the Bedrock AgentCore Python SDK.

      Deploying Your Strands Agent to Bedrock AgentCore Runtime

      Section titled “Deploying Your Strands Agent to Bedrock AgentCore Runtime”

      If you selected BedrockAgentCoreRuntime for computeType, the relevant CDK or Terraform infrastructure is generated which you can use to deploy your Strands Agent to Amazon Bedrock AgentCore Runtime.

      A CDK construct is generated for your agent, named based on the name you chose when running the generator, or <ProjectName>Agent by default.

      You can use this CDK construct in a CDK application:

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

      The generator provides an auth option to configure authentication for your Strands Agent. You can choose between IAM (default) or Cognito authentication when generating your agent.

      By default, your Strands Agent will be secured using IAM authentication, simply deploy it without any arguments:

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

      You can grant access to invoke your agent on Bedrock AgentCore Runtime using the grantInvokeAccess method, for example:

      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.grantInvokeAccess(lambdaFunction);
      }
      }

      When you select Cognito authentication, the generator configures the agent to use Cognito for authentication.

      The generated construct accepts an identity prop which configures Cognito authentication:

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

      The UserIdentity construct can be generated using the ts#react-website#auth generator, or you can create your own CDK UserPool and UserPoolClient.

      In order to build your Strands Agent for Bedrock AgentCore Runtime, a bundle target is added to your project, which:

      • Exports your Python dependencies to a requirements.txt file using uv export
      • Installs dependencies for the target platform (aarch64-manylinux_2_28) using uv pip install

      A docker target specific to your Strands Agent is also added, which copies the Dockerfile and bundled artifacts into a docker context directory. This co-locates the Dockerfile with the built output, allowing CDK to build the Docker image directly using AgentRuntimeArtifact.fromAsset.

      Your agent is automatically configured with observability using the AWS Distro for Open Telemetry (ADOT), by configuring auto-instrumentation in your Dockerfile.

      You can find traces in the CloudWatch AWS Console, by selecting “GenAI Observability” in the menu. Note that for traces to be populated you will need to enable Transaction Search.

      For more details, refer to the AgentCore documentation on observability.

      To invoke an Agent running locally via the <your-agent-name>-serve target, you can send a simple POST request to /invocations on the port your local agent is running on. For example, with curl:

      Terminal window
      curl -N -X POST http://localhost:8081/invocations \
      -d '{"message": "what is 3 + 5?"}' \
      -H "Content-Type: application/json"

      To invoke your Agent deployed to Bedrock AgentCore Runtime, you can send a POST request to the Bedrock AgentCore Runtime dataplane endpoint with your URL-encoded runtime ARN.

      You can obtain the runtime ARN from your infrastructure as follows:

      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,
      });
      }
      }

      The ARN will have the following format: arn:aws:bedrock-agentcore:<region>:<account>:runtime/<agent-runtime-id>.

      You can then URL-encode the ARN by replacing : with %3A and / with %2F.

      The Bedrock AgentCore Runtime dataplane URL for invoking the agent is as follows:

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

      The exact way to invoke this URL depends upon the authentication method used.

      For IAM Authentication, the request must be signed using AWS Signature Version 4 (SigV4).

      Terminal window
      acurl <region> bedrock-agentcore -N -X POST \
      'https://bedrock-agentcore.<region>.amazonaws.com/runtimes/<url-encoded-arn>/invocations' \
      -d '{"message": "what is 3 + 5?"}' \
      -H 'Content-Type: application/json'
      Click here for more details on configuring the above acurl command

      For Cognito Authentication, pass the Cognito Access Token in the Authorization header:

      Terminal window
      curl -N -X POST 'https://bedrock-agentcore.<region>.amazonaws.com/runtimes/<url-encoded-arn>/invocations' \
      -d '{"message": "what is 3 + 5?"}' \
      -H "Content-Type: application/json" \
      -H "Authorization: Bearer <access-token>"

      You can obtain the access token using the AWS CLI’s cognito-idp admin-initiate-auth command, for example:

      Terminal window
      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

      For invoking your Strands Agent from a React website, you can make use of the connection generator, which automatically sets up a client with the correct authentication (IAM or Cognito).

      1. Install the Nx Console VSCode Plugin if you haven't already
      2. Open the Nx Console in VSCode
      3. Click Generate (UI) in the "Common Nx Commands" section
      4. Search for @aws/nx-plugin - connection
      5. Fill in the required parameters
        • Click Generate

        Refer to the connection generator guide for details about how the connection is set up.

        To delegate work from this agent to a remote A2A agent (either TypeScript or Python), use the connection generator. It vends a SigV4-authenticated client for the target agent and AST-transforms this agent’s agent.py to register the remote A2A agent as a @tool-decorated delegate.

        1. Install the Nx Console VSCode Plugin if you haven't already
        2. Open the Nx Console in VSCode
        3. Click Generate (UI) in the "Common Nx Commands" section
        4. Search for @aws/nx-plugin - connection
        5. Fill in the required parameters
          • Click Generate

          Refer to the connection generator guide for details about how the connection is set up.