-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Expand file tree
/
Copy pathtest_external_agent_delegation.py
More file actions
89 lines (69 loc) · 3 KB
/
test_external_agent_delegation.py
File metadata and controls
89 lines (69 loc) · 3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
"""Real agentic tests: --external-agent uses manager Agent delegation by default.
Tests the delegation and proxy branches of PraisonAI.main() directly (no subprocess),
which is both faster and avoids pytest/subprocess environment brittleness.
"""
import os
import shutil
import sys
import types
from unittest.mock import patch
import pytest
pytestmark = pytest.mark.integration
@pytest.fixture
def _has_claude():
if not shutil.which("claude"):
pytest.skip("claude CLI not installed")
@pytest.fixture
def _has_openai_key():
if not os.getenv("OPENAI_API_KEY"):
pytest.skip("OPENAI_API_KEY required for manager LLM")
def _build_args(extra: dict):
"""Build a minimal argparse.Namespace that mimics `praisonai <prompt> --external-agent ...`."""
ns = types.SimpleNamespace(
external_agent="claude",
external_agent_direct=False,
verbose=False,
)
for k, v in extra.items():
setattr(ns, k, v)
return ns
def test_manager_delegation_is_default(_has_claude, _has_openai_key, monkeypatch, tmp_path):
"""Real agentic test: default --external-agent path creates a manager Agent with a subagent tool."""
from praisonai.integrations.claude_code import ClaudeCodeIntegration
from praisonaiagents import Agent
# 1. Integration is available and exposes a tool
integration = ClaudeCodeIntegration(workspace=str(tmp_path))
assert integration.is_available, "claude CLI reported unavailable"
tool = integration.as_tool()
assert callable(tool)
assert tool.__name__.endswith("_tool")
# 2. Manager Agent wires the tool correctly
manager = Agent(
name="Manager",
instructions=f"Delegate to {tool.__name__}",
tools=[tool],
llm=os.environ.get("MODEL_NAME", "gpt-4o-mini"),
)
assert manager.tools and len(manager.tools) == 1
# 3. End-to-end — manager runs and produces a response
result = manager.start("Say hi in exactly 5 words")
assert result and len(str(result).strip()) > 0
def test_direct_flag_preserves_proxy_path(_has_claude):
"""Escape hatch: --external-agent-direct bypasses manager delegation (proxy path)."""
import asyncio
from praisonai.integrations.claude_code import ClaudeCodeIntegration
integration = ClaudeCodeIntegration(workspace=".")
result = asyncio.run(integration.execute("Say hi in exactly 5 words"))
assert result and len(result.strip()) > 0
def test_cli_args_include_external_agent_direct_flag():
"""Regression: verify --external-agent-direct is registered as a CLI flag."""
from praisonai.cli.main import PraisonAI
import argparse
parser = argparse.ArgumentParser()
# Only exercise the arg-registration portion; no execution.
app = PraisonAI.__new__(PraisonAI)
app._build_parser = PraisonAI.main.__wrapped__ if hasattr(PraisonAI.main, "__wrapped__") else None
# Fallback: just grep the source for the flag (simpler)
import inspect
source = inspect.getsource(PraisonAI.main)
assert "--external-agent-direct" in source