Skip to main content

Conversation Lifecycle and Human-in-the-Loop

Back to main doc

Conversation Models

OpenShell and Rossoctl support three distinct conversation models. Each agent type uses one or more of these models.

Model 1: Terminal Session (OpenShell native)

  • Agents: openshell_claude, openshell_opencode
  • Context storage: Agent process memory (lost on pod restart)
  • Session persistence: dtach + PVC for workspace files
  • Multi-turn: Natural — continuous terminal I/O

Model 2: A2A Request-Response (Rossoctl native)

  • Agents: weather_agent, adk_agent, claude_sdk_agent
  • Context storage: Rossoctl backend PostgreSQL
  • Session persistence: Database-backed (survives pod restart)
  • Multi-turn: Backend reconstructs context from DB each turn

Model 3: Exec-Based Interaction (Hybrid)

  • Agents: weather_supervised (via kubectl exec), builtin sandboxes (via ExecSandbox gRPC)
  • Context storage: Rossoctl backend PostgreSQL + workspace PVC
  • Session persistence: Backend manages context, PVC preserves files
  • Multi-turn: Backend sends accumulated context with each exec

Current Agent Context Capabilities

AgentContext SourceMulti-TurnPersist Across RestartConversation Model
weather_agentNoneStatelessNoModel 2 (A2A)
adk_agentADK in-memorycontextId returned but not preservedNoModel 2 (A2A)
claude_sdk_agentNoneStatelessNoModel 2 (A2A)
weather_supervisedNoneStatelessNoModel 3 (exec)
openshell_claudeAgent process memoryTerminal sessionWith dtach + --keepModel 1 (terminal)
openshell_opencodeAgent process memoryTerminal sessionWith dtach + --keepModel 1 (terminal)

How to Enable Multi-Turn for Each Agent

A2A Agents (weather, ADK, Claude SDK)

Option A: Backend-managed context (recommended) The Rossoctl backend stores conversation history in PostgreSQL. Each turn, the backend loads the full history and includes it in the A2A request as additional context. The agent itself remains stateless.

# Backend pseudo-code
history = session_db.get_history(session_id)
prompt = f"Previous conversation:\n{history}\n\nNew message: {user_message}"
response = await a2a_send(agent_url, prompt, context_id=session_id)
session_db.append_turn(session_id, user_message, response)

Option B: Agent-side session store Add a PVC to the agent deployment and store conversation state on disk. The agent loads state from disk on each request using a session ID.

Option C: ADK contextId fix Wait for upstream Google ADK to support client-sent contextId in to_a2a(). This would enable native multi-turn without backend involvement.

Builtin Sandboxes (Claude, OpenCode)

Option A: Terminal session (native) The CLI+SSH model provides natural multi-turn. The agent process maintains context in memory. With dtach, the session survives disconnects.

Option B: ExecSandbox + backend context The Rossoctl backend calls ExecSandbox gRPC to send prompts. The backend maintains conversation history in PostgreSQL and reconstructs context for each exec call.

Human-in-the-Loop (HITL) Design

What HITL means in the sandbox context

HITL is when an agent needs human approval before performing a sensitive action. Examples:

  • Agent wants to push code to a git branch → needs approval
  • Agent wants to install a package → needs policy review
  • Agent wants to access a restricted API → needs credential approval
  • Agent wants to delete files → needs confirmation

Current HITL support

LayerHITL SupportHow
OpenShell OPA policyImplicit denyPolicy blocks disallowed actions; agent gets error
OpenShell proxyImplicit denyHTTP CONNECT denied for blocked hosts
Rossoctl UIHitlApprovalCard componentUI component exists for approval workflows
Rossoctl backendSession eventsCan intercept and hold agent actions

HITL Architecture

HITL Levels

LevelDescriptionImplementationPhase
L0: Implicit denyPolicy blocks action, agent gets errorOPA Rego default allow = falseCurrent (PoC)
L1: Log and allowAction allowed, event logged for auditSupervisor proxy + OCSF eventsPhase 2
L2: Async reviewAction allowed, human reviews after the factBackend event stream + UIPhase 2
L3: Sync approvalAction blocked until human approvesProxy hold + gateway webhook + UI cardPhase 3

HITL Use Cases Per Agent

Use Caseweatheradkclaude_sdksupervisedopenshell_claudeopenshell_opencode
Approve LLM callN/AL1L1L1L1L1
Approve external API callN/AL0L0L0/L3L3L3
Approve file writeN/AN/AN/AL0L3L3
Approve git pushN/AN/AN/AN/AL3L3
Approve package installN/AN/AN/AL0L3L3
Budget limit reachedN/AL2L2N/AL2L2

What's needed for each HITL level

LevelComponentsStatus
L0OPA policy + supervisor proxyImplemented in weather_supervised
L1L0 + OCSF event export + OTelRequires supervisor OTLP exporter
L2L1 + backend event ingestion + UI displayRequires backend webhook + EventsPanel
L3L2 + proxy request hold + gateway webhook + HitlApprovalCardRequires upstream OpenShell support for policy REVIEW_REQUIRED decision

E2E Test Use Cases

Multi-Turn Conversation Tests

TestAgentStatusWhat it validates
Sequential messages (3 turns)weather, adk, claude_sdkPASSAgent handles sequential A2A requests
Sequential messages (supervised)weather_supervisedSKIP (netns)exec-based multi-turn
Context isolationweather, adk, claude_sdkPASSIndependent conversations don't share state
Context continuity (agent-side)weather, adk, claude_sdkSKIPAgent doesn't preserve contextId
Context continuity (backend-managed)ALLTODO Phase 2Backend reconstructs context from DB
Conversation survives restartALLSKIP (destructive)Context persists via backend DB

Skill Execution Tests

TestAgentStatusWhat it validates
PR review skilladk, claude_sdkPASSLLM follows skill instructions
RCA skillclaude_sdkPASSLLM applies RCA methodology
Security review skillclaude_sdkPASSLLM identifies vulnerabilities
Real GitHub PR reviewadk, claude_sdkPASSEnd-to-end skill with real data
Native skill executionopenshell_claudeTODO Phase 2Claude reads .claude/skills/ directly
Skill via ExecSandboxopenshell_opencodeTODO Phase 2Backend injects skill into exec prompt
Skill (no LLM agents)weather, supervisedSKIP (by design)N/A

HITL Tests

TestAgentStatusWhat it validates
L0: OPA blocks egressweather_supervisedPASSDisallowed host rejected by proxy
L0: policy deny loggedweather_supervisedTODO Phase 2Deny event appears in logs
L1: LLM call loggedadk, claude_sdkTODO Phase 2Token usage event exported via OTel
L2: budget exceeded eventadk, claude_sdkTODO Phase 2Backend receives budget alert
L3: approve external APIopenshell_claudeTODO Phase 3UI shows approval card, human approves
L3: reject file writeopenshell_claudeTODO Phase 3Agent gets 403 after human rejects

Workspace Persistence Tests

TestAgentStatusWhat it validates
Session written to PVCopenshell generic, claude, opencodePASSData persists on PVC
PVC survives sandbox deletionALL sandbox typesPASSPVC independent of CR
Workspace restore after restartopenshell_*TODO Phase 2Backend loads workspace + DB history
File browser reads PVCopenshell_*TODO Phase 2Rossoctl UI FileBrowser browses PVC