CrowNest
Guides

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

Terminal
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

Terminal
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.

Terminal
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

Terminal
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.

On this page