Skip to content

feat: Agent-to-agent calls timeout at 60s due to Claude Code MCP HTTP limit #104

Description

@vybe

Summary

Agent-to-agent calls via MCP chat_with_agent timeout after 60 seconds regardless of the timeout_seconds parameter. This is caused by Claude Code's hardcoded 60-second MCP HTTP transport timeout. While this is a Claude Code limitation, Trinity could provide better patterns to work around it.

Component

MCP Server / Task Execution Service / Agent Runtime

Priority

P1 - Major feature (agent collaboration) is broken for any task taking >60 seconds

Current Behavior

  1. Agent A calls mcp__trinity__chat_with_agent(agent_name="B", message="...", parallel=true, timeout_seconds=900)
  2. Trinity backend correctly sets 900s timeout and acquires slot with TTL=1200s (timeout + 5min buffer)
  3. Agent B starts processing
  4. After 60 seconds, Claude Code's MCP HTTP client times out the connection
  5. Agent A receives no response (connection dropped)
  6. Agent B may continue executing, but result is lost
  7. Execution shows: Task execution timed out after 60 seconds

Evidence

Slot acquisition logs show the backend received the correct timeout:

[Slots] Agent 'target-agent' acquired slot 1/3 for execution XXX (TTL=360s)

TTL=360s = 60s timeout + 300s buffer, confirming Claude Code passed 60s despite tool schema defaulting to 600s.

Root Cause

Claude Code has a hardcoded 60-second timeout for MCP HTTP tool calls. This is documented in multiple Claude Code GitHub issues:

The MCP tool's timeout_seconds parameter controls backend execution time, but Claude Code kills the HTTP connection after 60s regardless.

Impact

  • Oracle agents cannot query Cornelius (knowledge graph) for complex lookups
  • Any agent-to-agent collaboration requiring >60s reasoning fails
  • Scheduled tasks that delegate to other agents fail silently
  • Users see "timed out after 60 seconds" errors despite configuring longer timeouts

Proposed Solutions

Option 1: Streaming/Chunked Response (Recommended)

Implement streaming responses for the task endpoint that send periodic heartbeats:

# Instead of waiting for full completion, stream progress
async def execute_task_streaming(agent_name, message, timeout_seconds):
    execution_id = start_execution(agent_name, message)
    
    async def stream_progress():
        while not is_complete(execution_id):
            yield f"data: {json.dumps({'status': 'running', 'id': execution_id})}\n\n"
            await asyncio.sleep(5)
        yield f"data: {json.dumps({'status': 'complete', 'result': get_result(execution_id)})}\n\n"
    
    return StreamingResponse(stream_progress(), media_type="text/event-stream")

This may reset Claude Code's timeout on each chunk (needs testing).

Option 2: Async + Polling MCP Tools

Add dedicated MCP tools for async workflow:

// Start execution, return immediately
start_agent_task(agent_name, message) -> { execution_id: string }

// Check status (fast, <1s)
get_execution_status(execution_id) -> { status: "running" | "complete" | "failed" }

// Get result when complete (fast, <1s)  
get_execution_result(execution_id) -> { result: string }

Calling agents would be instructed to poll in their CLAUDE.md:

For long-running agent calls:
1. Call start_agent_task() to get execution_id
2. Loop: sleep 10s, call get_execution_status()
3. When complete, call get_execution_result()

Option 3: Callback Pattern

Allow target agent to call back to source agent with results:

chat_with_agent(
  agent_name: "target",
  message: "...",
  callback_agent: "source",  // NEW: Target calls this agent when done
  callback_message_template: "Result for execution {id}: {result}"
)

Requires bidirectional permissions.

Option 4: Documentation + Guidance

At minimum, document the 60s limitation clearly:

  • In MCP tool descriptions
  • In agent CLAUDE.md templates
  • Recommend async: true + manual polling pattern

Workarounds (Current)

Users can partially work around this by:

  1. Using async: true and manually polling execution status via API
  2. Keeping agent responses under 60 seconds
  3. Using shared files/database for results instead of synchronous calls

Environment

  • Trinity version: 77c88b0 and later
  • Claude Code: Latest (60s limit confirmed in docs)
  • Affects: All agent-to-agent MCP calls via HTTP transport

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions