{"id":81002,"date":"2026-06-21T17:35:08","date_gmt":"2026-06-21T17:35:08","guid":{"rendered":"https:\/\/www.europesays.com\/ai\/81002\/"},"modified":"2026-06-21T17:35:08","modified_gmt":"2026-06-21T17:35:08","slug":"tool-calling-explained-how-ai-agents-decide-what-to-do-next","status":"publish","type":"post","link":"https:\/\/www.europesays.com\/ai\/81002\/","title":{"rendered":"Tool Calling, Explained: How AI Agents Decide What to Do Next"},"content":{"rendered":"<p class=\"wp-block-paragraph\">In my <a href=\"https:\/\/towardsdatascience.com\/structured-outputs-with-llms-json-mode-function-calling-and-when-to-use-each\/\" rel=\"nofollow noopener\" target=\"_blank\">latest post<\/a>,  how to get structured, machine-readable outputs as a response from an LLM, using JSON Mode, function calling, and structured outputs. In that post, we briefly touched on the idea of function calling, approaching it as a method for obtaining structured responses. Nevertheless, function calling is something that goes well beyond just getting structured data back from a model, since it is essentially the backbone of agentic AI workflows. So, in today\u2019s post, we are going to take a closer look at exactly this topic.<\/p>\n<p class=\"wp-block-paragraph\">In all of the examples we have covered so far, the LLM is just used as a passive responder, meaning it receives a question and then generates an answer, and that\u2019s it. But what if we want the LLM not just to respond with something but instead to do something? Or to put it more precisely, what if we want an action to be triggered based on the model\u2019s response? This action may be anything: look up into live data, send a message, query a database, call an external API, and so on. <\/p>\n<p class=\"wp-block-paragraph\">This is made possible with tool calling. Tool calling is what transforms an LLM from a very smart text generator into something that can actually trigger actions and interact with the world around it. <\/p>\n<p class=\"wp-block-paragraph\">So, let\u2019s take a look!<\/p>\n<p>What is Tool Calling?<\/p>\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/www.ibm.com\/think\/topics\/tool-calling\" data-type=\"link\" data-id=\"https:\/\/www.ibm.com\/think\/topics\/tool-calling\" rel=\"nofollow noopener\" target=\"_blank\">Tool calling<\/a> (also called <a href=\"https:\/\/developers.openai.com\/api\/docs\/guides\/function-calling\" data-type=\"link\" data-id=\"https:\/\/developers.openai.com\/api\/docs\/guides\/function-calling\" rel=\"nofollow noopener\" target=\"_blank\">function calling<\/a>) is the mechanism by which an LLM can request the execution of external functions or APIs as part of generating its response. In other words, instead of just returning text, the model can execute a specific function with specific arguments, as a response to the user\u2019s request.<\/p>\n<p class=\"wp-block-paragraph\">The key thing to understand here is that the model itself does not execute the tool. It only decides which tool to call and with what arguments. The actual execution of the selected tool happens in our own code, in which the request to the AI model is included. We then feed the tool\u2019s result back to the AI model, which uses it to generate a final response to the user.<\/p>\n<p class=\"wp-block-paragraph\">This is the tool calling loop, which includes the following steps:<\/p>\n<p>The user submits a message<\/p>\n<p>The AI model takes the message as input and produces an output, which is essentially a decision on which tool to utilise and with which arguments<\/p>\n<p>The model\u2019s response containing the tool selection and respective arguments to be used is passed back to the code. The code \u2013 with no involvement of the AI model \u2013 executes the selected tool with the selected arguments. This execution produces some kind of result (e.g., a calculation, information obtained from an API, etc.), and this result is then passed back to the AI model.<\/p>\n<p>The AI model takes as input the result of the tool and produces a final response to the user based on that.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.europesays.com\/ai\/wp-content\/uploads\/2026\/06\/image-296-1024x623.png\" alt=\"\" class=\"wp-image-668340\"\/><\/p>\n<p class=\"wp-block-paragraph\">Again, the model generates a tool call, not a tool execution. The two are very different things, and conflating them is one of the most common sources of confusion.<\/p>\n<p class=\"wp-block-paragraph\">But what exactly is a tool call? In practice, it means that the model returns a structured, machine-readable response using Function Calling, as we saw in the previous post. In this response, content is None; there is no natural language answer, just a structured instruction indicating which tool to call and with what arguments. It is only after we execute the tool and pass the result back that the model generates an actual text response for the user.<\/p>\n<p class=\"wp-block-paragraph\">But let\u2019s see this in practice!<\/p>\n<p class=\"wp-block-paragraph\">We\u2019ll start with a simple example using just one tool and one call, and then progressively build up to some more interesting scenarios.<\/p>\n<p>1. A single tool: weather API<\/p>\n<p class=\"wp-block-paragraph\">I think that the most common example of tool use with AI that comes to mind is a weather API (the cornerstone of custom, live data), so let\u2019s imagine we\u2019re building a weather assistant. In particular, we want to create a mechanism in which the user asks about the weather, and instead of just letting the AI model make something up (which the model would very happily do \ud83d\ude43), we want it to call a real weather function and get actual data about the weather from somewhere else, outside the LLM. To get the weather data, I will be using <a href=\"https:\/\/open-meteo.com\/\" rel=\"nofollow noopener\" target=\"_blank\">Open-Meteo<\/a>, a free, open-source weather API that happily requires no API key. <\/p>\n<p class=\"wp-block-paragraph\">To use a tool, we have to initially declare it in tools. <\/p>\n<p>from openai import OpenAI<br \/>\nimport json<\/p>\n<p>client = OpenAI(api_key=&#8221;your_api_key&#8221;)<\/p>\n<p># Step 1: define the tool<br \/>\ntools = [<br \/>\n    {<br \/>\n        &#8220;type&#8221;: &#8220;function&#8221;,<br \/>\n        &#8220;function&#8221;: {<br \/>\n            &#8220;name&#8221;: &#8220;get_current_weather&#8221;,<br \/>\n            &#8220;description&#8221;: &#8220;Get the current weather for a given city&#8221;,<br \/>\n            &#8220;parameters&#8221;: {<br \/>\n                &#8220;type&#8221;: &#8220;object&#8221;,<br \/>\n                &#8220;properties&#8221;: {<br \/>\n                    &#8220;city&#8221;: {<br \/>\n                        &#8220;type&#8221;: &#8220;string&#8221;,<br \/>\n                        &#8220;description&#8221;: &#8220;The name of the city, e.g. Athens&#8221;<br \/>\n                    },<br \/>\n                    &#8220;unit&#8221;: {<br \/>\n                        &#8220;type&#8221;: &#8220;string&#8221;,<br \/>\n                        &#8220;enum&#8221;: [&#8220;celsius&#8221;, &#8220;fahrenheit&#8221;],<br \/>\n                        &#8220;description&#8221;: &#8220;The temperature unit to use&#8221;<br \/>\n                    }<br \/>\n                },<br \/>\n                &#8220;required&#8221;: [&#8220;city&#8221;]<br \/>\n            }<br \/>\n        }<br \/>\n    }<br \/>\n]<\/p>\n<p class=\"wp-block-paragraph\">Notice how the actual tool to be used (the weather API) is mentioned nowhere up to this point. Instead, the model decides which tool to call based on three things: the function description (\u201cGet the current weather for a given city\u201d), the parameter descriptions (\u201cThe name of the city, e.g., Athens\u201d), and the enforced schema. It is purely from this information that the model figures out whether this is the right tool to call for a given user message and with what arguments. Thus, writing clear and accurate descriptions when defining our tools is of key importance for the model to successfully identify and call the right tool based on the user\u2019s input.<\/p>\n<p class=\"wp-block-paragraph\">So, after we have defined the tools variable, we can then make a request to the AI model:<\/p>\n<p># Step 2: send the user message along with the tool definition<br \/>\nmessages = [<br \/>\n    {&#8220;role&#8221;: &#8220;user&#8221;, &#8220;content&#8221;: &#8220;What&#8217;s the weather like in Athens right now?&#8221;}<br \/>\n]<\/p>\n<p>response = client.chat.completions.create(<br \/>\n    model=&#8221;gpt-4o-mini&#8221;,<br \/>\n    tools=tools,<br \/>\n    messages=messages<br \/>\n)<\/p>\n<p>print(response.choices[0].message)<\/p>\n<p class=\"wp-block-paragraph\">Here\u2019s what happens when we make this request. The model reads the user\u2019s message, \u201cWhat\u2019s the weather like in Athens right now?\u201d, and understands that the available tool get_current_weather can help answer this query with real, live data. So, rather than generating a text response directly, it decides to call the tool first. More specifically, the model\u2019s response at this point looks like this:<\/p>\n<p>ChatCompletionMessage(<br \/>\n    content=None,<br \/>\n    role=&#8217;assistant&#8217;,<br \/>\n    tool_calls=[<br \/>\n        ChatCompletionMessageToolCall(<br \/>\n            id=&#8217;call_abc123&#8242;,<br \/>\n            type=&#8217;function&#8217;,<br \/>\n            function=Function(<br \/>\n                name=&#8217;get_current_weather&#8217;,<br \/>\n                arguments='{&#8220;city&#8221;: &#8220;Athens&#8221;, &#8220;unit&#8221;: &#8220;celsius&#8221;}&#8217;<br \/>\n            )<br \/>\n        )<br \/>\n    ]<br \/>\n)<\/p>\n<p class=\"wp-block-paragraph\">Notice how content is None, because the model isn\u2019t returning a text response, but a tool call. Now it\u2019s our job to actually execute the tool, the model selected, and return the result back to it. In our case, this is going to be making the API request to the weather API, using the arguments (that is, the city and unit of measurement) provided in the AI model\u2019s response:<\/p>\n<p># Step 3: execute the tool using the Open-Meteo API<br \/>\nimport requests<\/p>\n<p>def get_current_weather(city: str, unit: str = &#8220;celsius&#8221;):<br \/>\n    # geocode the city name to coordinates<br \/>\n    geo = requests.get(<br \/>\n        &#8220;https:\/\/geocoding-api.open-meteo.com\/v1\/search&#8221;,<br \/>\n        params={&#8220;name&#8221;: city, &#8220;count&#8221;: 1}<br \/>\n    ).json()<br \/>\n    lat = geo[&#8220;results&#8221;][0][&#8220;latitude&#8221;]<br \/>\n    lon = geo[&#8220;results&#8221;][0][&#8220;longitude&#8221;]<\/p>\n<p>    # fetch current weather<br \/>\n    weather = requests.get(<br \/>\n        &#8220;https:\/\/api.open-meteo.com\/v1\/forecast&#8221;,<br \/>\n        params={<br \/>\n            &#8220;latitude&#8221;: lat,<br \/>\n            &#8220;longitude&#8221;: lon,<br \/>\n            &#8220;current&#8221;: &#8220;temperature_2m,weather_code&#8221;,<br \/>\n            &#8220;temperature_unit&#8221;: unit<br \/>\n        }<br \/>\n    ).json()<\/p>\n<p>    temp = weather[&#8220;current&#8221;][&#8220;temperature_2m&#8221;]<br \/>\n    return {&#8220;city&#8221;: city, &#8220;temperature&#8221;: temp, &#8220;unit&#8221;: unit}<\/p>\n<p># extract the tool call from the response<br \/>\ntool_call = response.choices[0].message.tool_calls[0]<br \/>\narguments = json.loads(tool_call.function.arguments)<\/p>\n<p># call the actual function<br \/>\nweather_result = get_current_weather(**arguments)<\/p>\n<p class=\"wp-block-paragraph\">we can then append the tool\u2019s result to the message history and then send everything back to the model:<\/p>\n<p># Step 4: add the assistant&#8217;s tool call AND the tool result to the message history<br \/>\nmessages.append(response.choices[0].message)  # important: append the tool call first<br \/>\nmessages.append({<br \/>\n    &#8220;role&#8221;: &#8220;tool&#8221;,<br \/>\n    &#8220;tool_call_id&#8221;: tool_call.id,  # links the result back to the specific tool call<br \/>\n    &#8220;content&#8221;: json.dumps(weather_result)<br \/>\n})<\/p>\n<p># Step 5: send everything back to the model for a final response<br \/>\nfinal_response = client.chat.completions.create(<br \/>\n    model=&#8221;gpt-4o-mini&#8221;,<br \/>\n    tools=tools,<br \/>\n    messages=messages<br \/>\n)<\/p>\n<p>print(final_response.choices[0].message.content)<\/p>\n<p class=\"wp-block-paragraph\">And now, we finally get a proper text response:<\/p>\n<p>It&#8217;s currently 29\u00b0C in Athens. Sounds like a great day to be outside!<\/p>\n<p class=\"wp-block-paragraph\">\ud83c\udf68 <a href=\"https:\/\/datacream.substack.com\/\" rel=\"nofollow noopener\" target=\"_blank\">DataCream<\/a> is a newsletter offering stories and tutorials on AI, data, and tech. If you are interested in these topics, <a href=\"https:\/\/datacream.substack.com\/\" rel=\"nofollow noopener\" target=\"_blank\">subscribe here<\/a>!<\/p>\n<p>2. Letting the model choose from multiple tools<\/p>\n<p class=\"wp-block-paragraph\">Now let\u2019s take a look at a more realistic example. In a real-world agentic application, the model typically has access to not one, but multiple tools, and as a result, it needs to figure out which one (or ones) need to be used based on what the user is asking.<\/p>\n<p class=\"wp-block-paragraph\">Let\u2019s extend our initial weather API example by adding an additional tool for currencies. For this, we\u2019ll use <a href=\"https:\/\/frankfurter.dev\/\" rel=\"nofollow noopener\" target=\"_blank\">Frankfurter<\/a>, a currency API providing European Central Bank daily rates, again with no API key requirement. So, let\u2019s update our tools variable by adding a second tool for converting currencies:<\/p>\n<p>tools = [<br \/>\n    {<br \/>\n        &#8220;type&#8221;: &#8220;function&#8221;,<br \/>\n        &#8220;function&#8221;: {<br \/>\n            &#8220;name&#8221;: &#8220;get_current_weather&#8221;,<br \/>\n            &#8220;description&#8221;: &#8220;Get the current weather for a given city&#8221;,<br \/>\n            &#8220;parameters&#8221;: {<br \/>\n                &#8220;type&#8221;: &#8220;object&#8221;,<br \/>\n                &#8220;properties&#8221;: {<br \/>\n                    &#8220;city&#8221;: {&#8220;type&#8221;: &#8220;string&#8221;, &#8220;description&#8221;: &#8220;The name of the city&#8221;},<br \/>\n                    &#8220;unit&#8221;: {&#8220;type&#8221;: &#8220;string&#8221;, &#8220;enum&#8221;: [&#8220;celsius&#8221;, &#8220;fahrenheit&#8221;]}<br \/>\n                },<br \/>\n                &#8220;required&#8221;: [&#8220;city&#8221;]<br \/>\n            }<br \/>\n        }<br \/>\n    },<br \/>\n    {<br \/>\n        &#8220;type&#8221;: &#8220;function&#8221;,<br \/>\n        &#8220;function&#8221;: {<br \/>\n            &#8220;name&#8221;: &#8220;convert_currency&#8221;,<br \/>\n            &#8220;description&#8221;: &#8220;Convert an amount from one currency to another&#8221;,<br \/>\n            &#8220;parameters&#8221;: {<br \/>\n                &#8220;type&#8221;: &#8220;object&#8221;,<br \/>\n                &#8220;properties&#8221;: {<br \/>\n                    &#8220;amount&#8221;: {&#8220;type&#8221;: &#8220;number&#8221;, &#8220;description&#8221;: &#8220;The amount to convert&#8221;},<br \/>\n                    &#8220;from_currency&#8221;: {&#8220;type&#8221;: &#8220;string&#8221;, &#8220;description&#8221;: &#8220;The source currency code, e.g. USD&#8221;},<br \/>\n                    &#8220;to_currency&#8221;: {&#8220;type&#8221;: &#8220;string&#8221;, &#8220;description&#8221;: &#8220;The target currency code, e.g. EUR&#8221;}<br \/>\n                },<br \/>\n                &#8220;required&#8221;: [&#8220;amount&#8221;, &#8220;from_currency&#8221;, &#8220;to_currency&#8221;]<br \/>\n            }<br \/>\n        }<br \/>\n    }<br \/>\n]<\/p>\n<p class=\"wp-block-paragraph\">And also set up the actual convert_currency function using the Frankfurter API:<\/p>\n<p>def convert_currency(amount: float, from_currency: str, to_currency: str):<br \/>\n    response = requests.get(<br \/>\n        f&#8221;https:\/\/api.frankfurter.dev\/v2\/rate\/{from_currency}\/{to_currency}&#8221;<br \/>\n    ).json()<\/p>\n<p>    rate = response[&#8220;rate&#8221;]<br \/>\n    converted = round(amount * rate, 2)<br \/>\n    return {<br \/>\n        &#8220;amount&#8221;: amount,<br \/>\n        &#8220;from_currency&#8221;: from_currency,<br \/>\n        &#8220;to_currency&#8221;: to_currency,<br \/>\n        &#8220;converted_amount&#8221;: converted,<br \/>\n        &#8220;rate&#8221;: rate<br \/>\n    }<\/p>\n<p class=\"wp-block-paragraph\">In this way, the model can handle a much wider range of user requests; it can now also answer about currencies, on top of the weather \ud83d\ude0b. Now, if the user asks \u201cWhat\u2019s the weather in Athens?\u201d, the model should call get_current_weather. If they ask \u201cHow much is 100 USD in EUR?\u201d, it should call convert_currency. And if we ask something irrelevant to both weather and currencies for which neither of the available tools can help, the model will simply respond in text without calling any tool at all.<\/p>\n<p class=\"wp-block-paragraph\">But let\u2019s see this in action:<\/p>\n<p>messages = [<br \/>\n    {&#8220;role&#8221;: &#8220;user&#8221;, &#8220;content&#8221;: &#8220;How much is 200 USD in EUR?&#8221;}<br \/>\n]<\/p>\n<p>response = client.chat.completions.create(<br \/>\n    model=&#8221;gpt-4o-mini&#8221;,<br \/>\n    tools=tools,<br \/>\n    messages=messages<br \/>\n)<\/p>\n<p>tool_call = response.choices[0].message.tool_calls[0]<\/p>\n<p class=\"wp-block-paragraph\">Let\u2019s take a glance at the response:<\/p>\n<p>print(tool_call.function.name)        <\/p>\n<p class=\"wp-block-paragraph\">from which we get convert_currency. So, the model understood that the question \u201cHow much is 200 USD in EUR?\u201d is relevant to the convert_currency tool. Let\u2019s also take a look at the arguments:<\/p>\n<p>print(tool_call.function.arguments)  <\/p>\n<p class=\"wp-block-paragraph\">from which we get <\/p>\n<p class=\"wp-block-paragraph\">&#8216;{&#8220;amount&#8221;: 200, &#8220;from_currency&#8221;: &#8220;USD&#8221;, &#8220;to_currency&#8221;: &#8220;EUR&#8221;}&#8217;<\/p>\n<p class=\"wp-block-paragraph\">So, the model correctly identifies convert_currency as the right tool and fills in the appropriate arguments, without us doing anything other than providing appropriate tool descriptions, and the user providing an appropriate message. This exact decision-making mechanism is what makes tool-calling the foundation of agentic systems.<\/p>\n<p>3. Calling multiple tools at once<\/p>\n<p class=\"wp-block-paragraph\">Another interesting tool calling scenario is that many models, like gpt-4o, can call multiple tools in a single response when the user\u2019s request requires it. This is known as <a href=\"https:\/\/platform.claude.com\/docs\/en\/agents-and-tools\/tool-use\/parallel-tool-use\" data-type=\"link\" data-id=\"https:\/\/platform.claude.com\/docs\/en\/agents-and-tools\/tool-use\/parallel-tool-use\" rel=\"nofollow noopener\" target=\"_blank\">parallel tool calling<\/a>.<\/p>\n<p class=\"wp-block-paragraph\">For example, let\u2019s imagine a scenario where the user asks in a single request something that requires the use of both the get_current_weather and convert_currency tools to obtain the required info:<\/p>\n<p>messages = [<br \/>\n    {&#8220;role&#8221;: &#8220;user&#8221;, &#8220;content&#8221;: &#8220;What&#8217;s the weather in Athens and how much is 100 USD in EUR?&#8221;}<br \/>\n]<\/p>\n<p>response = client.chat.completions.create(<br \/>\n    model=&#8221;gpt-4o-mini&#8221;,<br \/>\n    tools=tools,<br \/>\n    messages=messages<br \/>\n)<\/p>\n<p>for tool_call in response.choices[0].message.tool_calls:<br \/>\n    print(tool_call.function.name)<br \/>\n    print(tool_call.function.arguments)<\/p>\n<p class=\"wp-block-paragraph\">In this case, the response we get is the following:<\/p>\n<p>get_current_weather<br \/>\n{&#8220;city&#8221;: &#8220;Athens&#8221;}<\/p>\n<p>convert_currency<br \/>\n{&#8220;amount&#8221;: 100, &#8220;from_currency&#8221;: &#8220;USD&#8221;, &#8220;to_currency&#8221;: &#8220;EUR&#8221;}<\/p>\n<p class=\"wp-block-paragraph\">Notice how both tools are called in a single model response. We can then execute the respective tools with the provided arguments and pass back the tool results to the model together. This is much more efficient than sequential calls, and it\u2019s how more advanced agents handle multi-part requests.<\/p>\n<p>On my mind: So, what makes this agentic?<\/p>\n<p class=\"wp-block-paragraph\">One thing that has always gotten on my nerves is the term \u201cagentic\u201d being slapped on everything. Agents, agentic workflows, anything originating from the word agent is very sexy nowadays, but as you may have already discovered yourself, not everything sold as agentic really is.<\/p>\n<p class=\"wp-block-paragraph\">So let\u2019s take a step back and think about what an agent actually is in the first place. At its core, an agent is something that perceives its environment, processes that information in some way, has a goal, and then decides what action to take in order to achieve it. Think about what our tool calling mechanism is doing: it perceives the tools available, decides which one is appropriate to address the user\u2019s request (if any), and passes that decision on to the rest of the code for execution. That, in its simplest form, is agency.<\/p>\n<p class=\"wp-block-paragraph\">In real-world agentic applications, the tool calling loop runs not one but multiple times, with the model using the results of one tool call to decide whether, and which, tool to call next. This is sometimes called a <a href=\"https:\/\/www.ibm.com\/think\/topics\/react-agent\" data-type=\"link\" data-id=\"https:\/\/www.ibm.com\/think\/topics\/react-agent\" rel=\"nofollow noopener\" target=\"_blank\">ReAct loop<\/a> (Reason + Act), and it\u2019s what allows agents to handle complex, multi-step tasks that can\u2019t be solved in a single call.<\/p>\n<p class=\"wp-block-paragraph\">Ultimately, what I find most fascinating about tool calling is how it changes the nature of what an LLM is. Up to this point, a language model was essentially a very sophisticated input-output function, which takes text as input and generates text as output. But with the tool calling, we gain access to an endless collection of additional functionalities, which we can combine with the reasoning power of the LLM to create systems that are far more capable than either alone.<\/p>\n<p class=\"has-text-align-center wp-block-paragraph\">\u2728 Thank you for reading! \u2728<\/p>\n<p class=\"has-text-align-center wp-block-paragraph\">If you made it this far, <a style=\"color: inherit;\" href=\"https:\/\/pialgorithms.com\/\" rel=\"nofollow noopener\" target=\"_blank\">you might find pialgorithms useful<\/a> \u2014 a platform we\u2019ve been building that helps teams securely manage organizational knowledge in one place.<\/p>\n<p class=\"has-text-align-center wp-block-paragraph\">Loved this post? Join me on \ud83d\udc8c<a href=\"https:\/\/datacream.substack.com\/\" data-type=\"link\" data-id=\"https:\/\/datacream.substack.com\/\" rel=\"nofollow noopener\" target=\"_blank\">Substack<\/a> and \ud83d\udcbc<a href=\"https:\/\/www.linkedin.com\/in\/mariamouschoutzi\/\" data-type=\"link\" data-id=\"https:\/\/www.linkedin.com\/in\/mariamouschoutzi\/\" rel=\"nofollow noopener\" target=\"_blank\">LinkedIn<\/a><\/p>\n<p class=\"has-text-align-center wp-block-paragraph\">All images by the author, except mentioned otherwise.<\/p>\n","protected":false},"excerpt":{"rendered":"In my latest post, how to get structured, machine-readable outputs as a response from an LLM, using JSON&hellip;\n","protected":false},"author":2,"featured_media":81003,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6],"tags":[179,7493,23817,415,7067,5147,44142],"class_list":["post-81002","post","type-post","status-publish","format-standard","has-post-thumbnail","category-agentic-ai","tag-agentic-ai","tag-agentic-artificial-intelligence","tag-deep-dives","tag-llm","tag-programming","tag-python","tag-tool-calling"],"_links":{"self":[{"href":"https:\/\/www.europesays.com\/ai\/wp-json\/wp\/v2\/posts\/81002","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.europesays.com\/ai\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.europesays.com\/ai\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.europesays.com\/ai\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.europesays.com\/ai\/wp-json\/wp\/v2\/comments?post=81002"}],"version-history":[{"count":0,"href":"https:\/\/www.europesays.com\/ai\/wp-json\/wp\/v2\/posts\/81002\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.europesays.com\/ai\/wp-json\/wp\/v2\/media\/81003"}],"wp:attachment":[{"href":"https:\/\/www.europesays.com\/ai\/wp-json\/wp\/v2\/media?parent=81002"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.europesays.com\/ai\/wp-json\/wp\/v2\/categories?post=81002"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.europesays.com\/ai\/wp-json\/wp\/v2\/tags?post=81002"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}