Skip to main content

Multi-Turn Conversation

Test file: rossoctl/tests/e2e/openshell/test_05_multiturn_conversation.py Tests: 12 | Pass: 9 | Skip: 3 (Kind, fresh cluster)

What This Tests

Validates that agents handle sequential A2A messages with context continuity, isolation between independent conversations, and service persistence across delayed requests.

Architecture Under Test

Test Matrix

Testweather_agentadk_agentclaude_sdk_agentweather_supervisedos_claudeos_opencodeos_generic
3 sequential messages✅ (exec)
Context isolation⏭️ needs A2A
Context continuity⏭️ stateless⏭️ ADK gap⏭️ stateless⏭️ Phase 2
Service persistence

Skip reasons:

  • stateless — Agent doesn't return contextId (Rossoctl backend will manage context externally)
  • ADK gap — ADK to_a2a() doesn't support client-sent contextId (upstream limitation)
  • needs A2A — Supervised agent netns blocks port-forward; ExecSandbox gRPC needed for multi-turn
  • Phase 2 — Requires PVC-backed session store + Rossoctl backend integration
  • — Builtin sandboxes use terminal sessions (persistent by nature), not A2A

Test Details

test_multiturn__agent__responds_to_3_sequential_messages (parametrized: 3 A2A agents)

  • What: Send 3 sequential messages and verify responses
  • Asserts:
    • Each turn has "result" in response
    • Text not empty for each turn
    • contextId extracted and passed to next turn
  • Debug points: Response structure, text length, contextId
  • Agent coverage: weather_agent, adk_agent, claude_sdk_agent
  • Skip condition: LLM agents skip if OPENSHELL_LLM_AVAILABLE != true

test_multiturn__weather_supervised__kubectl_exec

  • What: Supervised agent: test via kubectl exec (netns blocks port-forward)
  • Asserts: exec succeeds, stdout contains "alive"
  • Debug points: exec returncode, stderr
  • Agent coverage: weather_supervised
  • Note: Basic liveness test only; multi-turn requires ExecSandbox gRPC

test_context_isolation__agent__independent_requests_isolated (parametrized: 3 A2A agents)

  • What: Two independent requests should have different contextIds
  • Asserts: contextId from request A != contextId from request B
  • Debug points: contextIds, response text
  • Agent coverage: weather_agent, adk_agent, claude_sdk_agent
  • Skip condition: Agent doesn't return contextId OR LLM not available

test_context_isolation__weather_supervised__netns_blocks_test

  • What: Supervised agent: context isolation test requires A2A
  • Asserts: N/A (always skips)
  • Agent coverage: weather_supervised
  • Skip reason: netns blocks port-forward; TODO: ExecSandbox gRPC integration

test_context_continuity__agent__context_preserved_across_turns (parametrized: 3 A2A agents)

  • What: If agent returns contextId, it should persist across turns
  • Asserts:
    • Turn 1 returns contextId
    • Turn 2 with same contextId returns same or related contextId
  • Debug points: contextId values across turns
  • Agent coverage: weather_agent, adk_agent, claude_sdk_agent
  • Skip condition:
    • Agent is stateless (no contextId)
    • ADK upstream doesn't preserve client-sent contextId
    • TODO: Rossoctl backend session store will manage context externally

test_context_continuity__weather_supervised__requires_grpc

  • What: Supervised agent: context continuity requires ExecSandbox gRPC
  • Asserts: N/A (always skips)
  • Agent coverage: weather_supervised
  • Skip reason: Phase 2 integration needed

test_service_persistence__agent__responds_after_delay (parametrized: 3 A2A agents)

  • What: Send message, wait 10s, send again — agent should still respond
  • Asserts:
    • First request succeeds
    • Second request (after delay) succeeds
  • Debug points: Response text, delay duration
  • Agent coverage: weather_agent, adk_agent, claude_sdk_agent
  • Note: Validates that agents are long-running services (not ephemeral pods)

Context Management Models

Agent TypeContext StoragecontextId SupportFuture State
weather_agentNone (stateless)NoRossoctl backend session store
adk_agentIn-memoryReturns contextId, ignores client'sUpstream PR or backend override
claude_sdk_agentNone (stateless)NoRossoctl backend session store
weather_supervisedNone (stateless)NoBackend + ExecSandbox gRPC
openshell_claudePVC /workspace/.claude/Native (via Claude API)Phase 2 provider integration
openshell_opencodePVC /workspace/Via LiteLLMPhase 2 provider integration

Agent-Specific Prompts

Tests use type-appropriate prompts for each agent:

AGENT_PROMPTS = {
"weather-agent-supervised": [
"What's the weather in Seattle?",
"What about New York?",
"And in Tokyo?",
],
"adk-agent-supervised": [
"Hello, who are you?",
"What can you help with?",
"Thank you!",
],
"claude-sdk-agent": [
"Hello, who are you?",
"What capabilities do you have?",
"Goodbye!",
],
}

Future Expansion

Agent TypeWhen AddedWhat's Needed
openshell_claudePhase 2ExecSandbox gRPC adapter for terminal session → A2A translation
openshell_opencodePhase 2ExecSandbox gRPC adapter for terminal session → A2A translation
Context continuityPhase 2Rossoctl backend session store (PVC-backed PostgreSQL + checkpointer)
ADK contextUpstream PRADK to_a2a() must respect client contextId

Common Failure Modes

SymptomCauseFix
Empty responseAgent initialization delayAdd retry with exponential backoff
contextId changesAgent restarts between turnsAdd PVC-backed checkpointer
Connection refusedPort-forward killedReestablish port-forward between turns
Timeout on turn 3Agent resource exhaustionCheck pod memory/CPU limits