Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Dec 1, 2025

The openagents network list --status command always showed "No networks found" regardless of whether networks were running. The command was a static placeholder with no actual discovery logic.

Changes

  • Added discover_running_networks() function - Scans common OpenAgents ports (8700, 8570, 8050, etc.) via /api/health endpoint to identify running networks
  • Extracts network metadata - Returns network name, ID, port, running status, and PID (via ss on Linux, lsof on macOS)
  • Deduplicates results - Same network found on multiple hosts (localhost/127.0.0.1) only appears once
  • Graceful error handling - Connection errors, timeouts, and non-OpenAgents responses handled silently

Example

# Before: Always shows "No networks found"
$ openagents network list --status
╭───────────────────┬────────┬──────┬─────╮
│ Name              │ Status │ Port │ PID │
├───────────────────┼────────┼──────┼─────┤
│ No networks found │ —      │ —    │ —   │
╰───────────────────┴────────┴──────┴─────╯

# After: Detects running networks
$ openagents network list --status
╭────────────────┬─────────┬──────┬──────╮
│ Name           │ Status  │ Port │ PID  │
├────────────────┼─────────┼──────┼──────┤
│ DefaultNetwork │ Running │ 8700 │ 5349 │
╰────────────────┴─────────┴──────┴──────╯

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • api.openai.com
    • Triggering command: /usr/bin/python python -m pytest tests/ -x -q (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

This section details on the original issue you should resolve

<issue_title>openagents network list --status command fails to detect running networks</issue_title>
<issue_description></issue_description>

Comments on the Issue (you are @copilot in this section)


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

@vercel
Copy link

vercel bot commented Dec 1, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
openagents-studio Ready Ready Preview Comment Dec 1, 2025 3:19am

Co-authored-by: zomux <1029280+zomux@users.noreply.github.com>
Co-authored-by: zomux <1029280+zomux@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix openagents network list --status command detection issue Fix network list --status command to detect running networks Dec 1, 2025
Copilot AI requested a review from zomux December 1, 2025 03:21
@zomux zomux marked this pull request as ready for review December 1, 2025 03:25
Copilot AI review requested due to automatic review settings December 1, 2025 03:25
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes the openagents network list --status command which previously showed "No networks found" regardless of whether networks were actually running. The fix adds real network discovery functionality by scanning common OpenAgents ports for running network instances.

  • Implements discover_running_networks() function to scan for active networks via HTTP health checks
  • Adds PID detection for discovered networks using platform-specific commands (ss for Linux, lsof for macOS)
  • Includes comprehensive test suite covering various scenarios (connection errors, timeouts, deduplication, etc.)

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 16 comments.

File Description
src/openagents/cli.py Adds discover_running_networks() function and integrates it into network_list command to detect and display running networks
tests/network/test_network_discovery.py Comprehensive test suite for network discovery functionality covering edge cases, error handling, and deduplication

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

if result.returncode == 0 and result.stdout:
# Find lines containing the port and extract PID
for line in result.stdout.split("\n"):
if f":{port}" in line:
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The port search pattern f":{port}" in line 1867 could produce false positives. For example, when searching for port 8700, it would also match port 18700 or 28700.

Consider using a more precise pattern with word boundaries or specific delimiters:

if f":{port} " in line or f":{port}\t" in line or line.rstrip().endswith(f":{port}"):
Suggested change
if f":{port}" in line:
if (
f":{port} " in line
or f":{port}\t" in line
or line.rstrip().endswith(f":{port}")
):

Copilot uses AI. Check for mistakes.
Comment on lines +91 to +93
import requests

with patch('requests.get', side_effect=requests.exceptions.Timeout()):
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The import statement is inside the test function. While this works, it's better practice to import at the module level or use proper mocking. Since requests is already being patched with patch('requests.get', ...), the import is unnecessary here.

Consider removing the import statement:

def test_discover_handles_timeout(self):
    """Test that timeouts are handled gracefully."""
    from requests.exceptions import Timeout
    
    with patch('requests.get', side_effect=Timeout()):
        networks = discover_running_networks(
            ports=[8700],
            hosts=["localhost"],
            timeout=1.0
        )

    assert networks == []

Copilot uses AI. Check for mistakes.
Comment on lines +178 to +180
import requests

with patch('requests.get', side_effect=requests.exceptions.ConnectionError("No network")):
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The import statement is inside the test function. While this works, it's better practice to import at the module level. Since you're only using the module to reference the exception, consider importing at the top.

Consider removing the import statement:

def test_discover_with_default_ports(self):
    """Test discovery uses reasonable default ports."""
    from requests.exceptions import ConnectionError
    
    with patch('requests.get', side_effect=ConnectionError("No network")):
        # Just verify it runs without error using defaults
        networks = discover_running_networks(timeout=0.1)
    
    assert networks == []

Copilot uses AI. Check for mistakes.
}
}

with patch('requests.get', return_value=mock_response):
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The patch target 'requests.get' patches the requests module globally. Since discover_running_networks imports requests inside the function, the patch target should be 'openagents.cli.requests.get' to patch it where it's used, not where it's defined.

However, since requests is imported inside the function, the current approach happens to work. For better practice and clarity, consider either:

  1. Moving the import requests to the top of cli.py
  2. Or updating the patch target to 'openagents.cli.requests.get'

Current approach works but may be fragile if the import location changes.

Copilot uses AI. Check for mistakes.
Comment on lines +1820 to +1821
import requests
import re
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The requests and re modules are imported inside the function. While this works, it's better practice to import them at the module level for consistency with the rest of the file and to avoid repeated import overhead if the function is called multiple times.

Consider moving these imports to the top of the file:

import re
import requests

Copilot uses AI. Check for mistakes.
Comment on lines +78 to +80
import requests

with patch('requests.get', side_effect=requests.exceptions.ConnectionError()):
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The import statement is inside the test function. While this works, it's better practice to import at the module level or use proper mocking. Since requests is already being patched with patch('requests.get', ...), the import is unnecessary here.

Consider removing the import statement:

def test_discover_handles_connection_error(self):
    """Test that connection errors are handled gracefully."""
    from requests.exceptions import ConnectionError
    
    with patch('requests.get', side_effect=ConnectionError()):
        networks = discover_running_networks(
            ports=[8700],
            hosts=["localhost"],
            timeout=1.0
        )

    assert networks == []

Copilot uses AI. Check for mistakes.

if status:
table.add_column("Name", style="cyan")
table.add_column("Status", style="green")
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The status_text contains Rich markup ([green]Running[/green] or [red]Stopped[/red]), but when the status is "Stopped", the table column header is styled as "green". This creates a visual inconsistency where the column is labeled with green styling but may contain red-colored "Stopped" text.

Consider using a neutral style for the Status column header or using a style like "bold" that doesn't imply a specific state:

table.add_column("Status", style="bold")
Suggested change
table.add_column("Status", style="green")
table.add_column("Status", style="bold")

Copilot uses AI. Check for mistakes.
timeout=2,
)
if result.returncode == 0 and result.stdout:
pid = result.stdout.strip().split("\n")[0]
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The PID detection only handles Linux (sys.platform.startswith("linux")) and macOS (sys.platform == "darwin"), but doesn't handle Windows or other platforms. While the pid variable defaults to None, it would be clearer to have an explicit comment or log message indicating that PID detection is not supported on other platforms.

Consider adding a comment or else clause:

elif sys.platform == "darwin":
    # macOS PID detection
    ...
# Note: PID detection not supported on Windows and other platforms
Suggested change
pid = result.stdout.strip().split("\n")[0]
pid = result.stdout.strip().split("\n")[0]
else:
# PID detection not supported on Windows and other platforms
logging.debug(f"PID detection is not supported on platform: {sys.platform}")

Copilot uses AI. Check for mistakes.
Comment on lines +1848 to +1851
# Skip if we've already found this network
if network_id in seen_networks:
continue
seen_networks.add(network_id)
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If multiple networks return no network_id field, they will all be assigned the default value "unknown" and subsequently deduplicated as if they were the same network. This could hide multiple distinct networks that lack IDs.

Consider using a combination of host, port, and network_name for deduplication when network_id is "unknown":

network_id = network_data.get("network_id", "unknown")

# Create a unique identifier for deduplication
if network_id == "unknown":
    dedup_key = f"{host}:{port}:{network_data.get('network_name', 'Unknown')}"
else:
    dedup_key = network_id

if dedup_key in seen_networks:
    continue
seen_networks.add(dedup_key)
Suggested change
# Skip if we've already found this network
if network_id in seen_networks:
continue
seen_networks.add(network_id)
# Create a unique deduplication key
if network_id == "unknown":
dedup_key = f"{host}:{port}:{network_data.get('network_name', 'Unknown')}"
else:
dedup_key = network_id
# Skip if we've already found this network
if dedup_key in seen_networks:
continue
seen_networks.add(dedup_key)

Copilot uses AI. Check for mistakes.
used by the `openagents network list --status` command.
"""

import pytest
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'pytest' is not used.

Suggested change
import pytest

Copilot uses AI. Check for mistakes.
@zomux zomux merged commit fb9f409 into develop Dec 1, 2025
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

openagents network list --status command fails to detect running networks

2 participants