Notebooks
M
Microsoft
04 Semantic Kernel Tool

04 Semantic Kernel Tool

04-tool-useagentic-aiai-agents-frameworkcode_samplesagentic-RAGagentic-frameworksemantic-kernelmicrosoft-ai-agents-for-beginnersgenerative-aiai-agentsautogen

Semantic Kernel Tool Use Example

Import the Needed Packages

[1]

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:

  1. Provides a list of destinations using the get_destinations function
  2. Provides a list of availability for each destination using the get_availabilty function,
[2]

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.

[3]

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.

[4]

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.

[6]
---------------------------------------------------------------------------
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'}}"))