From c8c5d4d960a031daadcaa2b6eaa2c122d25280d8 Mon Sep 17 00:00:00 2001 From: Roxanne Farhad Date: Wed, 29 Oct 2025 16:58:54 -0400 Subject: [PATCH 01/30] adding the basic workflows --- .github/workflows/agentex-tutorials-test.yml | 29 ++++++ .../build-and-push-tutorial-agent.yml | 88 +++++++++++++++++++ .../00_base/040_other_sdks/project/acp.py | 27 ++---- 3 files changed, 126 insertions(+), 18 deletions(-) create mode 100644 .github/workflows/agentex-tutorials-test.yml diff --git a/.github/workflows/agentex-tutorials-test.yml b/.github/workflows/agentex-tutorials-test.yml new file mode 100644 index 00000000..1639aab9 --- /dev/null +++ b/.github/workflows/agentex-tutorials-test.yml @@ -0,0 +1,29 @@ +name: Test Tutorial Agents + +on: + workflow_dispatch: + +jobs: + test-tutorials: + timeout-minutes: 10 + name: test-tutorials + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install Rye + run: | + curl -sSf https://rye.astral.sh/get | bash + echo "$HOME/.rye/shims" >> $GITHUB_PATH + env: + RYE_VERSION: "0.44.0" + RYE_INSTALL_OPTION: "--yes" + + - name: Bootstrap + run: ./scripts/bootstrap + + - name: Simple validation test + run: | + echo "✅ Tutorial test workflow is working!" + echo "Rye version: $(rye --version)" + echo "Python version: $(python --version)" diff --git a/.github/workflows/build-and-push-tutorial-agent.yml b/.github/workflows/build-and-push-tutorial-agent.yml index 855950da..d2c1d85d 100644 --- a/.github/workflows/build-and-push-tutorial-agent.yml +++ b/.github/workflows/build-and-push-tutorial-agent.yml @@ -24,3 +24,91 @@ on: required: true type: string default: "latest" + +permissions: + contents: read + packages: write + +jobs: + build-and-push-agent: + timeout-minutes: 10 + name: Build Tutorial Agent + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Validate agent path exists + run: | + if [ ! -d "${{ inputs.agent_path }}" ]; then + echo "❌ Error: Agent path '${{ inputs.agent_path }}' does not exist" + exit 1 + fi + echo "✅ Agent path verified: ${{ inputs.agent_path }}" + + - name: Validate manifest.yaml exists + run: | + if [ ! -f "${{ inputs.agent_path }}/manifest.yaml" ]; then + echo "❌ Error: manifest.yaml not found in '${{ inputs.agent_path }}'" + exit 1 + fi + echo "✅ manifest.yaml found" + echo "### Validation Summary" >> $GITHUB_STEP_SUMMARY + echo "- **Agent Path**: ${{ inputs.agent_path }}" >> $GITHUB_STEP_SUMMARY + echo "- **Version Tag**: ${{ inputs.version_tag }}" >> $GITHUB_STEP_SUMMARY + echo "- **Status**: ✅ Validation passed" >> $GITHUB_STEP_SUMMARY + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: "3.12" + + - name: Get latest agentex-sdk version from PyPI + id: get-version + run: | + LATEST_VERSION=$(curl -s https://pypi.org/pypi/agentex-sdk/json | jq -r '.info.version') + echo "Latest agentex-sdk version: $LATEST_VERSION" + echo "AGENTEX_SDK_VERSION=$LATEST_VERSION" >> $GITHUB_ENV + pip install agentex-sdk==$LATEST_VERSION + echo "Installed agentex-sdk version $LATEST_VERSION" + + - name: Generate Image name + id: image-name + run: | + # Remove examples/tutorials/ prefix and replace / with - + AGENT_NAME=$(echo "${{ inputs.agent_path }}" | sed 's|^examples/tutorials/||' | sed 's|/|-|g') + echo "AGENT_NAME=$AGENT_NAME" >> $GITHUB_ENV + echo "agent_name=$AGENT_NAME" >> $GITHUB_OUTPUT + echo "Agent name set to $AGENT_NAME" + + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and Push Agent Image + env: + REGISTRY: ghcr.io + run: | + AGENT_NAME="${{ steps.image-name.outputs.agent_name }}" + VERSION_TAG="${{ inputs.version_tag }}" + REPOSITORY_NAME="${{ github.repository }}/tutorial-agents/${AGENT_NAME}" + FULL_IMAGE="${REGISTRY}/${REPOSITORY_NAME}:${VERSION_TAG}" + + agentex agents build \ + --manifest "${{ inputs.agent_path }}/manifest.yaml" \ + --registry "${REGISTRY}" \ + --tag "${VERSION_TAG}" \ + --platforms "linux/amd64" \ + --repository-name "${REPOSITORY_NAME}" \ + --push + + echo "Successfully built and pushed: ${FULL_IMAGE}" + echo "### Build Complete" >> $GITHUB_STEP_SUMMARY + echo "- **Image**: \`${FULL_IMAGE}\`" >> $GITHUB_STEP_SUMMARY diff --git a/examples/tutorials/10_agentic/00_base/040_other_sdks/project/acp.py b/examples/tutorials/10_agentic/00_base/040_other_sdks/project/acp.py index fb5e4bfa..c833a8d5 100644 --- a/examples/tutorials/10_agentic/00_base/040_other_sdks/project/acp.py +++ b/examples/tutorials/10_agentic/00_base/040_other_sdks/project/acp.py @@ -42,6 +42,7 @@ config=AgenticACPConfig(type="base"), ) + class StateModel(BaseModel): input_list: List[dict] turn_number: int @@ -53,11 +54,7 @@ class StateModel(BaseModel): args=["-y", "@modelcontextprotocol/server-sequential-thinking"], ), StdioServerParameters( - command="uvx", - args=["openai-websearch-mcp"], - env={ - "OPENAI_API_KEY": os.environ.get("OPENAI_API_KEY", "") - } + command="uvx", args=["openai-websearch-mcp"], env={"OPENAI_API_KEY": os.environ.get("OPENAI_API_KEY", "")} ), ] @@ -72,6 +69,7 @@ async def handle_task_create(params: CreateTaskParams): ) await adk.state.create(task_id=params.task.id, agent_id=params.agent.id, state=state) + @acp.on_task_event_send async def handle_event_send(params: SendEventParams): # !!! Warning: Because "Agentic" ACPs are designed to be fully asynchronous, race conditions can occur if parallel events are sent. It is highly recommended to use the "temporal" type in the AgenticACPConfig instead to handle complex use cases. The "base" ACP is only designed to be used for simple use cases and for learning purposes. @@ -85,7 +83,6 @@ async def handle_event_send(params: SendEventParams): if params.event.content.author != "user": raise ValueError(f"Expected user message, got {params.event.content.author}") - # Retrieve the task state. Each event is handled as a new turn, so we need to get the state for the current turn. task_state = await adk.state.get_by_task_and_agent(task_id=params.task.id, agent_id=params.agent.id) if not task_state: @@ -94,12 +91,8 @@ async def handle_event_send(params: SendEventParams): state.turn_number += 1 # Add the new user message to the message history state.input_list.append({"role": "user", "content": params.event.content.content}) - - async with adk.tracing.span( - trace_id=params.task.id, - name=f"Turn {state.turn_number}", - input=state - ) as span: + + async with adk.tracing.span(trace_id=params.task.id, name=f"Turn {state.turn_number}", input=state) as span: # Echo back the user's message so it shows up in the UI. This is not done by default so the agent developer has full control over what is shown to the user. await adk.messages.create( task_id=params.task.id, @@ -156,6 +149,7 @@ async def handle_event_send(params: SendEventParams): if span: span.output = state + @acp.on_task_cancel async def handle_task_cancel(params: CancelTaskParams): """Default task cancel handler""" @@ -173,8 +167,8 @@ async def mcp_server_context(mcp_server_params: list[StdioServerParameters]): servers = [] for params in mcp_server_params: server = MCPServerStdio( - name=f"Server: {params.command}", - params=params.model_dump(), + name=f"Server: {params.command}", + params=params.model_dump(), cache_tools_list=True, client_session_timeout_seconds=60, ) @@ -253,7 +247,6 @@ async def run_openai_agent_with_custom_streaming( try: # Process streaming events with TaskMessage creation async for event in result.stream_events(): - if event.type == "run_item_stream_event": if event.item.type == "tool_call_item": tool_call_item = event.item.raw_item @@ -374,9 +367,7 @@ async def run_openai_agent_with_custom_streaming( if span: span.output = { "new_items": [ - item.raw_item.model_dump() - if isinstance(item.raw_item, BaseModel) - else item.raw_item + item.raw_item.model_dump() if isinstance(item.raw_item, BaseModel) else item.raw_item for item in result.new_items ], "final_output": result.final_output, From 75ac121ea62fc562e6ed2e0b6117a47da404bfa0 Mon Sep 17 00:00:00 2001 From: Roxanne Farhad Date: Wed, 29 Oct 2025 18:19:46 -0400 Subject: [PATCH 02/30] adding a workaround for now --- .github/workflows/agentex-tutorials-test.yml | 48 ++++--- ...all_agentic_tests.sh => run_agent_test.sh} | 126 +++++------------- 2 files changed, 68 insertions(+), 106 deletions(-) rename examples/tutorials/{run_all_agentic_tests.sh => run_agent_test.sh} (70%) diff --git a/.github/workflows/agentex-tutorials-test.yml b/.github/workflows/agentex-tutorials-test.yml index 1639aab9..57934678 100644 --- a/.github/workflows/agentex-tutorials-test.yml +++ b/.github/workflows/agentex-tutorials-test.yml @@ -5,25 +5,41 @@ on: jobs: test-tutorials: - timeout-minutes: 10 - name: test-tutorials + timeout-minutes: 15 + name: test-tutorial-${{ matrix.tutorial }} runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Install Rye + steps: + - name: Install UV run: | - curl -sSf https://rye.astral.sh/get | bash - echo "$HOME/.rye/shims" >> $GITHUB_PATH - env: - RYE_VERSION: "0.44.0" - RYE_INSTALL_OPTION: "--yes" + curl -LsSf https://astral.sh/uv/install.sh | sh + echo "$HOME/.local/bin" >> $GITHUB_PATH - - name: Bootstrap - run: ./scripts/bootstrap + - name: Checkout scale-agentex repo + uses: actions/checkout@v4 + with: + repository: scaleapi/scale-agentex + path: scale-agentex - - name: Simple validation test + - name: Navigate to scale-agentex repo run: | - echo "✅ Tutorial test workflow is working!" - echo "Rye version: $(rye --version)" - echo "Python version: $(python --version)" + cd scale-agentex/agentex + echo "🚀 Starting dependencies (Postgres, Redis, Temporal, MongoDB)..." + + # Start all services except the agentex service + docker compose up + + echo "⏳ Waiting for dependencies to be healthy..." + + # Wait for services to be healthy + for i in {1..30}; do + if docker compose ps | grep -q "healthy"; then + echo "✅ Dependencies are healthy" + break + fi + echo " Attempt $i/30: Waiting for services..." + sleep 5 + done + + # Verify all deps are up + docker compose ps diff --git a/examples/tutorials/run_all_agentic_tests.sh b/examples/tutorials/run_agent_test.sh similarity index 70% rename from examples/tutorials/run_all_agentic_tests.sh rename to examples/tutorials/run_agent_test.sh index f2454263..f546ec3a 100755 --- a/examples/tutorials/run_all_agentic_tests.sh +++ b/examples/tutorials/run_agent_test.sh @@ -1,16 +1,14 @@ #!/bin/bash # -# Run all agentic tutorial tests +# Run a single agent tutorial test # -# This script runs the test runner for all agentic tutorials in sequence. -# It stops at the first failure unless --continue-on-error is specified. +# This script runs the test for a single agent tutorial. +# It starts the agent, runs tests against it, then stops the agent. # # Usage: -# ./run_all_agentic_tests.sh # Run all tutorials -# ./run_all_agentic_tests.sh --continue-on-error # Run all, continue on error -# ./run_all_agentic_tests.sh # Run single tutorial -# ./run_all_agentic_tests.sh --view-logs # View most recent agent logs -# ./run_all_agentic_tests.sh --view-logs # View logs for specific tutorial +# ./run_agent_test.sh # Run single tutorial test +# ./run_agent_test.sh --view-logs # View logs for specific tutorial +# ./run_agent_test.sh --view-logs # View most recent agent logs # set -e # Exit on error @@ -28,44 +26,17 @@ AGENT_PORT=8000 AGENTEX_SERVER_PORT=5003 # Parse arguments -CONTINUE_ON_ERROR=false -SINGLE_TUTORIAL="" +TUTORIAL_PATH="" VIEW_LOGS=false for arg in "$@"; do - if [[ "$arg" == "--continue-on-error" ]]; then - CONTINUE_ON_ERROR=true - elif [[ "$arg" == "--view-logs" ]]; then + if [[ "$arg" == "--view-logs" ]]; then VIEW_LOGS=true else - SINGLE_TUTORIAL="$arg" + TUTORIAL_PATH="$arg" fi done -# Find all agentic tutorial directories -ALL_TUTORIALS=( - # sync tutorials - "00_sync/000_hello_acp" - "00_sync/010_multiturn" - "00_sync/020_streaming" - # base tutorials - "10_agentic/00_base/000_hello_acp" - "10_agentic/00_base/010_multiturn" - "10_agentic/00_base/020_streaming" - "10_agentic/00_base/030_tracing" - "10_agentic/00_base/040_other_sdks" - "10_agentic/00_base/080_batch_events" -# "10_agentic/00_base/090_multi_agent_non_temporal" This will require its own version of this - # temporal tutorials - "10_agentic/10_temporal/000_hello_acp" - "10_agentic/10_temporal/010_agent_chat" - "10_agentic/10_temporal/020_state_machine" -) - -PASSED=0 -FAILED=0 -FAILED_TESTS=() - # Function to check prerequisites for running this test suite check_prerequisites() { # Check that we are in the examples/tutorials directory @@ -280,8 +251,6 @@ execute_tutorial_test() { # Start the agent if ! start_agent "$tutorial"; then echo -e "${RED}❌ FAILED to start agent: $tutorial${NC}" - ((FAILED++)) - FAILED_TESTS+=("$tutorial") return 1 fi @@ -289,12 +258,9 @@ execute_tutorial_test() { local test_passed=false if run_test "$tutorial"; then echo -e "${GREEN}✅ PASSED: $tutorial${NC}" - ((PASSED++)) test_passed=true else echo -e "${RED}❌ FAILED: $tutorial${NC}" - ((FAILED++)) - FAILED_TESTS+=("$tutorial") fi # Stop the agent @@ -313,23 +279,30 @@ execute_tutorial_test() { main() { # Handle --view-logs flag if [ "$VIEW_LOGS" = true ]; then - if [[ -n "$SINGLE_TUTORIAL" ]]; then - view_agent_logs "$SINGLE_TUTORIAL" + if [[ -n "$TUTORIAL_PATH" ]]; then + view_agent_logs "$TUTORIAL_PATH" else view_agent_logs fi exit 0 fi - echo "================================================================================" - if [[ -n "$SINGLE_TUTORIAL" ]]; then - echo "Running Single Tutorial Test: $SINGLE_TUTORIAL" - else - echo "Running All Agentic Tutorial Tests" - if [ "$CONTINUE_ON_ERROR" = true ]; then - echo -e "${YELLOW}⚠️ Running in continue-on-error mode${NC}" - fi + # Require tutorial path + if [[ -z "$TUTORIAL_PATH" ]]; then + echo -e "${RED}❌ Error: Tutorial path is required${NC}" + echo "" + echo "Usage:" + echo " ./run_agent_test.sh # Run single tutorial test" + echo " ./run_agent_test.sh --view-logs # View logs for specific tutorial" + echo " ./run_agent_test.sh --view-logs # View most recent agent logs" + echo "" + echo "Example:" + echo " ./run_agent_test.sh 00_sync/000_hello_acp" + exit 1 fi + + echo "================================================================================" + echo "Running Tutorial Test: $TUTORIAL_PATH" echo "================================================================================" echo "" @@ -338,46 +311,19 @@ main() { echo "" - # Determine which tutorials to run - if [[ -n "$SINGLE_TUTORIAL" ]]; then - TUTORIALS=("$SINGLE_TUTORIAL") - else - TUTORIALS=("${ALL_TUTORIALS[@]}") - fi - - # Iterate over tutorials - for tutorial in "${TUTORIALS[@]}"; do - execute_tutorial_test "$tutorial" - - # Exit early if in fail-fast mode - if [ "$CONTINUE_ON_ERROR" = false ] && [ $FAILED -gt 0 ]; then - echo "" - echo -e "${RED}Stopping due to test failure. Use --continue-on-error to continue.${NC}" - exit 1 - fi - done - - # Print summary - echo "" - echo "================================================================================" - echo "Test Summary" - echo "================================================================================" - echo -e "Total: $((PASSED + FAILED))" - echo -e "${GREEN}Passed: $PASSED${NC}" - echo -e "${RED}Failed: $FAILED${NC}" - echo "" - - if [ $FAILED -gt 0 ]; then - echo "Failed tests:" - for test in "${FAILED_TESTS[@]}"; do - echo -e " ${RED}✗${NC} $test" - done + # Execute the single tutorial test + if execute_tutorial_test "$TUTORIAL_PATH"; then echo "" - exit 1 + echo "================================================================================" + echo -e "${GREEN}🎉 Test passed for: $TUTORIAL_PATH${NC}" + echo "================================================================================" + exit 0 else - echo -e "${GREEN}🎉 All tests passed!${NC}" echo "" - exit 0 + echo "================================================================================" + echo -e "${RED}❌ Test failed for: $TUTORIAL_PATH${NC}" + echo "================================================================================" + exit 1 fi } From 8f51022bcbe9854ec77f280a17a6abe13c8a44d7 Mon Sep 17 00:00:00 2001 From: Roxanne Farhad Date: Wed, 29 Oct 2025 18:25:54 -0400 Subject: [PATCH 03/30] adding this part of the pipeline --- .github/workflows/agentex-tutorials-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/agentex-tutorials-test.yml b/.github/workflows/agentex-tutorials-test.yml index 57934678..bb519157 100644 --- a/.github/workflows/agentex-tutorials-test.yml +++ b/.github/workflows/agentex-tutorials-test.yml @@ -27,7 +27,7 @@ jobs: echo "🚀 Starting dependencies (Postgres, Redis, Temporal, MongoDB)..." # Start all services except the agentex service - docker compose up + docker compose up -d echo "⏳ Waiting for dependencies to be healthy..." From 54996c23d91d87404e70c82ab524989d3a29d43e Mon Sep 17 00:00:00 2001 From: Roxanne Farhad Date: Wed, 29 Oct 2025 18:37:39 -0400 Subject: [PATCH 04/30] adding the test running part --- .github/workflows/agentex-tutorials-test.yml | 114 +++++++++++++++++++ examples/tutorials/run_agent_test.sh | 72 +++++++++++- requirements-dev.lock | 34 +++--- requirements.lock | 33 +++--- 4 files changed, 216 insertions(+), 37 deletions(-) diff --git a/.github/workflows/agentex-tutorials-test.yml b/.github/workflows/agentex-tutorials-test.yml index bb519157..43e938b6 100644 --- a/.github/workflows/agentex-tutorials-test.yml +++ b/.github/workflows/agentex-tutorials-test.yml @@ -10,11 +10,22 @@ jobs: runs-on: ubuntu-latest steps: + - name: Checkout agentex-python repo + uses: actions/checkout@v4 + - name: Install UV run: | curl -LsSf https://astral.sh/uv/install.sh | sh echo "$HOME/.local/bin" >> $GITHUB_PATH + - name: Install Rye + run: | + curl -sSf https://rye.astral.sh/get | bash + echo "$HOME/.rye/shims" >> $GITHUB_PATH + env: + RYE_VERSION: "0.44.0" + RYE_INSTALL_OPTION: "--yes" + - name: Checkout scale-agentex repo uses: actions/checkout@v4 with: @@ -43,3 +54,106 @@ jobs: # Verify all deps are up docker compose ps + + - name: Run Parallel Tutorial Tests + working-directory: ./examples/tutorials + run: | + + # Find all tutorial directories + tutorial_paths=() + for dir in $(find . -name "manifest.yaml" -exec dirname {} \; | sort); do + tutorial_paths+=("${dir#./}") # Remove leading ./ + done + + echo "Found ${#tutorial_paths[@]} tutorials:" + printf ' %s\n' "${tutorial_paths[@]}" + + # Run tests in parallel with unique ports + pids=() + failed_tests=() + passed_tests=() + + for i in "${!tutorial_paths[@]}"; do + tutorial="${tutorial_paths[$i]}" + port=$((8000 + i)) + + echo "" + echo "=========================================" + echo "Starting test $((i+1))/${#tutorial_paths[@]}: $tutorial (port $port)" + echo "=========================================" + + # Modify manifest.yaml to use unique port + manifest_path="$tutorial/manifest.yaml" + if [ -f "$manifest_path" ]; then + # Backup original manifest + cp "$manifest_path" "$manifest_path.backup" + + # Update port in manifest (modify the line containing 'port: 8000' or 'port: XXXX') + sed -i "s/port: [0-9]*/port: $port/" "$manifest_path" + + echo "Updated $manifest_path to use port $port" + fi + + # Run test in background with unique port + ( + AGENTEX_API_BASE_URL="http://localhost:5003" \ + ./run_agent_test.sh --build-cli "$tutorial" + + if [ $? -eq 0 ]; then + echo "✅ PASSED: $tutorial (port $port)" + echo "$tutorial" > "/tmp/passed_$i.txt" + else + echo "❌ FAILED: $tutorial (port $port)" + echo "$tutorial" > "/tmp/failed_$i.txt" + fi + ) & + + pids+=($!) + done + + # Wait for all tests to complete + echo "" + echo "Waiting for all tests to complete..." + for pid in "${pids[@]}"; do + wait "$pid" + done + + # Restore all original manifests + echo "" + echo "Restoring original manifest files..." + for tutorial in "${tutorial_paths[@]}"; do + if [ -f "$tutorial/manifest.yaml.backup" ]; then + mv "$tutorial/manifest.yaml.backup" "$tutorial/manifest.yaml" + echo "Restored $tutorial/manifest.yaml" + fi + done + + # Collect results + for i in "${!tutorial_paths[@]}"; do + if [ -f "/tmp/passed_$i.txt" ]; then + passed_tests+=($(cat "/tmp/passed_$i.txt")) + elif [ -f "/tmp/failed_$i.txt" ]; then + failed_tests+=($(cat "/tmp/failed_$i.txt")) + fi + done + + # Print summary + echo "" + echo "=========================================" + echo "TEST SUMMARY" + echo "=========================================" + echo "Total: ${#tutorial_paths[@]}" + echo "Passed: ${#passed_tests[@]}" + echo "Failed: ${#failed_tests[@]}" + + if [ ${#failed_tests[@]} -gt 0 ]; then + echo "" + echo "Failed tests:" + for test in "${failed_tests[@]}"; do + echo " ❌ $test" + done + exit 1 + else + echo "" + echo "🎉 All tests passed!" + fi diff --git a/examples/tutorials/run_agent_test.sh b/examples/tutorials/run_agent_test.sh index f546ec3a..cf272822 100755 --- a/examples/tutorials/run_agent_test.sh +++ b/examples/tutorials/run_agent_test.sh @@ -7,6 +7,7 @@ # # Usage: # ./run_agent_test.sh # Run single tutorial test +# ./run_agent_test.sh --build-cli # Build CLI from source and run test # ./run_agent_test.sh --view-logs # View logs for specific tutorial # ./run_agent_test.sh --view-logs # View most recent agent logs # @@ -28,10 +29,13 @@ AGENTEX_SERVER_PORT=5003 # Parse arguments TUTORIAL_PATH="" VIEW_LOGS=false +BUILD_CLI=false for arg in "$@"; do if [[ "$arg" == "--view-logs" ]]; then VIEW_LOGS=true + elif [[ "$arg" == "--build-cli" ]]; then + BUILD_CLI=true else TUTORIAL_PATH="$arg" fi @@ -105,7 +109,8 @@ start_agent() { cd "$tutorial_path" || return 1 # Start the agent in background and capture PID - uv run agentex agents run --manifest manifest.yaml > "$logfile" 2>&1 & + local agentex_cmd=$(get_agentex_command) + $agentex_cmd agents run --manifest manifest.yaml > "$logfile" 2>&1 & local pid=$! # Return to original directory @@ -275,6 +280,58 @@ execute_tutorial_test() { fi } +# Function to build CLI from source +build_cli() { + echo -e "${YELLOW}🔨 Building CLI from source...${NC}" + + # Navigate to the repo root (two levels up from examples/tutorials) + local repo_root="../../" + local original_dir="$PWD" + + cd "$repo_root" || { + echo -e "${RED}❌ Failed to navigate to repo root${NC}" + return 1 + } + + # Check if rye is available + if ! command -v rye &> /dev/null; then + echo -e "${RED}❌ rye is required to build the CLI${NC}" + echo "Please install rye: curl -sSf https://rye.astral.sh/get | bash" + cd "$original_dir" + return 1 + fi + + # Build the CLI + echo -e "${YELLOW}Running rye sync --all-features...${NC}" + if ! rye sync --all-features; then + echo -e "${RED}❌ Failed to sync dependencies${NC}" + cd "$original_dir" + return 1 + fi + + echo -e "${YELLOW}Running rye build...${NC}" + if ! rye build; then + echo -e "${RED}❌ Failed to build package${NC}" + cd "$original_dir" + return 1 + fi + + echo -e "${GREEN}✅ CLI built successfully${NC}" + cd "$original_dir" + return 0 +} + +# Function to get the appropriate agentex command +get_agentex_command() { + if [ "$BUILD_CLI" = true ]; then + # Use the local build via rye run from repo root + echo "../../rye run agentex" + else + # Use the system-installed version + echo "uv run agentex" + fi +} + # Main execution function main() { # Handle --view-logs flag @@ -293,11 +350,13 @@ main() { echo "" echo "Usage:" echo " ./run_agent_test.sh # Run single tutorial test" + echo " ./run_agent_test.sh --build-cli # Build CLI from source and run test" echo " ./run_agent_test.sh --view-logs # View logs for specific tutorial" echo " ./run_agent_test.sh --view-logs # View most recent agent logs" echo "" - echo "Example:" + echo "Examples:" echo " ./run_agent_test.sh 00_sync/000_hello_acp" + echo " ./run_agent_test.sh --build-cli 00_sync/000_hello_acp" exit 1 fi @@ -311,6 +370,15 @@ main() { echo "" + # Build CLI if requested + if [ "$BUILD_CLI" = true ]; then + if ! build_cli; then + echo -e "${RED}❌ Failed to build CLI from source${NC}" + exit 1 + fi + echo "" + fi + # Execute the single tutorial test if execute_tutorial_test "$TUTORIAL_PATH"; then echo "" diff --git a/requirements-dev.lock b/requirements-dev.lock index a282ef7f..6cc2787b 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -113,9 +113,9 @@ httpx==0.27.2 # via mcp # via openai # via respx -httpx-aiohttp==0.1.9 # via scale-gp # via scale-gp-beta +httpx-aiohttp==0.1.9 # via agentex-sdk httpx-sse==0.4.1 # via mcp @@ -219,20 +219,6 @@ prompt-toolkit==3.0.51 propcache==0.3.1 # via aiohttp # via yarl -pydantic==2.11.9 - # via agentex-sdk - # via agentex-sdk - # via fastapi - # via litellm - # via mcp - # via openai - # via openai-agents - # via pydantic-settings - # via python-on-whales - # via scale-gp - # via scale-gp-beta -pydantic-core==2.33.2 - # via pydantic protobuf==5.29.5 # via ddtrace # via temporalio @@ -247,6 +233,19 @@ pyasn1==0.6.1 # via rsa pyasn1-modules==0.4.2 # via google-auth +pydantic==2.11.9 + # via agentex-sdk + # via fastapi + # via litellm + # via mcp + # via openai + # via openai-agents + # via pydantic-settings + # via python-on-whales + # via scale-gp + # via scale-gp-beta +pydantic-core==2.33.2 + # via pydantic pydantic-settings==2.10.1 # via mcp pygments==2.18.0 @@ -383,9 +382,6 @@ typing-extensions==4.12.2 # via pydantic # via pydantic-core # via pyright - # via typing-inspection -typing-inspection==0.4.1 - # via pydantic # via python-on-whales # via referencing # via scale-gp @@ -393,6 +389,8 @@ typing-inspection==0.4.1 # via temporalio # via typer # via typing-inspection +typing-inspection==0.4.1 + # via pydantic # via pydantic-settings tzdata==2025.2 # via agentex-sdk diff --git a/requirements.lock b/requirements.lock index 81d91576..e5070bc3 100644 --- a/requirements.lock +++ b/requirements.lock @@ -99,12 +99,12 @@ httpcore==1.0.9 httpx==0.27.2 # via agentex-sdk # via httpx-aiohttp -httpx-aiohttp==0.1.9 # via litellm # via mcp # via openai # via scale-gp # via scale-gp-beta +httpx-aiohttp==0.1.9 # via agentex-sdk httpx-sse==0.4.1 # via mcp @@ -200,19 +200,6 @@ prompt-toolkit==3.0.51 propcache==0.3.1 # via aiohttp # via yarl -pydantic==2.11.9 - # via agentex-sdk - # via fastapi - # via litellm - # via mcp - # via openai - # via openai-agents - # via pydantic-settings - # via python-on-whales - # via scale-gp - # via scale-gp-beta -pydantic-core==2.33.2 - # via pydantic protobuf==5.29.5 # via ddtrace # via temporalio @@ -227,6 +214,19 @@ pyasn1==0.6.1 # via rsa pyasn1-modules==0.4.2 # via google-auth +pydantic==2.11.9 + # via agentex-sdk + # via fastapi + # via litellm + # via mcp + # via openai + # via openai-agents + # via pydantic-settings + # via python-on-whales + # via scale-gp + # via scale-gp-beta +pydantic-core==2.33.2 + # via pydantic pydantic-settings==2.10.1 # via mcp pygments==2.19.2 @@ -351,9 +351,6 @@ typing-extensions==4.12.2 # via opentelemetry-api # via pydantic # via pydantic-core - # via typing-inspection -typing-inspection==0.4.1 - # via pydantic # via python-on-whales # via referencing # via scale-gp @@ -361,6 +358,8 @@ typing-inspection==0.4.1 # via temporalio # via typer # via typing-inspection +typing-inspection==0.4.1 + # via pydantic # via pydantic-settings tzdata==2025.2 # via agentex-sdk From bd1a1290b44c1ece45c633bc4bf72f5e1e28a9a7 Mon Sep 17 00:00:00 2001 From: Roxanne Farhad Date: Thu, 30 Oct 2025 13:15:35 -0400 Subject: [PATCH 05/30] show logs if the agent test times out --- examples/tutorials/run_agent_test.sh | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/examples/tutorials/run_agent_test.sh b/examples/tutorials/run_agent_test.sh index cf272822..b515d723 100755 --- a/examples/tutorials/run_agent_test.sh +++ b/examples/tutorials/run_agent_test.sh @@ -78,7 +78,14 @@ wait_for_agent_ready() { done echo -e "${RED}❌ Timeout waiting for ${name} agent to be ready${NC}" - echo "Check logs: tail -f $logfile" + echo -e "${YELLOW}📋 Agent logs:${NC}" + if [[ -f "$logfile" ]]; then + echo "----------------------------------------" + tail -50 "$logfile" + echo "----------------------------------------" + else + echo "❌ Log file not found: $logfile" + fi return 1 } From 2446a363cd228d03e7f1fe6e5e8ab5e1a19023a5 Mon Sep 17 00:00:00 2001 From: Roxanne Farhad Date: Fri, 31 Oct 2025 15:17:16 -0400 Subject: [PATCH 06/30] fixing this pipeline --- examples/tutorials/run_agent_test.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/tutorials/run_agent_test.sh b/examples/tutorials/run_agent_test.sh index b515d723..6763475f 100755 --- a/examples/tutorials/run_agent_test.sh +++ b/examples/tutorials/run_agent_test.sh @@ -331,8 +331,8 @@ build_cli() { # Function to get the appropriate agentex command get_agentex_command() { if [ "$BUILD_CLI" = true ]; then - # Use the local build via rye run from repo root - echo "../../rye run agentex" + # Use the local build via rye run (rye is in PATH) + echo "rye run agentex" else # Use the system-installed version echo "uv run agentex" From e10ad36f4fc3233e7a594255a960bc02fc177764 Mon Sep 17 00:00:00 2001 From: Roxanne Farhad Date: Sun, 2 Nov 2025 10:37:51 -0500 Subject: [PATCH 07/30] fixing the rye issue --- .github/workflows/agentex-tutorials-test.yml | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/.github/workflows/agentex-tutorials-test.yml b/.github/workflows/agentex-tutorials-test.yml index 43e938b6..15a553a7 100644 --- a/.github/workflows/agentex-tutorials-test.yml +++ b/.github/workflows/agentex-tutorials-test.yml @@ -21,7 +21,13 @@ jobs: - name: Install Rye run: | curl -sSf https://rye.astral.sh/get | bash + # Source the rye environment as recommended by the installer + source "$HOME/.rye/env" + # Add to PATH for subsequent steps echo "$HOME/.rye/shims" >> $GITHUB_PATH + # Verify installation + which rye + rye --version env: RYE_VERSION: "0.44.0" RYE_INSTALL_OPTION: "--yes" @@ -58,6 +64,12 @@ jobs: - name: Run Parallel Tutorial Tests working-directory: ./examples/tutorials run: | + # Ensure rye is available (source the environment from previous step) + source "$HOME/.rye/env" + + # Verify rye is working + echo "Rye version: $(rye --version)" + echo "Rye path: $(which rye)" # Find all tutorial directories tutorial_paths=() @@ -73,7 +85,8 @@ jobs: failed_tests=() passed_tests=() - for i in "${!tutorial_paths[@]}"; do + # Run only the first test for sanity check + for i in 0; do tutorial="${tutorial_paths[$i]}" port=$((8000 + i)) From 7e69b1a2c0600341b0897822541cc7a790569698 Mon Sep 17 00:00:00 2001 From: Roxanne Farhad Date: Sun, 2 Nov 2025 11:15:14 -0500 Subject: [PATCH 08/30] debug pipeline --- examples/tutorials/run_agent_test.sh | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/examples/tutorials/run_agent_test.sh b/examples/tutorials/run_agent_test.sh index 6763475f..1e266ef8 100755 --- a/examples/tutorials/run_agent_test.sh +++ b/examples/tutorials/run_agent_test.sh @@ -115,6 +115,30 @@ start_agent() { # Change to tutorial directory cd "$tutorial_path" || return 1 + # Debug current directory and virtualenv status + echo -e "${YELLOW}DEBUG: Current directory: $PWD${NC}" + echo -e "${YELLOW}DEBUG: Tutorial path: $tutorial_path${NC}" + + # Check if .venv exists + echo -e "${YELLOW}DEBUG: Tutorial .venv contents:${NC}" + if [ -d ".venv" ]; then + ls -la .venv/ || echo "Cannot list .venv contents" + else + echo "No .venv directory found" + fi + + # Check what packages are available in rye context + echo -e "${YELLOW}DEBUG: Available packages in tutorial rye context:${NC}" + rye run pip list 2>/dev/null || echo "Cannot list packages" + + # Specifically check for agentex-sdk + echo -e "${YELLOW}DEBUG: Checking for agentex-sdk:${NC}" + rye run pip show agentex-sdk 2>/dev/null || echo "agentex-sdk not found in virtualenv" + + # Show rye project status + echo -e "${YELLOW}DEBUG: Rye show output:${NC}" + rye show 2>/dev/null || echo "No rye project detected" + # Start the agent in background and capture PID local agentex_cmd=$(get_agentex_command) $agentex_cmd agents run --manifest manifest.yaml > "$logfile" 2>&1 & From fcb8313a78641311ce14e4e1a78cee95d68773fe Mon Sep 17 00:00:00 2001 From: Roxanne Farhad Date: Sun, 2 Nov 2025 12:16:11 -0500 Subject: [PATCH 09/30] another way --- .github/workflows/agentex-tutorials-test.yml | 30 ++---- examples/tutorials/run_agent_test.sh | 97 +++++++++----------- uv.lock | 12 +-- 3 files changed, 58 insertions(+), 81 deletions(-) diff --git a/.github/workflows/agentex-tutorials-test.yml b/.github/workflows/agentex-tutorials-test.yml index 15a553a7..8941b1ca 100644 --- a/.github/workflows/agentex-tutorials-test.yml +++ b/.github/workflows/agentex-tutorials-test.yml @@ -18,20 +18,6 @@ jobs: curl -LsSf https://astral.sh/uv/install.sh | sh echo "$HOME/.local/bin" >> $GITHUB_PATH - - name: Install Rye - run: | - curl -sSf https://rye.astral.sh/get | bash - # Source the rye environment as recommended by the installer - source "$HOME/.rye/env" - # Add to PATH for subsequent steps - echo "$HOME/.rye/shims" >> $GITHUB_PATH - # Verify installation - which rye - rye --version - env: - RYE_VERSION: "0.44.0" - RYE_INSTALL_OPTION: "--yes" - - name: Checkout scale-agentex repo uses: actions/checkout@v4 with: @@ -61,15 +47,19 @@ jobs: # Verify all deps are up docker compose ps + - name: Build AgentEx SDK + run: | + echo "🔨 Building AgentEx SDK wheel..." + uv build + echo "✅ SDK built successfully" + ls -la dist/ + - name: Run Parallel Tutorial Tests working-directory: ./examples/tutorials run: | - # Ensure rye is available (source the environment from previous step) - source "$HOME/.rye/env" - - # Verify rye is working - echo "Rye version: $(rye --version)" - echo "Rye path: $(which rye)" + # Verify uv is working + echo "UV version: $(uv --version)" + echo "UV path: $(which uv)" # Find all tutorial directories tutorial_paths=() diff --git a/examples/tutorials/run_agent_test.sh b/examples/tutorials/run_agent_test.sh index 1e266ef8..2cb5d9c3 100755 --- a/examples/tutorials/run_agent_test.sh +++ b/examples/tutorials/run_agent_test.sh @@ -115,33 +115,33 @@ start_agent() { # Change to tutorial directory cd "$tutorial_path" || return 1 - # Debug current directory and virtualenv status - echo -e "${YELLOW}DEBUG: Current directory: $PWD${NC}" - echo -e "${YELLOW}DEBUG: Tutorial path: $tutorial_path${NC}" - - # Check if .venv exists - echo -e "${YELLOW}DEBUG: Tutorial .venv contents:${NC}" - if [ -d ".venv" ]; then - ls -la .venv/ || echo "Cannot list .venv contents" - else - echo "No .venv directory found" - fi - - # Check what packages are available in rye context - echo -e "${YELLOW}DEBUG: Available packages in tutorial rye context:${NC}" - rye run pip list 2>/dev/null || echo "Cannot list packages" + # Start the agent in background and capture PID + local manifest_path="$PWD/manifest.yaml" # Always use full path - # Specifically check for agentex-sdk - echo -e "${YELLOW}DEBUG: Checking for agentex-sdk:${NC}" - rye run pip show agentex-sdk 2>/dev/null || echo "agentex-sdk not found in virtualenv" + echo -e "${YELLOW}DEBUG: Manifest path: $manifest_path${NC}" + echo -e "${YELLOW}DEBUG: Log file: $logfile${NC}" - # Show rye project status - echo -e "${YELLOW}DEBUG: Rye show output:${NC}" - rye show 2>/dev/null || echo "No rye project detected" + if [ "$BUILD_CLI" = true ]; then + echo -e "${YELLOW}DEBUG: Using locally built wheel${NC}" + + # From tutorial subdirectory, we need to go up 4 levels to reach repo root + # tutorials/00_sync/000_hello_acp -> tutorials -> examples -> agentex-python + local wheel_file=$(ls ../../../../dist/agentex_sdk-*.whl 2>/dev/null | head -n1) + if [[ -z "$wheel_file" ]]; then + echo -e "${RED}❌ No built wheel found in ../../../../dist/agentex_sdk-*.whl${NC}" + echo -e "${YELLOW}💡 Please build the local SDK first by running: uv build${NC}" + echo -e "${YELLOW}💡 From the repo root directory: /Users/roxanne.farhad/Desktop/scale/agentex-python${NC}" + cd "$original_dir" + return 1 + fi - # Start the agent in background and capture PID - local agentex_cmd=$(get_agentex_command) - $agentex_cmd agents run --manifest manifest.yaml > "$logfile" 2>&1 & + echo -e "${YELLOW}DEBUG: Using wheel: $wheel_file${NC}" + # Use the built wheel + uv run --with "$wheel_file" agentex agents run --manifest "$manifest_path" > "$logfile" 2>&1 & + else + echo -e "${YELLOW}DEBUG: Using system CLI${NC}" + uv run agentex agents run --manifest manifest.yaml > "$logfile" 2>&1 & + fi local pid=$! # Return to original directory @@ -311,9 +311,9 @@ execute_tutorial_test() { fi } -# Function to build CLI from source -build_cli() { - echo -e "${YELLOW}🔨 Building CLI from source...${NC}" +# Function to check if built wheel is available +check_built_wheel() { + echo -e "${YELLOW}🔍 Checking for locally built wheel...${NC}" # Navigate to the repo root (two levels up from examples/tutorials) local repo_root="../../" @@ -324,44 +324,31 @@ build_cli() { return 1 } - # Check if rye is available - if ! command -v rye &> /dev/null; then - echo -e "${RED}❌ rye is required to build the CLI${NC}" - echo "Please install rye: curl -sSf https://rye.astral.sh/get | bash" + # Check if wheel exists + local wheel_file=$(ls dist/agentex_sdk-*.whl 2>/dev/null | head -n1) + if [[ -z "$wheel_file" ]]; then + echo -e "${RED}❌ No built wheel found in dist/agentex_sdk-*.whl${NC}" + echo -e "${YELLOW}💡 Please build the local SDK first by running: uv build${NC}" + echo -e "${YELLOW}💡 From the repo root directory: $(pwd)${NC}" cd "$original_dir" return 1 fi - # Build the CLI - echo -e "${YELLOW}Running rye sync --all-features...${NC}" - if ! rye sync --all-features; then - echo -e "${RED}❌ Failed to sync dependencies${NC}" - cd "$original_dir" - return 1 - fi + echo -e "${GREEN}✅ Found built wheel: $wheel_file${NC}" - echo -e "${YELLOW}Running rye build...${NC}" - if ! rye build; then - echo -e "${RED}❌ Failed to build package${NC}" + # Test the wheel by running agentex --help + echo -e "${YELLOW}Verifying built wheel...${NC}" + if ! uv run --with "$wheel_file" agentex --help >/dev/null 2>&1; then + echo -e "${RED}❌ Failed to run agentex with built wheel${NC}" cd "$original_dir" return 1 fi - echo -e "${GREEN}✅ CLI built successfully${NC}" + echo -e "${GREEN}✅ Built wheel verified successfully${NC}" cd "$original_dir" return 0 } -# Function to get the appropriate agentex command -get_agentex_command() { - if [ "$BUILD_CLI" = true ]; then - # Use the local build via rye run (rye is in PATH) - echo "rye run agentex" - else - # Use the system-installed version - echo "uv run agentex" - fi -} # Main execution function main() { @@ -401,10 +388,10 @@ main() { echo "" - # Build CLI if requested + # Check built wheel if requested if [ "$BUILD_CLI" = true ]; then - if ! build_cli; then - echo -e "${RED}❌ Failed to build CLI from source${NC}" + if ! check_built_wheel; then + echo -e "${RED}❌ Failed to find or verify built wheel${NC}" exit 1 fi echo "" diff --git a/uv.lock b/uv.lock index 6efbfe03..b6dc230e 100644 --- a/uv.lock +++ b/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 2 +revision = 3 requires-python = ">=3.12, <4" resolution-markers = [ "python_full_version >= '3.13'", @@ -8,7 +8,7 @@ resolution-markers = [ [[package]] name = "agentex-sdk" -version = "0.4.19" +version = "0.5.0" source = { editable = "." } dependencies = [ { name = "aiohttp" }, @@ -76,7 +76,7 @@ requires-dist = [ { name = "distro", specifier = ">=1.7.0,<2" }, { name = "fastapi", specifier = ">=0.115.0,<0.116" }, { name = "httpx", specifier = ">=0.27.2,<0.28" }, - { name = "httpx-aiohttp", marker = "extra == 'aiohttp'", specifier = ">=0.1.8" }, + { name = "httpx-aiohttp", marker = "extra == 'aiohttp'", specifier = ">=0.1.9" }, { name = "ipykernel", specifier = ">=6.29.5" }, { name = "jinja2", specifier = ">=3.1.3,<4" }, { name = "json-log-formatter", specifier = ">=1.1.1" }, @@ -723,15 +723,15 @@ wheels = [ [[package]] name = "httpx-aiohttp" -version = "0.1.8" +version = "0.1.9" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "aiohttp" }, { name = "httpx" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/37/19/ae2d2bf1f57fdd23c8ad83675599fb5c407fa13bc20e90f00cffa4dea3aa/httpx_aiohttp-0.1.8.tar.gz", hash = "sha256:756c5e74cdb568c3248ba63fe82bfe8bbe64b928728720f7eaac64b3cf46f308", size = 25401, upload-time = "2025-07-04T10:40:32.329Z" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/f2/9a86ce9bc48cf57dabb3a3160dfed26d8bbe5a2478a51f9d1dbf89f2f1fc/httpx_aiohttp-0.1.9.tar.gz", hash = "sha256:4ee8b22e6f2e7c80cd03be29eff98bfe7d89bd77f021ce0b578ee76b73b4bfe6", size = 206023, upload-time = "2025-10-15T08:52:57.475Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/54/7a/514c484b88cc4ebbcd2e27e92b86019c0c5bb920582f5fbb10b7e6c78574/httpx_aiohttp-0.1.8-py3-none-any.whl", hash = "sha256:b7bd958d1331f3759a38a0ba22ad29832cb63ca69498c17735228055bf78fa7e", size = 6180, upload-time = "2025-07-04T10:40:31.522Z" }, + { url = "https://files.pythonhosted.org/packages/a1/db/5cfa8254a86c34a1ab7fe0dbec9f81bb5ebd831cbdd65aa4be4f37027804/httpx_aiohttp-0.1.9-py3-none-any.whl", hash = "sha256:3dc2845568b07742588710fcf3d72db2cbcdf2acc93376edf85f789c4d8e5fda", size = 6180, upload-time = "2025-10-15T08:52:56.521Z" }, ] [[package]] From be036c0306df581f4570c5dcbe3720d47c0da1a9 Mon Sep 17 00:00:00 2001 From: Roxanne Farhad Date: Sun, 2 Nov 2025 12:29:39 -0500 Subject: [PATCH 10/30] bump the version --- uv.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uv.lock b/uv.lock index b6dc230e..4f296427 100644 --- a/uv.lock +++ b/uv.lock @@ -8,7 +8,7 @@ resolution-markers = [ [[package]] name = "agentex-sdk" -version = "0.5.0" +version = "0.5.3" source = { editable = "." } dependencies = [ { name = "aiohttp" }, From 30875eab57a46321bf4092b0a9b129e589d06083 Mon Sep 17 00:00:00 2001 From: Roxanne Farhad Date: Sun, 2 Nov 2025 12:35:04 -0500 Subject: [PATCH 11/30] adding the logs here --- examples/tutorials/run_agent_test.sh | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/examples/tutorials/run_agent_test.sh b/examples/tutorials/run_agent_test.sh index 71a0ab82..3e236434 100755 --- a/examples/tutorials/run_agent_test.sh +++ b/examples/tutorials/run_agent_test.sh @@ -272,6 +272,19 @@ run_test() { return 0 else echo -e "${RED}❌ Tests failed for ${name}${NC}" + + # Print agent logs to help with debugging + local logfile="/tmp/agentex-${name}.log" + if [[ -f "$logfile" ]]; then + echo "" + echo -e "${YELLOW}📋 Agent logs for debugging:${NC}" + echo "----------------------------------------" + tail -50 "$logfile" + echo "----------------------------------------" + else + echo -e "${YELLOW}⚠️ No agent log file found at: $logfile${NC}" + fi + return 1 fi } From ea16c53d408680dec03239e49dcf5bf3d0c484f1 Mon Sep 17 00:00:00 2001 From: Roxanne Farhad Date: Sun, 2 Nov 2025 12:37:12 -0500 Subject: [PATCH 12/30] add failed logs --- .github/workflows/agentex-tutorials-test.yml | 83 +++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/.github/workflows/agentex-tutorials-test.yml b/.github/workflows/agentex-tutorials-test.yml index 8941b1ca..fb32c181 100644 --- a/.github/workflows/agentex-tutorials-test.yml +++ b/.github/workflows/agentex-tutorials-test.yml @@ -61,6 +61,33 @@ jobs: echo "UV version: $(uv --version)" echo "UV path: $(which uv)" + # Start background job to continuously poll AgentEx container logs + echo "🔍 Starting AgentEx container log polling in background..." + ( + echo "Log polling started at $(date)" + + # Function to get container logs + get_logs() { + echo "=== AgentEx Container Logs $(date) ===" + docker logs agentex --tail=20 2>/dev/null || { + echo "⚠️ Failed to get logs from 'agentex' container" + echo "Available containers:" + docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Image}}" + } + echo "=== End Logs ===" + echo "" + } + + # Poll logs every 2 seconds (very frequent for debugging) + while true; do + get_logs + sleep 2 + done + ) & + + LOG_POLLER_PID=$! + echo "📋 Log poller started with PID: $LOG_POLLER_PID" + # Find all tutorial directories tutorial_paths=() for dir in $(find . -name "manifest.yaml" -exec dirname {} \; | sort); do @@ -99,7 +126,7 @@ jobs: # Run test in background with unique port ( - AGENTEX_API_BASE_URL="http://localhost:5003" \ + AGENTEX_API_BASE_URL="http://host.docker.internal:5003" \ ./run_agent_test.sh --build-cli "$tutorial" if [ $? -eq 0 ]; then @@ -121,6 +148,32 @@ jobs: wait "$pid" done + # Always show AgentEx server container logs immediately after tests complete + echo "" + echo "=========================================" + echo "AGENTEX SERVER CONTAINER LOGS" + echo "=========================================" + + # Show AgentEx server container logs + echo "📋 AgentEx server container logs:" + echo "----------------------------------------" + + echo "Available containers:" + docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Image}}" + + echo "" + echo "AgentEx container logs (last 100 lines):" + docker logs agentex --tail=100 2>/dev/null || { + echo "❌ Failed to get logs from 'agentex' container" + echo "Available containers:" + docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Image}}" + } + echo "----------------------------------------" + + # Stop the log poller + echo "🛑 Stopping log poller (PID: $LOG_POLLER_PID)" + kill $LOG_POLLER_PID 2>/dev/null || echo "Log poller already stopped" + # Restore all original manifests echo "" echo "Restoring original manifest files..." @@ -140,6 +193,7 @@ jobs: fi done + # Print summary echo "" echo "=========================================" @@ -155,6 +209,33 @@ jobs: for test in "${failed_tests[@]}"; do echo " ❌ $test" done + + echo "" + echo "=========================================" + echo "TUTORIAL AGENT LOGS FOR FAILED TESTS" + echo "=========================================" + + # Show logs for failed tests + for test in "${failed_tests[@]}"; do + test_name=$(basename "$test") + logfile="/tmp/agentex-${test_name}.log" + + echo "" + echo "📋 Tutorial agent logs for $test ($logfile):" + echo "----------------------------------------" + + if [ -f "$logfile" ]; then + echo "Last 100 lines of tutorial agent logs:" + tail -100 "$logfile" + else + echo "⚠️ No log file found at: $logfile" + echo "Available log files:" + ls -la /tmp/agentex-*.log 2>/dev/null || echo " (none)" + fi + + echo "----------------------------------------" + done + exit 1 else echo "" From b4d87d730e524a8602ede5dad6c8877cf8302977 Mon Sep 17 00:00:00 2001 From: Roxanne Farhad Date: Sun, 2 Nov 2025 13:10:51 -0500 Subject: [PATCH 13/30] checking tutorial ports --- .github/workflows/agentex-tutorials-test.yml | 28 ++++++++++-- examples/tutorials/run_agent_test.sh | 48 +++++++++++++++++++- 2 files changed, 72 insertions(+), 4 deletions(-) diff --git a/.github/workflows/agentex-tutorials-test.yml b/.github/workflows/agentex-tutorials-test.yml index fb32c181..f0cd122e 100644 --- a/.github/workflows/agentex-tutorials-test.yml +++ b/.github/workflows/agentex-tutorials-test.yml @@ -29,7 +29,7 @@ jobs: cd scale-agentex/agentex echo "🚀 Starting dependencies (Postgres, Redis, Temporal, MongoDB)..." - # Start all services except the agentex service + # Start all services docker compose up -d echo "⏳ Waiting for dependencies to be healthy..." @@ -44,8 +44,26 @@ jobs: sleep 5 done - # Verify all deps are up + # Wait specifically for AgentEx server to be ready + echo "⏳ Waiting for AgentEx server to be ready..." + for i in {1..30}; do + if curl -s --max-time 5 http://localhost:5003/health >/dev/null 2>&1; then + echo "✅ AgentEx server is ready" + break + fi + echo " Attempt $i/30: Waiting for AgentEx server..." + sleep 5 + done + + # Debug port mappings + echo "🔍 Docker port mappings:" docker compose ps + echo "" + echo "🔍 Docker port details:" + docker compose ps --format "table {{.Name}}\t{{.Image}}\t{{.Ports}}" + echo "" + echo "🔍 Testing AgentEx server accessibility:" + curl -v --max-time 10 http://localhost:5003/health 2>&1 || echo "❌ AgentEx not accessible on localhost:5003" - name: Build AgentEx SDK run: | @@ -124,9 +142,13 @@ jobs: echo "Updated $manifest_path to use port $port" fi + # Debug connectivity before running test + echo "🔍 Pre-test connectivity check:" + curl -v --max-time 5 http://localhost:5003/agents 2>&1 || echo "❌ /agents endpoint not accessible" + # Run test in background with unique port ( - AGENTEX_API_BASE_URL="http://host.docker.internal:5003" \ + AGENTEX_API_BASE_URL="http://localhost:5003" \ ./run_agent_test.sh --build-cli "$tutorial" if [ $? -eq 0 ]; then diff --git a/examples/tutorials/run_agent_test.sh b/examples/tutorials/run_agent_test.sh index 3e236434..3a6c73ef 100755 --- a/examples/tutorials/run_agent_test.sh +++ b/examples/tutorials/run_agent_test.sh @@ -260,6 +260,52 @@ run_test() { # Change to tutorial directory cd "$tutorial_path" || return 1 + # Debug connectivity inside uv environment + echo -e "${YELLOW}🔍 Testing connectivity inside uv environment...${NC}" + uv run python -c " +import os +print(f'AGENTEX_API_BASE_URL: {os.environ.get(\"AGENTEX_API_BASE_URL\", \"NOT SET\")}') +try: + import httpx + response = httpx.get('http://localhost:5003/agents', timeout=10) + print(f'✅ HTTP request successful: {response.status_code}') + print(f'Response: {response.text}') +except Exception as e: + print(f'❌ HTTP request failed: {e}') + +print('\\n🔍 Testing AgentEx SDK send_message...') +try: + from agentex import Agentex + from agentex.types.agent_rpc_params import ParamsSendMessageRequest + from agentex.types import TextContentParam + + client = Agentex(base_url='http://localhost:5003') + print(f'✅ AgentEx client created successfully') + + # Make the same request as the failing test + response = client.agents.send_message( + agent_name='s000-hello-acp', + params=ParamsSendMessageRequest( + content=TextContentParam( + author='user', + content='Hello, Agent! How are you?', + type='text', + ) + ), + ) + print(f'✅ SDK send_message successful') + print(f'Response result: {response.result}') + if response.result: + print(f'Result length: {len(response.result)}') + if len(response.result) > 0: + print(f'First message content: {response.result[0].content}') + +except Exception as e: + print(f'❌ AgentEx SDK send_message failed: {e}') + import traceback + traceback.print_exc() +" + # Run the tests uv run pytest tests/test_agent.py -v -s local exit_code=$? @@ -428,4 +474,4 @@ main() { } # Run main function -main \ No newline at end of file +main From 6c7de97a85712d2739ce1ede25a61dae555f4f58 Mon Sep 17 00:00:00 2001 From: Roxanne Farhad Date: Mon, 3 Nov 2025 09:26:27 -0500 Subject: [PATCH 14/30] debuging the sdk version --- examples/tutorials/run_agent_test.sh | 33 +--------------------------- 1 file changed, 1 insertion(+), 32 deletions(-) diff --git a/examples/tutorials/run_agent_test.sh b/examples/tutorials/run_agent_test.sh index 3a6c73ef..9d18ef1d 100755 --- a/examples/tutorials/run_agent_test.sh +++ b/examples/tutorials/run_agent_test.sh @@ -266,44 +266,13 @@ run_test() { import os print(f'AGENTEX_API_BASE_URL: {os.environ.get(\"AGENTEX_API_BASE_URL\", \"NOT SET\")}') try: + import agentex; print(agentex.__version__) import httpx response = httpx.get('http://localhost:5003/agents', timeout=10) print(f'✅ HTTP request successful: {response.status_code}') print(f'Response: {response.text}') except Exception as e: print(f'❌ HTTP request failed: {e}') - -print('\\n🔍 Testing AgentEx SDK send_message...') -try: - from agentex import Agentex - from agentex.types.agent_rpc_params import ParamsSendMessageRequest - from agentex.types import TextContentParam - - client = Agentex(base_url='http://localhost:5003') - print(f'✅ AgentEx client created successfully') - - # Make the same request as the failing test - response = client.agents.send_message( - agent_name='s000-hello-acp', - params=ParamsSendMessageRequest( - content=TextContentParam( - author='user', - content='Hello, Agent! How are you?', - type='text', - ) - ), - ) - print(f'✅ SDK send_message successful') - print(f'Response result: {response.result}') - if response.result: - print(f'Result length: {len(response.result)}') - if len(response.result) > 0: - print(f'First message content: {response.result[0].content}') - -except Exception as e: - print(f'❌ AgentEx SDK send_message failed: {e}') - import traceback - traceback.print_exc() " # Run the tests From b61699b66c2bf8c5950f2c33d71bc6746c905f4a Mon Sep 17 00:00:00 2001 From: Roxanne Farhad Date: Mon, 3 Nov 2025 09:49:49 -0500 Subject: [PATCH 15/30] adding the hosting stuff --- .github/workflows/agentex-tutorials-test.yml | 5 +++- examples/tutorials/run_agent_test.sh | 27 +++++++++++++++++--- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/.github/workflows/agentex-tutorials-test.yml b/.github/workflows/agentex-tutorials-test.yml index f0cd122e..76f6b5b1 100644 --- a/.github/workflows/agentex-tutorials-test.yml +++ b/.github/workflows/agentex-tutorials-test.yml @@ -139,7 +139,10 @@ jobs: # Update port in manifest (modify the line containing 'port: 8000' or 'port: XXXX') sed -i "s/port: [0-9]*/port: $port/" "$manifest_path" - echo "Updated $manifest_path to use port $port" + # Update host_address to localhost for CI (Docker can't reach host.docker.internal from inside container) + sed -i "s/host_address: host.docker.internal/host_address: localhost/" "$manifest_path" + + echo "Updated $manifest_path to use port $port and host_address: localhost" fi # Debug connectivity before running test diff --git a/examples/tutorials/run_agent_test.sh b/examples/tutorials/run_agent_test.sh index 9d18ef1d..e5a75528 100755 --- a/examples/tutorials/run_agent_test.sh +++ b/examples/tutorials/run_agent_test.sh @@ -275,9 +275,30 @@ except Exception as e: print(f'❌ HTTP request failed: {e}') " - # Run the tests - uv run pytest tests/test_agent.py -v -s - local exit_code=$? + # Run the tests with retry mechanism + local max_retries=3 + local retry_count=0 + local exit_code=1 + + while [ $retry_count -lt $max_retries ]; do + echo -e "${YELLOW}🧪 Running tests (attempt $((retry_count + 1))/$max_retries)...${NC}" + + uv run pytest tests/test_agent.py -v -s + exit_code=$? + + if [ $exit_code -eq 0 ]; then + echo -e "${GREEN}✅ Tests passed on attempt $((retry_count + 1))${NC}" + break + else + retry_count=$((retry_count + 1)) + if [ $retry_count -lt $max_retries ]; then + echo -e "${YELLOW}⚠️ Tests failed on attempt $retry_count, retrying in 5 seconds...${NC}" + sleep 5 + else + echo -e "${RED}❌ Tests failed after $max_retries attempts${NC}" + fi + fi + done # Return to original directory cd "$original_dir" From cac62f87fe18dfac37d72c3a2c9c1856eb453e9f Mon Sep 17 00:00:00 2001 From: Roxanne Farhad Date: Mon, 3 Nov 2025 11:08:56 -0500 Subject: [PATCH 16/30] trying to fix this --- .github/workflows/agentex-tutorials-test.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/agentex-tutorials-test.yml b/.github/workflows/agentex-tutorials-test.yml index 76f6b5b1..06c81da4 100644 --- a/.github/workflows/agentex-tutorials-test.yml +++ b/.github/workflows/agentex-tutorials-test.yml @@ -139,10 +139,10 @@ jobs: # Update port in manifest (modify the line containing 'port: 8000' or 'port: XXXX') sed -i "s/port: [0-9]*/port: $port/" "$manifest_path" - # Update host_address to localhost for CI (Docker can't reach host.docker.internal from inside container) - sed -i "s/host_address: host.docker.internal/host_address: localhost/" "$manifest_path" + # Keep host_address as host.docker.internal for CI (allows Docker container to reach GitHub runner host) + # Note: The AgentEx server runs in Docker and needs host.docker.internal to reach the tutorial agent on the host - echo "Updated $manifest_path to use port $port and host_address: localhost" + echo "Updated $manifest_path to use port $port (keeping host_address: host.docker.internal)" fi # Debug connectivity before running test From 90d93e75825c8773d4cccc2f254466f115aa8548 Mon Sep 17 00:00:00 2001 From: Roxanne Farhad Date: Mon, 3 Nov 2025 11:24:23 -0500 Subject: [PATCH 17/30] fix comms --- .github/workflows/agentex-tutorials-test.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.github/workflows/agentex-tutorials-test.yml b/.github/workflows/agentex-tutorials-test.yml index 06c81da4..e2c9c7c3 100644 --- a/.github/workflows/agentex-tutorials-test.yml +++ b/.github/workflows/agentex-tutorials-test.yml @@ -24,6 +24,19 @@ jobs: repository: scaleapi/scale-agentex path: scale-agentex + - name: Configure Docker Compose for host networking + run: | + cd scale-agentex/agentex + echo "🔧 Configuring AgentEx container for GitHub Actions networking..." + + # Add extra_hosts to agentex service to make host.docker.internal work + # This allows the AgentEx container to reach the GitHub runner host + sed -i '/container_name: agentex/a\ extra_hosts:\n - "host.docker.internal:host-gateway"' docker-compose.yml + + echo "✅ Added extra_hosts configuration to agentex service" + echo "🔍 Updated agentex service config:" + grep -A 10 "container_name: agentex" docker-compose.yml || echo "Could not find agentex service" + - name: Navigate to scale-agentex repo run: | cd scale-agentex/agentex From 579dd9796168438d46b0075e61cdd3854cb6b585 Mon Sep 17 00:00:00 2001 From: Roxanne Farhad Date: Mon, 3 Nov 2025 11:30:22 -0500 Subject: [PATCH 18/30] adding the yq stuff --- .github/workflows/agentex-tutorials-test.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/agentex-tutorials-test.yml b/.github/workflows/agentex-tutorials-test.yml index e2c9c7c3..aefb0a48 100644 --- a/.github/workflows/agentex-tutorials-test.yml +++ b/.github/workflows/agentex-tutorials-test.yml @@ -29,9 +29,13 @@ jobs: cd scale-agentex/agentex echo "🔧 Configuring AgentEx container for GitHub Actions networking..." + # Install yq for YAML manipulation + sudo wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 + sudo chmod +x /usr/local/bin/yq + # Add extra_hosts to agentex service to make host.docker.internal work # This allows the AgentEx container to reach the GitHub runner host - sed -i '/container_name: agentex/a\ extra_hosts:\n - "host.docker.internal:host-gateway"' docker-compose.yml + yq eval '.services.agentex.extra_hosts = ["host.docker.internal:host-gateway"]' -i docker-compose.yml echo "✅ Added extra_hosts configuration to agentex service" echo "🔍 Updated agentex service config:" From 1ffabf7a614cff92de7d27cb62f57ba253c2ebe7 Mon Sep 17 00:00:00 2001 From: Roxanne Farhad Date: Mon, 3 Nov 2025 11:39:03 -0500 Subject: [PATCH 19/30] running all the tests again --- .github/workflows/agentex-tutorials-test.yml | 75 +++++++++++++------- 1 file changed, 50 insertions(+), 25 deletions(-) diff --git a/.github/workflows/agentex-tutorials-test.yml b/.github/workflows/agentex-tutorials-test.yml index aefb0a48..ca43bba0 100644 --- a/.github/workflows/agentex-tutorials-test.yml +++ b/.github/workflows/agentex-tutorials-test.yml @@ -38,8 +38,6 @@ jobs: yq eval '.services.agentex.extra_hosts = ["host.docker.internal:host-gateway"]' -i docker-compose.yml echo "✅ Added extra_hosts configuration to agentex service" - echo "🔍 Updated agentex service config:" - grep -A 10 "container_name: agentex" docker-compose.yml || echo "Could not find agentex service" - name: Navigate to scale-agentex repo run: | @@ -72,15 +70,6 @@ jobs: sleep 5 done - # Debug port mappings - echo "🔍 Docker port mappings:" - docker compose ps - echo "" - echo "🔍 Docker port details:" - docker compose ps --format "table {{.Name}}\t{{.Image}}\t{{.Ports}}" - echo "" - echo "🔍 Testing AgentEx server accessibility:" - curl -v --max-time 10 http://localhost:5003/health 2>&1 || echo "❌ AgentEx not accessible on localhost:5003" - name: Build AgentEx SDK run: | @@ -137,8 +126,8 @@ jobs: failed_tests=() passed_tests=() - # Run only the first test for sanity check - for i in 0; do + # Run all tutorial tests + for i in "${!tutorial_paths[@]}"; do tutorial="${tutorial_paths[$i]}" port=$((8000 + i)) @@ -162,9 +151,6 @@ jobs: echo "Updated $manifest_path to use port $port (keeping host_address: host.docker.internal)" fi - # Debug connectivity before running test - echo "🔍 Pre-test connectivity check:" - curl -v --max-time 5 http://localhost:5003/agents 2>&1 || echo "❌ /agents endpoint not accessible" # Run test in background with unique port ( @@ -252,34 +238,73 @@ jobs: echo " ❌ $test" done + + exit 1 + else + echo "" + echo "🎉 All tests passed!" + fi + + - name: Debug Logs for Failed Tests + if: always() + run: | + cd scale-agentex/agentex + + echo "" + echo "================================================================================" + echo "🐛 DEBUG LOGS (for troubleshooting)" + echo "================================================================================" + + # Show AgentEx server container logs + echo "" + echo "=========================================" + echo "AGENTEX SERVER LOGS" + echo "=========================================" + echo "📋 AgentEx server container logs (last 200 lines):" + echo "----------------------------------------" + docker logs agentex --tail=200 2>/dev/null || { + echo "❌ Failed to get logs from 'agentex' container" + echo "Available containers:" + docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Image}}" + } + echo "----------------------------------------" + + # Show tutorial agent logs for failed tests + cd ../../examples/tutorials + + # Check if there were any failed tests + failed_tests=() + for i in {0..20}; do # Check up to 20 possible tests + if [ -f "/tmp/failed_$i.txt" ]; then + failed_tests+=($(cat "/tmp/failed_$i.txt")) + fi + done + + if [ ${#failed_tests[@]} -gt 0 ]; then echo "" echo "=========================================" echo "TUTORIAL AGENT LOGS FOR FAILED TESTS" echo "=========================================" - # Show logs for failed tests for test in "${failed_tests[@]}"; do test_name=$(basename "$test") logfile="/tmp/agentex-${test_name}.log" echo "" - echo "📋 Tutorial agent logs for $test ($logfile):" + echo "📋 Tutorial agent logs for $test:" echo "----------------------------------------" if [ -f "$logfile" ]; then - echo "Last 100 lines of tutorial agent logs:" + echo "Tutorial agent logs (last 100 lines):" tail -100 "$logfile" else - echo "⚠️ No log file found at: $logfile" - echo "Available log files:" + echo "⚠️ No agent log file found at: $logfile" + echo "Available agent log files:" ls -la /tmp/agentex-*.log 2>/dev/null || echo " (none)" fi - echo "----------------------------------------" done - - exit 1 else echo "" - echo "🎉 All tests passed!" + echo "✅ No failed tests - no agent logs to show" fi From ba43d93b5554ce593f1bf0b4068528d286c8dabf Mon Sep 17 00:00:00 2001 From: Roxanne Farhad Date: Mon, 3 Nov 2025 11:50:13 -0500 Subject: [PATCH 20/30] adding the api ley --- .github/workflows/agentex-tutorials-test.yml | 3 +- examples/tutorials/run_agent_test.sh | 47 ++------------------ 2 files changed, 5 insertions(+), 45 deletions(-) diff --git a/.github/workflows/agentex-tutorials-test.yml b/.github/workflows/agentex-tutorials-test.yml index ca43bba0..30277a6c 100644 --- a/.github/workflows/agentex-tutorials-test.yml +++ b/.github/workflows/agentex-tutorials-test.yml @@ -70,7 +70,6 @@ jobs: sleep 5 done - - name: Build AgentEx SDK run: | echo "🔨 Building AgentEx SDK wheel..." @@ -80,6 +79,8 @@ jobs: - name: Run Parallel Tutorial Tests working-directory: ./examples/tutorials + env: + OPENAI_API_KEY: ${{ secrets.TUTORIAL_OPENAI_API_KEY }} run: | # Verify uv is working echo "UV version: $(uv --version)" diff --git a/examples/tutorials/run_agent_test.sh b/examples/tutorials/run_agent_test.sh index e5a75528..4ac6b6ee 100755 --- a/examples/tutorials/run_agent_test.sh +++ b/examples/tutorials/run_agent_test.sh @@ -119,11 +119,7 @@ start_agent() { # Start the agent in background and capture PID local manifest_path="$PWD/manifest.yaml" # Always use full path - echo -e "${YELLOW}DEBUG: Manifest path: $manifest_path${NC}" - echo -e "${YELLOW}DEBUG: Log file: $logfile${NC}" - if [ "$BUILD_CLI" = true ]; then - echo -e "${YELLOW}DEBUG: Using locally built wheel${NC}" # From tutorial subdirectory, we need to go up 4 levels to reach repo root # tutorials/00_sync/000_hello_acp -> tutorials -> examples -> agentex-python @@ -136,11 +132,9 @@ start_agent() { return 1 fi - echo -e "${YELLOW}DEBUG: Using wheel: $wheel_file${NC}" # Use the built wheel uv run --with "$wheel_file" agentex agents run --manifest "$manifest_path" > "$logfile" 2>&1 & else - echo -e "${YELLOW}DEBUG: Using system CLI${NC}" uv run agentex agents run --manifest manifest.yaml > "$logfile" 2>&1 & fi local pid=$! @@ -260,20 +254,6 @@ run_test() { # Change to tutorial directory cd "$tutorial_path" || return 1 - # Debug connectivity inside uv environment - echo -e "${YELLOW}🔍 Testing connectivity inside uv environment...${NC}" - uv run python -c " -import os -print(f'AGENTEX_API_BASE_URL: {os.environ.get(\"AGENTEX_API_BASE_URL\", \"NOT SET\")}') -try: - import agentex; print(agentex.__version__) - import httpx - response = httpx.get('http://localhost:5003/agents', timeout=10) - print(f'✅ HTTP request successful: {response.status_code}') - print(f'Response: {response.text}') -except Exception as e: - print(f'❌ HTTP request failed: {e}') -" # Run the tests with retry mechanism local max_retries=3 @@ -281,21 +261,19 @@ except Exception as e: local exit_code=1 while [ $retry_count -lt $max_retries ]; do - echo -e "${YELLOW}🧪 Running tests (attempt $((retry_count + 1))/$max_retries)...${NC}" + if [ $retry_count -gt 0 ]; then + echo -e "${YELLOW}🔄 Retrying tests (attempt $((retry_count + 1))/$max_retries)...${NC}" + fi uv run pytest tests/test_agent.py -v -s exit_code=$? if [ $exit_code -eq 0 ]; then - echo -e "${GREEN}✅ Tests passed on attempt $((retry_count + 1))${NC}" break else retry_count=$((retry_count + 1)) if [ $retry_count -lt $max_retries ]; then - echo -e "${YELLOW}⚠️ Tests failed on attempt $retry_count, retrying in 5 seconds...${NC}" sleep 5 - else - echo -e "${RED}❌ Tests failed after $max_retries attempts${NC}" fi fi done @@ -308,19 +286,6 @@ except Exception as e: return 0 else echo -e "${RED}❌ Tests failed for ${name}${NC}" - - # Print agent logs to help with debugging - local logfile="/tmp/agentex-${name}.log" - if [[ -f "$logfile" ]]; then - echo "" - echo -e "${YELLOW}📋 Agent logs for debugging:${NC}" - echo "----------------------------------------" - tail -50 "$logfile" - echo "----------------------------------------" - else - echo -e "${YELLOW}⚠️ No agent log file found at: $logfile${NC}" - fi - return 1 fi } @@ -363,7 +328,6 @@ execute_tutorial_test() { # Function to check if built wheel is available check_built_wheel() { - echo -e "${YELLOW}🔍 Checking for locally built wheel...${NC}" # Navigate to the repo root (two levels up from examples/tutorials) local repo_root="../../" @@ -384,17 +348,12 @@ check_built_wheel() { return 1 fi - echo -e "${GREEN}✅ Found built wheel: $wheel_file${NC}" - # Test the wheel by running agentex --help - echo -e "${YELLOW}Verifying built wheel...${NC}" if ! uv run --with "$wheel_file" agentex --help >/dev/null 2>&1; then echo -e "${RED}❌ Failed to run agentex with built wheel${NC}" cd "$original_dir" return 1 fi - - echo -e "${GREEN}✅ Built wheel verified successfully${NC}" cd "$original_dir" return 0 } From 5a13b313727c80de1139ff93116a26a5c1044c9a Mon Sep 17 00:00:00 2001 From: Roxanne Farhad Date: Mon, 3 Nov 2025 12:42:45 -0500 Subject: [PATCH 21/30] cleaning up --- .github/workflows/agentex-tutorials-test.yml | 198 +++++++++++++------ examples/tutorials/run_agent_test.sh | 96 +++++---- 2 files changed, 202 insertions(+), 92 deletions(-) diff --git a/.github/workflows/agentex-tutorials-test.yml b/.github/workflows/agentex-tutorials-test.yml index 30277a6c..0af6e77a 100644 --- a/.github/workflows/agentex-tutorials-test.yml +++ b/.github/workflows/agentex-tutorials-test.yml @@ -6,7 +6,7 @@ on: jobs: test-tutorials: timeout-minutes: 15 - name: test-tutorial-${{ matrix.tutorial }} + name: test-tutorials runs-on: ubuntu-latest steps: @@ -86,32 +86,32 @@ jobs: echo "UV version: $(uv --version)" echo "UV path: $(which uv)" - # Start background job to continuously poll AgentEx container logs - echo "🔍 Starting AgentEx container log polling in background..." + # Start background job to poll AgentEx container logs and write to file ( - echo "Log polling started at $(date)" + echo "AgentEx container log polling started at $(date)" > /tmp/agentex_container_logs.txt # Function to get container logs get_logs() { - echo "=== AgentEx Container Logs $(date) ===" - docker logs agentex --tail=20 2>/dev/null || { - echo "⚠️ Failed to get logs from 'agentex' container" - echo "Available containers:" - docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Image}}" - } - echo "=== End Logs ===" - echo "" + echo "=== AgentEx Container Logs $(date) ===" >> /tmp/agentex_container_logs.txt + docker logs agentex --tail=20 2>/dev/null >> /tmp/agentex_container_logs.txt || { + echo "⚠️ Failed to get logs from 'agentex' container" >> /tmp/agentex_container_logs.txt + echo "Available containers:" >> /tmp/agentex_container_logs.txt + docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Image}}" >> /tmp/agentex_container_logs.txt + } 2>/dev/null + echo "=== End Logs ===" >> /tmp/agentex_container_logs.txt + echo "" >> /tmp/agentex_container_logs.txt } - # Poll logs every 2 seconds (very frequent for debugging) + # Poll logs every 10 seconds during test execution while true; do get_logs - sleep 2 + sleep 10 done ) & LOG_POLLER_PID=$! - echo "📋 Log poller started with PID: $LOG_POLLER_PID" + echo "📋 AgentEx log polling started in background (PID: $LOG_POLLER_PID)" + # Find all tutorial directories tutorial_paths=() @@ -148,23 +148,30 @@ jobs: # Keep host_address as host.docker.internal for CI (allows Docker container to reach GitHub runner host) # Note: The AgentEx server runs in Docker and needs host.docker.internal to reach the tutorial agent on the host - - echo "Updated $manifest_path to use port $port (keeping host_address: host.docker.internal)" fi - # Run test in background with unique port + # Run test in background with unique port and show pytest output in real-time ( + test_output_file="/tmp/test_output_$i.log" + echo "Running test: $tutorial" | tee "$test_output_file" + echo "Port: $port" | tee -a "$test_output_file" + echo "========================================" | tee -a "$test_output_file" + AGENTEX_API_BASE_URL="http://localhost:5003" \ - ./run_agent_test.sh --build-cli "$tutorial" + ./run_agent_test.sh --build-cli --quiet "$tutorial" 2>&1 | tee -a "$test_output_file" - if [ $? -eq 0 ]; then + exit_code=${PIPESTATUS[0]} + if [ $exit_code -eq 0 ]; then echo "✅ PASSED: $tutorial (port $port)" echo "$tutorial" > "/tmp/passed_$i.txt" + echo "$test_output_file" > "/tmp/passed_output_$i.txt" else echo "❌ FAILED: $tutorial (port $port)" echo "$tutorial" > "/tmp/failed_$i.txt" + echo "$test_output_file" > "/tmp/failed_output_$i.txt" fi + exit $exit_code ) & pids+=($!) @@ -177,32 +184,6 @@ jobs: wait "$pid" done - # Always show AgentEx server container logs immediately after tests complete - echo "" - echo "=========================================" - echo "AGENTEX SERVER CONTAINER LOGS" - echo "=========================================" - - # Show AgentEx server container logs - echo "📋 AgentEx server container logs:" - echo "----------------------------------------" - - echo "Available containers:" - docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Image}}" - - echo "" - echo "AgentEx container logs (last 100 lines):" - docker logs agentex --tail=100 2>/dev/null || { - echo "❌ Failed to get logs from 'agentex' container" - echo "Available containers:" - docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Image}}" - } - echo "----------------------------------------" - - # Stop the log poller - echo "🛑 Stopping log poller (PID: $LOG_POLLER_PID)" - kill $LOG_POLLER_PID 2>/dev/null || echo "Log poller already stopped" - # Restore all original manifests echo "" echo "Restoring original manifest files..." @@ -223,6 +204,10 @@ jobs: done + # Stop the background log poller + echo "🛑 Stopping AgentEx log poller (PID: $LOG_POLLER_PID)" + kill $LOG_POLLER_PID 2>/dev/null || echo "Log poller already stopped" + # Print summary echo "" echo "=========================================" @@ -238,14 +223,101 @@ jobs: for test in "${failed_tests[@]}"; do echo " ❌ $test" done - - - exit 1 else echo "" echo "🎉 All tests passed!" fi + # Show comprehensive pytest summary + echo "" + echo "=========================================" + echo "PYTEST RESULTS SUMMARY" + echo "=========================================" + + # Collect all pytest results + total_passed_tests=0 + total_failed_tests=0 + total_pytest_tests=0 + + echo "" + echo "📊 PYTEST EXECUTION SUMMARY:" + echo "----------------------------------------" + + for i in "${!tutorial_paths[@]}"; do + tutorial="${tutorial_paths[$i]}" + output_file="/tmp/test_output_$i.log" + + if [ -f "$output_file" ]; then + # Extract pytest summary from each test + if grep -q "PYTEST OUTPUT" "$output_file"; then + pytest_section=$(sed -n '/========== PYTEST OUTPUT ==========/,/========== END PYTEST OUTPUT ==========/p' "$output_file") + + # Count individual test results in this tutorial + test_passed=$(echo "$pytest_section" | grep -c "PASSED" || echo "0") + test_failed=$(echo "$pytest_section" | grep -c "FAILED" || echo "0") + test_errors=$(echo "$pytest_section" | grep -c "ERROR" || echo "0") + + if [ "$test_passed" -gt 0 ] || [ "$test_failed" -gt 0 ] || [ "$test_errors" -gt 0 ]; then + tutorial_total=$((test_passed + test_failed + test_errors)) + total_pytest_tests=$((total_pytest_tests + tutorial_total)) + total_passed_tests=$((total_passed_tests + test_passed)) + total_failed_tests=$((total_failed_tests + test_failed + test_errors)) + + if [ "$test_failed" -gt 0 ] || [ "$test_errors" -gt 0 ]; then + echo "❌ $tutorial: $tutorial_total tests ($test_passed passed, $test_failed failed, $test_errors errors)" + else + echo "✅ $tutorial: $tutorial_total tests ($test_passed passed)" + fi + else + echo "⚠️ $tutorial: No pytest results found" + fi + else + echo "⚠️ $tutorial: No pytest output detected" + fi + else + echo "⚠️ $tutorial: No output file found" + fi + done + + echo "----------------------------------------" + echo "🏁 OVERALL PYTEST SUMMARY:" + echo " Total pytest tests run: $total_pytest_tests" + echo " Total pytest tests passed: $total_passed_tests" + echo " Total pytest tests failed: $total_failed_tests" + echo "" + + # Show detailed results for failed tests only + if [ ${#failed_tests[@]} -gt 0 ]; then + echo "❌ DETAILED FAILURE ANALYSIS:" + echo "----------------------------------------" + for i in "${!tutorial_paths[@]}"; do + if [ -f "/tmp/failed_$i.txt" ]; then + test_name=$(cat "/tmp/failed_$i.txt") + output_file=$(cat "/tmp/failed_output_$i.txt") + echo "" + echo "📋 FAILED: $test_name" + echo "----------------------------------------" + if [ -f "$output_file" ]; then + # Show just the pytest failure details + if grep -q "PYTEST OUTPUT" "$output_file"; then + echo "Pytest failure details:" + sed -n '/========== PYTEST OUTPUT ==========/,/========== END PYTEST OUTPUT ==========/p' "$output_file" + else + echo "No pytest output found. Showing last 40 lines:" + tail -40 "$output_file" + fi + else + echo "No output file found" + fi + echo "----------------------------------------" + fi + done + fi + + if [ ${#failed_tests[@]} -gt 0 ]; then + exit 1 + fi + - name: Debug Logs for Failed Tests if: always() run: | @@ -256,19 +328,27 @@ jobs: echo "🐛 DEBUG LOGS (for troubleshooting)" echo "================================================================================" - # Show AgentEx server container logs + # Show collected AgentEx server container logs echo "" echo "=========================================" - echo "AGENTEX SERVER LOGS" + echo "AGENTEX SERVER LOGS (COLLECTED DURING TESTS)" echo "=========================================" - echo "📋 AgentEx server container logs (last 200 lines):" - echo "----------------------------------------" - docker logs agentex --tail=200 2>/dev/null || { - echo "❌ Failed to get logs from 'agentex' container" - echo "Available containers:" - docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Image}}" - } - echo "----------------------------------------" + if [ -f "/tmp/agentex_container_logs.txt" ]; then + echo "📋 AgentEx server logs collected during test execution:" + echo "----------------------------------------" + cat /tmp/agentex_container_logs.txt + echo "----------------------------------------" + else + echo "⚠️ No AgentEx container logs file found" + echo "📋 Attempting to get current container logs:" + echo "----------------------------------------" + docker logs agentex --tail=50 2>/dev/null || { + echo "❌ Failed to get logs from 'agentex' container" + echo "Available containers:" + docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Image}}" + } + echo "----------------------------------------" + fi # Show tutorial agent logs for failed tests cd ../../examples/tutorials diff --git a/examples/tutorials/run_agent_test.sh b/examples/tutorials/run_agent_test.sh index 4ac6b6ee..42be1524 100755 --- a/examples/tutorials/run_agent_test.sh +++ b/examples/tutorials/run_agent_test.sh @@ -30,12 +30,15 @@ AGENTEX_SERVER_PORT=5003 TUTORIAL_PATH="" VIEW_LOGS=false BUILD_CLI=false +QUIET_MODE=false for arg in "$@"; do if [[ "$arg" == "--view-logs" ]]; then VIEW_LOGS=true elif [[ "$arg" == "--build-cli" ]]; then BUILD_CLI=true + elif [[ "$arg" == "--quiet" ]]; then + QUIET_MODE=true else TUTORIAL_PATH="$arg" fi @@ -56,7 +59,9 @@ check_prerequisites() { exit 1 fi - echo -e "${GREEN}✅ Prerequisites check passed${NC}" + if [ "$QUIET_MODE" = false ]; then + echo -e "${GREEN}✅ Prerequisites check passed${NC}" + fi } # Function to wait for agent to be ready @@ -96,7 +101,9 @@ start_agent() { local name=$(basename "$tutorial_path") local logfile="/tmp/agentex-${name}.log" - echo -e "${YELLOW}🚀 Starting ${name} agent...${NC}" + if [ "$QUIET_MODE" = false ]; then + echo -e "${YELLOW}🚀 Starting ${name} agent...${NC}" + fi # Check if tutorial directory exists if [[ ! -d "$tutorial_path" ]]; then @@ -121,13 +128,12 @@ start_agent() { if [ "$BUILD_CLI" = true ]; then - # From tutorial subdirectory, we need to go up 4 levels to reach repo root - # tutorials/00_sync/000_hello_acp -> tutorials -> examples -> agentex-python - local wheel_file=$(ls ../../../../dist/agentex_sdk-*.whl 2>/dev/null | head -n1) + # Use wheel from dist directory at repo root + local wheel_file=$(ls /home/runner/work/*/*/dist/agentex_sdk-*.whl 2>/dev/null | head -n1) if [[ -z "$wheel_file" ]]; then - echo -e "${RED}❌ No built wheel found in ../../../../dist/agentex_sdk-*.whl${NC}" + echo -e "${RED}❌ No built wheel found in dist/agentex_sdk-*.whl${NC}" echo -e "${YELLOW}💡 Please build the local SDK first by running: uv build${NC}" - echo -e "${YELLOW}💡 From the repo root directory: /Users/roxanne.farhad/Desktop/scale/agentex-python${NC}" + echo -e "${YELLOW}💡 From the repo root directory${NC}" cd "$original_dir" return 1 fi @@ -143,7 +149,9 @@ start_agent() { cd "$original_dir" echo "$pid" > "/tmp/agentex-${name}.pid" - echo -e "${GREEN}✅ ${name} agent started (PID: $pid, logs: $logfile)${NC}" + if [ "$QUIET_MODE" = false ]; then + echo -e "${GREEN}✅ ${name} agent started (PID: $pid, logs: $logfile)${NC}" + fi # Wait for agent to be ready if ! wait_for_agent_ready "$name"; then @@ -201,7 +209,9 @@ stop_agent() { local pidfile="/tmp/agentex-${name}.pid" local logfile="/tmp/agentex-${name}.log" - echo -e "${YELLOW}🛑 Stopping ${name} agent...${NC}" + if [ "$QUIET_MODE" = false ]; then + echo -e "${YELLOW}🛑 Stopping ${name} agent...${NC}" + fi # Check if PID file exists if [[ ! -f "$pidfile" ]]; then @@ -214,16 +224,22 @@ stop_agent() { # Check if process is running and kill it if kill -0 "$pid" 2>/dev/null; then - echo -e "${YELLOW}Stopping ${name} agent (PID: $pid)${NC}" + if [ "$QUIET_MODE" = false ]; then + echo -e "${YELLOW}Stopping ${name} agent (PID: $pid)${NC}" + fi kill "$pid" 2>/dev/null || true rm -f "$pidfile" else - echo -e "${YELLOW}⚠️ ${name} agent was not running${NC}" + if [ "$QUIET_MODE" = false ]; then + echo -e "${YELLOW}⚠️ ${name} agent was not running${NC}" + fi rm -f "$pidfile" fi - echo -e "${GREEN}✅ ${name} agent stopped${NC}" - echo -e "${YELLOW}Logs available at: $logfile${NC}" + if [ "$QUIET_MODE" = false ]; then + echo -e "${GREEN}✅ ${name} agent stopped${NC}" + echo -e "${YELLOW}Logs available at: $logfile${NC}" + fi return 0 } @@ -234,7 +250,9 @@ run_test() { local tutorial_path=$1 local name=$(basename "$tutorial_path") - echo -e "${YELLOW}🧪 Running tests for ${name}...${NC}" + if [ "$QUIET_MODE" = false ]; then + echo -e "${YELLOW}🧪 Running tests for ${name}...${NC}" + fi # Check if tutorial directory exists if [[ ! -d "$tutorial_path" ]]; then @@ -265,8 +283,11 @@ run_test() { echo -e "${YELLOW}🔄 Retrying tests (attempt $((retry_count + 1))/$max_retries)...${NC}" fi + # Always show pytest output, even in quiet mode + echo "========== PYTEST OUTPUT ==========" uv run pytest tests/test_agent.py -v -s exit_code=$? + echo "========== END PYTEST OUTPUT ==========" if [ $exit_code -eq 0 ]; then break @@ -294,10 +315,12 @@ run_test() { execute_tutorial_test() { local tutorial=$1 - echo "" - echo "--------------------------------------------------------------------------------" - echo "Testing: $tutorial" - echo "--------------------------------------------------------------------------------" + if [ "$QUIET_MODE" = false ]; then + echo "" + echo "--------------------------------------------------------------------------------" + echo "Testing: $tutorial" + echo "--------------------------------------------------------------------------------" + fi # Start the agent if ! start_agent "$tutorial"; then @@ -338,12 +361,12 @@ check_built_wheel() { return 1 } - # Check if wheel exists - local wheel_file=$(ls dist/agentex_sdk-*.whl 2>/dev/null | head -n1) + # Check if wheel exists in dist directory at repo root + local wheel_file=$(ls /home/runner/work/*/*/dist/agentex_sdk-*.whl 2>/dev/null | head -n1) if [[ -z "$wheel_file" ]]; then echo -e "${RED}❌ No built wheel found in dist/agentex_sdk-*.whl${NC}" echo -e "${YELLOW}💡 Please build the local SDK first by running: uv build${NC}" - echo -e "${YELLOW}💡 From the repo root directory: $(pwd)${NC}" + echo -e "${YELLOW}💡 From the repo root directory${NC}" cd "$original_dir" return 1 fi @@ -378,6 +401,7 @@ main() { echo "Usage:" echo " ./run_agent_test.sh # Run single tutorial test" echo " ./run_agent_test.sh --build-cli # Build CLI from source and run test" + echo " ./run_agent_test.sh --build-cli --quiet # Build CLI and run test (minimal output)" echo " ./run_agent_test.sh --view-logs # View logs for specific tutorial" echo " ./run_agent_test.sh --view-logs # View most recent agent logs" echo "" @@ -387,10 +411,12 @@ main() { exit 1 fi - echo "================================================================================" - echo "Running Tutorial Test: $TUTORIAL_PATH" - echo "================================================================================" - echo "" + if [ "$QUIET_MODE" = false ]; then + echo "================================================================================" + echo "Running Tutorial Test: $TUTORIAL_PATH" + echo "================================================================================" + echo "" + fi # Check prerequisites check_prerequisites @@ -408,16 +434,20 @@ main() { # Execute the single tutorial test if execute_tutorial_test "$TUTORIAL_PATH"; then - echo "" - echo "================================================================================" - echo -e "${GREEN}🎉 Test passed for: $TUTORIAL_PATH${NC}" - echo "================================================================================" + if [ "$QUIET_MODE" = false ]; then + echo "" + echo "================================================================================" + echo -e "${GREEN}🎉 Test passed for: $TUTORIAL_PATH${NC}" + echo "================================================================================" + fi exit 0 else - echo "" - echo "================================================================================" - echo -e "${RED}❌ Test failed for: $TUTORIAL_PATH${NC}" - echo "================================================================================" + if [ "$QUIET_MODE" = false ]; then + echo "" + echo "================================================================================" + echo -e "${RED}❌ Test failed for: $TUTORIAL_PATH${NC}" + echo "================================================================================" + fi exit 1 fi } From 550d043abcb48b8e2489d6295a73fb066b57925b Mon Sep 17 00:00:00 2001 From: Roxanne Farhad Date: Mon, 3 Nov 2025 13:49:50 -0500 Subject: [PATCH 22/30] adding the pytest stuff --- .github/workflows/agentex-tutorials-test.yml | 3 ++- examples/tutorials/run_agent_test.sh | 25 ++++++++++++++------ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/.github/workflows/agentex-tutorials-test.yml b/.github/workflows/agentex-tutorials-test.yml index 0af6e77a..ce552a96 100644 --- a/.github/workflows/agentex-tutorials-test.yml +++ b/.github/workflows/agentex-tutorials-test.yml @@ -158,8 +158,9 @@ jobs: echo "Port: $port" | tee -a "$test_output_file" echo "========================================" | tee -a "$test_output_file" + # Use stdbuf to ensure unbuffered output for real-time visibility AGENTEX_API_BASE_URL="http://localhost:5003" \ - ./run_agent_test.sh --build-cli --quiet "$tutorial" 2>&1 | tee -a "$test_output_file" + stdbuf -oL -eL ./run_agent_test.sh --build-cli --quiet "$tutorial" 2>&1 | tee -a "$test_output_file" exit_code=${PIPESTATUS[0]} if [ $exit_code -eq 0 ]; then diff --git a/examples/tutorials/run_agent_test.sh b/examples/tutorials/run_agent_test.sh index 42be1524..b2e7c8c9 100755 --- a/examples/tutorials/run_agent_test.sh +++ b/examples/tutorials/run_agent_test.sh @@ -68,16 +68,26 @@ check_prerequisites() { wait_for_agent_ready() { local name=$1 local logfile="/tmp/agentex-${name}.log" - local timeout=30 # seconds + local timeout=45 # seconds - increased to account for package installation time local elapsed=0 - echo -e "${YELLOW}⏳ Waiting for ${name} agent to be ready...${NC}" + if [ "$QUIET_MODE" = false ]; then + echo -e "${YELLOW}⏳ Waiting for ${name} agent to be ready...${NC}" + fi while [ $elapsed -lt $timeout ]; do - if grep -q "Application startup complete" "$logfile" 2>/dev/null || \ - grep -q "Running workers for task queue" "$logfile" 2>/dev/null; then - echo -e "${GREEN}✅ ${name} agent is ready${NC}" - return 0 + # Check if agent is successfully registered + if grep -q "Successfully registered agent" "$logfile" 2>/dev/null; then + + # For temporal agents, also wait for workers to be ready + if [[ "$tutorial_path" == *"temporal"* ]]; then + # This is a temporal agent - wait for workers too + if grep -q "Running workers for task queue" "$logfile" 2>/dev/null; then + return 0 + fi + else + return 0 + fi fi sleep 1 ((elapsed++)) @@ -285,7 +295,8 @@ run_test() { # Always show pytest output, even in quiet mode echo "========== PYTEST OUTPUT ==========" - uv run pytest tests/test_agent.py -v -s + # Use unbuffered output for real-time visibility + PYTHONUNBUFFERED=1 uv run pytest tests/test_agent.py -v -s --tb=short exit_code=$? echo "========== END PYTEST OUTPUT ==========" From 258045d51a5df2428602614418d6d4b1298d6acd Mon Sep 17 00:00:00 2001 From: Roxanne Farhad Date: Mon, 3 Nov 2025 14:04:50 -0500 Subject: [PATCH 23/30] simplifying to matrix --- .github/workflows/agentex-tutorials-test.yml | 345 ++----------------- examples/tutorials/run_agent_test.sh | 48 +-- 2 files changed, 42 insertions(+), 351 deletions(-) diff --git a/.github/workflows/agentex-tutorials-test.yml b/.github/workflows/agentex-tutorials-test.yml index ce552a96..8a1bf0a9 100644 --- a/.github/workflows/agentex-tutorials-test.yml +++ b/.github/workflows/agentex-tutorials-test.yml @@ -4,10 +4,31 @@ on: workflow_dispatch: jobs: - test-tutorials: - timeout-minutes: 15 - name: test-tutorials + find-tutorials: runs-on: ubuntu-latest + outputs: + tutorials: ${{ steps.get-tutorials.outputs.tutorials }} + steps: + - name: Checkout agentex-python repo + uses: actions/checkout@v4 + + - name: Find all tutorials + id: get-tutorials + run: | + cd examples/tutorials + tutorials=$(find . -name "manifest.yaml" -exec dirname {} \; | sort | sed 's|^\./||' | jq -R -s -c 'split("\n") | map(select(length > 0))') + echo "tutorials=$tutorials" >> $GITHUB_OUTPUT + echo "Found tutorials: $tutorials" + + test-tutorial: + needs: find-tutorials + runs-on: ubuntu-latest + timeout-minutes: 15 + strategy: + matrix: + tutorial: ${{ fromJson(needs.find-tutorials.outputs.tutorials) }} + fail-fast: false + name: test-${{ matrix.tutorial }} steps: - name: Checkout agentex-python repo @@ -34,15 +55,14 @@ jobs: sudo chmod +x /usr/local/bin/yq # Add extra_hosts to agentex service to make host.docker.internal work - # This allows the AgentEx container to reach the GitHub runner host yq eval '.services.agentex.extra_hosts = ["host.docker.internal:host-gateway"]' -i docker-compose.yml echo "✅ Added extra_hosts configuration to agentex service" - - name: Navigate to scale-agentex repo + - name: Start AgentEx Server run: | cd scale-agentex/agentex - echo "🚀 Starting dependencies (Postgres, Redis, Temporal, MongoDB)..." + echo "🚀 Starting AgentEx server and dependencies..." # Start all services docker compose up -d @@ -77,316 +97,11 @@ jobs: echo "✅ SDK built successfully" ls -la dist/ - - name: Run Parallel Tutorial Tests + - name: Test Tutorial working-directory: ./examples/tutorials env: OPENAI_API_KEY: ${{ secrets.TUTORIAL_OPENAI_API_KEY }} run: | - # Verify uv is working - echo "UV version: $(uv --version)" - echo "UV path: $(which uv)" - - # Start background job to poll AgentEx container logs and write to file - ( - echo "AgentEx container log polling started at $(date)" > /tmp/agentex_container_logs.txt - - # Function to get container logs - get_logs() { - echo "=== AgentEx Container Logs $(date) ===" >> /tmp/agentex_container_logs.txt - docker logs agentex --tail=20 2>/dev/null >> /tmp/agentex_container_logs.txt || { - echo "⚠️ Failed to get logs from 'agentex' container" >> /tmp/agentex_container_logs.txt - echo "Available containers:" >> /tmp/agentex_container_logs.txt - docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Image}}" >> /tmp/agentex_container_logs.txt - } 2>/dev/null - echo "=== End Logs ===" >> /tmp/agentex_container_logs.txt - echo "" >> /tmp/agentex_container_logs.txt - } - - # Poll logs every 10 seconds during test execution - while true; do - get_logs - sleep 10 - done - ) & - - LOG_POLLER_PID=$! - echo "📋 AgentEx log polling started in background (PID: $LOG_POLLER_PID)" - - - # Find all tutorial directories - tutorial_paths=() - for dir in $(find . -name "manifest.yaml" -exec dirname {} \; | sort); do - tutorial_paths+=("${dir#./}") # Remove leading ./ - done - - echo "Found ${#tutorial_paths[@]} tutorials:" - printf ' %s\n' "${tutorial_paths[@]}" - - # Run tests in parallel with unique ports - pids=() - failed_tests=() - passed_tests=() - - # Run all tutorial tests - for i in "${!tutorial_paths[@]}"; do - tutorial="${tutorial_paths[$i]}" - port=$((8000 + i)) - - echo "" - echo "=========================================" - echo "Starting test $((i+1))/${#tutorial_paths[@]}: $tutorial (port $port)" - echo "=========================================" - - # Modify manifest.yaml to use unique port - manifest_path="$tutorial/manifest.yaml" - if [ -f "$manifest_path" ]; then - # Backup original manifest - cp "$manifest_path" "$manifest_path.backup" - - # Update port in manifest (modify the line containing 'port: 8000' or 'port: XXXX') - sed -i "s/port: [0-9]*/port: $port/" "$manifest_path" - - # Keep host_address as host.docker.internal for CI (allows Docker container to reach GitHub runner host) - # Note: The AgentEx server runs in Docker and needs host.docker.internal to reach the tutorial agent on the host - fi - - - # Run test in background with unique port and show pytest output in real-time - ( - test_output_file="/tmp/test_output_$i.log" - echo "Running test: $tutorial" | tee "$test_output_file" - echo "Port: $port" | tee -a "$test_output_file" - echo "========================================" | tee -a "$test_output_file" - - # Use stdbuf to ensure unbuffered output for real-time visibility - AGENTEX_API_BASE_URL="http://localhost:5003" \ - stdbuf -oL -eL ./run_agent_test.sh --build-cli --quiet "$tutorial" 2>&1 | tee -a "$test_output_file" - - exit_code=${PIPESTATUS[0]} - if [ $exit_code -eq 0 ]; then - echo "✅ PASSED: $tutorial (port $port)" - echo "$tutorial" > "/tmp/passed_$i.txt" - echo "$test_output_file" > "/tmp/passed_output_$i.txt" - else - echo "❌ FAILED: $tutorial (port $port)" - echo "$tutorial" > "/tmp/failed_$i.txt" - echo "$test_output_file" > "/tmp/failed_output_$i.txt" - fi - exit $exit_code - ) & - - pids+=($!) - done - - # Wait for all tests to complete - echo "" - echo "Waiting for all tests to complete..." - for pid in "${pids[@]}"; do - wait "$pid" - done - - # Restore all original manifests - echo "" - echo "Restoring original manifest files..." - for tutorial in "${tutorial_paths[@]}"; do - if [ -f "$tutorial/manifest.yaml.backup" ]; then - mv "$tutorial/manifest.yaml.backup" "$tutorial/manifest.yaml" - echo "Restored $tutorial/manifest.yaml" - fi - done - - # Collect results - for i in "${!tutorial_paths[@]}"; do - if [ -f "/tmp/passed_$i.txt" ]; then - passed_tests+=($(cat "/tmp/passed_$i.txt")) - elif [ -f "/tmp/failed_$i.txt" ]; then - failed_tests+=($(cat "/tmp/failed_$i.txt")) - fi - done - - - # Stop the background log poller - echo "🛑 Stopping AgentEx log poller (PID: $LOG_POLLER_PID)" - kill $LOG_POLLER_PID 2>/dev/null || echo "Log poller already stopped" - - # Print summary - echo "" - echo "=========================================" - echo "TEST SUMMARY" - echo "=========================================" - echo "Total: ${#tutorial_paths[@]}" - echo "Passed: ${#passed_tests[@]}" - echo "Failed: ${#failed_tests[@]}" - - if [ ${#failed_tests[@]} -gt 0 ]; then - echo "" - echo "Failed tests:" - for test in "${failed_tests[@]}"; do - echo " ❌ $test" - done - else - echo "" - echo "🎉 All tests passed!" - fi - - # Show comprehensive pytest summary - echo "" - echo "=========================================" - echo "PYTEST RESULTS SUMMARY" - echo "=========================================" - - # Collect all pytest results - total_passed_tests=0 - total_failed_tests=0 - total_pytest_tests=0 - - echo "" - echo "📊 PYTEST EXECUTION SUMMARY:" - echo "----------------------------------------" - - for i in "${!tutorial_paths[@]}"; do - tutorial="${tutorial_paths[$i]}" - output_file="/tmp/test_output_$i.log" - - if [ -f "$output_file" ]; then - # Extract pytest summary from each test - if grep -q "PYTEST OUTPUT" "$output_file"; then - pytest_section=$(sed -n '/========== PYTEST OUTPUT ==========/,/========== END PYTEST OUTPUT ==========/p' "$output_file") - - # Count individual test results in this tutorial - test_passed=$(echo "$pytest_section" | grep -c "PASSED" || echo "0") - test_failed=$(echo "$pytest_section" | grep -c "FAILED" || echo "0") - test_errors=$(echo "$pytest_section" | grep -c "ERROR" || echo "0") - - if [ "$test_passed" -gt 0 ] || [ "$test_failed" -gt 0 ] || [ "$test_errors" -gt 0 ]; then - tutorial_total=$((test_passed + test_failed + test_errors)) - total_pytest_tests=$((total_pytest_tests + tutorial_total)) - total_passed_tests=$((total_passed_tests + test_passed)) - total_failed_tests=$((total_failed_tests + test_failed + test_errors)) - - if [ "$test_failed" -gt 0 ] || [ "$test_errors" -gt 0 ]; then - echo "❌ $tutorial: $tutorial_total tests ($test_passed passed, $test_failed failed, $test_errors errors)" - else - echo "✅ $tutorial: $tutorial_total tests ($test_passed passed)" - fi - else - echo "⚠️ $tutorial: No pytest results found" - fi - else - echo "⚠️ $tutorial: No pytest output detected" - fi - else - echo "⚠️ $tutorial: No output file found" - fi - done - - echo "----------------------------------------" - echo "🏁 OVERALL PYTEST SUMMARY:" - echo " Total pytest tests run: $total_pytest_tests" - echo " Total pytest tests passed: $total_passed_tests" - echo " Total pytest tests failed: $total_failed_tests" - echo "" - - # Show detailed results for failed tests only - if [ ${#failed_tests[@]} -gt 0 ]; then - echo "❌ DETAILED FAILURE ANALYSIS:" - echo "----------------------------------------" - for i in "${!tutorial_paths[@]}"; do - if [ -f "/tmp/failed_$i.txt" ]; then - test_name=$(cat "/tmp/failed_$i.txt") - output_file=$(cat "/tmp/failed_output_$i.txt") - echo "" - echo "📋 FAILED: $test_name" - echo "----------------------------------------" - if [ -f "$output_file" ]; then - # Show just the pytest failure details - if grep -q "PYTEST OUTPUT" "$output_file"; then - echo "Pytest failure details:" - sed -n '/========== PYTEST OUTPUT ==========/,/========== END PYTEST OUTPUT ==========/p' "$output_file" - else - echo "No pytest output found. Showing last 40 lines:" - tail -40 "$output_file" - fi - else - echo "No output file found" - fi - echo "----------------------------------------" - fi - done - fi - - if [ ${#failed_tests[@]} -gt 0 ]; then - exit 1 - fi - - - name: Debug Logs for Failed Tests - if: always() - run: | - cd scale-agentex/agentex - - echo "" - echo "================================================================================" - echo "🐛 DEBUG LOGS (for troubleshooting)" - echo "================================================================================" - - # Show collected AgentEx server container logs - echo "" - echo "=========================================" - echo "AGENTEX SERVER LOGS (COLLECTED DURING TESTS)" - echo "=========================================" - if [ -f "/tmp/agentex_container_logs.txt" ]; then - echo "📋 AgentEx server logs collected during test execution:" - echo "----------------------------------------" - cat /tmp/agentex_container_logs.txt - echo "----------------------------------------" - else - echo "⚠️ No AgentEx container logs file found" - echo "📋 Attempting to get current container logs:" - echo "----------------------------------------" - docker logs agentex --tail=50 2>/dev/null || { - echo "❌ Failed to get logs from 'agentex' container" - echo "Available containers:" - docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Image}}" - } - echo "----------------------------------------" - fi - - # Show tutorial agent logs for failed tests - cd ../../examples/tutorials - - # Check if there were any failed tests - failed_tests=() - for i in {0..20}; do # Check up to 20 possible tests - if [ -f "/tmp/failed_$i.txt" ]; then - failed_tests+=($(cat "/tmp/failed_$i.txt")) - fi - done - - if [ ${#failed_tests[@]} -gt 0 ]; then - echo "" - echo "=========================================" - echo "TUTORIAL AGENT LOGS FOR FAILED TESTS" - echo "=========================================" - - for test in "${failed_tests[@]}"; do - test_name=$(basename "$test") - logfile="/tmp/agentex-${test_name}.log" - - echo "" - echo "📋 Tutorial agent logs for $test:" - echo "----------------------------------------" - - if [ -f "$logfile" ]; then - echo "Tutorial agent logs (last 100 lines):" - tail -100 "$logfile" - else - echo "⚠️ No agent log file found at: $logfile" - echo "Available agent log files:" - ls -la /tmp/agentex-*.log 2>/dev/null || echo " (none)" - fi - echo "----------------------------------------" - done - else - echo "" - echo "✅ No failed tests - no agent logs to show" - fi + echo "Testing tutorial: ${{ matrix.tutorial }}" + AGENTEX_API_BASE_URL="http://localhost:5003" \ + ./run_agent_test.sh --build-cli "${{ matrix.tutorial }}" diff --git a/examples/tutorials/run_agent_test.sh b/examples/tutorials/run_agent_test.sh index b2e7c8c9..c5729d49 100755 --- a/examples/tutorials/run_agent_test.sh +++ b/examples/tutorials/run_agent_test.sh @@ -30,15 +30,12 @@ AGENTEX_SERVER_PORT=5003 TUTORIAL_PATH="" VIEW_LOGS=false BUILD_CLI=false -QUIET_MODE=false for arg in "$@"; do if [[ "$arg" == "--view-logs" ]]; then VIEW_LOGS=true elif [[ "$arg" == "--build-cli" ]]; then BUILD_CLI=true - elif [[ "$arg" == "--quiet" ]]; then - QUIET_MODE=true else TUTORIAL_PATH="$arg" fi @@ -59,9 +56,7 @@ check_prerequisites() { exit 1 fi - if [ "$QUIET_MODE" = false ]; then - echo -e "${GREEN}✅ Prerequisites check passed${NC}" - fi + echo -e "${GREEN}✅ Prerequisites check passed${NC}" } # Function to wait for agent to be ready @@ -71,9 +66,7 @@ wait_for_agent_ready() { local timeout=45 # seconds - increased to account for package installation time local elapsed=0 - if [ "$QUIET_MODE" = false ]; then - echo -e "${YELLOW}⏳ Waiting for ${name} agent to be ready...${NC}" - fi + echo -e "${YELLOW}⏳ Waiting for ${name} agent to be ready...${NC}" while [ $elapsed -lt $timeout ]; do # Check if agent is successfully registered @@ -111,9 +104,7 @@ start_agent() { local name=$(basename "$tutorial_path") local logfile="/tmp/agentex-${name}.log" - if [ "$QUIET_MODE" = false ]; then - echo -e "${YELLOW}🚀 Starting ${name} agent...${NC}" - fi + echo -e "${YELLOW}🚀 Starting ${name} agent...${NC}" # Check if tutorial directory exists if [[ ! -d "$tutorial_path" ]]; then @@ -159,9 +150,7 @@ start_agent() { cd "$original_dir" echo "$pid" > "/tmp/agentex-${name}.pid" - if [ "$QUIET_MODE" = false ]; then - echo -e "${GREEN}✅ ${name} agent started (PID: $pid, logs: $logfile)${NC}" - fi + echo -e "${GREEN}✅ ${name} agent started (PID: $pid, logs: $logfile)${NC}" # Wait for agent to be ready if ! wait_for_agent_ready "$name"; then @@ -219,9 +208,7 @@ stop_agent() { local pidfile="/tmp/agentex-${name}.pid" local logfile="/tmp/agentex-${name}.log" - if [ "$QUIET_MODE" = false ]; then - echo -e "${YELLOW}🛑 Stopping ${name} agent...${NC}" - fi + echo -e "${YELLOW}🛑 Stopping ${name} agent...${NC}" # Check if PID file exists if [[ ! -f "$pidfile" ]]; then @@ -234,22 +221,16 @@ stop_agent() { # Check if process is running and kill it if kill -0 "$pid" 2>/dev/null; then - if [ "$QUIET_MODE" = false ]; then - echo -e "${YELLOW}Stopping ${name} agent (PID: $pid)${NC}" - fi + echo -e "${YELLOW}Stopping ${name} agent (PID: $pid)${NC}" kill "$pid" 2>/dev/null || true rm -f "$pidfile" else - if [ "$QUIET_MODE" = false ]; then - echo -e "${YELLOW}⚠️ ${name} agent was not running${NC}" - fi + echo -e "${YELLOW}⚠️ ${name} agent was not running${NC}" rm -f "$pidfile" fi - if [ "$QUIET_MODE" = false ]; then - echo -e "${GREEN}✅ ${name} agent stopped${NC}" - echo -e "${YELLOW}Logs available at: $logfile${NC}" - fi + echo -e "${GREEN}✅ ${name} agent stopped${NC}" + echo -e "${YELLOW}Logs available at: $logfile${NC}" return 0 } @@ -260,9 +241,7 @@ run_test() { local tutorial_path=$1 local name=$(basename "$tutorial_path") - if [ "$QUIET_MODE" = false ]; then - echo -e "${YELLOW}🧪 Running tests for ${name}...${NC}" - fi + echo -e "${YELLOW}🧪 Running tests for ${name}...${NC}" # Check if tutorial directory exists if [[ ! -d "$tutorial_path" ]]; then @@ -293,12 +272,9 @@ run_test() { echo -e "${YELLOW}🔄 Retrying tests (attempt $((retry_count + 1))/$max_retries)...${NC}" fi - # Always show pytest output, even in quiet mode - echo "========== PYTEST OUTPUT ==========" - # Use unbuffered output for real-time visibility - PYTHONUNBUFFERED=1 uv run pytest tests/test_agent.py -v -s --tb=short + # Stream pytest output directly in real-time + uv run pytest tests/test_agent.py -v -s exit_code=$? - echo "========== END PYTEST OUTPUT ==========" if [ $exit_code -eq 0 ]; then break From cebe84d3d7d15182cb59b649fea844c2eeade0d9 Mon Sep 17 00:00:00 2001 From: Roxanne Farhad Date: Mon, 3 Nov 2025 14:17:16 -0500 Subject: [PATCH 24/30] fixing tests --- .github/workflows/agentex-tutorials-test.yml | 125 ++++++++++++++++++ .../project/workflow.py | 75 ++++++----- 2 files changed, 164 insertions(+), 36 deletions(-) diff --git a/.github/workflows/agentex-tutorials-test.yml b/.github/workflows/agentex-tutorials-test.yml index 8a1bf0a9..4af5e6ae 100644 --- a/.github/workflows/agentex-tutorials-test.yml +++ b/.github/workflows/agentex-tutorials-test.yml @@ -101,7 +101,132 @@ jobs: working-directory: ./examples/tutorials env: OPENAI_API_KEY: ${{ secrets.TUTORIAL_OPENAI_API_KEY }} + HEALTH_CHECK_PORT: 8080 # Use non-privileged port for temporal worker health checks run: | echo "Testing tutorial: ${{ matrix.tutorial }}" AGENTEX_API_BASE_URL="http://localhost:5003" \ ./run_agent_test.sh --build-cli "${{ matrix.tutorial }}" + + - name: Upload Test Results + if: always() + uses: actions/upload-artifact@v4 + with: + name: test-results-${{ replace(matrix.tutorial, '/', '-') }} + path: | + /tmp/agentex-*.log + retention-days: 1 + + test-summary: + if: always() + needs: [find-tutorials, test-tutorial] + runs-on: ubuntu-latest + name: Test Summary + steps: + - name: Download All Test Results + uses: actions/download-artifact@v4 + with: + path: test-results + pattern: test-results-* + + - name: Generate Test Summary + run: | + echo "# 🧪 Tutorial Tests Summary" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + # Get tutorial list from needs context + tutorials='${{ needs.find-tutorials.outputs.tutorials }}' + + # Initialize counters + total_tutorials=0 + passed_tutorials=0 + failed_tutorials=0 + + # Arrays to track results + passed_tests=() + failed_tests=() + + echo "## 📊 Overall Results" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + # Process each tutorial result + for tutorial_dir in test-results/test-results-*/; do + if [ -d "$tutorial_dir" ]; then + # Extract sanitized name and convert back to original tutorial path + sanitized_name=$(basename "$tutorial_dir" | sed 's/test-results-//') + tutorial_name=$(echo "$sanitized_name" | sed 's/-/\//g') + total_tutorials=$((total_tutorials + 1)) + + # Determine success/failure based on presence of error logs or patterns + if find "$tutorial_dir" -name "*.log" -exec grep -l "FAILED\|ERROR\|Traceback" {} \; | head -1 >/dev/null; then + failed_tutorials=$((failed_tutorials + 1)) + failed_tests+=("$tutorial_name") + else + passed_tutorials=$((passed_tutorials + 1)) + passed_tests+=("$tutorial_name") + fi + fi + done + + # Show summary stats + echo "| Status | Count |" >> $GITHUB_STEP_SUMMARY + echo "|--------|-------|" >> $GITHUB_STEP_SUMMARY + echo "| ✅ **Passed** | **$passed_tutorials** |" >> $GITHUB_STEP_SUMMARY + echo "| ❌ **Failed** | **$failed_tutorials** |" >> $GITHUB_STEP_SUMMARY + echo "| 📊 **Total** | **$total_tutorials** |" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + # Show passed tests + if [ $passed_tutorials -gt 0 ]; then + echo "## ✅ Passed Tutorials ($passed_tutorials)" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + for test in "${passed_tests[@]}"; do + echo "- ✅ \`$test\`" >> $GITHUB_STEP_SUMMARY + done + echo "" >> $GITHUB_STEP_SUMMARY + fi + + # Show failed tests with details + if [ $failed_tutorials -gt 0 ]; then + echo "## ❌ Failed Tutorials ($failed_tutorials)" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + for test in "${failed_tests[@]}"; do + echo "### 🔍 \`$test\`" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + # Find the log file for this test (convert back to sanitized name) + sanitized_test_name=$(echo "$test" | sed 's/\//-/g') + log_file=$(find "test-results/test-results-$sanitized_test_name" -name "*.log" | head -1) + if [ -f "$log_file" ]; then + # Extract pytest failures + if grep -q "FAILED\|ERROR" "$log_file"; then + echo "**Failed Tests:**" >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + grep -A 5 -B 1 "FAILED\|ERROR" "$log_file" | head -20 >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + fi + + # Show any Python tracebacks + if grep -q "Traceback" "$log_file"; then + echo "**Error Details:**" >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + # Get the last traceback in the file + awk '/Traceback \(most recent call last\)/{p=1} p{print} /^[^ ]/ && p && !/Traceback/{p=0}' "$log_file" | tail -20 >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + fi + else + echo "_No log file found for detailed error analysis_" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + fi + done + fi + + # Set exit code based on results + if [ $failed_tutorials -gt 0 ]; then + echo "❌ Some tutorials failed. Check the details above." >> $GITHUB_STEP_SUMMARY + exit 1 + else + echo "🎉 All tutorials passed successfully!" >> $GITHUB_STEP_SUMMARY + fi diff --git a/examples/tutorials/10_agentic/10_temporal/070_open_ai_agents_sdk_tools/project/workflow.py b/examples/tutorials/10_agentic/10_temporal/070_open_ai_agents_sdk_tools/project/workflow.py index 49d7b9ea..3a84c900 100644 --- a/examples/tutorials/10_agentic/10_temporal/070_open_ai_agents_sdk_tools/project/workflow.py +++ b/examples/tutorials/10_agentic/10_temporal/070_open_ai_agents_sdk_tools/project/workflow.py @@ -5,7 +5,7 @@ PATTERN 1: Simple External Tools as Activities (activity_as_tool) - Convert individual Temporal activities directly into agent tools -- 1:1 mapping between tool calls and activities +- 1:1 mapping between tool calls and activities - Best for: single non-deterministic operations (API calls, DB queries) - Example: get_weather activity → weather tool @@ -19,30 +19,30 @@ WHY THIS APPROACH IS GAME-CHANGING: =================================== -There's a crucial meta-point that should be coming through here: **why is this different?** -This approach is truly transactional because of how the `await` works in Temporal workflows. -Consider a "move money" example - if the operation fails between the withdraw and deposit, -Temporal will resume exactly where it left off - the agent gets real-world flexibility even +There's a crucial meta-point that should be coming through here: **why is this different?** +This approach is truly transactional because of how the `await` works in Temporal workflows. +Consider a "move money" example - if the operation fails between the withdraw and deposit, +Temporal will resume exactly where it left off - the agent gets real-world flexibility even if systems die. -**Why even use Temporal? Why are we adding complexity?** The gain is enormous when you +**Why even use Temporal? Why are we adding complexity?** The gain is enormous when you consider what happens without it: -In a traditional approach without Temporal, if you withdraw money but then the system crashes -before depositing, you're stuck in a broken state. The money has been withdrawn, but never -deposited. In a banking scenario, you can't just "withdraw again" - the money is already gone +In a traditional approach without Temporal, if you withdraw money but then the system crashes +before depositing, you're stuck in a broken state. The money has been withdrawn, but never +deposited. In a banking scenario, you can't just "withdraw again" - the money is already gone from the source account, and your agent has no way to recover or know what state it was in. -This is why you can't build very complicated agents without this confidence in transactional +This is why you can't build very complicated agents without this confidence in transactional behavior. Temporal gives us: - **Guaranteed execution**: If the workflow starts, it will complete, even through failures - **Exact resumption**: Pick up exactly where we left off, not start over -- **Transactional integrity**: Either both operations complete, or the workflow can be designed +- **Transactional integrity**: Either both operations complete, or the workflow can be designed to handle partial completion - **Production reliability**: Build agents that can handle real-world complexity and failures -Without this foundation, agents remain fragile toys. With Temporal, they become production-ready +Without this foundation, agents remain fragile toys. With Temporal, they become production-ready systems that can handle the complexities of the real world. """ @@ -72,11 +72,13 @@ logger = make_logger(__name__) + @workflow.defn(name=environment_variables.WORKFLOW_NAME) class ExampleTutorialWorkflow(BaseWorkflow): """ Minimal async workflow template for AgentEx Temporal agents. """ + def __init__(self): super().__init__(display_name=environment_variables.AGENT_NAME) self._complete_task = False @@ -85,35 +87,35 @@ def __init__(self): @workflow.signal(name=SignalName.RECEIVE_EVENT) async def on_task_event_send(self, params: SendEventParams) -> None: logger.info(f"Received task message instruction: {params}") - - # Echo back the client's message to show it in the UI. This is not done by default + + # Echo back the client's message to show it in the UI. This is not done by default # so the agent developer has full control over what is shown to the user. await adk.messages.create(task_id=params.task.id, content=params.event.content) # ============================================================================ # OpenAI Agents SDK + Temporal Integration: Two Patterns for Tool Creation # ============================================================================ - + # #### When to Use Activities for Tools # # You'll want to use the activity pattern for tools in the following scenarios: # - # - **API calls within the tool**: Whenever your tool makes an API call (external - # service, database, etc.), you must wrap it as an activity since these are + # - **API calls within the tool**: Whenever your tool makes an API call (external + # service, database, etc.), you must wrap it as an activity since these are # non-deterministic operations that could fail or return different results - # - **Idempotent single operations**: When the tool performs an already idempotent - # single call that you want to ensure gets executed reliably with Temporal's retry + # - **Idempotent single operations**: When the tool performs an already idempotent + # single call that you want to ensure gets executed reliably with Temporal's retry # guarantees # - # Let's start with the case where it is non-deterministic. If this is the case, we - # want this tool to be an activity to guarantee that it will be executed. The way to - # do this is to add some syntax to make the tool call an activity. Let's create a tool - # that gives us the weather and create a weather agent. For this example, we will just - # return a hard-coded string but we can easily imagine this being an API call to a - # weather service which would make it non-deterministic. First we will create a new - # file called `activities.py`. Here we will create a function to get the weather and + # Let's start with the case where it is non-deterministic. If this is the case, we + # want this tool to be an activity to guarantee that it will be executed. The way to + # do this is to add some syntax to make the tool call an activity. Let's create a tool + # that gives us the weather and create a weather agent. For this example, we will just + # return a hard-coded string but we can easily imagine this being an API call to a + # weather service which would make it non-deterministic. First we will create a new + # file called `activities.py`. Here we will create a function to get the weather and # simply add an activity annotation on top. - + # There are TWO key patterns for integrating tools with the OpenAI Agents SDK in Temporal: # # PATTERN 1: Simple External Tools as Activities @@ -147,7 +149,7 @@ async def on_task_event_send(self, params: SendEventParams) -> None: # The get_weather activity will be executed with durability guarantees activity_as_tool( get_weather, # This is defined in activities.py as @activity.defn - start_to_close_timeout=timedelta(seconds=10) + start_to_close_timeout=timedelta(seconds=10), ), ], ) @@ -156,7 +158,7 @@ async def on_task_event_send(self, params: SendEventParams) -> None: result = await Runner.run(weather_agent, params.event.content.content) # ============================================================================ - # PATTERN 2: Multiple Activities Within Tools + # PATTERN 2: Multiple Activities Within Tools # ============================================================================ # Use this pattern when: # - You need multiple sequential non-deterministic operations within one tool @@ -171,7 +173,7 @@ async def on_task_event_send(self, params: SendEventParams) -> None: # # BENEFITS: # - Guaranteed execution order (withdraw THEN deposit) - # - Each step is durable and retryable individually + # - Each step is durable and retryable individually # - Atomic operations from the agent's perspective # - Better than having LLM make multiple separate tool calls @@ -186,7 +188,7 @@ async def on_task_event_send(self, params: SendEventParams) -> None: # move_money, # ], # ) - + # # Run the agent - when it calls move_money tool, it will create TWO activities: # # 1. withdraw_money activity # # 2. deposit_money activity (only after withdraw succeeds) @@ -195,17 +197,17 @@ async def on_task_event_send(self, params: SendEventParams) -> None: # ============================================================================ # PATTERN COMPARISON SUMMARY: # ============================================================================ - # + # # Pattern 1 (activity_as_tool): | Pattern 2 (function_tool with activities): # - Single activity per tool call | - Multiple activities per tool call - # - 1:1 tool to activity mapping | - 1:many tool to activity mapping + # - 1:1 tool to activity mapping | - 1:many tool to activity mapping # - Simple non-deterministic ops | - Complex multi-step operations # - Let LLM sequence multiple tools | - Code controls activity sequencing # - Example: get_weather, db_lookup | - Example: money_transfer, multi_step_workflow # # BOTH patterns provide: # - Automatic retries and failure recovery - # - Full observability in Temporal UI + # - Full observability in Temporal UI # - Durable execution guarantees # - Seamless integration with OpenAI Agents SDK # ============================================================================ @@ -234,11 +236,12 @@ async def on_task_create(self, params: CreateTaskParams) -> str: await workflow.wait_condition( lambda: self._complete_task, - timeout=None, # Set a timeout if you want to prevent the task from running indefinitely. Generally this is not needed. Temporal can run hundreds of millions of workflows in parallel and more. Only do this if you have a specific reason to do so. + timeout=None, # Set a timeout if you want to prevent the task from running indefinitely. Generally this is not needed. Temporal can run hundreds of millions of workflows in parallel and more. Only do this if you have a specific reason to do so. ) return "Task completed" @workflow.signal async def fulfill_order_signal(self, success: bool) -> None: if success == True: - await self._pending_confirmation.put(True) \ No newline at end of file + await self._pending_confirmation.put(True) + From 95401c04d3ad3ff4d8377d5b290ceadf9076799b Mon Sep 17 00:00:00 2001 From: Roxanne Farhad Date: Mon, 3 Nov 2025 14:32:09 -0500 Subject: [PATCH 25/30] testing this --- .github/workflows/agentex-tutorials-test.yml | 111 ++++++++++++------ .../010_agent_chat/tests/test_agent.py | 29 ++++- 2 files changed, 100 insertions(+), 40 deletions(-) diff --git a/.github/workflows/agentex-tutorials-test.yml b/.github/workflows/agentex-tutorials-test.yml index 4af5e6ae..3b2ae9f4 100644 --- a/.github/workflows/agentex-tutorials-test.yml +++ b/.github/workflows/agentex-tutorials-test.yml @@ -16,9 +16,21 @@ jobs: id: get-tutorials run: | cd examples/tutorials - tutorials=$(find . -name "manifest.yaml" -exec dirname {} \; | sort | sed 's|^\./||' | jq -R -s -c 'split("\n") | map(select(length > 0))') + # Find all tutorials and exclude specific temporal ones + all_tutorials=$(find . -name "manifest.yaml" -exec dirname {} \; | sort | sed 's|^\./||') + + # Filter out the specified temporal tutorials that are being updated + filtered_tutorials=$(echo "$all_tutorials" | grep -v -E "(10_temporal/050_|10_temporal/070_|10_temporal/080_)") + + # Convert to JSON array + tutorials=$(echo "$filtered_tutorials" | jq -R -s -c 'split("\n") | map(select(length > 0))') + echo "tutorials=$tutorials" >> $GITHUB_OUTPUT - echo "Found tutorials: $tutorials" + echo "All tutorials found: $(echo "$all_tutorials" | wc -l)" + echo "Filtered tutorials: $(echo "$filtered_tutorials" | wc -l)" + echo "Excluded tutorials:" + echo "$all_tutorials" | grep -E "(10_temporal/050_|10_temporal/070_|10_temporal/080_)" || echo " (none matched exclusion pattern)" + echo "Final tutorial list: $tutorials" test-tutorial: needs: find-tutorials @@ -101,19 +113,32 @@ jobs: working-directory: ./examples/tutorials env: OPENAI_API_KEY: ${{ secrets.TUTORIAL_OPENAI_API_KEY }} - HEALTH_CHECK_PORT: 8080 # Use non-privileged port for temporal worker health checks + HEALTH_CHECK_PORT: 8080 # Use non-privileged port for temporal worker health checks run: | echo "Testing tutorial: ${{ matrix.tutorial }}" AGENTEX_API_BASE_URL="http://localhost:5003" \ ./run_agent_test.sh --build-cli "${{ matrix.tutorial }}" - name: Upload Test Results + if: always() + run: | + # Sanitize tutorial name for artifact upload + SANITIZED_NAME=$(echo "${{ matrix.tutorial }}" | sed 's/\//-/g') + echo "Uploading test results for: ${{ matrix.tutorial }} (as: test-results-$SANITIZED_NAME)" + + # Create a temporary directory with the sanitized name + mkdir -p "test-results-$SANITIZED_NAME" + cp /tmp/agentex-*.log "test-results-$SANITIZED_NAME/" 2>/dev/null || echo "No log files to copy" + + # Upload using the actions/upload-artifact action + echo "artifact-name=test-results-$SANITIZED_NAME" >> $GITHUB_ENV + + - name: Upload Artifact if: always() uses: actions/upload-artifact@v4 with: - name: test-results-${{ replace(matrix.tutorial, '/', '-') }} - path: | - /tmp/agentex-*.log + name: ${{ env.artifact-name }} + path: test-results-* retention-days: 1 test-summary: @@ -136,6 +161,17 @@ jobs: # Get tutorial list from needs context tutorials='${{ needs.find-tutorials.outputs.tutorials }}' + # Debug: Show what we're working with + echo "🔍 DEBUG: Tutorial list from find-tutorials job:" + echo "$tutorials" + echo "" + echo "🔍 DEBUG: Downloaded artifacts:" + ls -la test-results/ || echo "No test-results directory found" + echo "" + echo "🔍 DEBUG: Artifact contents:" + find test-results/ -type f -name "*.log" || echo "No log files found" + echo "" + # Initialize counters total_tutorials=0 passed_tutorials=0 @@ -156,13 +192,18 @@ jobs: tutorial_name=$(echo "$sanitized_name" | sed 's/-/\//g') total_tutorials=$((total_tutorials + 1)) - # Determine success/failure based on presence of error logs or patterns - if find "$tutorial_dir" -name "*.log" -exec grep -l "FAILED\|ERROR\|Traceback" {} \; | head -1 >/dev/null; then - failed_tutorials=$((failed_tutorials + 1)) - failed_tests+=("$tutorial_name") - else - passed_tutorials=$((passed_tutorials + 1)) - passed_tests+=("$tutorial_name") + # Check if there are any log files in this directory + if find "$tutorial_dir" -name "*.log" -type f | grep -q .; then + # Determine success/failure based on pytest-specific failure patterns + if find "$tutorial_dir" -name "*.log" -exec grep -l "FAILED.*::" {} \; | head -1 >/dev/null || \ + find "$tutorial_dir" -name "*.log" -exec grep -l "=== FAILURES ===" {} \; | head -1 >/dev/null || \ + find "$tutorial_dir" -name "*.log" -exec grep -l "AssertionError" {} \; | head -1 >/dev/null; then + failed_tutorials=$((failed_tutorials + 1)) + failed_tests+=("$tutorial_name") + else + passed_tutorials=$((passed_tutorials + 1)) + passed_tests+=("$tutorial_name") + fi fi fi done @@ -185,42 +226,42 @@ jobs: echo "" >> $GITHUB_STEP_SUMMARY fi - # Show failed tests with details + # Show pytest failures only for failed tests if [ $failed_tutorials -gt 0 ]; then echo "## ❌ Failed Tutorials ($failed_tutorials)" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + # Extract and append pytest failures from each failed test for test in "${failed_tests[@]}"; do - echo "### 🔍 \`$test\`" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - # Find the log file for this test (convert back to sanitized name) sanitized_test_name=$(echo "$test" | sed 's/\//-/g') log_file=$(find "test-results/test-results-$sanitized_test_name" -name "*.log" | head -1) if [ -f "$log_file" ]; then - # Extract pytest failures - if grep -q "FAILED\|ERROR" "$log_file"; then - echo "**Failed Tests:**" >> $GITHUB_STEP_SUMMARY - echo '```' >> $GITHUB_STEP_SUMMARY - grep -A 5 -B 1 "FAILED\|ERROR" "$log_file" | head -20 >> $GITHUB_STEP_SUMMARY - echo '```' >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - fi - - # Show any Python tracebacks - if grep -q "Traceback" "$log_file"; then - echo "**Error Details:**" >> $GITHUB_STEP_SUMMARY - echo '```' >> $GITHUB_STEP_SUMMARY - # Get the last traceback in the file - awk '/Traceback \(most recent call last\)/{p=1} p{print} /^[^ ]/ && p && !/Traceback/{p=0}' "$log_file" | tail -20 >> $GITHUB_STEP_SUMMARY - echo '```' >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY + echo "================================================================================================" >> $GITHUB_STEP_SUMMARY + echo "FAILED: $test" >> $GITHUB_STEP_SUMMARY + echo "================================================================================================" >> $GITHUB_STEP_SUMMARY + + # Extract pytest output between the delimiters, or show pytest summary if no delimiters + if grep -q "========== PYTEST OUTPUT ==========" "$log_file"; then + sed -n '/========== PYTEST OUTPUT ==========/,/========== END PYTEST OUTPUT ==========/p' "$log_file" | \ + sed '1d;$d' >> $GITHUB_STEP_SUMMARY + else + # If no delimiters, try to extract pytest-related lines + grep -E "(FAILED|ERROR|AssertionError|collected.*items|=====.*=====|::.*FAILED)" "$log_file" >> $GITHUB_STEP_SUMMARY || \ + echo "No pytest output found in log file" >> $GITHUB_STEP_SUMMARY fi + echo "" >> $GITHUB_STEP_SUMMARY else - echo "_No log file found for detailed error analysis_" >> $GITHUB_STEP_SUMMARY + echo "================================================================================================" >> $GITHUB_STEP_SUMMARY + echo "FAILED: $test (No log file found)" >> $GITHUB_STEP_SUMMARY + echo "================================================================================================" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY fi done + + echo '```' >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY fi # Set exit code based on results diff --git a/examples/tutorials/10_agentic/10_temporal/010_agent_chat/tests/test_agent.py b/examples/tutorials/10_agentic/10_temporal/010_agent_chat/tests/test_agent.py index 025693ec..34862d10 100644 --- a/examples/tutorials/10_agentic/10_temporal/010_agent_chat/tests/test_agent.py +++ b/examples/tutorials/10_agentic/10_temporal/010_agent_chat/tests/test_agent.py @@ -160,7 +160,12 @@ async def test_multi_turn_conversation(self, client: AsyncAgentex, agent_id: str sleep_interval=1.0, ): assert isinstance(message, TaskMessage) - if message.content and message.content.type == "text" and message.content.author == "agent" and message.content.content: + if ( + message.content + and message.content.type == "text" + and message.content.author == "agent" + and message.content.content + ): break # Wait a bit for state to update @@ -177,7 +182,12 @@ async def test_multi_turn_conversation(self, client: AsyncAgentex, agent_id: str timeout=30, sleep_interval=1.0, ): - if message.content and message.content.type == "text" and message.content.author == "agent" and message.content.content: + if ( + message.content + and message.content.type == "text" + and message.content.author == "agent" + and message.content.content + ): response_text = message.content.content.lower() assert "blue" in response_text, f"Expected 'blue' in response but got: {response_text}" found_response = True @@ -211,16 +221,24 @@ async def stream_messages() -> None: # noqa: ANN101 async for event in stream_agent_response( client=client, task_id=task.id, - timeout=20, + timeout=60, ): msg_type = event.get("type") if msg_type == "full": task_message_update = StreamTaskMessageFull.model_validate(event) if task_message_update.parent_task_message and task_message_update.parent_task_message.id: finished_message = await client.messages.retrieve(task_message_update.parent_task_message.id) - if finished_message.content and finished_message.content.type == "text" and finished_message.content.author == "user": + if ( + finished_message.content + and finished_message.content.type == "text" + and finished_message.content.author == "user" + ): user_message_found = True - elif finished_message.content and finished_message.content.type == "text" and finished_message.content.author == "agent": + elif ( + finished_message.content + and finished_message.content.type == "text" + and finished_message.content.author == "agent" + ): agent_response_found = True elif finished_message.content and finished_message.content.type == "reasoning": tool_response_found = True @@ -243,5 +261,6 @@ async def stream_messages() -> None: # noqa: ANN101 assert user_message_found, "User message not found in stream" assert agent_response_found, "Agent response not found in stream" + if __name__ == "__main__": pytest.main([__file__, "-v"]) From bfab5aa344fcdcdb95b54e4a98546a808c85f5b3 Mon Sep 17 00:00:00 2001 From: Roxanne Farhad Date: Mon, 3 Nov 2025 17:03:26 -0500 Subject: [PATCH 26/30] cleaning up --- .github/workflows/agentex-tutorials-test.yml | 145 +----------------- .../040_other_sdks/tests/test_agent.py | 21 ++- examples/tutorials/run_agent_test.sh | 2 +- 3 files changed, 26 insertions(+), 142 deletions(-) diff --git a/.github/workflows/agentex-tutorials-test.yml b/.github/workflows/agentex-tutorials-test.yml index 3b2ae9f4..d40a1727 100644 --- a/.github/workflows/agentex-tutorials-test.yml +++ b/.github/workflows/agentex-tutorials-test.yml @@ -20,7 +20,7 @@ jobs: all_tutorials=$(find . -name "manifest.yaml" -exec dirname {} \; | sort | sed 's|^\./||') # Filter out the specified temporal tutorials that are being updated - filtered_tutorials=$(echo "$all_tutorials" | grep -v -E "(10_temporal/050_|10_temporal/070_|10_temporal/080_)") + filtered_tutorials=$(echo "$all_tutorials" | grep -v -E "(temporal)") # Convert to JSON array tutorials=$(echo "$filtered_tutorials" | jq -R -s -c 'split("\n") | map(select(length > 0))') @@ -119,27 +119,15 @@ jobs: AGENTEX_API_BASE_URL="http://localhost:5003" \ ./run_agent_test.sh --build-cli "${{ matrix.tutorial }}" - - name: Upload Test Results + - name: Record test result + id: test-result if: always() run: | - # Sanitize tutorial name for artifact upload - SANITIZED_NAME=$(echo "${{ matrix.tutorial }}" | sed 's/\//-/g') - echo "Uploading test results for: ${{ matrix.tutorial }} (as: test-results-$SANITIZED_NAME)" - - # Create a temporary directory with the sanitized name - mkdir -p "test-results-$SANITIZED_NAME" - cp /tmp/agentex-*.log "test-results-$SANITIZED_NAME/" 2>/dev/null || echo "No log files to copy" - - # Upload using the actions/upload-artifact action - echo "artifact-name=test-results-$SANITIZED_NAME" >> $GITHUB_ENV - - - name: Upload Artifact - if: always() - uses: actions/upload-artifact@v4 - with: - name: ${{ env.artifact-name }} - path: test-results-* - retention-days: 1 + if [ "${{ steps.run-test.outcome }}" == "success" ]; then + echo "result=passed" >> $GITHUB_OUTPUT + else + echo "result=failed" >> $GITHUB_OUTPUT + fi test-summary: if: always() @@ -147,12 +135,6 @@ jobs: runs-on: ubuntu-latest name: Test Summary steps: - - name: Download All Test Results - uses: actions/download-artifact@v4 - with: - path: test-results - pattern: test-results-* - - name: Generate Test Summary run: | echo "# 🧪 Tutorial Tests Summary" >> $GITHUB_STEP_SUMMARY @@ -160,114 +142,3 @@ jobs: # Get tutorial list from needs context tutorials='${{ needs.find-tutorials.outputs.tutorials }}' - - # Debug: Show what we're working with - echo "🔍 DEBUG: Tutorial list from find-tutorials job:" - echo "$tutorials" - echo "" - echo "🔍 DEBUG: Downloaded artifacts:" - ls -la test-results/ || echo "No test-results directory found" - echo "" - echo "🔍 DEBUG: Artifact contents:" - find test-results/ -type f -name "*.log" || echo "No log files found" - echo "" - - # Initialize counters - total_tutorials=0 - passed_tutorials=0 - failed_tutorials=0 - - # Arrays to track results - passed_tests=() - failed_tests=() - - echo "## 📊 Overall Results" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - - # Process each tutorial result - for tutorial_dir in test-results/test-results-*/; do - if [ -d "$tutorial_dir" ]; then - # Extract sanitized name and convert back to original tutorial path - sanitized_name=$(basename "$tutorial_dir" | sed 's/test-results-//') - tutorial_name=$(echo "$sanitized_name" | sed 's/-/\//g') - total_tutorials=$((total_tutorials + 1)) - - # Check if there are any log files in this directory - if find "$tutorial_dir" -name "*.log" -type f | grep -q .; then - # Determine success/failure based on pytest-specific failure patterns - if find "$tutorial_dir" -name "*.log" -exec grep -l "FAILED.*::" {} \; | head -1 >/dev/null || \ - find "$tutorial_dir" -name "*.log" -exec grep -l "=== FAILURES ===" {} \; | head -1 >/dev/null || \ - find "$tutorial_dir" -name "*.log" -exec grep -l "AssertionError" {} \; | head -1 >/dev/null; then - failed_tutorials=$((failed_tutorials + 1)) - failed_tests+=("$tutorial_name") - else - passed_tutorials=$((passed_tutorials + 1)) - passed_tests+=("$tutorial_name") - fi - fi - fi - done - - # Show summary stats - echo "| Status | Count |" >> $GITHUB_STEP_SUMMARY - echo "|--------|-------|" >> $GITHUB_STEP_SUMMARY - echo "| ✅ **Passed** | **$passed_tutorials** |" >> $GITHUB_STEP_SUMMARY - echo "| ❌ **Failed** | **$failed_tutorials** |" >> $GITHUB_STEP_SUMMARY - echo "| 📊 **Total** | **$total_tutorials** |" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - - # Show passed tests - if [ $passed_tutorials -gt 0 ]; then - echo "## ✅ Passed Tutorials ($passed_tutorials)" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - for test in "${passed_tests[@]}"; do - echo "- ✅ \`$test\`" >> $GITHUB_STEP_SUMMARY - done - echo "" >> $GITHUB_STEP_SUMMARY - fi - - # Show pytest failures only for failed tests - if [ $failed_tutorials -gt 0 ]; then - echo "## ❌ Failed Tutorials ($failed_tutorials)" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - echo '```' >> $GITHUB_STEP_SUMMARY - - # Extract and append pytest failures from each failed test - for test in "${failed_tests[@]}"; do - # Find the log file for this test (convert back to sanitized name) - sanitized_test_name=$(echo "$test" | sed 's/\//-/g') - log_file=$(find "test-results/test-results-$sanitized_test_name" -name "*.log" | head -1) - if [ -f "$log_file" ]; then - echo "================================================================================================" >> $GITHUB_STEP_SUMMARY - echo "FAILED: $test" >> $GITHUB_STEP_SUMMARY - echo "================================================================================================" >> $GITHUB_STEP_SUMMARY - - # Extract pytest output between the delimiters, or show pytest summary if no delimiters - if grep -q "========== PYTEST OUTPUT ==========" "$log_file"; then - sed -n '/========== PYTEST OUTPUT ==========/,/========== END PYTEST OUTPUT ==========/p' "$log_file" | \ - sed '1d;$d' >> $GITHUB_STEP_SUMMARY - else - # If no delimiters, try to extract pytest-related lines - grep -E "(FAILED|ERROR|AssertionError|collected.*items|=====.*=====|::.*FAILED)" "$log_file" >> $GITHUB_STEP_SUMMARY || \ - echo "No pytest output found in log file" >> $GITHUB_STEP_SUMMARY - fi - echo "" >> $GITHUB_STEP_SUMMARY - else - echo "================================================================================================" >> $GITHUB_STEP_SUMMARY - echo "FAILED: $test (No log file found)" >> $GITHUB_STEP_SUMMARY - echo "================================================================================================" >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - fi - done - - echo '```' >> $GITHUB_STEP_SUMMARY - echo "" >> $GITHUB_STEP_SUMMARY - fi - - # Set exit code based on results - if [ $failed_tutorials -gt 0 ]; then - echo "❌ Some tutorials failed. Check the details above." >> $GITHUB_STEP_SUMMARY - exit 1 - else - echo "🎉 All tutorials passed successfully!" >> $GITHUB_STEP_SUMMARY - fi diff --git a/examples/tutorials/10_agentic/00_base/040_other_sdks/tests/test_agent.py b/examples/tutorials/10_agentic/00_base/040_other_sdks/tests/test_agent.py index 13bc084e..7ffe49e6 100644 --- a/examples/tutorials/10_agentic/00_base/040_other_sdks/tests/test_agent.py +++ b/examples/tutorials/10_agentic/00_base/040_other_sdks/tests/test_agent.py @@ -114,7 +114,7 @@ async def test_send_event_and_poll_simple_query(self, client: AsyncAgentex, agen break # Verify state has been updated by polling the states for 10 seconds - for i in range(10): + for i in range(20): if i == 9: raise Exception("Timeout waiting for state updates") states = await client.states.list(agent_id=agent_id, task_id=task.id) @@ -187,7 +187,12 @@ async def test_multi_turn_conversation_with_state(self, client: AsyncAgentex, ag sleep_interval=1.0, ): assert isinstance(message, TaskMessage) - if message.content and message.content.type == "text" and message.content.author == "agent" and message.content.content: + if ( + message.content + and message.content.type == "text" + and message.content.author == "agent" + and message.content.content + ): break ## keep polling the states for 10 seconds for the input_list and turn_number to be updated @@ -216,7 +221,12 @@ async def test_multi_turn_conversation_with_state(self, client: AsyncAgentex, ag timeout=30, sleep_interval=1.0, ): - if message.content and message.content.type == "text" and message.content.author == "agent" and message.content.content: + if ( + message.content + and message.content.type == "text" + and message.content.author == "agent" + and message.content.content + ): response_text = message.content.content.lower() assert "blue" in response_text found_response = True @@ -273,7 +283,10 @@ async def stream_messages() -> None: # For full messages, content is at the top level # For delta messages, we need to check parent_task_message if msg_type == "full": - if event.get("content", {}).get("type") == "text" and event.get("content", {}).get("author") == "user": + if ( + event.get("content", {}).get("type") == "text" + and event.get("content", {}).get("author") == "user" + ): user_message_found = True elif msg_type == "done": break diff --git a/examples/tutorials/run_agent_test.sh b/examples/tutorials/run_agent_test.sh index c5729d49..d8effb76 100755 --- a/examples/tutorials/run_agent_test.sh +++ b/examples/tutorials/run_agent_test.sh @@ -263,7 +263,7 @@ run_test() { # Run the tests with retry mechanism - local max_retries=3 + local max_retries=5 local retry_count=0 local exit_code=1 From c03960214c6dd91563c6ea01d70ddf3304fcbfc6 Mon Sep 17 00:00:00 2001 From: Roxanne Farhad Date: Tue, 4 Nov 2025 14:38:03 -0500 Subject: [PATCH 27/30] final version --- .github/workflows/agentex-tutorials-test.yml | 16 +++- .../build-and-push-tutorial-agent.yml | 84 ------------------- 2 files changed, 13 insertions(+), 87 deletions(-) diff --git a/.github/workflows/agentex-tutorials-test.yml b/.github/workflows/agentex-tutorials-test.yml index d40a1727..804add76 100644 --- a/.github/workflows/agentex-tutorials-test.yml +++ b/.github/workflows/agentex-tutorials-test.yml @@ -51,25 +51,35 @@ jobs: curl -LsSf https://astral.sh/uv/install.sh | sh echo "$HOME/.local/bin" >> $GITHUB_PATH + - name: Pull latest AgentEx image + run: | + echo "🐳 Pulling latest Scale AgentEx Docker image..." + docker pull ghcr.io/scaleapi/scale-agentex/agentex:latest + echo "✅ Successfully pulled AgentEx Docker image" + - name: Checkout scale-agentex repo uses: actions/checkout@v4 with: repository: scaleapi/scale-agentex path: scale-agentex - - name: Configure Docker Compose for host networking + - name: Configure Docker Compose for pulled image and host networking run: | cd scale-agentex/agentex - echo "🔧 Configuring AgentEx container for GitHub Actions networking..." + echo "🔧 Configuring AgentEx container to use pulled image and host networking..." # Install yq for YAML manipulation sudo wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 sudo chmod +x /usr/local/bin/yq + # Override to use pulled image instead of building + yq eval '.services.agentex.image = "ghcr.io/scaleapi/scale-agentex/agentex:latest"' -i docker-compose.yml + yq eval 'del(.services.agentex.build)' -i docker-compose.yml + # Add extra_hosts to agentex service to make host.docker.internal work yq eval '.services.agentex.extra_hosts = ["host.docker.internal:host-gateway"]' -i docker-compose.yml - echo "✅ Added extra_hosts configuration to agentex service" + echo "✅ Configured docker-compose to use pulled image with host access" - name: Start AgentEx Server run: | diff --git a/.github/workflows/build-and-push-tutorial-agent.yml b/.github/workflows/build-and-push-tutorial-agent.yml index d2c1d85d..91585451 100644 --- a/.github/workflows/build-and-push-tutorial-agent.yml +++ b/.github/workflows/build-and-push-tutorial-agent.yml @@ -28,87 +28,3 @@ on: permissions: contents: read packages: write - -jobs: - build-and-push-agent: - timeout-minutes: 10 - name: Build Tutorial Agent - runs-on: ubuntu-latest - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Validate agent path exists - run: | - if [ ! -d "${{ inputs.agent_path }}" ]; then - echo "❌ Error: Agent path '${{ inputs.agent_path }}' does not exist" - exit 1 - fi - echo "✅ Agent path verified: ${{ inputs.agent_path }}" - - - name: Validate manifest.yaml exists - run: | - if [ ! -f "${{ inputs.agent_path }}/manifest.yaml" ]; then - echo "❌ Error: manifest.yaml not found in '${{ inputs.agent_path }}'" - exit 1 - fi - echo "✅ manifest.yaml found" - echo "### Validation Summary" >> $GITHUB_STEP_SUMMARY - echo "- **Agent Path**: ${{ inputs.agent_path }}" >> $GITHUB_STEP_SUMMARY - echo "- **Version Tag**: ${{ inputs.version_tag }}" >> $GITHUB_STEP_SUMMARY - echo "- **Status**: ✅ Validation passed" >> $GITHUB_STEP_SUMMARY - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: "3.12" - - - name: Get latest agentex-sdk version from PyPI - id: get-version - run: | - LATEST_VERSION=$(curl -s https://pypi.org/pypi/agentex-sdk/json | jq -r '.info.version') - echo "Latest agentex-sdk version: $LATEST_VERSION" - echo "AGENTEX_SDK_VERSION=$LATEST_VERSION" >> $GITHUB_ENV - pip install agentex-sdk==$LATEST_VERSION - echo "Installed agentex-sdk version $LATEST_VERSION" - - - name: Generate Image name - id: image-name - run: | - # Remove examples/tutorials/ prefix and replace / with - - AGENT_NAME=$(echo "${{ inputs.agent_path }}" | sed 's|^examples/tutorials/||' | sed 's|/|-|g') - echo "AGENT_NAME=$AGENT_NAME" >> $GITHUB_ENV - echo "agent_name=$AGENT_NAME" >> $GITHUB_OUTPUT - echo "Agent name set to $AGENT_NAME" - - - name: Login to GitHub Container Registry - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Build and Push Agent Image - env: - REGISTRY: ghcr.io - run: | - AGENT_NAME="${{ steps.image-name.outputs.agent_name }}" - VERSION_TAG="${{ inputs.version_tag }}" - REPOSITORY_NAME="${{ github.repository }}/tutorial-agents/${AGENT_NAME}" - FULL_IMAGE="${REGISTRY}/${REPOSITORY_NAME}:${VERSION_TAG}" - - agentex agents build \ - --manifest "${{ inputs.agent_path }}/manifest.yaml" \ - --registry "${REGISTRY}" \ - --tag "${VERSION_TAG}" \ - --platforms "linux/amd64" \ - --repository-name "${REPOSITORY_NAME}" \ - --push - - echo "Successfully built and pushed: ${FULL_IMAGE}" - echo "### Build Complete" >> $GITHUB_STEP_SUMMARY - echo "- **Image**: \`${FULL_IMAGE}\`" >> $GITHUB_STEP_SUMMARY From 3f59e445b86181624810f6bb8d471dc4b03ce004 Mon Sep 17 00:00:00 2001 From: Roxanne Farhad Date: Tue, 4 Nov 2025 14:48:42 -0500 Subject: [PATCH 28/30] adding better messages --- .github/workflows/agentex-tutorials-test.yml | 158 ++++++++++++++++++- 1 file changed, 157 insertions(+), 1 deletion(-) diff --git a/.github/workflows/agentex-tutorials-test.yml b/.github/workflows/agentex-tutorials-test.yml index 804add76..d1cf6d13 100644 --- a/.github/workflows/agentex-tutorials-test.yml +++ b/.github/workflows/agentex-tutorials-test.yml @@ -120,6 +120,7 @@ jobs: ls -la dist/ - name: Test Tutorial + id: run-test working-directory: ./examples/tutorials env: OPENAI_API_KEY: ${{ secrets.TUTORIAL_OPENAI_API_KEY }} @@ -129,26 +130,181 @@ jobs: AGENTEX_API_BASE_URL="http://localhost:5003" \ ./run_agent_test.sh --build-cli "${{ matrix.tutorial }}" + - name: Print agent logs on failure + if: failure() + working-directory: ./examples/tutorials + run: | + echo "🚨 Test failed for tutorial: ${{ matrix.tutorial }}" + echo "📋 Printing agent logs..." + + # Look for agent log files in the tutorial directory + if find "${{ matrix.tutorial }}" -name "*.log" -type f 2>/dev/null | grep -q .; then + echo "Found agent log files:" + find "${{ matrix.tutorial }}" -name "*.log" -type f -exec echo "=== {} ===" \; -exec cat {} \; + else + echo "No .log files found, checking for other common log locations..." + fi + + # Check for any output files or dumps + if find "${{ matrix.tutorial }}" -name "agent_output*" -o -name "debug*" -o -name "*.out" 2>/dev/null | grep -q .; then + echo "Found other output files:" + find "${{ matrix.tutorial }}" -name "agent_output*" -o -name "debug*" -o -name "*.out" -exec echo "=== {} ===" \; -exec cat {} \; + fi + + # Print the last 50 lines of any python processes that might still be running + echo "🔍 Checking for running python processes..." + ps aux | grep python || echo "No python processes found" + - name: Record test result id: test-result if: always() run: | + # Create results directory + mkdir -p test-results + + # Determine result if [ "${{ steps.run-test.outcome }}" == "success" ]; then + result="passed" echo "result=passed" >> $GITHUB_OUTPUT + echo "tutorial=${{ matrix.tutorial }}" >> $GITHUB_OUTPUT else + result="failed" echo "result=failed" >> $GITHUB_OUTPUT + echo "tutorial=${{ matrix.tutorial }}" >> $GITHUB_OUTPUT fi + # Save result to file for artifact upload + # Create a safe filename from tutorial path + safe_name=$(echo "${{ matrix.tutorial }}" | tr '/' '_' | tr -d ' ') + echo "$result" > "test-results/result-${safe_name}.txt" + echo "${{ matrix.tutorial }}" > "test-results/tutorial-${safe_name}.txt" + + - name: Upload test result + if: always() + uses: actions/upload-artifact@v4 + with: + name: test-result-${{ strategy.job-index }} + path: test-results/ + retention-days: 1 + test-summary: if: always() needs: [find-tutorials, test-tutorial] runs-on: ubuntu-latest name: Test Summary steps: + - name: Download all test results + uses: actions/download-artifact@v4 + with: + pattern: test-result-* + path: all-results/ + merge-multiple: true + continue-on-error: true + - name: Generate Test Summary run: | echo "# 🧪 Tutorial Tests Summary" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - # Get tutorial list from needs context + # Initialize counters + passed_count=0 + failed_count=0 + skipped_count=0 + total_count=0 + + # Get all tutorials that were supposed to run tutorials='${{ needs.find-tutorials.outputs.tutorials }}' + + if [ -d "all-results" ] && [ "$(ls -A all-results 2>/dev/null)" ]; then + echo "📊 Processing individual test results from artifacts..." + + echo "## Test Results" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "| Tutorial | Status | Result |" >> $GITHUB_STEP_SUMMARY + echo "|----------|--------|--------|" >> $GITHUB_STEP_SUMMARY + + # Process each result file + for result_file in all-results/result-*.txt; do + if [ -f "$result_file" ]; then + # Extract the safe name from filename + safe_name=$(basename "$result_file" .txt | sed 's/result-//') + + # Get corresponding tutorial name file + tutorial_file="all-results/tutorial-${safe_name}.txt" + + if [ -f "$tutorial_file" ]; then + tutorial_name=$(cat "$tutorial_file") + result=$(cat "$result_file") + + total_count=$((total_count + 1)) + + if [ "$result" = "passed" ]; then + echo "| \`$tutorial_name\` | ✅ | Passed |" >> $GITHUB_STEP_SUMMARY + passed_count=$((passed_count + 1)) + else + echo "| \`$tutorial_name\` | ❌ | Failed |" >> $GITHUB_STEP_SUMMARY + failed_count=$((failed_count + 1)) + fi + fi + fi + done + + # Check for any tutorials that didn't have results (skipped/cancelled) + echo "$tutorials" | jq -r '.[]' | while read expected_tutorial; do + safe_expected=$(echo "$expected_tutorial" | tr '/' '_' | tr -d ' ') + if [ ! -f "all-results/result-${safe_expected}.txt" ]; then + echo "| \`$expected_tutorial\` | ⏭️ | Skipped/Cancelled |" >> $GITHUB_STEP_SUMMARY + skipped_count=$((skipped_count + 1)) + total_count=$((total_count + 1)) + fi + done + + else + echo "⚠️ No individual test results found. This could mean:" + echo "- Test jobs were cancelled before completion" + echo "- Artifacts failed to upload" + echo "- No tutorials were found to test" + echo "" + + overall_result="${{ needs.test-tutorial.result }}" + echo "Overall job status: **$overall_result**" + + if [[ "$overall_result" == "success" ]]; then + echo "✅ All tests appear to have passed based on job status." + elif [[ "$overall_result" == "failure" ]]; then + echo "❌ Some tests appear to have failed based on job status." + echo "" + echo "💡 **Tip:** Check individual job logs for specific failure details." + elif [[ "$overall_result" == "cancelled" ]]; then + echo "⏭️ Tests were cancelled." + else + echo "❓ Test status is unclear: $overall_result" + fi + + # Don't show detailed breakdown when we don't have individual results + tutorial_count=$(echo "$tutorials" | jq -r '. | length') + echo "" + echo "Expected tutorial count: $tutorial_count" + fi + + # Only show detailed statistics if we have individual results + if [ -d "all-results" ] && [ "$(ls -A all-results 2>/dev/null)" ]; then + echo "" >> $GITHUB_STEP_SUMMARY + echo "## Summary Statistics" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "- **Total Tests:** $total_count" >> $GITHUB_STEP_SUMMARY + echo "- **Passed:** $passed_count ✅" >> $GITHUB_STEP_SUMMARY + echo "- **Failed:** $failed_count ❌" >> $GITHUB_STEP_SUMMARY + echo "- **Skipped:** $skipped_count ⏭️" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + + if [ $failed_count -eq 0 ] && [ $passed_count -gt 0 ]; then + echo "🎉 **All tests passed!**" >> $GITHUB_STEP_SUMMARY + elif [ $failed_count -gt 0 ]; then + echo "⚠️ **Some tests failed.** Check individual job logs for details." >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "💡 **Tip:** Look for the 'Print agent logs on failure' step in failed jobs for debugging information." >> $GITHUB_STEP_SUMMARY + else + echo "ℹ️ **Tests were cancelled or skipped.**" >> $GITHUB_STEP_SUMMARY + fi + fi From cdb7eacc527c5282cde952003957913ab5f811aa Mon Sep 17 00:00:00 2001 From: Roxanne Farhad Date: Tue, 4 Nov 2025 15:12:11 -0500 Subject: [PATCH 29/30] adding better artifact names --- .github/workflows/agentex-tutorials-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/agentex-tutorials-test.yml b/.github/workflows/agentex-tutorials-test.yml index d1cf6d13..69bb6af9 100644 --- a/.github/workflows/agentex-tutorials-test.yml +++ b/.github/workflows/agentex-tutorials-test.yml @@ -183,7 +183,7 @@ jobs: if: always() uses: actions/upload-artifact@v4 with: - name: test-result-${{ strategy.job-index }} + name: test-result-${{ matrix.tutorial }} path: test-results/ retention-days: 1 From dfbf3e25b809c54bfa70089ef7efd2138624b773 Mon Sep 17 00:00:00 2001 From: Roxanne Farhad Date: Fri, 7 Nov 2025 12:14:44 -0500 Subject: [PATCH 30/30] fixing linter --- .github/workflows/agentex-tutorials-test.yml | 7 ++++++- .../00_base/000_hello_acp/tests/test_agent.py | 2 +- .../project/workflow.py | 13 ------------- examples/tutorials/run_agent_test.sh | 3 --- 4 files changed, 7 insertions(+), 18 deletions(-) diff --git a/.github/workflows/agentex-tutorials-test.yml b/.github/workflows/agentex-tutorials-test.yml index 69bb6af9..eb6da476 100644 --- a/.github/workflows/agentex-tutorials-test.yml +++ b/.github/workflows/agentex-tutorials-test.yml @@ -1,6 +1,10 @@ name: Test Tutorial Agents on: + pull_request: + branches: [ main ] + push: + branches: [ main ] workflow_dispatch: jobs: @@ -178,12 +182,13 @@ jobs: safe_name=$(echo "${{ matrix.tutorial }}" | tr '/' '_' | tr -d ' ') echo "$result" > "test-results/result-${safe_name}.txt" echo "${{ matrix.tutorial }}" > "test-results/tutorial-${safe_name}.txt" + echo "safe_name=${safe_name}" >> $GITHUB_OUTPUT - name: Upload test result if: always() uses: actions/upload-artifact@v4 with: - name: test-result-${{ matrix.tutorial }} + name: test-result-${{ steps.test-result.outputs.safe_name }} path: test-results/ retention-days: 1 diff --git a/examples/tutorials/10_async/00_base/000_hello_acp/tests/test_agent.py b/examples/tutorials/10_async/00_base/000_hello_acp/tests/test_agent.py index 257c27df..08cac7a7 100644 --- a/examples/tutorials/10_async/00_base/000_hello_acp/tests/test_agent.py +++ b/examples/tutorials/10_async/00_base/000_hello_acp/tests/test_agent.py @@ -96,7 +96,7 @@ async def test_send_event_and_poll(self, client: AsyncAgentex, agent_id: str): ): assert isinstance(message, TaskMessage) if message.content and message.content.type == "text" and message.content.author == "agent": - assert "Hello! I've received your message" in message.content.content + assert "Hello! I've received your task" in message.content.content break diff --git a/examples/tutorials/10_async/10_temporal/070_open_ai_agents_sdk_tools/project/workflow.py b/examples/tutorials/10_async/10_temporal/070_open_ai_agents_sdk_tools/project/workflow.py index c31075b8..2204d3a0 100644 --- a/examples/tutorials/10_async/10_temporal/070_open_ai_agents_sdk_tools/project/workflow.py +++ b/examples/tutorials/10_async/10_temporal/070_open_ai_agents_sdk_tools/project/workflow.py @@ -98,8 +98,6 @@ logger = make_logger(__name__) -<<<<<<< HEAD:examples/tutorials/10_agentic/10_temporal/070_open_ai_agents_sdk_tools/project/workflow.py -======= class StateModel(BaseModel): """ State model for preserving conversation history across turns. @@ -112,7 +110,6 @@ class StateModel(BaseModel): turn_number: int ->>>>>>> main:examples/tutorials/10_async/10_temporal/070_open_ai_agents_sdk_tools/project/workflow.py @workflow.defn(name=environment_variables.WORKFLOW_NAME) class At070OpenAiAgentsSdkToolsWorkflow(BaseWorkflow): """ @@ -132,8 +129,6 @@ def __init__(self): async def on_task_event_send(self, params: SendEventParams) -> None: logger.info(f"Received task message instruction: {params}") -<<<<<<< HEAD:examples/tutorials/10_agentic/10_temporal/070_open_ai_agents_sdk_tools/project/workflow.py -======= if self._state is None: raise ValueError("State is not initialized") @@ -146,7 +141,6 @@ async def on_task_event_send(self, params: SendEventParams) -> None: # Add the user message to conversation history self._state.input_list.append({"role": "user", "content": params.event.content.content}) ->>>>>>> main:examples/tutorials/10_async/10_temporal/070_open_ai_agents_sdk_tools/project/workflow.py # Echo back the client's message to show it in the UI. This is not done by default # so the agent developer has full control over what is shown to the user. await adk.messages.create(task_id=params.task.id, content=params.event.content) @@ -235,8 +229,6 @@ async def on_task_event_send(self, params: SendEventParams) -> None: self._parent_span_id = params.task.id # ============================================================================ -<<<<<<< HEAD:examples/tutorials/10_agentic/10_temporal/070_open_ai_agents_sdk_tools/project/workflow.py -======= # HOOKS: Create Streaming Lifecycle Messages # ============================================================================ # TemporalStreamingHooks integrates with OpenAI Agents SDK lifecycle events @@ -281,7 +273,6 @@ async def on_task_event_send(self, params: SendEventParams) -> None: span.output = self._state.model_dump() # ============================================================================ ->>>>>>> main:examples/tutorials/10_async/10_temporal/070_open_ai_agents_sdk_tools/project/workflow.py # PATTERN 2: Multiple Activities Within Tools # ============================================================================ # Use this pattern when: @@ -365,7 +356,3 @@ async def on_task_create(self, params: CreateTaskParams) -> str: async def fulfill_order_signal(self, success: bool) -> None: if success == True: await self._pending_confirmation.put(True) -<<<<<<< HEAD:examples/tutorials/10_agentic/10_temporal/070_open_ai_agents_sdk_tools/project/workflow.py - -======= ->>>>>>> main:examples/tutorials/10_async/10_temporal/070_open_ai_agents_sdk_tools/project/workflow.py diff --git a/examples/tutorials/run_agent_test.sh b/examples/tutorials/run_agent_test.sh index c2dede18..f396cfd0 100755 --- a/examples/tutorials/run_agent_test.sh +++ b/examples/tutorials/run_agent_test.sh @@ -23,9 +23,6 @@ GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color -AGENT_PORT=8000 -AGENTEX_SERVER_PORT=5003 - # Parse arguments TUTORIAL_PATH="" VIEW_LOGS=false