claude CLI subprocess that owns a shell, a working directory, and session files on disk. Hosting it is not like hosting a stateless API wrapper. Every running agent is a long-lived process tied to local state, which shapes how you allocate resources, persist sessions, and scale across tenants.
This page covers self-hosting on your own infrastructure. For deployable Dockerfiles and Kubernetes manifests, see the hosting cookbook.
If you do not need infrastructure control, custom isolation, or your own data plane, consider Managed Agents instead: a hosted REST API where Anthropic runs the agent and the sandbox, so your application sends events and streams back results with no hosting infrastructure to operate.
For security hardening beyond basic sandboxing, including network controls, credential management, and isolation options, see Secure Deployment.
The subprocess model
Every hosting decision on this page follows from how the SDK runs the agent. When your code callsquery(), the SDK spawns a separate claude CLI process and talks to it over stdio. That subprocess owns the shell, the working directory, and the JSONL session transcripts on local disk.
cwd on each query() call when sessions need separate filesystems:
State that lives on local disk
Three kinds of agent state live on the container’s filesystem by default. None of them survive a container restart, a scale-down, or a move to a different node.
To persist transcripts across hosts, configure a
SessionStore adapter. Memory files and other working-directory artifacts need their own storage strategy, such as a mounted volume or an object-store sync.
For how sessions, resumption, and forking work at the API level, see Sessions.
Choose a session pattern
These four patterns cover session lifecycle: how long a container lives relative to the sessions it serves. For where the container runs, the hosting cookbook has deployable code for local Docker, Modal, and Kubernetes. Choose a session pattern here and a deployment target from the cookbook.Ephemeral sessions
Create a container for each user task and destroy it when the task completes. Best for one-off tasks. The user may still interact with the AI while the task is completing, but once completed the container is destroyed. Example workloads include bug investigation and fix, invoice and receipt extraction, document translation, and media transformation. The container runs a one-shot entrypoint that calls the SDK and exits. In TypeScript, save the file asentrypoint.mts or set "type": "module" in package.json so top-level await is available.
Long-running sessions
Run persistent container instances, often hosting multiple SDK processes per container, to serve ongoing work. Best for agents that take autonomous action, serve content, or handle high-volume message streams. Example workloads include an email agent that triages and responds to incoming mail, a site builder that hosts a per-user editable site through container ports, and a chat bot that handles continuous traffic from a platform like Slack. The container exposes an HTTP or WebSocket endpoint and maps each active session to a long-lived query and the subprocess behind it. In TypeScript, usestreamInput() to add turns to an active session and startup() to pre-warm subprocesses ahead of incoming traffic. In Python, use ClaudeSDKClient to hold a session open across turns. Size the container so it can hold the maximum number of concurrent sessions in memory.
Hybrid sessions
Ephemeral containers that hydrate from aSessionStore on startup and persist updates back. Best for sessions that span many interactions but sit idle between them. The container spins down during idle periods and spins back up when the user returns.
Example workloads include a personal project manager with intermittent check-ins, deep research that pauses and resumes over hours, and a customer support agent that loads ticket history across interactions.
Tune your provider’s idle timeout to how frequently you expect users to return. Shutting a container down without a SessionStore configured loses the transcript with it, so the store is required for this pattern, not optional.
The pattern hinges on resuming a session by ID with a shared store attached: