Strands Agents
Native sandbox providers for Strands Agents, Python and TypeScript.
Native inis.run sandbox providers for Strands Agents' Sandbox surface — gives Strands its standard sandbox_bash and sandbox_file_editor tools backed by a real, isolated inis.run session instead of the local host.
Verified against strands-agents==1.50.2 (Python) and @strands-agents/sdk==1.11.2 (TypeScript).
Install
pip install inis-strands-agents # Python
npm install @inis-run/strands-agents @strands-agents/sdk @inis-run/sdk # TypeScript / NodeQuickstart: attached (recommended)
One inis.run session for the whole conversation, owned by your app.
from inis import AsyncClient
from strands import Agent
from inis_strands_agents import InisSandbox
client = AsyncClient()
session = await client.sessions.create(egress_default="deny")
sandbox = InisSandbox.wrap(session)
agent = Agent(model="...", sandbox=sandbox)
await agent.invoke_async("list files in /workspace")
await agent.invoke_async("now write hello.txt")
await session.destroy() # this app owns the session; the adapter never willimport { Client } from "@inis-run/sdk";
import { Agent } from "@strands-agents/sdk";
import { InisSandbox } from "@inis-run/strands-agents";
const client = new Client();
const session = await client.sessions.create({ egress: { mode: "deny" } });
const sandbox = InisSandbox.wrap(session);
const agent = new Agent({ model, sandbox });
await agent.invoke("list files in /workspace");
await agent.invoke("now write hello.txt");
await session.destroy(); // this app owns the session; the adapter never willOwned: the adapter creates and destroys the session for you
from strands import Agent
from inis_strands_agents import InisSandbox
async with await InisSandbox.create(egress_default="deny") as sandbox:
agent = Agent(model="...", sandbox=sandbox)
await agent.invoke_async("...")
# session destroyed on exitimport { Agent } from "@strands-agents/sdk";
import { InisSandbox } from "@inis-run/strands-agents";
const sandbox = await InisSandbox.create(undefined, { egress: { mode: "deny" } });
try {
const agent = new Agent({ model, sandbox });
await agent.invoke("...");
} finally {
await sandbox.close();
}InisSandbox.create()'s options also accept connections — inline Connections to create alongside the session.
Either way, Agent({ sandbox }) registers sandbox_bash and sandbox_file_editor automatically — no separate tool wiring needed. Session create/destroy, egress, pause/resume, and fork stay host-controlled.
What it does
- Streaming shell execution — distinct stdout/stderr chunks, then a final result
- Binary-safe file read/write/remove/list, routed to inis.run's native
/filesendpoints - Per-call
timeout— genuinely kills the remote process on expiry - Per-call
env— via a validated shell-export prefix (inis.run's exec API fixes env at session creation) - Cancellation: Python
asynciotask cancellation preempts a running command outright; TypeScriptAbortSignalcan only preempt at a chunk boundary (Session.execStreamhas no cancellation parameter of its own) — a real, tested asymmetry between the two packages, not a bug in one of them.
Notes
PTY isn't implemented in either language: the Sandbox/PosixShellSandbox shell/file contract has no PTY concept to hook into. Output-file collection is always empty, same as every other shell-based Sandbox — read a produced file back explicitly instead.