Parallel tasks and batches
Use a batch for independent agent tasks. Use a fleet when you need to address and manage the same workers across multiple operations.
Run parallel agents
Send independent prompts to different sessions in one sandbox. These tasks inspect the workspace without editing it.
import { Sandbox } from '@tangle-network/sandbox';
const apiKey = process.env.TANGLE_API_KEY;
if (!apiKey) throw new Error('Set TANGLE_API_KEY');
const tangle = new Sandbox({
apiKey,
baseUrl: 'https://sandbox.tangle.tools',
});
const box = await tangle.create({
maxLifetimeSeconds: 900,
});
await box.waitFor('running');
// Sessions can share a workspace; these tasks only inspect it.
const tasks = [
['tools', 'Report Node.js, Python and Git versions. Do not edit files.'],
['workspace', 'List workspace files and package managers. Do not edit files.'],
];
const results = await Promise.all(tasks.map(([sessionId, prompt]) =>
box.prompt(prompt, { sessionId }),
));
for (const [index, result] of results.entries()) {
console.log(tasks[index][0], result.response ?? result.error);
}
await box.delete();Sessions share this sandbox’s files. Use separate sandboxes when concurrent tasks need isolated workspaces.
Run a batch
Set TANGLE_BATCH_JOB_ID to the saved ID of this job.
This example runs each task in a temporary sandbox and returns a combined result.
import { Sandbox } from "@tangle-network/sandbox";
const apiKey = process.env.TANGLE_API_KEY;
if (!apiKey) throw new Error("Set TANGLE_API_KEY");
const client = new Sandbox({
apiKey,
baseUrl: "https://sandbox.tangle.tools",
});
const jobId = process.env.TANGLE_BATCH_JOB_ID;
if (!jobId) throw new Error("Set TANGLE_BATCH_JOB_ID to your saved job ID");
const result = await client.runBatch(
{
tasks: [
{ id: "add", message: "Create a JavaScript addition function and test it." },
{ id: "reverse", message: "Create a JavaScript string reversal function and test it." },
],
backends: [{ id: "worker", type: "opencode" }],
},
{ idempotencyKey: jobId },
);
console.log(result.totalSuccess, result.totalFailure);Batch sandboxes are deleted after the run by default. Select workers from the supported harnesses.
Reuse an idempotencyKey only for the same request body.
A keyed batch continues after a disconnect; repeating the request joins active work or replays a retained result.
Disconnecting an unkeyed batch cancels its server work.
Manage a fleet
Create named workers, run a command across them, and delete the fleet when the work finishes.
import { Sandbox } from "@tangle-network/sandbox";
const apiKey = process.env.TANGLE_API_KEY;
if (!apiKey) throw new Error("Set TANGLE_API_KEY");
const client = new Sandbox({
apiKey,
baseUrl: "https://sandbox.tangle.tools",
});
const fleet = await client.fleets.create({
defaults: { maxLifetimeSeconds: 900 },
machines: [{ machineId: "worker-1" }, { machineId: "worker-2" }],
maxConcurrentCreates: 2,
policy: { maxMachines: 2, maxConcurrentCreates: 2 },
});
const results = await fleet.dispatchExec("node --version", {
machines: fleet.ids,
maxConcurrent: 2,
timeoutMs: 30000,
});
for (const result of results) {
console.log(result.machineId, result.ok, result.error?.message);
}
await fleet.delete();maxConcurrent limits concurrent command dispatches.
Fleet policies constrain provisioning and do not replace account quotas.
Keep the fleet ID when another process needs to inspect or continue the same workers.
For worker selection, mixed harnesses, spending limits, and cleanup, see Fleets.