Agent recipes
Short, task-oriented paths for building an agent harness on inis.run — organised by what you're trying to do, not by API endpoint.
Seven jobs an agent builder is usually trying to get done, each with the real, checked pattern and a link to executable source. If you haven't yet, start with the Quickstart — everything below builds on its create/write/read/destroy shape and its one semantic rule: you destroy the sessions you create, and never the ones you only attach to.
Runnable, tested versions of the patterns below live in
examples/agent-harness
(Python and TypeScript) — read the source, don't retype it from here.
If a coding agent (not your own runtime agent) is doing this integration work for you, point it at the coding-agent skill instead of this page — it routes to the same examples and adapters in a format built for that.
Run model-written code in an isolated sandbox
The base case: hand a session to an agent's tool-calling loop and let it run arbitrary code without touching your own infrastructure.
- Canonical example: Quickstart
- Framework adapters: Pydantic AI, Vercel AI SDK, LangChain / Deep Agents — each keeps the model-facing tool surface to bounded exec/file operations by default; session lifecycle administration (pause/resume/checkpoint/expose) is opt-in, not something the model can reach for on its own.
- Limits: Organisation limits
- Error recovery: Errors
- Cleanup: destroy an owned session in a
finally/withblock, on both the success and the failure path — see the Quickstart's own header for why that's non-negotiable.
Keep state across agent turns
One session per conversation/thread, persisted by ID so any later turn — same process or a different one — can pick it back up.
- Canonical example:
persistent_tool_loopinexamples/agent-harness— a host-side thread-ID-to-session-ID store (never a shared live session object), multiple tool calls in one turn, and a second turn served by a completely separate client proving the filesystem and a running background process both persisted. - Session lifecycle background: Session lifecycle
- Limits: idle timeout / max lifetime knobs, same page
- Error recovery: a
session_not_liveon a live-only call usually just means a wake race — see Errors and retry - Cleanup: destroy the one session a thread owns when its conversation ends, not on every turn
- Don't pre-build a pool of idle live sessions to dodge cold starts — Production best practices covers why the platform's own resume tiers already do that job, and what to check before trusting a connection your code held open across a pause
Explore several branches safely
Fork a session once shared setup is done, run different candidates on the independent children, and grade outside the sandbox.
- Canonical example:
branch_and_evaluateinexamples/agent-harness— uses the realfork(count=…)signature (not ann=kwarg, not an iterable result), proves the concurrency claim with a wall-clock check instead of asserting it, and is explicit that the batch-exec helper is sequential server-side, not a parallelism primitive. - Concepts: Fork
- Why fork instead of one ever-growing conversation: forking clones a live session's filesystem to seed N children cheaply, so exploring several candidates costs a fast, warm clone per branch instead of repeating expensive setup or paying for N sessions live from the start.
- Limits: a hard, account-independent cap of
count<=16per fork call (HardMaxForkCount), and a lower default per-request cap ofcount<=4(DefaultMaxForkCount) unless an account has a raised limit — see the example's own README for how these two are easy to conflate - Error recovery: fork requests fail closed with a specific code per
reason (over either count limit vs. an account's live-session
concurrency cap) — branch on
code, not the message - Cleanup: every forked child is its own independent, independently billed session — destroy each one explicitly, not just the parent
Control or deny egress
Lock a session to an explicit domain allowlist, or block outbound network access entirely, per session or per project/org.
- Canonical guide: Networking & egress — has real, checked Python/TypeScript/CLI samples already; not duplicated here
- Limits: allowlist size cap, same page
- Error recovery: Errors
- Cleanup: n/a — egress policy lives with the session and is torn down with it
Transfer files and artifacts
Get files a session produced out to durable storage with a link that outlives the session, or move files in.
- Canonical guide: Artifacts — real, checked Python/TypeScript/CLI samples already; not duplicated here
- Limits: per-capture size/file-count caps, retention window, same page
- Error recovery: a capture can land
failed; poll and retry - Cleanup: artifacts outlive the session on purpose — delete explicitly when no longer needed, they aren't torn down with it
Cancel or time out work
Bound how long a command can run, or stop something already running.
- Canonical example:
error_recovery_and_limitsinexamples/agent-harness—exec(..., timeout_ms=…)for a hard cap on one command,kill_process()for stopping a named background job on demand from anywhere. Also documents the real gap: there is no separate primitive to cancel an arbitrary in-flightexec()call from a different process — only disconnecting fromexec_stream()cancels a foreground command, and only from the same calling process. True remote cancellation of an unrelated in-flight request is a real product gap, not a docs gap. - Limits: Organisation limits
- Error recovery:
timed_outon the result, not an exception — check it - Cleanup:
kill_processbefore session teardown for a graceful stop;destroy()will SIGKILL everything regardless if you skip it
Recover from a paused, expired, failed, or capacity-limited session
- Canonical example:
error_recovery_and_limitsinexamples/agent-harness— branches onInisError.code/.retryable/.retry_after(never message text) for a 404 (gone), a 400 (invalid request, deterministic against the documented hard fork-count cap), and a 429 (capacity-limited, retryable — demonstrated against a scripted error sequence rather than forcing a real account over its limit). A session stuck instate="failed"is documented as a pattern (poll, readstatus_reason, recreate) rather than shown live — forcing a real provisioning failure on demand isn't something this example does. - Error codes reference: Errors
- Session lifecycle background (pause/resume, wake-on-op, hot/warm/cold): Session lifecycle
- Cleanup: a gone session (404) needs a fresh replacement, not a retry; a
retryable error (429/503) is safe to retry with backoff using the
server's own
retryable/retry_aftersignal