View source on GitHub
- Kubernetes Pod - Container running the agent-server
- Kubernetes Service - Network access to the pod
- Persistent Volume Claim (PVC) - Storage for the workspace files
- Ingress/HTTPRoute - External routing
- ServiceAccount, PodDisruptionBudget - Supporting K8s resources
How It Works
Based on the runtime-api implementation, here’s what happens when you delete a conversation:1. Conversation Deletion (DELETE /api/v1/app-conversations/{conversation_id})
The OpenHands Cloud API:
- Marks the conversation as deleted in the database
- Checks if any other conversations share the same sandbox
- If no other conversations use the sandbox, triggers sandbox cleanup
2. Sandbox Cleanup (Runtime API)
The runtime API’sdelete_runtime_and_workspace_in_k8s() function removes all Kubernetes resources:
- The underlying PersistentVolume (PV) is freed
- Storage quota is released
- Associated costs stop accumulating
3. Resource Lifecycle States
* For standard (non-fuse) runtimes, the PVC persists when stopped to allow resuming. A VolumeSnapshot may be taken before deletion for archival purposes.
Prerequisites
Run It
Quick Start: Complete Workflow Demo
Run the complete workflow example to see the entire process:- Create a new test conversation (provisions sandbox + PVC)
- Show conversation details (sandbox_id, status, etc.)
- Ask for confirmation to archive
- Delete the conversation (releases PVC)
- Verify deletion
Force Immediate PVC Cleanup
If you need to release PVCs immediately without waiting for the cleanup cronjob, use the sandbox DELETE endpoint directly:- Conversation DELETE (
archive_sandbox.py) - Deletes conversation, cleans up sandbox only if no other conversations use it - Sandbox DELETE (
force_cleanup.py) - Forces immediate cleanup of all K8s resources including PVC, regardless of conversation state
stop_runtime() function, which immediately executes delete_runtime_and_workspace_in_k8s(). This bypasses the cleanup cronjob and releases the PVC right away.
When to use force cleanup:
- ✅ You need immediate storage release
- ✅ You’re cleaning up test/development sandboxes
- ✅ You’ve verified no important data remains
- ⚠️ Warning: This deletes the sandbox even if conversations still reference it!
List All Conversations
- Conversation ID
- Title
- Sandbox ID (the runtime ID)
- Status (RUNNING, STOPPED, etc.)
- Cost metrics
Archive a Specific Conversation
- Show conversation details
- Ask for confirmation
- Delete the conversation
- Trigger sandbox cleanup (if no other conversations use it)
- Release the PVC
Bulk Cleanup Stopped Conversations
- Find all stopped conversations
- Show a summary
- Ask for confirmation
- Archive all stopped conversations
- Release their PVCs
Important Concepts
Warm Runtimes and PVC Types
OpenHands supports two types of sandboxes:Standard (PVC-backed)
- PVC provisioned at startup
- Workspace stored on persistent disk
- PVC persists through pause/resume
- Must delete conversation to release PVC
Fuse/Dormant (S3-backed)
- No PVC provisioned
- Workspace stored in S3 via fusey
- Mounted dynamically at claim time
- Fast resume without PVC snapshots
- No PVC cleanup needed - just deletes S3 objects
Cleanup Cronjob
The runtime-api runs a cleanup cronjob (cleanup.py) every 5 minutes that:
- Cleanup stuck PVCs - Removes PVCs that never bound
- Cleanup terminated pods - Removes pods with no DB record
- Pause idle runtimes - Pauses runtimes idle > 30 min (configurable)
- Snapshot and delete idle PVCs - For paused standard runtimes
- Delete old fuse workspaces - Purges S3 objects for stopped fuse runtimes > 30 days
- Delete old runtimes - Removes K8s resources for runtimes stopped > 1 day
Files in This Example
archive_sandbox.py- Main CLI tool for archiving conversationsforce_cleanup.py- Force immediate PVC cleanup by deleting sandbox directlyexample_create_and_archive.py- Complete workflow demonstrationrequirements.txt- Python dependenciesREADME.md- This documentation
Best Practices
When to Archive
✅ Do archive:- Test conversations you no longer need
- Failed or error conversations
- Completed one-off tasks
- Conversations stopped for > 7 days
- Active conversations (status: RUNNING)
- Conversations you plan to resume soon
- Conversations with important work not yet backed up
Before Archiving
- Download important files from the workspace
- Export conversation history if needed (use the download endpoint)
- Check for workspace archives - OpenHands may automatically archive workspaces before pause (see
tags.archiveworkspacepath)
Workspace Archiving (Automatic)
OpenHands can automatically archive workspace contents before pausing/stopping:- Download workspace as tar.gz or git-delta
- Upload to S3 with manifest
- Tag conversation with archive path
- Then delete the PVC
conversation.tags.archiveworkspacepath to see if an archive exists.
Monitoring and Verification
Check Kubernetes Resources
If you have kubectl access to the runtime cluster:Check via API
Example: Full Workflow
Here’s a complete example of creating and archiving a sandbox:Troubleshooting
”Conversation not found” error
The conversation may already be deleted. This is safe to ignore.PVC still exists after deletion
Possible reasons:- Another conversation uses the same sandbox - The sandbox is shared
- Cleanup not yet run - K8s deletion is asynchronous, may take a few seconds
- Kubernetes finalizers - PV/PVC may have finalizers delaying deletion
Can’t delete running conversation
You can delete running conversations - the API will stop them first. However, it’s cleaner to stop them explicitly:Summary
Key Takeaways:- ✅ Two ways to release PVCs:
- Conversation DELETE - Deletes conversation, cleans up sandbox if not shared
- Sandbox DELETE - Force immediate cleanup, always releases PVC
- ✅ No runtime-api access needed - Use enterprise-server API with
OH_API_KEY - ✅ Pausing/Stopping preserves the PVC - For resuming work later
- ✅ Force cleanup for immediate release - Use
force_cleanup.pyto bypass cronjob - ✅ Bulk cleanup available - Archive all stopped conversations/sandboxes at once
- ✅ Automatic workspace archiving - May preserve files before PVC deletion
- ✅ Check before deleting - Download important files first
When in doubt, remember: DELETE sandbox → Immediate PVC release → Storage freed instantly ✨
APIs Used
Enterprise-Server API (OpenHands Cloud)
You can use these endpoints with just yourOH_API_KEY - no direct runtime-api access required:
Key Insight: Both conversation DELETE and sandbox DELETE work through the enterprise-server API. You do NOT need direct runtime-api access to force PVC cleanup!
How It Works
When you callDELETE /api/v1/sandboxes/{sandbox_id}:
- Enterprise-Server validates your API key
- Calls runtime-api’s
/stopendpoint internally - Runtime-api executes
delete_runtime_and_workspace_in_k8s() - PVC is immediately deleted from Kubernetes
Runtime-API Direct Access (Optional)
If you have direct runtime-api access (e.g., via port-forward for testing), you can also use:
However, in production you should use the enterprise-server API (sandbox DELETE) which provides proper authentication, rate limiting, and audit logging.
Related
OpenHands Runtime API
The service managing sandboxes
OpenHands Cloud API Documentation
Full API reference
Kubernetes PVC Documentation
Persistent volume concepts

