Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions agentrun/server/agui_protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,11 +206,6 @@ async def run_agent(request: Request):
headers=sse_headers,
)

@router.get("/health")
async def health_check():
"""健康检查端点"""
return {"status": "ok", "protocol": "ag-ui", "version": "1.0"}

return router

async def parse_request(
Expand Down
10 changes: 10 additions & 0 deletions agentrun/server/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@ def __init__(

self.agent_invoker = AgentInvoker(invoke_agent)

# 注册 health check 路由
self._register_health_check()

# 配置 CORS
self._setup_cors(config.cors_origins if config else None)

Expand All @@ -145,6 +148,13 @@ def __init__(
# 挂载所有协议的 Router
self._mount_protocols(protocols)

def _register_health_check(self):
"""注册 /health 健康检查路由 / Register /health health check route"""

Comment on lines +152 to +153
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

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

AgentRunServer now always registers a root GET /health route. Note that AGUIProtocolHandler already defines GET /health on its router; if the AG-UI prefix is configured to an empty string (or a custom protocol mounts at root with the same path), the protocol’s /health will be shadowed by the server-level route, leading to ambiguous/unreachable behavior depending on route order. Consider guarding registration (skip if an existing GET /health route already exists), or using a dedicated non-conflicting path (e.g. /_health) for the server-level endpoint.

Suggested change
"""注册 /health 健康检查路由 / Register /health health check route"""
"""注册 /health 健康检查路由 / Register /health health check route
如果应用中已经存在 GET /health 路由例如协议自身定义了该路由),
则不会重复注册以避免路由冲突或被覆盖
"""
# Check if a GET /health route already exists to avoid conflicts
for route in getattr(self.app, "routes", []):
path = getattr(route, "path", None)
methods = getattr(route, "methods", None)
if path == "/health" and methods and "GET" in methods:
logger.warning(
"Skipping registration of server-level GET /health route "
"because an existing GET /health route was found."
)
return

Copilot uses AI. Check for mistakes.
@self.app.get("/health")
async def health_check():
return {"status": "ok"}

def _wrap_with_memory(
self,
invoke_agent: InvokeAgentHandler,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ def _start_server(app: FastAPI) -> tuple:
base_url = f"http://127.0.0.1:{port}"
for i in range(50):
try:
httpx.get(f"{base_url}/ag-ui/agent/health", timeout=0.2)
httpx.get(f"{base_url}/health", timeout=0.2)
break
except Exception:
if i == 49:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -671,7 +671,7 @@ async def invoke_agent(request: AgentRequest):
base_url = f"http://127.0.0.1:{port}"
for i in range(50):
try:
httpx.get(f"{base_url}/ag-ui/agent/health", timeout=0.2)
httpx.get(f"{base_url}/health", timeout=0.2)
break
except Exception:
if i == 49:
Expand Down
16 changes: 0 additions & 16 deletions tests/unittests/server/test_agui_protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,22 +43,6 @@ def get_client(self, invoke_agent):
server = AgentRunServer(invoke_agent=invoke_agent)
return TestClient(server.as_fastapi_app())

@pytest.mark.asyncio
async def test_health_check(self):
"""测试健康检查端点"""

def invoke_agent(request: AgentRequest):
return "Hello"

client = self.get_client(invoke_agent)
response = client.get("/ag-ui/agent/health")

assert response.status_code == 200
data = response.json()
assert data["status"] == "ok"
assert data["protocol"] == "ag-ui"
assert data["version"] == "1.0"

@pytest.mark.asyncio
async def test_value_error_handling(self):
"""测试 ValueError 处理"""
Expand Down
37 changes: 37 additions & 0 deletions tests/unittests/server/test_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,43 @@ def get_client(self, invoke_agent):

return TestClient(app)

async def test_health_check(self):
"""测试 /health 健康检查路由"""

client = self.get_client(self.get_invoke_agent_non_streaming())

response = client.get("/health")

assert response.status_code == 200
assert response.json() == {"status": "ok"}

async def test_health_check_post_not_allowed(self):
"""测试 POST /health 不被允许"""

client = self.get_client(self.get_invoke_agent_non_streaming())

response = client.post("/health")

# FastAPI 对不匹配的方法返回 405
assert response.status_code == 405

async def test_health_check_with_custom_protocols(self):
"""测试自定义协议列表时 /health 仍可用"""
from agentrun.server.openai_protocol import OpenAIProtocolHandler

server = AgentRunServer(
invoke_agent=self.get_invoke_agent_non_streaming(),
protocols=[OpenAIProtocolHandler()],
)
Comment on lines +148 to +154
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

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

This test imports OpenAIProtocolHandler from the internal module path (agentrun.server.openai_protocol). Elsewhere in the test suite it’s imported from the public agentrun.server package exports; using the internal path makes the test more brittle to refactors. Prefer from agentrun.server import OpenAIProtocolHandler here for consistency and stability.

Copilot uses AI. Check for mistakes.
from fastapi.testclient import TestClient

client = TestClient(server.as_fastapi_app())

response = client.get("/health")

assert response.status_code == 200
assert response.json() == {"status": "ok"}

async def test_server_non_streaming_protocols(self):
"""测试非流式的 OpenAI 和 AGUI 服务器响应功能"""

Expand Down
Loading