Skip to main content
For the TypeScript examples, use the TypeScript setup, including "type": "module" and the tsx runner. An Agent, a Session handle and a runtime process have different lifetimes. Close the objects you create, and stop a shared runtime only when the application has finished with it.

Handle both forms of failure

Use the quickstart setup with OPENAI_API_KEY. Save this as lifecycle.ts; run node --env-file=.env --import tsx lifecycle.ts.
A provider or run limit can produce an unsuccessful terminal result, so a fulfilled promise is not enough to establish success. Setup, protocol, transport and lifecycle problems may reject instead. The isSdkError guard recognizes tagged SDK errors with kinds such as configuration, binary, transport, protocol, closed and session_conflict. Do not match human-readable messages to make policy decisions.

Share a client intentionally

This separate example owns one local runtime and lends its client to an Agent. No process-global shutdown() is needed for that owned client.
Session.send() returns ResultMessage and takes a single prompt argument in v2. Check subtype; it does not have the facade’s RunResult.isError convenience field. Low-level Session.stream() also has no caller-supplied signal option in v2. Use session.interrupt()/abort() to stop an active turn, or the facade’s Agent.run()/stream() signal support when that fits your application. A default isolated runtime stores state in scratch storage removed when its owner closes. session.close() normally releases the local handle without deleting the server session, but closing the runtime’s owner can remove the entire scratch database. See sessions before designing persistence.

Cancel and finish cleanup

Pass an AbortSignal to Agent.run() or Agent.stream(). For an existing low-level Session, call session.interrupt()/abort() or close its owner. Breaking a for await loop returns the iterator and aborts its owned turn. Abandoning an iterator without returning or aborting it can leave work active. Repeated close() calls are safe. Closing during active work requests cancellation and waits for bounded cleanup. Cleanup itself can fail; an aggregate error can contain multiple underlying failures. The finally chains above ensure the outer owner is still closed if handle cleanup rejects. Call shutdown() once at the boundary where the application no longer needs any default Agent. Do not call it after each HTTP request in a service that has other concurrent default Agents. It does not close clients you constructed and injected yourself.

Retry side effects carefully

A lost connection does not prove a tool did not execute. Before replaying a task, inspect the persisted conversation and your application’s operation state. Add idempotency keys or duplicate detection to custom tools that send messages, charge accounts or modify external services. Configuration/state isolation does not sandbox the host filesystem, subprocesses or network. Custom callbacks execute in your SDK process even when the runtime is isolated or remote. Keep their privileges and cleanup under application control. Custom spawnProcess adapters are an advanced escape hatch: they must implement the documented child-process streams, lifecycle events, kill behavior and exit/signal state. Prefer the bundled spawn path unless your deployment needs a custom process owner.