Skip to main content

OpenShell OpenCode Sandbox

Back to agent catalog | main doc

Type: Builtin Sandbox Framework: OpenCode CLI (open-source) LLM: OpenAI-compatible (works with LiteMaaS) Supervisor: Yes (all protection layers active) Sandbox Model: Tier 1 (OpenShell Sandbox CR, full supervisor) Status: Sandbox CR tested, LLM execution investigating (LiteMaaS compatible)

1. Overview

Pre-installed OpenCode CLI in the OpenShell base sandbox image. OpenCode is an open-source, Go-based AI coding agent that supports 75+ AI models via OpenAI-compatible API format. Unlike Claude Code, OpenCode works with LiteMaaS because it uses the standard OpenAI chat/completions format.

Key advantage: OpenCode can run in headless HTTP server mode, making it potentially wrappable as an A2A service without a custom adapter.

2. Architecture

3. Files

# No custom files — uses upstream OpenShell base image
# Image: ghcr.io/nvidia/openshell-community/sandboxes/base:latest (~1.1GB)
# CRD: agents.x-k8s.io/v1alpha1 Sandbox

4. Deployment

Same as openshell-claude — create a Sandbox CR with the base image.

LLM Provider Configuration

kubectl set env statefulset/openshell-gateway -n openshell-system \
OPENAI_API_KEY=<litemass-key> \
OPENAI_BASE_URL=https://litellm-prod.apps.maas.redhatworkshops.io/v1 \
OPENAI_MODEL=llama-scout-17b

5. Capabilities

CapabilitySupportedNotes
A2A protocolNo (but wrappable)Has headless HTTP server mode
Multi-turn contextYesSQLite session storage
Tool callingYes8 built-in tools + MCP servers
Subagent delegationNoSingle-agent architecture
Memory/knowledgePartialSession DB + config files persist
Skill executionVia promptSkill markdown included in prompt
HITL approvalL0-L3Tool permission system

OpenCode-Specific Features

FeatureStorageNotes
Session DB~/.opencode/opencode.db (SQLite)Full conversation history
Config~/.config/opencode/ or .opencode/Provider config, themes
Custom commandscommands/ subdirectoryMarkdown-defined commands
MCP serversConfig fileLocal + remote MCP support
Tool resultsSession DBFile edits, terminal output

OpenCode Headless Modes

ModeCommandUse Case
Direct promptopencode -p "..."Single-turn, non-interactive
JSON outputopencode -p "..." -f jsonMachine-readable response
HTTP serveropencode servePersistent API server
Web serveropencode webBrowser-based interface
Quiet modeopencode -p "..." -qScripting (no spinner)

6. Rossoctl Integration

6.1 Communication Adapter

Three options (in order of preference):

  1. ExecSandbox with -p flag (Phase 2): opencode -p "prompt" -f json Returns structured JSON. Simplest to implement.

  2. OpenCode HTTP server mode (Phase 2+): opencode serve inside the sandbox, Rossoctl backend calls the HTTP API. Supports sessions natively.

  3. A2A wrapper service (Phase 3): Custom Starlette wrapper that translates A2A JSON-RPC to OpenCode HTTP API calls.

6.2 Session Management

DataStorageSurvives Restart?Rossoctl Access
Session history~/.opencode/opencode.db (SQLite)Yes (PVC)Backend reads SQLite
Config~/.config/opencode/Yes (PVC)FileBrowser
Workspace files/sandbox/project/Yes (PVC)FileBrowser
Custom commandscommands/ dirYes (PVC)FileBrowser

6.3 Observable Events

EventSourceRossoctl UI ComponentPhase
Tool calls (edit, bash)Session DB / JSON outputEventsPanelPhase 2
LLM responseJSON output -f jsonAgentChatPhase 2
File modificationsWorkspace PVC diffFileBrowserPhase 2
Session historySQLite DBSessionSidebarPhase 2
MCP tool callsSession DBEventsPanelPhase 3

6.4 FileBrowser Integration

PathContentBrowsablePreview
/sandbox/.opencode/Session DB + configYesSQLite not previewable; config as JSON
/sandbox/.config/opencode/Provider configYesYAML/JSON
/sandbox/project/Agent-modified codeYesFull syntax highlight
/sandbox/commands/Custom commandsYesMarkdown

7. LLM Compatibility

ProviderProtocolWorks?Notes
LiteMaaSOpenAI-compatYesNative format — best candidate for testing
Budget ProxyOpenAI-compatYesVia gateway provider config
OllamaOpenAI-compatYesLocal testing
Anthropic APIClaude messagesYesVia OpenRouter or direct

Key advantage: OpenCode uses OpenAI-compatible format natively. This means it can work with LiteMaaS (llama-scout-17b) without any format conversion. This is the best candidate for testing builtin sandbox skill execution.

8. Policy Configuration

Same as openshell-claude — all supervisor protection layers active in the base image.

9. Skill Execution

OpenCode uses OpenAI-compatible APIs and can route through LiteLLM. The run_opencode_in_sandbox() helper in conftest.py creates a Sandbox CR, injects OPENAI_API_KEY from the litellm-virtual-keys secret, and runs opencode run via kubectl exec.

Supported Skills

SkillTestStatusNotes
PR Reviewtest_pr_review__openshell_opencodePASSVia @ai-sdk/openai-compatible + LiteLLM
RCAtest_rca__openshell_opencodePASSSame provider config
Security Reviewtest_security_review__openshell_opencodePASSSame provider config
Real GitHub PRtest_review_real_github_pr__opencode⏭️ timeoutSandbox creation + large diff exceeds timeout

/v1/responses API — Solved via @ai-sdk/openai-compatible

OpenCode's built-in OpenAI provider calls /v1/responses (Responses API), which non-OpenAI backends (LiteMaaS, Ollama) don't support. The fix is to use the @ai-sdk/openai-compatible provider, which calls /v1/chat/completions instead.

The test helper (conftest.py:run_opencode_in_sandbox) writes an OpenCode config into the sandbox before running:

{
"provider": {
"litellm": {
"npm": "@ai-sdk/openai-compatible",
"options": { "baseURL": "http://litellm-model-proxy.team1.svc:4000/v1" },
"models": { "gpt-4o-mini": {} }
}
}
}

Then runs: opencode run -m litellm/gpt-4o-mini "<prompt>"

Requirements for OpenCode to work:

  1. LiteLLM v1.83.10+ deployed with model aliases
  2. litellm-virtual-keys Secret with api-key in the sandbox namespace
  3. @ai-sdk/openai-compatible config written to $HOME/.config/opencode/config.json
  4. Model name uses litellm/ prefix (routes through the compatible provider)

Sources: OpenCode providers docs, LiteLLM /responses docs

How to Test Manually (When Blocker Is Resolved)

# The conftest helper does this automatically, but for manual testing:

# 1. Create sandbox with OpenCode + LiteLLM credentials
kubectl apply -f - <<EOF
apiVersion: agents.x-k8s.io/v1alpha1
kind: Sandbox
metadata:
name: opencode-test
namespace: team1
spec:
podTemplate:
spec:
containers:
- name: sandbox
image: ghcr.io/nvidia/openshell-community/sandboxes/base:latest
env:
- name: OPENAI_API_KEY
valueFrom:
secretKeyRef:
name: litellm-virtual-keys
key: api-key
- name: OPENAI_BASE_URL
value: "http://litellm-model-proxy.team1.svc.cluster.local:4000/v1"
EOF

# 2. Wait for pod, then exec
kubectl wait -n team1 sandbox/opencode-test --for=jsonpath='{.status.phase}'=Running --timeout=60s
kubectl exec -n team1 sandbox-opencode-test-0 -- \
opencode run -m openai/gpt-4o-mini "Review: def f(x): eval(x)"

Via OpenShell Provider (Once TLS + Ingress Enabled)

openshell provider create --name rossoctl-litellm \
--type generic \
--credential "OPENAI_API_KEY=$(kubectl get secret litellm-virtual-keys \
-n team1 -o jsonpath='{.data.api-key}' | base64 -d)"

openshell sandbox create --name opencode-test \
--provider rossoctl-litellm \
--policy /tmp/policy-litellm.yaml \
--no-auto-providers

# Inside sandbox:
export OPENAI_BASE_URL="http://litellm-model-proxy.team1.svc.cluster.local:4000/v1"
opencode run -m openai/gpt-4o-mini "Review this code for security issues: ..."

10. Testing Status

Test FileTestsPassSkipNotes
test_04_sandbox_lifecycle110Sandbox CR created
test_07_skill_execution532PR review, RCA, security pass; real GH PR + CLI check skip
test_10_workspace_persistence330PVC write + sandbox creation pass

11. Sandbox Deployment Models

ModelSupportedNotes
Mode 1: Rossoctl DeploymentPossibleRun OpenCode HTTP server as a Deployment
Mode 2: Sandbox CRCurrentGateway creates pod from base image
Mode 2 + PVCSupportedWorkspace + session DB persist
Mode 2 + HTTP serverPlannedopencode serve inside sandbox, backend calls API