> ## Documentation Index
> Fetch the complete documentation index at: https://docs.braintrust.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Loop runtime

> Run Loop threads inside a self-hosted AWS data plane with an opt-in ECS service that executes each thread in an isolated MicroVM sandbox.

The Loop runtime is an opt-in ECS Fargate service that runs [** Loop**](https://docs.braintrust.dev/loop.md) threads in your own data plane, using isolated AWS Lambda MicroVM sandboxes for command execution and investigation tasks. It is disabled by default, so Loop and Patterns are unavailable until you enable it.

> [!NOTE]
>
> The Loop runtime requires AWS Terraform module v6.5.2 or later, a [supported AWS region](#supported-aws-regions), and a [Braintrust Gateway](https://docs.braintrust.dev/admin/self-hosting/configure/gateway.md) for model requests. It is not available on GCP or Azure.

## What the runtime provides

Loop does its investigation work in a sandbox, an isolated environment where it reads, searches, and lists trace files directly and runs commands against your data. That is what lets it work through a trace too large to read in one pass, and keep going on a long investigation instead of being bound to a browser session. Threads persist, so users can leave and resume them.

The Loop runtime and its isolated sandboxes also support [Loop automations](https://docs.braintrust.dev/loop/automations.md), which perform recurring work on a schedule. [** Patterns**](https://docs.braintrust.dev/observe/patterns.md) runs as a scheduled Loop automation, so it requires the runtime too.

On Braintrust-hosted deployments, Braintrust provides the sandbox. Self-hosted deployments provide it themselves by enabling this service.

## Supported AWS regions

The Loop runtime is not available in every [region supported by the Braintrust data plane](https://docs.braintrust.dev/admin/self-hosting/deploy.md#1-configure-the-terraform-module). For both self-hosted and [BYOC](https://docs.braintrust.dev/admin/deployment/byoc.md) deployments on AWS, it requires regional support for the `AWS::Lambda::MicrovmImage` CloudFormation resource. The data plane regions that lack this support are `ca-central-1`, `eu-west-2`, `eu-west-3`, and `sa-east-1`.

Enabling the runtime in one of these regions can fail with `Template format error: Unrecognized resource types: [AWS::Lambda::MicrovmImage]`. Leave `enable_loop_runtime` set to `false` there and [contact Braintrust](mailto:support@braintrust.dev) for deployment guidance. AWS [continues to add MicroVM regions](https://aws.amazon.com/about-aws/whats-new/2026/08/lambda-microvms-5-additional-regions/), so confirm coverage for your region with Braintrust.

## Enable the runtime

Set `enable_loop_runtime` in your data plane module, then run `terraform apply`:

```hcl theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
module "braintrust-data-plane" {
  source = "github.com/braintrustdata/terraform-aws-braintrust-data-plane"

  enable_loop_runtime = true

  # ... other configuration ...
}
```

`enable_loop_runtime` deploys the ECS service and its sandboxes. It is `false` by default. It doesn't require `enable_ecs_api`. The runtime works with either API routing mode.

After the apply completes, Loop is available across your organization.

### Sandbox egress

On module v6.10.0 and later, sandboxes have no direct outbound access. They reach the network only through the Loop runtime's egress gateway, which Loop also uses to clone [connected GitHub repositories](https://docs.braintrust.dev/loop/github.md).

> [!WARNING]
>
> **Breaking change in v6.10.0:** `loop_runtime_sandbox_egress_mode` is deprecated and accepts only `"restricted"`. Internet egress for sandboxes is removed. If your configuration sets `loop_runtime_sandbox_egress_mode = "internet"`, the plan fails. Remove the variable or set it to `"restricted"` before you upgrade.

The module isolates sandboxes with these components:

* **Sandbox VPC**: A dedicated VPC with no outbound route. It uses the `10.255.0.0/16` CIDR block by default, which you can [change](#choose-the-sandbox-vpc-cidr) on module v7.0.0 and later. To use a VPC you manage instead, see [Supply your own sandbox VPC](#supply-your-own-sandbox-vpc).
* **Egress gateway**: A proxy on port 4002 of the runtime tasks that authorizes each request. Sandboxes reach it through a PrivateLink interface endpoint in the sandbox VPC.
* **DNS firewall**: A Route 53 Resolver DNS firewall in the sandbox VPC that allows only the endpoint's hostname and blocks every other name. The module outputs that hostname as `loop_runtime_sandbox_egress_gateway_dns_name`.

The egress gateway requires Loop runtime v2.16.0 or later. The module's default runtime version meets this requirement. If you set `loop_runtime_version_override`, pin it to v2.16.0 or later, such as `"v2.16.0"`.

### Choose the sandbox VPC CIDR

On module v7.0.0 and later, `loop_runtime_sandbox_vpc_cidr` sets the IPv4 CIDR block of the module-created sandbox VPC. It defaults to `"10.255.0.0/16"` and accepts prefix lengths from `/16` through `/21`:

```hcl theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
loop_runtime_sandbox_vpc_cidr = "10.255.0.0/21"
```

The module creates six `/24` subnets at offsets 1 through 6 within that block: three connector subnets followed by three egress gateway endpoint subnets. The default keeps the VPC and subnet CIDRs of earlier module versions. The variable has no effect when you [supply your own sandbox VPC](#supply-your-own-sandbox-vpc).

> [!WARNING]
>
> Changing `loop_runtime_sandbox_vpc_cidr` on an existing deployment replaces the sandbox VPC and its subnets, which interrupts sandbox connectivity until the apply completes.

### Supply your own sandbox VPC

On module v6.9.0 and later, sandboxes can use a VPC you manage instead of the module-created one.

> [!WARNING]
>
> Sandboxes run untrusted code. Braintrust recommends a dedicated, isolated VPC. Avoid shared corporate VPCs with connectivity to internal services or other networks, because code running in a sandbox can use that access.

Set the VPC ID and three distinct private subnet IDs together:

```hcl theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
module "braintrust-data-plane" {
  source = "github.com/braintrustdata/terraform-aws-braintrust-data-plane"

  enable_loop_runtime                                   = true
  loop_runtime_sandbox_existing_vpc_id                  = "vpc-0123456789abcdef0"    # Replace with your sandbox VPC ID
  loop_runtime_sandbox_existing_private_subnet_1_id     = "subnet-0123456789abcdef0" # Replace with your subnet IDs
  loop_runtime_sandbox_existing_private_subnet_2_id     = "subnet-0123456789abcdef1"
  loop_runtime_sandbox_existing_private_subnet_3_id     = "subnet-0123456789abcdef2"
  loop_runtime_sandbox_manage_existing_vpc_dns_firewall = true # v6.10.0+. Omit to manage DNS yourself.

  # ... other configuration ...
}
```

The module checks that each subnet belongs to the supplied VPC. On v6.10.0 and later, it creates the sandbox security group and the egress gateway endpoint in your VPC, and at least one supplied subnet must share an availability zone with one of the main VPC's private subnets, or the apply fails. The module doesn't manage routes in your VPC, so isolating it is your responsibility.

DNS restrictions depend on `loop_runtime_sandbox_manage_existing_vpc_dns_firewall` (v6.10.0+, default `false`):

* **`true`**: The module associates a Route 53 Resolver DNS firewall with your VPC that allows the egress gateway endpoint's hostname and blocks every other name. The firewall applies to the entire VPC, so use a VPC dedicated to sandboxes.
* **`false`**: The module leaves DNS policy to you. Before sandboxes run, restrict DNS in your VPC so that it resolves only the hostname in the `loop_runtime_sandbox_egress_gateway_dns_name` output.

On v6.9.0, the module creates a security group with no outbound rules and doesn't manage DNS. Configure DNS restrictions equivalent to the module-created VPC yourself, such as a DNS firewall that blocks every domain.

### Network traffic

* **Model requests**: The runtime requires a Braintrust Gateway for Loop's LLM calls. On module v6.5.2 to v6.8.x, it sends them to your deployment's AI proxy, so set `enable_ai_gateway = true` to have the proxy forward them to your private Gateway. On v6.9.0 and later, it sends them to your private Gateway load balancer when `enable_ai_gateway = true`, or to the Braintrust-hosted Gateway when `use_global_ai_gateway_origin = true`.
* **Runtime to sandboxes**: On module v6.9.0 and later, the runtime's HTTPS and WebSocket connections to active sandboxes go through a `lambda-microvm` interface VPC endpoint in your main VPC, with private DNS. The endpoint policy allows connections only to sandboxes in your deployment's AWS account. Earlier versions don't create this endpoint. MicroVM management API calls use the standard Lambda service endpoint.
* **Sandboxes to runtime**: On module v6.10.0 and later, sandboxes connect to the runtime's egress gateway on port 4002 through a PrivateLink endpoint service backed by an internal Network Load Balancer in your main VPC. The endpoint service allows only principals in your deployment's AWS account. See [Sandbox egress](#sandbox-egress).

## Scaling

The runtime's ECS service autoscales on target CPU and memory utilization. On module v6.10.0 and later, it also scales on average claimed conversation utilization, with the target percentage set by `loop_runtime_target_conversation_utilization`. On v6.10.0 and later, `loop_runtime_max_capacity` defaults to `50` instead of `4`. If you rely on the earlier ceiling to bound cost, set it explicitly.

When ECS stops a runtime task on v6.10.0 and later, for example, during scale-in or a deployment, the runtime drains in-progress turns for up to 90 seconds before it shuts down.

## Enable Patterns

The runtime doesn't start Patterns. Each project turns Patterns on separately, and the person who does it needs permission to create project automations. See [Enable Patterns](https://docs.braintrust.dev/observe/patterns/enable.md).

## Telemetry

On module v6.7.0 and later, the Loop runtime sends `metrics` and `traces` for its own service to Braintrust's control plane, in addition to whatever [telemetry](https://docs.braintrust.dev/admin/self-hosting/configure/telemetry.md) types your deployment configures. Braintrust uses them to diagnose runtime problems while the service stabilizes, and you can't turn them off while the runtime is enabled.

These traces describe the runtime's operation and can include model and tool identifiers, timing information, and errors. If your deployment can't send this telemetry, leave the Loop runtime disabled and [contact Braintrust](mailto:support@braintrust.dev).

## Configuration reference

| Variable | Default | Description |
| - | - | - |
| `enable_loop_runtime` | `false` | Deploy the Loop runtime ECS service and its sandboxes. |
| `loop_runtime_version_override` | `null` | Pin the Loop runtime image and MicroVM guest artifact to a specific version tag. When unset, v6.9.0 and later use the module release's version. Earlier versions track the latest 2.x release. On v6.10.0 and later, the pinned version must be v2.16.0 or later. |
| `loop_runtime_task_cpu` | `2048` | CPU units for each Loop runtime task. 1024 CPU units equal 1 vCPU. |
| `loop_runtime_task_memory` | `8192` | Memory (MiB) for each Loop runtime task. |
| `loop_runtime_ephemeral_storage_gib` | `null` | Task ephemeral storage in GiB (21 to 200). `null` uses the Fargate default of 20. |
| `loop_runtime_min_capacity` | `1` | Minimum number of running Loop runtime tasks. |
| `loop_runtime_max_capacity` | `50` | Maximum number of running Loop runtime tasks. The default is `4` on v6.9.0 and earlier. |
| `loop_runtime_target_cpu_utilization` | `40` | Target average CPU utilization percentage for autoscaling. |
| `loop_runtime_target_memory_utilization` | `50` | Target average memory utilization percentage for autoscaling. |
| `loop_runtime_target_conversation_utilization` | `50` | Target average claimed conversation utilization percentage for autoscaling (v6.10.0+). Must be between 1 and 100. |
| `loop_runtime_log_retention_days` | `14` | CloudWatch log retention in days. Must be a valid CloudWatch Logs retention value. |
| `loop_runtime_enable_execute_command` | `false` | Enable ECS Exec on the Loop runtime service. |
| `loop_runtime_alb_deregistration_delay` | `900` | Deregistration delay in seconds for the Loop runtime ALB target group. |
| `loop_runtime_extra_env_vars` | `{}` | Extra environment variables merged into the Loop runtime container. |
| `loop_runtime_sandbox_egress_mode` | `"restricted"` | Deprecated on v6.10.0 and later, where it accepts only `"restricted"`. On v6.9.0 and earlier, exactly `"internet"` uses AWS-managed internet egress, and any other value is treated as restricted, which blocks all outbound network access and name resolution from sandboxes. The default is `"internet"` on v6.6.0 and earlier. |
| `loop_runtime_sandbox_vpc_cidr` | `"10.255.0.0/16"` | IPv4 CIDR block for the module-created sandbox VPC (v7.0.0+), from `/16` through `/21`. Ignored when `loop_runtime_sandbox_existing_vpc_id` is set. Changing it replaces the sandbox VPC and subnets. |
| `loop_runtime_sandbox_existing_vpc_id` | `null` | Existing VPC for restricted sandbox egress (v6.9.0+). Requires the three subnet variables. |
| `loop_runtime_sandbox_existing_private_subnet_1_id`, `_2_id`, `_3_id` | `null` | Private subnets in the supplied sandbox VPC (v6.9.0+). Required with `loop_runtime_sandbox_existing_vpc_id`. |
| `loop_runtime_sandbox_manage_existing_vpc_dns_firewall` | `false` | Manage a DNS firewall in the supplied sandbox VPC that allows only the egress gateway endpoint's hostname (v6.10.0+). The module always manages the DNS firewall in its own sandbox VPC. |
| `loop_runtime_microvm_minimum_memory_mib` | `2048` | Minimum memory (MiB) provisioned for each sandbox. |
| `loop_runtime_microvm_max_idle_duration_seconds` | `900` | Seconds without traffic before a sandbox auto-suspends. |
| `loop_runtime_microvm_suspended_duration_seconds` | `28800` | Seconds a suspended sandbox remains resumable before termination. |
| `loop_runtime_microvm_maximum_duration_seconds` | `28800` | Maximum sandbox lifetime across running and suspended states. |
| `loop_runtime_microvm_auth_token_expiration_minutes` | `30` | Endpoint auth token lifetime in minutes for sandbox invocations. |
| `enable_loop_runtime_microvm_runtime_logs` | `false` | Export sandbox stdout and stderr to CloudWatch. Output can include sandbox contents. |

On module v6.8.1 and later, the runtime serves the organization named by `braintrust_org_name`. Earlier versions used a separate `loop_runtime_org_name` variable. Remove it from your configuration before you upgrade, or the plan fails with `An argument named "loop_runtime_org_name" is not expected here`.

## Next steps

* Learn [what Loop can do](https://docs.braintrust.dev/loop/capabilities.md) once the runtime is running.
* Review [thread and sandbox limits](https://docs.braintrust.dev/loop/manage.md#sandboxes) that apply to your users.
* Configure [networking and connectivity](https://docs.braintrust.dev/admin/self-hosting/configure/networking.md) for the rest of your deployment.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.