Skip to content

Optional features and their cost

Rayito never charges by surprise. With no options, a sandbox costs only the MicroVM itself: the SDK creates no other AWS resource and makes no paid calls. Each feature on this page is off by default and is turned on with an explicit SDK option, never with an environment variable or a configuration file. What they need (a table, some IAM policies) you deploy yourself in your account with a CloudFormation template; Rayito hosts no server. The only exception is the fleet recipe (since 0.17.0, ADR-034): deploy_agent() saves it by default because a standard Parameter Store parameter is free and its KMS request falls in the free tier; --no-save-recipe turns it off.

At a glance

Feature Default What it turns on Cost IAM How to turn it off
Secret injection off secrets= / secrets: the value of a Secrets Manager secret reaches a command, terminal or cell as an environment variable $0.40 per secret per month + $0.05 per 10,000 reads (one per secret every 5 min with the default cache) read the rayito/* secrets (RayitoSecretsReader, secrets-access stack) do not pass secrets=
Secret management (CRUD) off SecretStore(...): create, list, update and delete secrets (also the E2B shim's Secret) $0.40 per secret per month until you delete it + $0.05 per 10,000 calls administer the rayito/* secrets (RayitoSecretsAdmin, secrets-access stack) do not instantiate SecretStore and destroy() the secrets created
Metadata index off index=DynamoDbIndex(...): filter list() by metadata also over paused sandboxes ≈ $0.03/month for 10,000 sandboxes; empty table, $0 write and read on your table (RayitoIndexWriter, RayitoIndexReader, metadata-index stack) do not pass index=; rayito stack destroy metadata-index
OpenTelemetry traces off tracer_provider= / tracerProvider: rayito.* spans of your calls $0 from Rayito; whatever your exporter costs none of its own do not pass tracer_provider=
S3 mounts off mounts= / mounts: an S3 bucket as a sandbox folder (rayito-base-caps) $0 of its own; the bucket's S3 requests RayitoS3MountAccess on the execution role (s3-mounts stack) do not pass mounts=
Sizes off size= / size: launch the image of another size (512mb to 8gb) more $/h the bigger the size; snapshot per published image none additional (the optional sizes-guard stack restricts which sizes are launched) do not pass size=
Events and webhooks off events= / events: lifecycle events stored and delivered to your webhooks ≈ $0.40/month for the stack at rest; the rest by use EventsLauncherPolicy, EventsReaderPolicy or EventsWebhookAdminPolicy depending on the task (events-webhooks stack) do not pass events=; rayito events destroy
OTLP export off telemetry= / telemetry: sandbox metrics over OTLP to CloudWatch ≈ $0.00002 per sandbox-hour RayitoOtlpExport on the execution role (otlp-export stack) do not pass telemetry=
Secret gateway off gateways= / gateways: use a secret from the sandbox without being able to read it (with presets for an agent's model: bedrock_gateway, anthropic_gateway, openai_compatible_gateway and those in Agent providers) $0.05 per 10,000 reads + the secret read the secrets (RayitoSecretsReader) do not pass gateways=
Templates off Template.build(): build an image from the DSL ≈ $0.04/week per image version RayitoTemplateBuilder (templates stack) do not call Template.build()
Agent templates (since 0.8.0) off AgentTemplate(...).build(): image with OpenCode/deepagents and their pins ≈ $0.057/week per image version (≈ 3.1 GB; see Pricing) RayitoTemplateBuilder (templates stack) do not build the template
Agent in the sandbox (since 0.8.0) off sbx.agent.run()/.stream()/.prepare(): a code agent running inside the sandbox, with its model through the gateway $0 of the SDK's own; the model by tokens (see cost of an agent) and what the gateway already costs that of the chosen secret gateway do not call sbx.agent
Deploy your agent (since 0.14.0) off; published in 0.14.0, accepted on real AWS on 2026-10-17 AgentProject.build()/.run()/.deploy() and rayito agent build, run and deploy: a Strands, Hermes, LangGraph, deepagents, OpenCode or custom agent as an image, a one-off run or an HTTP service (export() makes no AWS call) an image version (≈ $0.056/week with rayito-agent) and, if you deploy it, the VM while it lives (≈ $0.126/h; see Pricing) + the model per token RayitoTemplateBuilder (the templates stack) and that of the chosen secret gateway do not call build()/run()/deploy(); rayito agent stop
Several sessions and several VMs (since 0.14.0) off; published in 0.14.0, accepted on real AWS on 2026-10-17 deploy_agent()/deployAgent() and rayito agent deploy: an agent you already have, detected without touching its code, as a fleet (ScalingOptions: min_vms, max_vms, warm_vms, shared or dedicated sessions) with a queue; --dry-run and detect make no AWS call per running VM ≈ $0.126/h with 2 GB, an image version ≈ $0.056/week and parked slots only the snapshot (see Pricing) + the model per token those of Sandbox.create()/list()/kill() and AgentTemplate.build() (RayitoSandboxRunner, RayitoTemplateBuilder) do not call deploy_agent(); fleet.stop() or rayito agent stop <name>
Fleet recipe (since 0.17.0) on (the only exception, ADR-034: free on the standard tier) deploy_agent()/deployAgent() and rayito agent deploy save the fleet recipe (secret names, never values) in Parameter Store; AgentFleet.connect(name) reads it and creates matching VMs; stop() deletes it $0 for the standard parameter; one KMS request per write and per read (20,000 free per month, then $0.03 per 10,000) ssm:PutParameter, ssm:GetParameter and ssm:DeleteParameter on parameter/rayito/agents/* (AgentRecipe statement); no KMS save_recipe=False / saveRecipe: false / --no-save-recipe
Renewing the Bedrock key (since 0.17.0) off renew_gateway_keys=True / renewGatewayKeys: true / --renew-gateway-keys: signs a short-term key locally and writes it to the bedrock gateway's secret before creating each VM $0.05 per 10,000 Secrets Manager calls (DescribeSecret; PutSecretValue at most once every 900 s per gateway) secretsmanager:DescribeSecret, secretsmanager:PutSecretValue and bedrock:CallWithBearerToken do not pass the option
Deploy to AgentCore (since 0.15.0) off; published in 0.15.0, accepted on real AWS on 2026-10-19 rayito agent deploy --target agentcore, deploy_agent(target="agentcore") and deployAgent(path, { target: "agentcore" }): the agent you already have on Amazon Bedrock AgentCore Runtime, with no local Docker (CodeBuild build, image in ECR, runtime with a least-privilege role); --dry-run and plan_deploy() make no AWS call one stack per agent (ECR repository, CodeBuild project, two roles), one build per new content (≈ $0.0034 per minute) and a runtime that charges only with sessions ($0.0895 per vCPU-hour and $0.00945 per GB-hour); image in ECR at $0.10 per GB-month (see Pricing) + the model per token CloudFormation, ECR, CodeBuild, IAM (PassRole), S3 on rayito/images/agentcore/* and bedrock-agentcore:* (list); it uses no MicroVMs or secrets gateway do not pass --target agentcore; rayito agent delete <name> --target agentcore
Agent on AgentCore with CDK (since 0.15.0) off; published in 0.15.0, accepted on real AWS on 2026-10-20 RayitoAgent from rayito.cdk (extra cdk) / rayito/cdk (peers aws-cdk-lib and constructs) in your CDK app, and cdk deploy: the same agent as --target agentcore, with the same resources and IAM, as part of your stack; cdk synth makes no AWS call the same as Deploy to AgentCore (build ≈ $0.0034 per minute only with codeBuild(), runtime only with sessions, image in ECR at $0.10 per GB-month) + cents of Lambda and Step Functions per deployment + the assets in the CDK bootstrap bucket until cdk gc the CDK bootstrap execution role (by default nothing else; with a restricted one, the list) do not instantiate the construct; cdk destroy
MicroVMs image with CDK (since 0.15.0) off; published in 0.15.0, accepted on real AWS on 2026-10-20 RayitoMicrovmImage (and MicrovmImageArtifact) in your CDK app, and cdk deploy: an image with rayd, plus one per size, with its build role and log groups; sandboxes are still created with the SDK ≈ $0.04/week per image version and per size (one week minimum); logs at $0.50 per GB; the zip in the bootstrap bucket until cdk gc the CDK bootstrap execution role (with a restricted one, lambda:*MicrovmImage*, lambda:PassNetworkConnector and iam:PassRole; list) do not instantiate the construct; cdk destroy; rayito image prune for old versions
Secrets as environment variables off [secret_env], [[secret_env_from]], --secret-env and --secret-env-from: Secrets Manager values in the deployed agent's environment, read at startup (with the runtime role on AgentCore, with your credentials on MicroVMs); --create-secrets-from creates the secret from a .env $0.05 per 10,000 reads (one per secret and session or VM); the --create-secrets-from secret, $0.40 per month until you delete it on AgentCore, Rayito gives the role GetSecretValue on those secrets only; on MicroVMs, RayitoSecretsReader; for --create-secrets-from, CreateSecret, DescribeSecret and PutSecretValue drop the tables or the flags; delete the created secret
Create the model secret (since 0.14.0) off --create-secret / create_secret_from_env=True: stores the key from the provider's standard variable in Secrets Manager when deploying $0.40 per secret per month until you delete it secretsmanager:CreateSecret do not pass the option; SecretStore.destroy()
Publish the base image when deploying (since 0.14.0) off --base-artifact ZIP --yes / base_publisher=: publishes rayito-base-caps if it is missing ≈ $0.056/week per image version those of rayito image publish do not pass the option; rayito image prune
rayito setup publishes rayito-base-caps (since 0.17.0) off (ADR-034 D9) rayito setup --caps-image / caps_image=True / capsImage: true: publishes the image that rayito agent deploy uses on MicroVM from the same rayito-image.zip; the plan and --dry-run show the step and its cost ≈ $0.04/week per image version (snapshot storage) those of rayito setup do not pass --caps-image; rayito image prune
Pool: warm-up (warmup) (since 0.8.0) off PoolConfig(warmup=agent_pool_warmup(...)): pre-warm the agent runtime before parking each slot ≈ $0.64/slot/month with warmup (versus $0.60 for a base slot; see Pricing) that of the image/pool you already use do not pass warmup=
EFS volumes (experimental) off volumes= / volumes: an EFS file system shared live between sandboxes (rayito-base-caps-efs image); VolumeStore/EfsVolumes for the volumes and the stack $0 empty; $0.30/GB-month and $0.03/$0.06 per GB read/written (Elastic); the image takes ≈ 198 MB more CallerPolicyArn of the efs-volumes stack on the execution role; DescribeMountTargets and the access point CRUD on the caller do not pass volumes=; EfsVolumes.destroy(delete_file_system=True)
Custom domain (experimental) off CustomDomain(...): an HTTPS URL under your domain for a sandbox port, without proxy headers (CloudFront distribution in your account, custom-domain stack); not yet verified end to end on real AWS $0 at rest; ~$0.085/GB + $0.0075/10,000 HTTPS requests, plus the Function and one KeyValueStore read per request CloudFormation and CloudFront for the stack; cloudfront-keyvaluestore:DescribeKeyValueStore/PutKey/DeleteKey for the routes do not instantiate CustomDomain; rayito domain destroy
Management dashboard (SDK and local dashboard) off Quotas, UsageCost, Fleet and rayito dashboard (in both CLIs): quotas and allocated memory, billed and estimated cost, sandboxes, images and bulk actions (read-only unless allow_actions=True / --allow-actions); the local dashboard serves a page on 127.0.0.1 $0 for the reads, estimate() and Quotas.report(); paid: billed() $0.01 per Cost Explorer request (24 h cache per instance, ≈ $0.30/month with a long-lived instance; in the dashboard only with --cost-explorer), events() DynamoDB reads (only with --events-stack); resume bills compute again servicequotas:ListServiceQuotas, Lambda MicroVMs reads, ce:GetCostAndUsage only with billed() / --cost-explorer do not call its methods; close the dashboard with Ctrl+C
Dashboard in your account (dashboard stack) off rayito stack deploy dashboard / OptionalStacks().deploy("dashboard"): the same page and API as the local dashboard, served from a Lambda with Function URL and Cognito, with separate read and actions roles and an append-only audit; own theme through ThemeJson or SSM ≈ $0 at rest (Lambda, on-demand DynamoDB and Cognito only by use; the Function URL is public and unauthenticated traffic bills invocations, bound it with ReservedConcurrency); Cost Explorer $0.01 per query only with EnableCostExplorer=true (worst case ≈ $6/month); an Advanced SSM parameter for theme or logo, $0.05/month plus interactions the stack's permissions (CAPABILITY_IAM); the function only reads MicroVMs and quotas, and acts only with the actions role from AllowActions=true rayito stack destroy dashboard
CloudWatch dashboard off rayito dashboard cloudwatch prints the JSON of a dashboard (Logs Insights over /rayito/*, OTLP metrics and quota usage) without calling AWS; the dashboard-cloudwatch stack deploys it $0 with fewer than 4 dashboards, $3/month per dashboard from the fourth; Logs Insights bills the scanned GB on open or refresh whoever deploys, cloudwatch:PutDashboard; whoever views, logs:StartQuery rayito stack destroy dashboard-cloudwatch
Multiple accounts in the dashboard off rayito dashboard --account NAME=ROLE_ARN: see other accounts, read-only, with a role that is assumed; the dashboard-read-role stack creates that role in each target account $0 (IAM and STS do not bill) sts:AssumeRole on the target roles; each role, five reads do not pass --account; rayito stack destroy dashboard-read-role
Quota alerts off rayito stack deploy quota-alerts: a scheduled Lambda publishes to SNS when allocated memory crosses a quota threshold (one alert per crossing) and publishes usage as a metric ≈ $0.30/month (one custom metric); the rest in free tiers CAPABILITY_IAM; the function reads MicroVMs and quotas and writes to its topic, its row and its metrics namespace rayito stack destroy quota-alerts
Local proxy (rayito sandbox proxy) — (CLI only, in Python and in TypeScript) serves a sandbox port on 127.0.0.1 $0: it uses free Lambda calls what infra/iam.yaml already gives (SandboxLauncherPolicy) Ctrl+C
MCP server (rayito-mcp) off the executable (Python mcp extra or TypeScript optional peers @modelcontextprotocol/server and zod): one sandbox per server process, created on the first tool that needs it and destroyed on shutdown; with --http, loopback only and no authentication a running MicroVM while it is used and one snapshot per suspend cycle; nothing lives beyond RAYITO_MCP_TIMEOUT_SECONDS SandboxLauncherPolicy (infra/iam.yaml) close the server from the MCP host

Each name leads to the feature's full guide; below there is a short example of the most used ones. These are approximate figures for us-east-1: the exact ones, with their lookup date and the link to AWS's pricing page, are in Features with AWS cost and in each feature's guide. The price of MicroVMs, the pool and an agent is in Pricing.

You deploy the infrastructure yourself: rayito stack

The features that need something in your account (a table, some IAM policies, some Lambdas) ship it as a component of rayito stack: rayito stack deploy <component> prints the "Cost and activation" block and asks for confirmation, rayito stack status says what is deployed and rayito stack destroy deletes it. Since 0.6.1, redeploying keeps the parameters you do not repeat. In the SDK, OptionalStacks.

The nine rayito stack components, and which feature from the table above each one uses. None deploys itself:

Component For which feature What it creates Idle cost
secrets-access Secret injection and management, secret gateway 2 IAM policies $0
metadata-index Metadata index on-demand DynamoDB table + 2 IAM policies $0 with the table empty
s3-mounts S3 mounts 1 IAM policy $0
sizes-guard Sizes (optional) 1 IAM policy $0
events-webhooks Events and webhooks (also rayito events deploy) secret, table, 3 Lambdas, queues, scheduler and policies ≈ $0.40/month
otlp-export OTLP export with the execution role 1 IAM policy $0
templates Templates and agent templates 1 IAM policy $0
efs-volumes (experimental) EFS volumes EFS file system, mount targets, security groups, connector, role and policy, in your VPC $0 with the file system empty
custom-domain (experimental) Custom domain (also rayito domain deploy) CloudFront distribution, Function and KeyValueStore $0 with no traffic

Parameters of each: Optional stacks.

Experimental

EFS volumes and custom domain, published in 0.7.0, are experimental: you can use them, but their API may change in a minor, and custom domain has not yet been verified end to end on real AWS (see the warning on its page). domain= in Sandbox.create() still raises UnimplementedError without calling AWS: use CustomDomain. Status: What's new.

The metadata index is not yet accepted on real AWS

Secrets were accepted against real AWS with release 0.5.0, and OpenTelemetry traces do not call AWS, so their tests with an in-memory exporter are the complete proof. The index is tested with a simulated DynamoDB, but its test against real AWS has not yet been run: it is, together with custom domain (experimental), the only feature on this page without that acceptance.

Outside this page: the transfer bucket

Exporting RAYITO_TRANSFER_BUCKET (or passing transfer=) makes files of 8 MiB or more and presigned URLs go through S3, which charges for its requests and temporary storage. It is not an optional feature in this list, but it is the only environment variable with a cost of its own: Files and S3.

Examples

A short example per feature. Each one has its full guide, with the options, the detailed cost and the errors.

Secret injection

Full guide, cache rules and threat model: Secrets.

from rayito import Sandbox, SecretCache

cache = SecretCache(ttl_seconds=300)  # optional; does not call AWS
with Sandbox.create(secrets={"OPENAI_API_KEY": "openai"}, secret_cache=cache) as sbx:
    sbx.commands.run("python agent.py")  # 1 GetSecretValue per TTL, not per command
    sbx.commands.run("env", secrets={"GH_TOKEN": "gh"})
// npm install @aws-sdk/client-secrets-manager   (optional peer)
import { Sandbox, SecretCache } from "rayito";

const secretCache = new SecretCache({ ttlSeconds: 300 });
await using sbx = await Sandbox.create({ secrets: { OPENAI_API_KEY: "openai" }, secretCache });
await sbx.commands.run("python agent.py");
await sbx.commands.run("env", { secrets: { GH_TOKEN: "gh" } });

The sandbox code can read an injected secret: with untrusted code, use short-lived, least-privilege credentials.

Secret management (CRUD)

Each secret is billed until you delete it: turning the feature off means no longer instantiating SecretStore and destroy()ing the secrets created.

import os

from rayito import SecretStore

store = SecretStore(region="us-east-1")  # does not call AWS until the first method
store.create("openai", os.environ["OPENAI_API_KEY"], metadata={"team": "ml"})
print([info.name for info in store.list(limit=20).items])
store.destroy("openai")  # stops billing
import { SecretStore } from "rayito";

const store = new SecretStore({ region: "us-east-1" });
await store.create("openai", process.env.OPENAI_API_KEY ?? "", { metadata: { team: "ml" } });
console.log((await store.list({ limit: 20 })).items.map((info) => info.name));
await store.destroy("openai");

The E2B shim (from rayito.e2b import Secret) uses the same SecretStore; differences in E2B compatibility.

Metadata index (DynamoDB)

Deploy the table first (once, $0 at rest) with infra/metadata-index.yaml. Full guide: Metadata index.

from rayito import DynamoDbIndex, Sandbox

idx = DynamoDbIndex("rayito-sandboxes")  # does not call AWS yet
with Sandbox.create(metadata={"user": "42"}, index=idx) as sbx:  # 1 PutItem
    sbx.pause()
    for item in Sandbox.list(metadata={"user": "42"}, states=["SUSPENDED"], index=idx):
        print(item.sandbox_id, item.state)  # 1 BatchGetItem per page
import { DynamoDbIndex, Sandbox } from "rayito";

const index = new DynamoDbIndex({ tableName: "rayito-sandboxes" });
await using sbx = await Sandbox.create({ metadata: { user: "42" }, index });
await sbx.pause();
for await (const item of Sandbox.list({ metadata: { user: "42" }, states: ["SUSPENDED"], index })) {
  console.log(item.sandboxId, item.state);
}
rayito sandbox list --metadata user=42 --state suspended --index-table rayito-sandboxes

SDK OpenTelemetry traces

Full guide, span names, attributes and what is never recorded: OpenTelemetry.

from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import SimpleSpanProcessor
from opentelemetry.sdk.trace.export.in_memory_span_exporter import InMemorySpanExporter

from rayito import Sandbox

exporter = InMemorySpanExporter()
provider = TracerProvider()
provider.add_span_processor(SimpleSpanProcessor(exporter))

with Sandbox.create(tracer_provider=provider) as sbx:  # span "rayito.sandbox.create"
    sbx.commands.run("echo hello")  # span "rayito.commands.run"
print([span.name for span in exporter.get_finished_spans()])
import { BasicTracerProvider, InMemorySpanExporter, SimpleSpanProcessor } from "@opentelemetry/sdk-trace-base";
import { Sandbox } from "rayito";

const exporter = new InMemorySpanExporter();
const provider = new BasicTracerProvider({ spanProcessors: [new SimpleSpanProcessor(exporter)] });

{
  await using sbx = await Sandbox.create({ tracerProvider: provider }); // span "rayito.sandbox.create"
  await sbx.commands.run("echo hello"); // span "rayito.commands.run"
}
console.log(exporter.getFinishedSpans().map((span) => span.name));

Without tracer_provider=/tracerProvider (the default): no span and no opentelemetry/@opentelemetry/api import at run time.

rayito sandbox proxy

rayito sandbox proxy microvm-<id> --port 8000
# serves http://127.0.0.1:8000 -> guest port 8000,
# renewing the JWE before it expires; Ctrl+C to stop.

It listens only on loopback (127.0.0.1) unless you pass --bind <ip> together with --allow-remote: whoever reaches that port uses the sandbox with your access. No SDK option is needed: it is CLI-only, with no AWS cost of its own. Guide: Local proxy.

Features with AWS cost

The full sheet for each feature, with the exact AWS API calls and the SDK file where it is documented.

Feature Status Python option TypeScript option Default What it turns on AWS resources / calls Approximate cost IAM needed How to turn it off Where
Secret injection available (0.5.0) secrets= secrets None / undefined Delivers the value of one or more secrets as an environment variable of a command, PTY, Python cell, code context or slot taken from the pool (the sandbox code can read it); the cache is set with secret_cache=SecretCache(...) / secretCache secretsmanager:GetSecretValue once per secret and SecretCache TTL (300 s by default; a hit makes 0 calls), never once per call; no new resources SM: $0.05/10,000 calls (≈ $0.04/month per secret and process with the default TTL) + the secret itself, $0.40/secret-month (Secrets Manager pricing, checked 2026-09-30, us-east-1) secretsmanager:GetSecretValue (and DescribeSecret) on …:secret:rayito/* on the caller's credentials (RayitoSecretsReader policy from infra/secrets-access.yaml); kms:Decrypt only with a customer-managed KMS key Do not pass secrets= / secrets or secret_cache= / secretCache (or pass None/undefined) clients/python/src/rayito/_secrets.py / clients/typescript/src/secrets/inject.ts
Secret management (CRUD) available (0.5.0) SecretStore(...) new SecretStore({...}) not instantiated = no boto3/SDK client Create, update, list and delete Rayito-native secrets under a prefix (and the E2B shim's Secret/AsyncSecret) One Secrets Manager secret per create; secretsmanager:CreateSecret/PutSecretValue/UpdateSecret/DescribeSecret/ListSecrets/DeleteSecret (AWS_API_NOTES.md §19) SM: $0.40/secret-month until destroy + $0.05/10,000 calls (Secrets Manager pricing, checked 2026-09-30, us-east-1) Secrets Manager CRUD under the configured prefix (rayito/ by default; destroy needs DescribeSecret in addition to DeleteSecret) and ListSecrets on * (RayitoSecretsAdmin policy from infra/secrets-access.yaml, which already includes both); adds kms:GenerateDataKey/kms:Decrypt on the key if kms_key_id=/kmsKeyId is passed (customer-managed key); without that parameter, the AWS-managed key charges nothing and requires no separate KMS permission Do not instantiate SecretStore / new SecretStore(...) (explicit calls only) and destroy() the secrets created clients/python/src/rayito/_secrets.py / clients/typescript/src/secrets/store.ts
Metadata index (DynamoDB) implemented in 0.5.0, pending acceptance on real AWS index=DynamoDbIndex(...) index: new DynamoDbIndex({...}) None / undefined Writes an immutable row per sandbox (metadata, image, startedAt, TTL) to your DynamoDB table on creation (create(), PoolConfig) and joins it with list-microvms to filter list()/paginate() by metadata also over SUSPENDED, without probing Health or waking anything; also in the shim (Sandbox.list(..., index=), E2B(index=)) and the CLI (--index-table) dynamodb:PutItem once per created sandbox (conditional) and dynamodb:BatchGetItem once per list-microvms page when listing with metadata + index; you deploy the table (infra/metadata-index.yaml, on-demand, TTL on expires_at); never DeleteItem DynamoDB on-demand (DynamoDB on-demand pricing, checked 2026-09-30, us-east-1): $0.625 per million WRUs (~1 per create ≈ $0.000000625) + $0.125 per million RRUs (BatchGetItem is billed per item read: 0.5 RRU per candidate sandbox, eventually consistent read of ≤ 4 KB) + $0.25/GB-month after 25 GB free; TTL deletion free. Example: 10,000 sandboxes/month ≈ 10,000 WRUs ($0.006) and a daily list() over them ≈ 300,000 items × 0.5 = 150,000 RRUs ($0.019): ≈ $0.03/month; empty table $0 dynamodb:PutItem (writer, RayitoIndexWriter policy) and dynamodb:BatchGetItem (reader, RayitoIndexReader) on the table ARN, on the caller's credentials Do not pass index= / index (or pass None/undefined); delete the infra/metadata-index.yaml stack to stop paying for storage clients/python/src/rayito/_index.py / clients/typescript/src/index/dynamodb.ts
SDK OpenTelemetry traces available (0.5.0) tracer_provider= tracerProvider None / undefined Instruments create/connect/kill/pause/resume (instance and class/static), commands.run, run_code/runCode and files.* with rayito.* spans (SpanKind.CLIENT) on the TracerProvider you already have configured None of its own: Rayito creates or calls no AWS service for this — the cost depends on your exporter (CloudWatch, your own collector, …) $0 from Rayito: the OTel exporter is paid for and configured by whoever turns it on, not this SDK (CloudWatch pricing only if you export there, checked 2026-09-30) None of Rayito's own; whatever your OTel exporter requires Do not pass tracer_provider= / tracerProvider (or pass None/undefined) clients/python/src/rayito/_otel.py / clients/typescript/src/otel.ts
S3 mounts available (0.6.0) mounts={"/mnt/data": S3Mount(...)} mounts: { "/mnt/data": new S3Mount({...}) } None / undefined Mounts an S3 bucket (or a prefix) as a sandbox folder with mount-s3, only on rayito-base-caps and only the buckets in the image's allowlist (RAYITO_ALLOWED_MOUNT_BUCKETS) No new resources: the normal S3 requests (GetObject/ListObjectsV2, and PutObject/DeleteObject with write access) with the execution role; the IAM policy comes from the s3-mounts stack (rayito stack deploy s3-mounts) $0 of Rayito's own; the normal S3 requests and storage of the bucket (S3 pricing, checked 2026-10-01, us-east-1); the stack is $0 (IAM only) RayitoS3MountAccess (infra/s3-mounts.yaml) on the execution role, scoped to a bucket and its prefixes Do not pass mounts= / mounts; rayito stack destroy s3-mounts removes the policy (it deletes no objects) clients/python/src/rayito/sandbox_sync/main.py / clients/typescript/src/sandbox/sandbox.ts
Sizes available (0.6.0) size="4gb" size: "4gb" None / undefined Launches the image of the requested size (rayito-base-4gb) from the closed catalog of five sizes, resolved on the client; the image is published beforehand with rayito image publish --sizes Nothing new on launch; get_info() makes at most one free GetMicrovmImageVersion per version and process; each published size is one more image (create/update-microvm-image when publishing it); the optional sizes-guard stack is an IAM policy The bigger MicroVM costs more per hour: from $0.0315/h (512 MiB) to $0.5044/h (8192 MiB) at baseline (Limits, checked 2026-09-30, us-east-1); each published size adds snapshot storage, ≈ $0.04/week per version None additional to launch; sizes-guard (RayitoRunAllowedSizes) denies RunMicrovm outside the images you list Do not pass size= / size; delete the sized images' versions with rayito image prune --image-name ... and the sizes-guard stack if you deployed it clients/python/src/rayito/_sizing.py / clients/typescript/src/sizing/sizing.ts
Events and webhooks available (0.6.0) events=LifecycleEvents(...) events: new LifecycleEvents() None / undefined rayd emits signed created/paused/resumed/killed; the stack stores them (get_events) and delivers them to your webhooks with E2B's signature The events-webhooks stack (rayito events deploy): HMAC secret, DynamoDB table with streams, 3 Lambdas with their log groups, subscription filter, scheduler, failure SQS queues and 4 IAM policies; per sandbox, one secretsmanager:GetSecretValue of the stack key per LifecycleEvents instance ≈ $0.40/month at rest (the secret); DynamoDB, Lambda and SQS by use (Secrets Manager pricing, checked 2026-09-30, us-east-1) EventsLauncherPolicy (stack output) on the caller's credentials (EventsReaderPolicy for get_events, EventsWebhookAdminPolicy for the webhooks); the execution role writes to the image's log group Do not pass events= / events; rayito events destroy deletes the stack clients/python/src/rayito/sandbox_sync/main.py / clients/typescript/src/sandbox/sandbox.ts
OTLP export available (0.6.0) telemetry=TelemetryExport(...) telemetry: new TelemetryExport({...}) None / undefined rayd exports 7 CPU, memory and disk metrics over OTLP/HTTP every interval_s (60 s by default) PutMetricData per exported batch from the sandbox; with OtlpAuth.execution_role(), the otlp-export stack's policy on the execution role $0 for the option; CloudWatch bills OTLP ingestion at $0.50/GB: ≈ $0.00002 per sandbox-hour with interval_s=60 (AWS_API_NOTES.md Q120, CloudWatch pricing, checked 2026-10-02) cloudwatch:PutMetricData (RayitoOtlpExport) on the execution role; with OtlpAuth.bearer(...), read the token's secret Do not pass telemetry= / telemetry; delete the otlp-export stack if no sandbox uses it anymore clients/python/src/rayito/sandbox_sync/main.py / clients/typescript/src/sandbox/sandbox.ts
Secret gateway available (0.6.0) gateways={"anthropic": SecretGateway(...)} gateways: { anthropic: new SecretGateway({...}) } None / undefined rayd opens a gateway per route on loopback that injects the real header toward a fixed upstream: the sandbox code uses the secret without being able to read it secretsmanager:GetSecretValue once per header and SecretCache TTL; no new resources $0.05/10,000 calls plus the secret itself if it did not exist (Secrets Manager pricing, checked 2026-09-30, us-east-1) secretsmanager:GetSecretValue on the caller's credentials (RayitoSecretsReader) Do not pass gateways= / gateways clients/python/src/rayito/_secret_gateway/_domain.py / clients/typescript/src/secret-gateway/domain.ts
Templates available (0.6.0) Template.build(...) Template.build(...) without calling build = no client Builds a new image from the templates DSL, composed on top of a published rayito-base image (also rayito template build) GetMicrovmImageVersion, CreateMicrovmImage/UpdateMicrovmImage, GetMicrovmImage, ListMicrovmImageVersions; S3 GetObject/HeadObject/PutObject of the zip; logs only if the build fails (AWS_API_NOTES.md §27) Snapshot storage per new version, ≈ $0.04/week per version; the build is not billed separately; the context zip stays in your bucket (standard S3) RayitoTemplateBuilder (infra/templates.yaml, rayito stack deploy templates) on the caller's credentials Do not call Template.build(); delete the versions with rayito image prune clients/python/src/rayito/_templates/__init__.py / clients/typescript/src/templates/dsl.ts
EFS volumes experimental (0.7.0) volumes={"/mnt/data": EfsVolume(...)}; VolumeStore(...), EfsVolumes(...) volumes: { "/mnt/data": new EfsVolume({...}) }; new VolumeStore({...}), new EfsVolumes({...}) None / undefined rayd mounts each access point with amazon-efs-utils (TLS + IAM) in the same ConfigureSandbox as the rest; only on the optional rayito-base-caps-efs image, with execution_role_arn and a single own connector in egress (never INTERNET_EGRESS) create(): one DescribeMountTargets per file system if the volume carries no mount_target_ip; VolumeStore: CreateAccessPoint/DescribeAccessPoints/DeleteAccessPoint; the efs-volumes stack (EfsVolumes.deploy): encrypted file system, mount targets, security groups and connector, inside your VPC $0 empty; $0.30/GB-month (Standard), $0.016/GB-month (IA), $0.03/GB read and $0.06/GB written (Elastic) (EFS pricing, checked 2026-09-11, us-east-1); the image with amazon-efs-utils takes ≈ 198 MB more (Q122) The caller: access point CRUD and DescribeMountTargets; the execution role: the stack's CallerPolicyArn (ClientMount, ClientWrite unless read-only) Do not pass volumes= / volumes; EfsVolumes.destroy(delete_file_system=True) deletes the stack and the data clients/python/src/rayito/_volumes/ / clients/typescript/src/volumes/
Custom domain experimental (0.7.0, without end-to-end acceptance on real AWS) CustomDomain(public_domain=...), AsyncCustomDomain(...) new CustomDomain({ publicDomain }) not instantiated = no client A CloudFront distribution in your account whose CloudFront Function routes https://<port>-<alias>.<your-domain> to the sandbox, setting the AWS proxy headers itself; you register each route (register()/unregister()/refresh()) The custom-domain stack (CustomDomain.deploy, rayito domain deploy): distribution, CloudFront Function and KeyValueStore; per route, DescribeKeyValueStore/PutKey/DeleteKey (signed with SigV4A) $0 at rest; ~$0.085/GB + $0.0075/10,000 HTTPS requests, ~$0.10 per million Function invocations and ~$0.50 per million KeyValueStore reads; ~$5 per million PutKey/DeleteKey (CloudFront pricing, list figures not measured with a real distribution, us-east-1) The caller: cloudformation:*Stack* and the CloudFront permissions to create and delete the distribution, the Function and the KeyValueStore; cloudfront-keyvaluestore:DescribeKeyValueStore/PutKey/DeleteKey on the stack's KeyValueStore Do not instantiate CustomDomain; CustomDomain.destroy() or rayito domain destroy deletes the stack clients/python/src/rayito/_custom_domain/ / clients/typescript/src/custom-domain/
Management dashboard (SDK) published in 0.12.0, accepted on real AWS on 2026-10-14; the local dashboard of the TypeScript CLI (npx rayito dashboard), published in 0.13.0 and accepted on real AWS on 2026-10-16 Quotas(...), UsageCost(...), Fleet(...) (and AsyncQuotas, AsyncUsageCost, AsyncFleet) new Quotas({...}), new UsageCost({...}), new Fleet({...}) not instantiated or not called = no client; actions, allow_actions=False / allowActions: false Reads the applied quotas and the allocated memory against the region's quota, the billed MicroVM cost (Cost Explorer, by usage type, with a local cache) and the estimate per sandbox, and the inventory, images, events and bulk actions (kill, suspend, resume) with a queue that respects TPS Reads only, no resources: ListServiceQuotas, ListMicrovms, GetMicrovmImageVersion, ListMicrovmImages, ListMicrovmImageVersions and, with billed(), ce:GetCostAndUsage (us-east-1); with allow_actions=True, TerminateMicrovm/SuspendMicrovm/ResumeMicrovm (AWS_API_NOTES.md §30) $0 the reads; Cost Explorer $0.01 per request (Cost Explorer pricing, checked 2026-10-13, us-east-1), with a 24 h cache ≈ 30 requests/month ≈ $0.30; the per-sandbox estimate is free and never replaces the bill servicequotas:ListServiceQuotas and the Lambda MicroVMs reads; ce:GetCostAndUsage only for billed(); lambda:TerminateMicrovm/SuspendMicrovm/ResumeMicrovm only for the actions Do not call its methods; do not pass allow_actions=True clients/python/src/rayito/_dashboard/ / clients/typescript/src/dashboard/
Dashboard in your account (stack) published in 0.12.0, accepted on real AWS on 2026-10-14, also the AuthMode=aws-iam variant OptionalStacks().deploy("dashboard", artifact_bucket=...) new OptionalStacks().deploy("dashboard", { artifactBucket }) not deployed = no resources; deployed, read-only and without Cost Explorer A Lambda with Function URL serves the dashboard's page and API with Cognito sign-in (token validated in the function before routing), separate read and actions roles (AllowActions=true), an audit of every action in DynamoDB, a billed-cost cache and an own theme (ThemeJson / SSM) AWS::Lambda::Function and Url, AWS::Cognito::UserPool (+ client, domain and group), 2 AWS::DynamoDB::Table, AWS::IAM::Role (1 or 2), AWS::Logs::LogGroup, and with ThemeJson an AWS::SSM::Parameter; no CloudFront or buckets ≈ $0 at rest; by use: Lambda per request (public URL: unauthenticated traffic also bills, bound it with ReservedConcurrency), DynamoDB per action, with EnableCostExplorer=true Cost Explorer $0.01 per query with a 24 h cache (worst case ≈ $6/month) and, with a theme or logo in Advanced SSM parameters, $0.05/month each plus API interactions (Lambda, Cognito, SSM, Cost Explorer, checked 2026-10-13, us-east-1) cloudformation:*Stack with CAPABILITY_IAM to deploy; MicroVM and quota reads for the function; ce:GetCostAndUsage only with EnableCostExplorer=true; TerminateMicrovm/SuspendMicrovm/ResumeMicrovm only in the actions role Do not deploy it, or rayito stack destroy dashboard clients/python/src/rayito/_stacks/components/dashboard.py / clients/typescript/src/stacks/components/dashboard.ts
CloudWatch dashboard published in 0.12.0, accepted on real AWS on 2026-10-14 (the dashboard cloudwatch command of the TypeScript CLI, published in 0.13.0 and accepted on 2026-10-16); the OTLP charts' PromQL queries were checked through the API, not how the console draws them OptionalStacks().deploy("dashboard-cloudwatch") (or rayito dashboard cloudwatch) new OptionalStacks().deploy("dashboard-cloudwatch") not deployed = no resources; rayito dashboard cloudwatch only prints The JSON of a CloudWatch dashboard with Logs Insights widgets over /rayito/* and, with IncludeOtlp/IncludeQuota (--otlp/--quota), charts of the OTLP metrics and of quota usage One AWS::CloudWatch::Dashboard; printing it makes no call $0 with fewer than 4 dashboards, $3/month per dashboard from the fourth; Logs Insights $0.005 per GB scanned on open or refresh (CloudWatch, checked 2026-10-13, us-east-1) cloudwatch:PutDashboard, GetDashboard, DeleteDashboards to deploy; logs:StartQuery and logs:GetQueryResults to view it Do not deploy it, or rayito stack destroy dashboard-cloudwatch clients/python/src/rayito/_dashboard/_cloudwatch_board.py / clients/typescript/src/stacks/components/dashboard-cloudwatch.ts
Multiple accounts in the dashboard published in 0.12.0, accepted on real AWS on 2026-10-14 rayito dashboard --account NAME=<ARN>; OptionalStacks().deploy("dashboard-read-role", parameters={...}) new OptionalStacks().deploy("dashboard-read-role", { parameters }) without --account STS is not called; the role does not exist until deployed A view of other accounts in the local dashboard, read-only and without billed cost, with a role that is assumed and an optional ExternalId In the target account one AWS::IAM::Role; in the dashboard one sts:AssumeRole per account and the dashboard's reads $0 (IAM, checked 2026-10-13) sts:AssumeRole on the roles; each role only ListMicrovms, ListMicrovmImages, ListMicrovmImageVersions, GetMicrovmImageVersion and ListServiceQuotas Do not pass --account, or rayito stack destroy dashboard-read-role in each target account clients/python/src/rayito/_dashboard/_accounts.py / clients/python/src/rayito/_stacks/components/dashboard_read_role.py
Quota alerts published in 0.12.0, accepted on real AWS on 2026-10-13 OptionalStacks().deploy("quota-alerts", artifact_bucket=...) new OptionalStacks().deploy("quota-alerts", { artifactBucket }) not deployed = no resources A scheduled check that publishes to SNS when allocated memory crosses a threshold of the region's quota (one alert per crossing) and publishes usage as a custom metric AWS::Lambda::Function, AWS::Events::Rule, AWS::SNS::Topic, 1 AWS::DynamoDB::Table, AWS::IAM::Role, AWS::Logs::LogGroup ≈ $0.30/month for the metric; Lambda, EventBridge, DynamoDB and SNS in free tiers (CloudWatch, SNS, checked 2026-10-13, us-east-1) CAPABILITY_IAM to deploy; the function, MicroVM and quota reads, sns:Publish on its topic, GetItem/PutItem on its table and cloudwatch:PutMetricData with a fixed cloudwatch:namespace Do not deploy it, or rayito stack destroy quota-alerts clients/python/src/rayito/_stacks/components/quota_alerts.py / clients/typescript/src/stacks/components/quota-alerts.ts
Preparing the account (rayito setup) published in 0.15.0 — (CLI only, in Python and TypeScript) — (CLI only) not run = no resources; --dry-run only reads Prepares an account and region in one idempotent command: the artifact bucket if there is none to reuse, the IAM stack and the rayito-base image Only when there is no bucket, the rayito-m0-artifacts stack (infra/artifact-bucket.yaml: an AWS::S3::Bucket and its policy, with the zips under rayito/images/ expiring after 7 days); the rayito-m0-iam stack (CAPABILITY_NAMED_IAM); the image zip in the bucket and CreateMicrovmImage/UpdateMicrovmImage; reads GetCallerIdentity, DescribeStacks, HeadBucket, GetMicrovmImage, ListMicrovmImageVersions The IAM stack is free; the bucket costs nothing to exist and its zips, cents; each published image version ≈ $0.04/week of snapshot (one week minimum; see Pricing) Admin or bootstrap credentials, once: CloudFormation, creating IAM roles and policies, publishing images and, only when it creates the bucket, the S3 permissions CloudFormation uses to create it (list) Do not run rayito setup; to undo it, delete the rayito-m0-iam and rayito-m0-artifacts stacks and the image versions (rayito image prune); the bucket is kept when its stack is deleted (DeletionPolicy: Retain): empty it and delete it by hand clients/python/src/rayito/_account_setup/ / clients/typescript/src/account-setup/
Deploy your agent published in 0.14.0, accepted on real AWS on 2026-10-17 AgentProject.build(), .run(), .deploy() (export() makes no AWS call) project.build(), .run(), .deploy() of AgentProject not called = no resources A Strands, Hermes, LangGraph, deepagents, OpenCode or custom agent, detected in its folder, as an image, a one-off run or an HTTP service in a MicroVM (also rayito agent build, run and deploy) A new image version only if the content changed (zip in S3 and CreateMicrovmImage/UpdateMicrovmImage); with run()/deploy(), one MicroVM (RunMicrovm); the model, through the secrets gateway One image version ≈ $0.056/week with rayito-agent; the VM while it lives ≈ $0.126/h with 2 GB (see Pricing); the model is billed by its provider RayitoTemplateBuilder (templates stack), those of Sandbox.create() and that of the chosen secrets gateway Do not call build()/run()/deploy(); rayito agent stop; rayito image prune for the versions clients/python/src/rayito/_agent/_project_domain.py / clients/typescript/src/agent/project.ts
Several sessions and several VMs published in 0.14.0, accepted on real AWS on 2026-10-17 deploy_agent(path, options=AgentDeployOptions(scaling=ScalingOptions(...))) (and deploy_agent_async) deployAgent(path, { options: { scaling } }) not called = no resources; plan_deploy()/planDeploy(), --dry-run and rayito agent detect make no AWS call The agent you already have, without touching its code, as a MicroVM fleet with a queue: min_vms, max_vms, warm_vms and shared or dedicated sessions (also rayito agent deploy) min_vms MicroVMs (RunMicrovm) and warm_vms parked slots; a new image version if the content changed; reads GetCallerIdentity, HeadBucket, GetMicrovmImage, DescribeSecret; with session_index/sessionIndex, DynamoDB Per running VM ≈ $0.126/h with 2 GB; the image ≈ $0.056/week; a parked slot, only the snapshot (see Pricing); the model is billed by its provider Those of Sandbox.create()/list()/kill() and AgentTemplate.build() (RayitoSandboxRunner, RayitoTemplateBuilder), secretsmanager:DescribeSecret, sts:GetCallerIdentity and s3:ListBucket on the artifact bucket Do not call deploy_agent()/deployAgent(); fleet.stop() or rayito agent stop <name> clients/python/src/rayito/_agent/_deploy_facade.py / clients/typescript/src/agent/deploy.ts
Fleet recipe published in 0.17.0 AgentDeployOptions(save_recipe=False); AgentFleet.connect(name, use_recipe=False); fleet.stop(keep_recipe=True) options: { saveRecipe: false }; AgentFleet.connect(name, { useRecipe: false }); fleet.stop({ keepRecipe: true }) on (True / true): the only exception of ADR-034 After the deploy, saves what it used (no secret values) so AgentFleet.connect(name) creates matching VMs in another process and status() gives the real scaling One standard SecureString parameter per fleet: PutParameter on deploy, GetParameter when reconnecting without a project, DeleteParameter on stop; one KMS request (aws/ssm) per write and read $0 for the parameter; KMS within the 20,000 free requests per month, then $0.03 per 10,000 ssm:PutParameter, ssm:GetParameter, ssm:DeleteParameter on parameter/rayito/agents/* (AgentRecipe statement); no KMS save_recipe=False / saveRecipe: false / --no-save-recipe clients/python/src/rayito/_agent/_fleet_recipe_aws.py / clients/typescript/src/agent/fleet-recipe-aws.ts
Renewing the Bedrock key published in 0.17.0 AgentDeployOptions(renew_gateway_keys=True), AgentFleet.connect(name, renew_gateway_keys=True) (extra bedrock-keys) options: { renewGatewayKeys: true } (peer @aws/bedrock-token-generator) False / false Signs a short-term Bedrock key locally and writes it to the bedrock gateway's secret before creating each VM DescribeSecret and, at most once every 900 s per gateway, PutSecretValue; signing makes no AWS call $0.05 per 10,000 Secrets Manager calls secretsmanager:DescribeSecret, secretsmanager:PutSecretValue and bedrock:CallWithBearerToken Do not pass the option clients/python/src/rayito/_agent/_gateway_keys.py / clients/typescript/src/agent/gateway-keys.ts
Creating the model secret on deploy published in 0.14.0 AgentDeployOptions(create_secret_from_env=True) options: { createSecretFromEnv: true } False / false Stores in Secrets Manager the key from the provider's standard variable on deploy (--create-secret in the CLI) secretsmanager:CreateSecret, once per secret $0.40 per secret per month until you delete it (Secrets Manager pricing, checked 2026-09-30, us-east-1) secretsmanager:CreateSecret Do not pass the option; SecretStore.destroy() the secret clients/python/src/rayito/_agent/_deploy_plan.py / clients/typescript/src/agent/deploy-plan.ts
Publishing the base image on deploy published in 0.14.0 AgentDeployOptions(base_publisher=...) options: { basePublisher } None / undefined: a missing base is an error Publishes rayito-base-caps if it is missing (--base-artifact ZIP --yes in the CLI) Those of rayito image publish: the zip in S3 and CreateMicrovmImage/UpdateMicrovmImage ≈ $0.056/week per image version Those of rayito image publish (ImagePublisherPolicy) Do not pass the option; rayito image prune clients/python/src/rayito/_agent/_deploy_plan.py / clients/typescript/src/agent/deploy-plan.ts
Deploy to AgentCore published in 0.15.0, accepted on real AWS on 2026-10-19 deploy_agent(path, target="agentcore", agentcore=AgentCoreOptions(...)) (and deploy_agent_async); AgentCoreFleet deployAgent(path, { target: "agentcore", agentcore: {...} }); AgentCoreFleet target="microvm" / "microvm": without agentcore nothing is created; plan_deploy()/planDeploy() and --dry-run make no AWS call The agent you already have on Amazon Bedrock AgentCore Runtime, with no local Docker, with a least-privilege role (also rayito agent deploy --target agentcore) The rayito-agentcore-<name> stack (infra/agentcore-runtime.yaml: ECR repository, CodeBuild project with its log group, build role and runtime role); the build context zip in the bucket (deleted after the build); one CodeBuild build per new content; CreateAgentRuntime/UpdateAgentRuntime/GetAgentRuntime; on invoke, InvokeAgentRuntime Runtime $0.0895 per vCPU-hour and $0.00945 per GB-hour of actual use, only with sessions; build $0.0034 per arm1.small minute (100 min/month free); ECR $0.10 per GB-month (5 images); logs $0.50 per GB (Pricing, checked 2026-10-19, us-east-1); the model is billed by its provider CloudFormation with CAPABILITY_IAM on rayito-agentcore-*, S3 on rayito/images/agentcore/*, CodeBuild, ecr:DescribeImages, bedrock-agentcore:*AgentRuntime* and iam:PassRole (list); it uses neither MicroVMs nor the secrets gateway Do not pass target="agentcore"; rayito agent delete <name> --target agentcore or fleet.delete() clients/python/src/rayito/_agentcore/ / clients/typescript/src/agentcore/
Agent on AgentCore with CDK published in 0.15.0, accepted on real AWS on 2026-10-20 RayitoAgent(scope, id, project=...) from rayito.cdk (extra cdk) new RayitoAgent(scope, id, { project }) from rayito/cdk (peers aws-cdk-lib and constructs) not instantiated = no resources; cdk synth makes no AWS call The same agent as --target agentcore, with the same resources and IAM, inside your CDK app with cdk deploy A nested stack with the CLI's template; the code asset in the bootstrap bucket; two Rayito Python Lambda functions (OnEvent, IsComplete) and CDK's Provider (three Node.js Lambda functions and a Step Functions state machine); the AWS::BedrockAgentCore::Runtime and a resource that enforces MMDSv2; with localDocker(), no CodeBuild build The same as Deploy to AgentCore (build only with codeBuild()), plus cents of Lambda and Step Functions per deployment and the assets in the bootstrap bucket until cdk gc The CDK bootstrap execution role (by default, nothing else; with a restricted one, the list) Do not instantiate the construct; cdk destroy (and cdk gc for the assets) clients/python/src/rayito/cdk/_agent.py / clients/typescript/src/cdk/agent.ts
MicroVMs image with CDK published in 0.15.0, accepted on real AWS on 2026-10-20 RayitoMicrovmImage(scope, id, ...) and MicrovmImageArtifact from rayito.cdk (extra cdk) new RayitoMicrovmImage(scope, id, {...}) and MicrovmImageArtifact from rayito/cdk not instantiated = no resources A Lambda MicroVMs image with rayd, and one more per size, as part of your stack (equivalent to rayito image publish); sandboxes are still created with the SDK An S3 asset with the zip, a build role and, per image (the base and each size), a log group and an AWS::Lambda::MicrovmImage ≈ $0.04/week of snapshot per version and per size (one week minimum); logs $0.50 per GB; the zip in the bootstrap bucket until cdk gc The CDK bootstrap execution role (with a restricted one, lambda:*MicrovmImage*, lambda:PassNetworkConnector and iam:PassRole; list) Do not instantiate the construct; cdk destroy; rayito image prune for old versions clients/python/src/rayito/cdk/_microvm_image.py / clients/typescript/src/cdk/microvm-image.ts

A row becomes "available" when the feature is accepted against real AWS and published in a version (see the warning in At a glance); between acceptance and release it says "accepted on real AWS" and the date.

No AWS cost

Feature Option What it turns on AWS resources Cost Where
rayito sandbox proxy CLI rayito sandbox proxy <id> --port N (Python and TypeScript) Serves a guest port on 127.0.0.1 (another interface only with --bind + --allow-remote), renewing the x-aws-proxy-auth header's JWE before it expires lambda:GetMicrovm (once, for the endpoint) + lambda:CreateMicrovmAuthToken (~1 every 45 min per running proxy); IAM: lambda:GetMicrovm and lambda:CreateMicrovmAuthToken on the MicroVM (already in infra/iam.yaml's CallerPolicy) $0: both calls are free (quotas of 100 and 50 TPS, AWS_API_NOTES.md §11); if the sandbox was suspended, waking it through auto-resume bills its normal compute plus the snapshot read on resume, not the proxy itself clients/python/src/rayito/cli/_proxy.py (CLI)
rayito-mcp rayito-mcp executable (Python: pip install "rayito[mcp]"; TypeScript: npx -y -p rayito -p @modelcontextprotocol/server -p zod rayito-mcp) Creates one sandbox per process on the first tool that needs it and terminates it on shutdown; six tools (run_code, run_command, read_file, write_file, list_files, list_sandboxes) RunMicrovm on first use, TerminateMicrovm on shutdown, and each tool's calls; no resources that persist that of a running MicroVM while it is used plus one snapshot per suspend (cost model); with RAYITO_MCP_IDLE_SECONDS=0, no auto-suspend clients/python/src/rayito/mcp/ / clients/typescript/src/mcp/

It consumes no additional quota or money: it reuses free calls the SDK already makes. Guide: Local proxy.

For whoever adds an optional feature to Rayito

This page's rule is ADR-014 of ARCHITECTURE.md. Every new optional feature follows four rules, the same in Python and TypeScript (clients/python/src/rayito/_optional.py and clients/typescript/src/optional.ts):

  • (a) One named kwarg per feature. At most, a second kwarg with the configuration object. None/undefined is "off"; no environment variable, configuration file or global setter turns it on; turning on an option never changes the meaning of another kwarg.
  • (b) Immutable, reusable configuration object. Its class name says the AWS service (DynamoDbIndex, SecretCache, SecretStore) and it creates its boto3 / AWS SDK client lazily, on its first use — never in the configuration object's constructor or in the Sandbox's.
  • (c) TypeScript optional peers loaded on demand. The AWS SDK v3 clients that only these features use (@aws-sdk/client-secrets-manager, @aws-sdk/client-dynamodb) are optional peerDependencies: they are loaded with a dynamic import() only inside the already activated function (loadOptionalPeer), never at the top level of a module. @opentelemetry/api is also an optional peer, but only for types: src/otel.ts uses it with import type (erased at build), the SDK uses the tracerProvider the caller passes directly and loads nothing from @opentelemetry/api at run time. In Python, the equivalent is rayito[otel] via require_module, which imports opentelemetry.trace only when tracer_provider= is turned on.
  • (d) "Cost and activation" docstring block. Every cost option carries it, with the following template.

The template. The docstring (Python) or TSDoc (TypeScript) of the option that turns on each feature carries a block titled literally "Coste y activación" (the SDK's docstrings are written in Spanish):

Coste y activación
-------------------
Activa: <qué hace exactamente esta opción>
Recursos y llamadas AWS: <qué crea o llama, con nombres de API reales>
Coste aproximado: <cifra, región y fecha, con enlace a la página de precios>
IAM: <permisos mínimos necesarios>
Cómo apagarla: <qué valor la deja apagada — normalmente None/undefined>
Ejemplo:
    <fragmento runnable de ≤ 10 líneas>

scripts/tests/test_optional_features_docs.py checks, for each row marked "disponible" in the Features with AWS cost table, that the cited option symbol appears in the SDK file of its "Where" column within a single "Coste y activación" block that also carries the template's six sections.