Lambda MicroVM Sandbox#
Overview#
lambdaMicrovm.ts is the production sandbox provider for the in-app agent feature. It wraps AWS Lambda MicroVMs via @aws-sdk/client-lambda-microvms to give each agent conversation an isolated, stateful compute environment. The file lives at packages/shared/src/in-app-agent/server/sandbox/providers/lambdaMicrovm.ts (commit b97e819; later moved to web/src/features/in-app-agent/server/sandbox/providers/lambdaMicrovm.ts in PR #15492).
The provider implements the SandboxProvider interface, which defines three top-level operations: ensureSession, suspendSession, and terminateSession.
Session Lifecycle#
All session state is held in an in-memory Map<string, LambdaMicrovmSession> scoped to the provider instance. Each entry tracks the MicroVM's endpoint, an optional cached authToken, and the current toolCallFiles snapshot.
ensureSession#
ensureSession is the core entry point. When called with a conversationId and an optional existing sessionId, it:
- Looks up the existing MicroVM via
GetMicrovmCommand. If found andSUSPENDED, issues aResumeMicrovmCommandfirst. - Waits for the HTTP bridge inside the MicroVM to become ready (
waitForBridge, 30 s timeout, 500 ms polling interval). - Creates a new MicroVM via
RunMicrovmCommandif no existing session is found.
Key timing constants :
DEFAULT_SUSPEND_AFTER_IDLE_SECONDS = 60— auto-suspend after 1 minute of idleDEFAULT_TERMINATE_AFTER_SUSPEND_SECONDS = 8 * 60 * 60— terminate 8 hours after suspensionDEFAULT_MAXIMUM_DURATION_SECONDS = 3_600— hard 1-hour cap per session
New MicroVMs are launched with autoResumeEnabled: true and clientToken: randomUUID() for idempotency.
suspendSession#
Calls SuspendMicrovmCommand then removes the session from the in-memory map. ResourceNotFoundException / HTTP 404 errors are silently swallowed (session already gone).
terminateSession#
Calls TerminateMicrovmCommand. The in-memory entry is removed before the AWS call so the session is treated as gone even if the API call fails. Same 404-tolerance as suspend.
Operations & Authentication#
executeOperation dispatches the four supported operation types — read, write, edit, bash — to the MicroVM's HTTP bridge at {endpoint}/sandbox (port 5000) .
Each request carries:
X-aws-proxy-port: 5000X-aws-proxy-auth: <token>— a short-lived token fromCreateMicrovmAuthTokenCommand
Tokens are cached per session and refreshed proactively when within AUTH_TOKEN_REFRESH_BUFFER_MS = 60_000 ms of expiry (token lifetime is DEFAULT_AUTH_TOKEN_EXPIRATION_MINUTES = 30) .
Every operation also sends the current toolCallFiles snapshot in the POST body. This is the vector for a known race condition (see Known Issues below).
Optional Egress Network Connector#
If egressNetworkConnectorArn is provided (set via LANGFUSE_IN_APP_AGENT_SANDBOX_AWS_LAMBDA_MICROVM_EGRESS_NETWORK_CONNECTOR_ARN), it is passed as egressNetworkConnectors in RunMicrovmCommand to enforce network egress policy .
Health Check / Bridge Readiness#
waitForBridge polls {endpoint}/health with a fresh auth token on every attempt :
- Outer timeout:
BRIDGE_READY_TIMEOUT_MS = 30_000ms - Poll interval: 500 ms
- Aborts immediately if the MicroVM transitions to
TERMINATINGorTERMINATED
Note on timeout handling: The current
waitForBridgeandexecuteOperationfetch()calls use noAbortSignal. This means a hung health probe or operation request will never be cancelled by the caller. If adding timeouts, preferAbortSignal.timeout(ms)(Node 18+) for one-liners, orAbortController+clearTimeoutfor cases where you also need to abort on external signals. A related production incident (PR #14876) demonstrated that GC-fragileAbortControllerpatterns withAbortSignal.timeout()on derived signals can silently lose their timeout — always pass the originating signal, not a derived one.
Known Issues#
Global tool_calls Directory Race (Issue #15954)#
The sandbox runtime server uses a single global /workspace/tool_calls directory. Because executeOperation sends toolCallFiles with every request and the runtime deletes/recreates that directory atomically, concurrent sandbox calls can destroy each other's files .
Affected code paths:
packages/in-app-agent-sandbox-runtime/src/server.ts:71-85—syncToolCallFilesnukes and recreates the global directorypackages/in-app-agent-sandbox-runtime/src/server.ts:135-145— every/sandboxrequest triggers the synclambdaMicrovm.tslines sendingtoolCallFileson everyexecuteOperationcall
Fix direction: Use request/session-scoped directories instead of a single global one, or serialize per-session operations.
Configuration & Environment#
| Variable | Purpose |
|---|---|
LANGFUSE_IN_APP_AGENT_SANDBOX_PROVIDER | Must be set to enable the sandbox (gating decoupled from NODE_ENV in PR #15797) |
LANGFUSE_IN_APP_AGENT_SANDBOX_AWS_LAMBDA_MICROVM_EGRESS_NETWORK_CONNECTOR_ARN | Optional egress network policy ARN |
Key Source References#
| Reference | Description |
|---|---|
lambdaMicrovm.ts (commit b97e819) | Full provider implementation |
| PR #14712 — feat(agent): Add sandbox | Initial implementation |
| PR #15196 — egress network connector | Egress connector support |
| PR #15492 — Move in-app-agent out of EE | Moved to web/src/features/ |
| Issue #15954 — tool_calls directory race | Race condition in concurrent sandbox calls |
| PR #14876 — AbortSignal fix in secureLlmFetch | Pattern for correct abort signal propagation |