Skip to content

Add durable Strands sandbox support - #1768

Open
brianstrauch wants to merge 6 commits into
mainfrom
strands-temporal-sandbox
Open

Add durable Strands sandbox support#1768
brianstrauch wants to merge 6 commits into
mainfrom
strands-temporal-sandbox

Conversation

@brianstrauch

Copy link
Copy Markdown
Member

Summary

  • add an experimental activity-backed TemporalSandbox implementation for the Strands sandbox API
  • register lazy, worker-lifetime sandbox factories through StrandsPlugin
  • buffer execution streams for deterministic replay and optionally publish raw StreamChunk values through Workflow Streams
  • preserve Strands timeout and missing-path errors across the activity boundary
  • vend the standard sandbox bash and file-editor tools with user overrides
  • document lifecycle, payload, retry, streaming, and environment-value considerations

Testing

  • poe test -s -k strands
  • poe lint
  • git diff --check

@brianstrauch
brianstrauch requested review from a team as code owners August 20, 2026 02:48
@brianstrauch
brianstrauch requested a balanced review from Copilot August 20, 2026 03:02

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

brianstrauch and others added 4 commits August 20, 2026 16:22
A timeout is the deterministic outcome the caller's own `timeout` argument
asked for, so retrying just re-runs the same hanging command. Under Temporal's
unlimited-attempt default this meant SandboxTimeoutError never reached workflow
code and the agent could never observe the timeout and adapt.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Every built-in Strands sandbox raises a plain FileNotFoundError from
read/write/remove — only list_files raises the SandboxPathNotFoundError
subclass — so the old handlers were dead code and a missing path retried
forever instead of reaching workflow code. Catch the documented base class
instead, and carry the sandbox's own message through so a timeout reports the
duration it actually enforced rather than the one the caller requested.

Also fix the DockerSandbox import in the README, which is not re-exported from
strands.sandbox, and note that the sandbox cache is per worker process.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@patbeqo

patbeqo commented Aug 27, 2026

Copy link
Copy Markdown

@codex

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Swish!

Reviewed commit: ef2c383e3c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread temporalio/contrib/strands/README.md Outdated

The factory is called lazily on first use. Its sandbox instance is cached and
shared by all activities for that name for the worker's lifetime, so tools see
the same filesystem and working state. Provisioning and teardown of the backing

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is sharing one sandbox across all Workflow Executions intentional? Two concurrent Workflows using TemporalSandbox("build") can access the same files and processes, creating cross-tenant data exposure and race risks.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could do TemporalSandbox(workflow_id) to get per-workflow isolation, but good point, that's probably what we want as the default, actually.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think TemporalSandbox(workflow_id) works here because StrandsPlugin(sandboxes=...) has to know those names at Worker construction to register the activities, and workflow_id is only known at runtime.

I think the sandbox cache needs a composite key of (name, workflow_id). The factory then has to create something every worker can reach using that id. Maybe a named container with workflow_id?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants