1+ from humanloop .client import Humanloop
2+ from humanloop .types .chat_message import ChatMessage
3+
4+ from tests .integration .conftest import TestIdentifiers
5+
6+
7+ def test_agents_call (
8+ humanloop_test_client : Humanloop ,
9+ prompt : TestIdentifiers ,
10+ test_prompt_config : TestIdentifiers ,
11+ ) -> None :
12+ # Create a test agent configuration
13+ agent_config = {
14+ "provider" : test_prompt_config ['provider' ],
15+ "model" : test_prompt_config ['model' ],
16+ "temperature" : test_prompt_config ['temperature' ],
17+ "template" : test_prompt_config ['template' ],
18+ "max_iterations" : 1 ,
19+ }
20+
21+ # Define a simple agent path for testing
22+ agent_path = "test_agent"
23+
24+ # Test with a simple question
25+ response = humanloop_test_client .agents .call ( # type: ignore [attr-defined]
26+ path = agent_path ,
27+ agent = agent_config ,
28+ inputs = {"question" : "What is the capital of France?" },
29+ )
30+
31+ assert response is not None
32+ assert response .log_id is not None
33+ assert response .output_message is not None
34+ assert "Paris" in response .output_message .content
35+
36+
37+ def test_agents_call_stream (
38+ humanloop_test_client : Humanloop ,
39+ prompt : TestIdentifiers ,
40+ test_prompt_config : TestIdentifiers ,
41+ ) -> None :
42+ # Create a test agent configuration
43+ agent_config = {
44+ "provider" : test_prompt_config ['provider' ],
45+ "model" : test_prompt_config ['model' ],
46+ "temperature" : test_prompt_config ['temperature' ],
47+ "template" : test_prompt_config ['template' ],
48+ "max_iterations" : 1 ,
49+ }
50+
51+ # Define a simple agent path for testing
52+ agent_path = "test_agent_stream"
53+
54+ # Test with streaming response
55+ response = humanloop_test_client .agents .call_stream ( # type: ignore [attr-defined]
56+ path = agent_path ,
57+ agent = agent_config ,
58+ inputs = {"question" : "What is the capital of France?" },
59+ )
60+
61+ output = ""
62+ log_id = None
63+
64+ for chunk in response :
65+ assert chunk is not None
66+ if not log_id and chunk .log_id :
67+ log_id = chunk .log_id
68+
69+ if chunk .payload and chunk .payload .output :
70+ output += chunk .payload .output
71+
72+ assert log_id is not None
73+ assert "Paris" in output
74+
75+
76+ def test_agents_call_with_different_questions (
77+ humanloop_test_client : Humanloop ,
78+ prompt : TestIdentifiers ,
79+ test_prompt_config : TestIdentifiers ,
80+ ) -> None :
81+ # Create a test agent configuration
82+ agent_config = {
83+ "provider" : test_prompt_config ['provider' ],
84+ "model" : test_prompt_config ['model' ],
85+ "temperature" : test_prompt_config ['temperature' ],
86+ "template" : test_prompt_config ['template' ],
87+ "max_iterations" : 1 ,
88+ }
89+
90+ agent_path = "test_agent_questions"
91+
92+ # Test with a math question
93+ response = humanloop_test_client .agents .call ( # type: ignore [attr-defined]
94+ path = agent_path ,
95+ agent = agent_config ,
96+ inputs = {"question" : "What is 5 + 7?" },
97+ )
98+
99+ assert response is not None
100+ assert response .output_message is not None
101+ assert "12" in response .output_message .content
102+
103+ # Test with a different geography question
104+ response = humanloop_test_client .agents .call ( # type: ignore [attr-defined]
105+ path = agent_path ,
106+ agent = agent_config ,
107+ inputs = {"question" : "What is the capital of Japan?" },
108+ )
109+
110+ assert response is not None
111+ assert response .output_message is not None
112+ assert "Tokyo" in response .output_message .content
113+
114+
115+ def test_agents_call_with_modified_config (
116+ humanloop_test_client : Humanloop ,
117+ prompt : TestIdentifiers ,
118+ test_prompt_config : TestIdentifiers ,
119+ ) -> None :
120+ # Create a test agent configuration with modified temperature
121+ agent_config = {
122+ "provider" : test_prompt_config ['provider' ],
123+ "model" : test_prompt_config ['model' ],
124+ "temperature" : 0.1 , # Lower temperature
125+ "template" : test_prompt_config ['template' ],
126+ "max_iterations" : 1 ,
127+ }
128+
129+ agent_path = "test_agent_modified"
130+
131+ response = humanloop_test_client .agents .call ( # type: ignore [attr-defined]
132+ path = agent_path ,
133+ agent = agent_config ,
134+ inputs = {"question" : "What is the capital of France?" },
135+ )
136+
137+ assert response is not None
138+ assert response .output_message is not None
139+ assert "Paris" in response .output_message .content
140+
141+
142+ def test_agents_log (
143+ humanloop_test_client : Humanloop ,
144+ prompt : TestIdentifiers ,
145+ test_prompt_config : TestIdentifiers ,
146+ ) -> None :
147+ # Create a test agent configuration
148+ agent_config = {
149+ "provider" : test_prompt_config ['provider' ],
150+ "model" : test_prompt_config ['model' ],
151+ "temperature" : test_prompt_config ['temperature' ],
152+ "template" : test_prompt_config ['template' ],
153+ "max_iterations" : 1 ,
154+ }
155+
156+ agent_path = "test_agent_log"
157+
158+ # Test logging agent interaction
159+ response = humanloop_test_client .agents .log ( # type: ignore [attr-defined]
160+ path = agent_path ,
161+ agent = agent_config ,
162+ messages = [{"role" : "user" , "content" : "Hello" }],
163+ output = "Hello! How can I assist you today?" ,
164+ )
165+
166+ assert response is not None
167+ assert response .id is not None
168+ # For CreateAgentLogResponse, the id is used instead of log_id
169+
170+
171+ def test_agents_upsert (
172+ humanloop_test_client : Humanloop ,
173+ sdk_test_dir : str ,
174+ ) -> None :
175+ agent_path = f"{ sdk_test_dir } /test_agent_upsert"
176+
177+ # Create a test agent config for upsert
178+ agent_config = {
179+ "provider" : "openai" ,
180+ "model" : "gpt-4o-mini" ,
181+ "temperature" : 0.7 ,
182+ "template" : [
183+ {
184+ "role" : "system" ,
185+ "content" : "You are a helpful assistant specialized in answering geography questions." ,
186+ }
187+ ],
188+ "max_iterations" : 3 ,
189+ }
190+
191+ # Test upserting an agent
192+ response = humanloop_test_client .agents .upsert ( # type: ignore [attr-defined]
193+ path = agent_path ,
194+ ** agent_config ,
195+ )
196+
197+ assert response is not None
198+ assert response .id is not None
199+ assert response .path == agent_path
200+
201+ # Clean up after test
202+ humanloop_test_client .agents .delete (id = response .id )
203+
204+
205+ def test_agents_call_with_tool (
206+ humanloop_test_client : Humanloop ,
207+ prompt : TestIdentifiers ,
208+ test_prompt_config : TestIdentifiers ,
209+ ) -> None :
210+ # Define a simple tool in the inline format
211+ calculator_tool = {
212+ "type" : "inline" ,
213+ "json_schema" : {
214+ "name" : "calculator" ,
215+ "description" : "Calculate a math expression" ,
216+ "parameters" : {
217+ "type" : "object" ,
218+ "properties" : {
219+ "expression" : {
220+ "type" : "string" ,
221+ "description" : "The math expression to calculate"
222+ }
223+ },
224+ "required" : ["expression" ]
225+ }
226+ }
227+ }
228+
229+ # Create a test agent configuration with tools included
230+ agent_config = {
231+ "provider" : test_prompt_config ['provider' ],
232+ "model" : test_prompt_config ['model' ],
233+ "temperature" : test_prompt_config ['temperature' ],
234+ "template" : test_prompt_config ['template' ],
235+ "max_iterations" : 1 ,
236+ "tools" : [calculator_tool ], # Include tools in agent config
237+ }
238+
239+ agent_path = "test_agent_with_tool"
240+
241+ # Test with tool
242+ response = humanloop_test_client .agents .call ( # type: ignore [attr-defined]
243+ path = agent_path ,
244+ agent = agent_config ,
245+ inputs = {"question" : "Calculate 25 × 4" },
246+ tool_choice = {"type" : "function" , "function" : {"name" : "calculator" }}
247+ )
248+
249+ assert response is not None
250+ assert response .output_message is not None
251+ # The model should have made a tool call
252+ assert hasattr (response .output_message , 'tool_calls' ) and response .output_message .tool_calls
253+ for tool_call in response .output_message .tool_calls :
254+ if tool_call .function .name == "calculator" :
255+ assert "expression" in tool_call .function .arguments
256+
257+
258+ def test_agents_continue_call (
259+ humanloop_test_client : Humanloop ,
260+ prompt : TestIdentifiers ,
261+ test_prompt_config : TestIdentifiers ,
262+ ) -> None :
263+ # Define a simple tool in the inline format
264+ calculator_tool = {
265+ "type" : "inline" ,
266+ "json_schema" : {
267+ "name" : "calculator" ,
268+ "description" : "Calculate a math expression" ,
269+ "parameters" : {
270+ "type" : "object" ,
271+ "properties" : {
272+ "expression" : {
273+ "type" : "string" ,
274+ "description" : "The math expression to calculate"
275+ }
276+ },
277+ "required" : ["expression" ]
278+ }
279+ }
280+ }
281+
282+ # Create a test agent configuration with tools included
283+ agent_config = {
284+ "provider" : test_prompt_config ['provider' ],
285+ "model" : test_prompt_config ['model' ],
286+ "temperature" : test_prompt_config ['temperature' ],
287+ "template" : test_prompt_config ['template' ],
288+ "max_iterations" : 2 , # Need at least 2 for continue call
289+ "tools" : [calculator_tool ], # Include tools in agent config
290+ }
291+
292+ agent_path = "test_agent_continue"
293+
294+ # First make an initial call that will use a tool
295+ initial_response = humanloop_test_client .agents .call ( # type: ignore [attr-defined]
296+ path = agent_path ,
297+ agent = agent_config ,
298+ inputs = {"question" : "Calculate 25 × 4" },
299+ tool_choice = {"type" : "function" , "function" : {"name" : "calculator" }}
300+ )
301+
302+ assert initial_response is not None
303+ assert initial_response .log_id is not None
304+
305+ # Get the tool call from output_message
306+ assert hasattr (initial_response .output_message , 'tool_calls' ) and initial_response .output_message .tool_calls
307+ tool_call = None
308+ for tc in initial_response .output_message .tool_calls :
309+ if tc .function .name == "calculator" :
310+ tool_call = tc
311+ break
312+
313+ assert tool_call is not None
314+ assert tool_call .id is not None
315+
316+ # Now continue the call with a tool response
317+ continue_response = humanloop_test_client .agents .continue_call ( # type: ignore [attr-defined]
318+ log_id = initial_response .log_id ,
319+ messages = [{
320+ "role" : "tool" ,
321+ "content" : '{"result": 100}' ,
322+ "tool_call_id" : tool_call .id
323+ }],
324+ )
325+
326+ assert continue_response is not None
327+ assert continue_response .log_id == initial_response .log_id
328+ assert continue_response .output_message is not None
329+ assert "100" in continue_response .output_message .content
0 commit comments