Agent patterns
Recipes for stateful execution, artifacts, retries, and cleanup across MCP, CLI, and SDK surfaces.
CrowNest is built around a live Sandbox, a Workspace at /workspace, and
durable Artifacts for outputs you want to keep. These recipes cover the same
patterns across MCP, CLI, and SDK surfaces.
Stateful code execution
Use Code Runs when you want interpreter state. Variables and imports persist inside a Code Context for later runs in the same Sandbox.
MCP
Call run_code without sandbox_id to lazily create the default Sandbox.
The response includes sandbox_id and, when available, context_id.
run_code({ "code": "x = 40" })
run_code({ "code": "print(x + 2)" })Use get_usage when you need compute, credit, quota, and current MCP
session Sandbox state before continuing.
get_usage({})CLI
SANDBOX=$(crownest sandboxes create --template python --json | jq -r .data.id)
crownest code run "$SANDBOX" --code "x = 40"
crownest code run "$SANDBOX" --code "print(x + 2)"TypeScript SDK
import { createCrowNestClient } from "@crownest/sdk";
const client = createCrowNestClient();
const sandbox = await client.sandboxes.create({ template: "python" });
await sandbox.code.run({ code: "x = 40" });
const result = await sandbox.code.run({ code: "print(x + 2)" });
console.log(result.stdout);Python SDK
from crownest import CrowNest
client = CrowNest()
sandbox = client.sandboxes.create(template="python")
sandbox.code.run("x = 40")
result = sandbox.code.run("print(x + 2)")
print(result["stdout"])Create, run, collect, kill
Use Commands for process execution and Artifacts for durable outputs. Keep
working files under /workspace.
MCP
run_command({ "command": "python3 - <<'PY'\nfrom pathlib import Path\nPath('/workspace/report.txt').write_text('ready')\nPY" })
create_artifact({ "source_path": "/workspace/report.txt", "name": "report.txt" })
list_artifacts({})
kill_sandbox({ "sandbox_id": "sbx_..." })CLI
SANDBOX=$(crownest sandboxes create --template python --json | jq -r .data.id)
crownest commands run "$SANDBOX" -- python3 -c "from pathlib import Path; Path('/workspace/report.txt').write_text('ready')"
crownest artifacts create "$SANDBOX" /workspace/report.txt --name report.txt
crownest sandboxes kill "$SANDBOX"TypeScript SDK
const sandbox = await client.sandboxes.create({ template: "python" });
await sandbox.commands.run(
"python3 -c \"from pathlib import Path; Path('/workspace/report.txt').write_text('ready')\"",
);
const artifact = await sandbox.artifacts.create({
name: "report.txt",
path: "/workspace/report.txt",
});
await sandbox.kill();Python SDK
sandbox = client.sandboxes.create(template="python")
sandbox.commands.run(
"python3 -c \"from pathlib import Path; Path('/workspace/report.txt').write_text('ready')\""
)
artifact = sandbox.artifacts.create(path="/workspace/report.txt", name="report.txt")
sandbox.kill()Retry with idempotency keys
Use idempotency keys for mutating API/SDK calls that may be retried after a network failure. The API stores idempotent replay results for 24 hours.
CLI
The CLI exposes an idempotency key on Code Runs.
crownest code run "$SANDBOX" \
--idempotency-key "agent-step-42" \
--code "print('retry-safe')"TypeScript SDK
await client.sandboxes.create({
idempotencyKey: "agent-sandbox-42",
template: "python",
});
await sandbox.code.run({
code: "print('retry-safe')",
idempotencyKey: "agent-code-42",
});Python SDK
sandbox = client.sandboxes.create(
template="python",
idempotency_key="agent-sandbox-42",
)
sandbox.code.run(
"print('retry-safe')",
idempotency_key="agent-code-42",
)MCP tools do not expose caller-provided idempotency keys. Route replay-sensitive mutating steps through the CLI or SDK.
Cleanup with TTL and kill
Every live Sandbox has a Sandbox TTL. Extending a Sandbox resets its TTL from the call time; it does not pause, persist, or revive expired Sandboxes. Kill Sandboxes explicitly when the work is complete.
MCP
extend_sandbox({ "sandbox_id": "sbx_...", "ttl_ms": 1800000 })
kill_sandbox({ "sandbox_id": "sbx_..." })Sandboxes created by the MCP server are best-effort killed when the MCP
stdio process exits, but explicit kill_sandbox is still the cleanest
handoff.
CLI
crownest sandboxes extend "$SANDBOX" --ttl-ms 1800000
crownest sandboxes kill "$SANDBOX"TypeScript SDK
await sandbox.extend({ ttlMs: 1_800_000 });
await sandbox.kill();Python SDK
sandbox.extend(ttl_ms=1_800_000)
sandbox.kill()Discover the current surface
The Capability matrix maps operations to MCP, CLI,
and SDK surfaces. MCP hosts also receive startup instructions that describe
the lazy default Sandbox, /workspace, Code Run output promotion, usage
discovery, TTL behavior, retry/idempotency routing, and cleanup semantics.