recursive-agent 0.8.3

A Rust coding-agent platform: kernel, tools, multi-agent orchestration, HTTP API, MCP, and TUI
Documentation
name: "Python SDK smoke test"
description: |
  Verify the Python SDK (recursive-sdk) works end-to-end against the
  HTTP server:
    - Agent.create() opens a session
    - agent.send() returns a Run
    - run.wait() returns RunResult with all Phase-A fields populated:
        status, result (concatenated assistant text), num_turns, duration_ms

  Requires python3 + recursive-sdk to be installed in the e2e container.
  The Dockerfile installs the SDK from /sdk/python using pip.
sequential: true

setup:
  - name: "Kill any leftover server on port 9095"
    ignoreError: true
    exec:
      container: recursive-e2e
      command: |
        # Allocate a free port for this suite (host-mode port randomization).
        PORT=$(python3 -c "import socket; s=socket.socket(); s.bind(('',0)); p=s.getsockname()[1]; s.close(); print(p)")
        echo "$PORT" > /tmp/e2e-host-port-20.txt
        echo "suite-port=$PORT"
        export PORT=$(cat /tmp/e2e-host-port-20.txt)
        pkill -f 'recursive.*http --addr' 2>/dev/null || true
        sleep 1
        echo cleaned

  - name: "Reset state files"
    ignoreError: true
    exec:
      container: recursive-e2e
      command: export PORT=$(cat /tmp/e2e-host-port-20.txt); rm -f /tmp/sdk-result.txt /tmp/sdk-http.log && echo reset

  - name: "Start HTTP server on port 9095"
    exec:
      container: recursive-e2e
      command: |
        export PORT=$(cat /tmp/e2e-host-port-20.txt)
        RECURSIVE_HTTP_AUTH_KEYS=test-secret-key nohup recursive \
          --api-base http://aimock:4010/v1 \
          --api-key mock-key -m mock-chat \
          http --addr 0.0.0.0:$PORT \
          > /tmp/sdk-http.log 2>&1 &
        sleep 2
        echo started

  - name: "Sanity: GET /health returns ok"
    exec:
      container: recursive-e2e
      command: export PORT=$(cat /tmp/e2e-host-port-20.txt); curl -sf http://localhost:$PORT/health
    expect:
      exitCode: 0
      output:
        contains: "ok"

  - name: "Run Python SDK test script, save result to /tmp/sdk-result.txt"
    exec:
      container: recursive-e2e
      command: |
        export PORT=$(cat /tmp/e2e-host-port-20.txt)
        python3 - <<'PYEOF' > /tmp/sdk-result.txt
        from recursive_sdk import Agent
        import os
        with Agent.create(base_url='http://localhost:' + os.environ['PORT'], api_key='test-secret-key') as agent:
            run = agent.send('sdk-python-hello')
            result = run.wait()
            print('status=' + str(result.status))
            print('has_result=' + str(result.result is not None))
            print('num_turns=' + str(result.num_turns))
            print('has_duration=' + str(result.duration_ms is not None and result.duration_ms >= 0))
        PYEOF
        cat /tmp/sdk-result.txt
    expect:
      exitCode: 0
      output:
        contains:
          - "status=finished"
          - "has_result=True"

cases:
  - name: "Python SDK RunResult status is finished"
    file:
      container: recursive-e2e
      path: /tmp/sdk-result.txt
      exists: true
      contains: "status=finished"

  - name: "Python SDK RunResult has non-null result field"
    file:
      container: recursive-e2e
      path: /tmp/sdk-result.txt
      exists: true
      contains: "has_result=True"

  - name: "Python SDK RunResult has num_turns >= 1"
    file:
      container: recursive-e2e
      path: /tmp/sdk-result.txt
      exists: true
      contains: "num_turns=1"

  - name: "Python SDK RunResult has duration_ms populated"
    file:
      container: recursive-e2e
      path: /tmp/sdk-result.txt
      exists: true
      contains: "has_duration=True"

teardown:
  - name: "Stop HTTP server on 9095 and clean up"
    ignoreError: true
    exec:
      container: recursive-e2e
      command: |
        export PORT=$(cat /tmp/e2e-host-port-20.txt)
        pkill -f 'recursive.*http --addr' 2>/dev/null || true
        rm -f /tmp/sdk-result.txt /tmp/sdk-http.log
        echo stopped