04 Semantic Kernel Tool
Semantic Kernel Tool Use Example
Import the Needed Packages
Creating the Plugins
Semantic Kernel uses plugins as tools that can be called by the agent. A plugin can have multiple kernel_functions in it as a group.
In the example below, we create a DestinationsPlugin that has two functions:
- Provides a list of destinations using the
get_destinationsfunction - Provides a list of availability for each destination using the
get_availabiltyfunction,
Creating the Client
In this sample, we will use GitHub Models for access to the LLM.
The ai_model_id is defined as gpt-4o-mini. Try changing the model to another model available on the GitHub Models marketplace to see the different results.
For us to use the Azure Inference SDK that is used for the base_url for GitHub Models, we will use the OpenAIChatCompletion connector within Semantic Kernel. There are also other available connectors to use Semantic Kernel for other model providers.
Creating the Agent
Now we will create the Agent by using the Agent Name and Instructions that we can set.
You can change these settings to see how the differences in the agent's response.
Running the Agent
Now we wil run the AI Agent. In this snippet, we can add two messages to the user_input to show how the agent responds to followup questions.
The agent should call the correct function to get the list of available destinations and confirm the availability of a certain location.
You can change the user_inputs to see how the agent responds.
--------------------------------------------------------------------------- AuthenticationError Traceback (most recent call last) File ~/ai-agents-for-beginners/.venv/lib/python3.12/site-packages/semantic_kernel/connectors/ai/open_ai/services/open_ai_handler.py:87, in OpenAIHandler._send_completion_request(self, settings) 86 settings_dict.pop("parallel_tool_calls", None) ---> 87 response = await self.client.chat.completions.create(**settings_dict) 88 else: File ~/ai-agents-for-beginners/.venv/lib/python3.12/site-packages/openai/resources/chat/completions/completions.py:2028, in AsyncCompletions.create(self, messages, model, audio, frequency_penalty, function_call, functions, logit_bias, logprobs, max_completion_tokens, max_tokens, metadata, modalities, n, parallel_tool_calls, prediction, presence_penalty, reasoning_effort, response_format, seed, service_tier, stop, store, stream, stream_options, temperature, tool_choice, tools, top_logprobs, top_p, user, web_search_options, extra_headers, extra_query, extra_body, timeout) 2027 validate_response_format(response_format) -> 2028 return await self._post( 2029 "/chat/completions", 2030 body=await async_maybe_transform( 2031 { 2032 "messages": messages, 2033 "model": model, 2034 "audio": audio, 2035 "frequency_penalty": frequency_penalty, 2036 "function_call": function_call, 2037 "functions": functions, 2038 "logit_bias": logit_bias, 2039 "logprobs": logprobs, 2040 "max_completion_tokens": max_completion_tokens, 2041 "max_tokens": max_tokens, 2042 "metadata": metadata, 2043 "modalities": modalities, 2044 "n": n, 2045 "parallel_tool_calls": parallel_tool_calls, 2046 "prediction": prediction, 2047 "presence_penalty": presence_penalty, 2048 "reasoning_effort": reasoning_effort, 2049 "response_format": response_format, 2050 "seed": seed, 2051 "service_tier": service_tier, 2052 "stop": stop, 2053 "store": store, 2054 "stream": stream, 2055 "stream_options": stream_options, 2056 "temperature": temperature, 2057 "tool_choice": tool_choice, 2058 "tools": tools, 2059 "top_logprobs": top_logprobs, 2060 "top_p": top_p, 2061 "user": user, 2062 "web_search_options": web_search_options, 2063 }, 2064 completion_create_params.CompletionCreateParamsStreaming 2065 if stream 2066 else completion_create_params.CompletionCreateParamsNonStreaming, 2067 ), 2068 options=make_request_options( 2069 extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout 2070 ), 2071 cast_to=ChatCompletion, 2072 stream=stream or False, 2073 stream_cls=AsyncStream[ChatCompletionChunk], 2074 ) File ~/ai-agents-for-beginners/.venv/lib/python3.12/site-packages/openai/_base_client.py:1742, in AsyncAPIClient.post(self, path, cast_to, body, files, options, stream, stream_cls) 1739 opts = FinalRequestOptions.construct( 1740 method="post", url=path, json_data=body, files=await async_to_httpx_files(files), **options 1741 ) -> 1742 return await self.request(cast_to, opts, stream=stream, stream_cls=stream_cls) File ~/ai-agents-for-beginners/.venv/lib/python3.12/site-packages/openai/_base_client.py:1549, in AsyncAPIClient.request(self, cast_to, options, stream, stream_cls) 1548 log.debug("Re-raising status error") -> 1549 raise self._make_status_error_from_response(err.response) from None 1551 break AuthenticationError: Error code: 401 - {'error': {'code': 'unauthorized', 'message': 'Bad credentials', 'details': 'Bad credentials'}} The above exception was the direct cause of the following exception: ServiceResponseException Traceback (most recent call last) Cell In[6], line 78 70 html_output += ( 71 "<div style='margin-bottom:20px'>" 72 f"<div style='font-weight:bold'>{agent_name or 'Assistant'}:</div>" 73 f"<div style='margin-left:20px; white-space:pre-wrap'>{''.join(full_response)}</div></div><hr>" 74 ) 76 display(HTML(html_output)) ---> 78 await main() Cell In[6], line 25, in main() 22 current_function_name = None 23 argument_buffer = "" ---> 25 async for response in agent.invoke_stream( 26 messages=user_input, 27 thread=thread, 28 ): 29 thread = response.thread 30 agent_name = response.name File ~/ai-agents-for-beginners/.venv/lib/python3.12/site-packages/semantic_kernel/utils/telemetry/agent_diagnostics/decorators.py:39, in trace_agent_invocation.<locals>.wrapper_decorator(*args, **kwargs) 36 if agent.description: 37 span.set_attribute(gen_ai_attributes.AGENT_DESCRIPTION, agent.description) ---> 39 async for response in invoke_func(*args, **kwargs): 40 yield response File ~/ai-agents-for-beginners/.venv/lib/python3.12/site-packages/semantic_kernel/agents/chat_completion/chat_completion_agent.py:419, in ChatCompletionAgent.invoke_stream(self, messages, thread, on_intermediate_message, arguments, kernel, **kwargs) 417 role = None 418 response_builder: list[str] = [] --> 419 async for response_list in responses: 420 for response in response_list: 421 role = response.role File ~/ai-agents-for-beginners/.venv/lib/python3.12/site-packages/semantic_kernel/connectors/ai/chat_completion_client_base.py:261, in ChatCompletionClientBase.get_streaming_chat_message_contents(self, chat_history, settings, **kwargs) 259 all_messages: list["StreamingChatMessageContent"] = [] 260 function_call_returned = False --> 261 async for messages in self._inner_get_streaming_chat_message_contents( 262 chat_history, settings, request_index 263 ): 264 for msg in messages: 265 if msg is not None: File ~/ai-agents-for-beginners/.venv/lib/python3.12/site-packages/semantic_kernel/utils/telemetry/model_diagnostics/decorators.py:165, in trace_streaming_chat_completion.<locals>.inner_trace_streaming_chat_completion.<locals>.wrapper_decorator(*args, **kwargs) 159 @functools.wraps(completion_func) 160 async def wrapper_decorator( 161 *args: Any, **kwargs: Any 162 ) -> AsyncGenerator[list["StreamingChatMessageContent"], Any]: 163 if not are_model_diagnostics_enabled(): 164 # If model diagnostics are not enabled, just return the completion --> 165 async for streaming_chat_message_contents in completion_func(*args, **kwargs): 166 yield streaming_chat_message_contents 167 return File ~/ai-agents-for-beginners/.venv/lib/python3.12/site-packages/semantic_kernel/connectors/ai/open_ai/services/open_ai_chat_completion_base.py:110, in OpenAIChatCompletionBase._inner_get_streaming_chat_message_contents(self, chat_history, settings, function_invoke_attempt) 107 settings.messages = self._prepare_chat_history_for_request(chat_history) 108 settings.ai_model_id = settings.ai_model_id or self.ai_model_id --> 110 response = await self._send_request(settings) 111 if not isinstance(response, AsyncStream): 112 raise ServiceInvalidResponseError("Expected an AsyncStream[ChatCompletionChunk] response.") File ~/ai-agents-for-beginners/.venv/lib/python3.12/site-packages/semantic_kernel/connectors/ai/open_ai/services/open_ai_handler.py:59, in OpenAIHandler._send_request(self, settings) 57 if self.ai_model_type == OpenAIModelTypes.TEXT or self.ai_model_type == OpenAIModelTypes.CHAT: 58 assert isinstance(settings, OpenAIPromptExecutionSettings) # nosec ---> 59 return await self._send_completion_request(settings) 60 if self.ai_model_type == OpenAIModelTypes.EMBEDDING: 61 assert isinstance(settings, OpenAIEmbeddingPromptExecutionSettings) # nosec File ~/ai-agents-for-beginners/.venv/lib/python3.12/site-packages/semantic_kernel/connectors/ai/open_ai/services/open_ai_handler.py:104, in OpenAIHandler._send_completion_request(self, settings) 99 raise ServiceResponseException( 100 f"{type(self)} service failed to complete the prompt", 101 ex, 102 ) from ex 103 except Exception as ex: --> 104 raise ServiceResponseException( 105 f"{type(self)} service failed to complete the prompt", 106 ex, 107 ) from ex ServiceResponseException: ("<class 'semantic_kernel.connectors.ai.open_ai.services.open_ai_chat_completion.OpenAIChatCompletion'> service failed to complete the prompt", AuthenticationError("Error code: 401 - {'error': {'code': 'unauthorized', 'message': 'Bad credentials', 'details': 'Bad credentials'}}"))