IA & Agentes
Copilot Studio - Tools e Conectores [4] - Chamando uma Azure Function como tool
Copilot Studio - Tools & Connectors [4] - Calling an Azure Function as a tool
Fala dataholics! Penúltimo post da série de Tools e esse tem um gostinho especial pra mim, porque ele junta duas coisas que eu já falo há tempos aqui no blog: Azure Functions e agentes. No post [2] eu peguei uma API pública (a BrasilAPI) e transformei em tool. Hoje a API é sua: vou pegar uma Azure Function, o seu código serverless, e transformar ela em tool de um agente. Fiz uma animação curta explicando a ideia e embaixo dela eu abro o passo a passo com o código.
O que veremos nesse post:
Por que usar uma Function como tool
A Function que eu peguei (com código)
O caminho: HTTP trigger, OpenAPI, REST API tool
Autenticação com function key
Resumo
Por que usar uma Function como tool
Um conector pronto ou uma API pública são ótimos pra ler dado de fora, mas em algum momento você vai querer que o agente rode a sua lógica. Calcular uma regra de negócio, transformar um dado, bater num banco interno, falar com um sistema que só a sua empresa tem. É aí que a Azure Function encaixa: é o seu código, exposto por HTTP, rodando serverless (escala sozinha e você paga pelo uso). E o melhor, se você já tem Functions no ar, como as da minha série aqui do blog, dá pra reaproveitar sem reescrever nada.
A Function que eu peguei
Pra ficar concreto, imagina uma Function simples que responde o status de um pedido pelo número. No modelo novo do Python ela fica assim, com um HTTP trigger:
import azure.functions as func
import json
app = func.FunctionApp()
@app.route(route="pedido/{id}", auth_level=func.AuthLevel.FUNCTION)
def get_pedido(req: func.HttpRequest) -> func.HttpResponse:
pedido_id = req.route_params.get("id")
# aqui voce chamaria o seu sistema real
dados = {"id": pedido_id, "status": "em transporte", "previsao_dias": 2}
return func.HttpResponse(
json.dumps(dados), mimetype="application/json"
)Repara no auth_level=func.AuthLevel.FUNCTION. Isso quer dizer que a Function só responde pra quem mandar a function key, e essa key vai ser justamente a autenticação da nossa tool lá na frente. Guarda essa informação.
O caminho: da Function até o agente
Aqui está a parte boa: o caminho é o mesmo do post [2]. A Function nada mais é do que uma API REST, então a gente usa o wizard de REST API do Copilot Studio. O fluxo é esse:
HTTP trigger: sua Function já está exposta por HTTP, com uma URL do tipo
https://minhafunc.azurewebsites.net/api/pedido/123.OpenAPI: você descreve a Function num arquivo OpenAPI, igual fizemos com a BrasilAPI. Um detalhe importante: o Copilot Studio trabalha com OpenAPI 2.0 (Swagger) por baixo. Se você subir um 3.0 ele converte sozinho, mas se der erro estranho, vale gerar já em 2.0.
REST API tool: no agente, Add a tool, aba REST API, sobe o OpenAPI, e segue o mesmo wizard de upload, plugin details, autenticação, select tools e publish.
O agente chama: a tool entra na aba Tools com Trigger by agent, e o modelo decide chamar a sua Function quando o usuário perguntar algo que precise dela.
Um perrengue que vale avisar, porque pega muita gente: na hora de descrever o host no OpenAPI, coloca só o domínio, sem o https://. Se você botar o esquema junto (https://minhafunc.azurewebsites.net) o wizard reclama. O certo é minhafunc.azurewebsites.net no host e o https vai no campo de schemes.
Autenticação com function key
Lembra do auth_level=FUNCTION lá no código? É agora que ele importa. Na etapa de Authentication do wizard você escolhe API key e configura a function key pra ir no header x-functions-key (dá pra mandar como query ?code= também, mas header é mais limpo). A partir daí o agente manda a chave em toda chamada, e a sua Function continua protegida, sem ficar aberta pra qualquer um.
Reginaldo, e se eu quiser algo mais corporativo que uma chave?
Aí você vai de OAuth com Entra ID, e o caminho passa a ser um custom connector no Power Platform em vez do REST API direto. Pra começar e pra cenário interno, a function key resolve muito bem e é o que eu usaria no primeiro momento.
RESUMO
Uma Azure Function com HTTP trigger é o jeito de dar pro agente a sua lógica, não só leitura de dado de fora.
O caminho é o mesmo do post [2]: descreve a Function num OpenAPI e sobe como REST API tool.
O Copilot Studio usa OpenAPI 2.0 por baixo (converte o 3.0 sozinho). No host, só o domínio, sem https://.
Autenticação com function key: escolhe API key no wizard e manda no header
x-functions-key.Pra auth corporativa (OAuth / Entra ID), o caminho vira custom connector no Power Platform.
Com isso o agente já roda o seu próprio código serverless. No último post da série a gente sobe o degrau final e conecta o Databricks como tool, e aí junta de vez o mundo de agentes com o mundo de dados, que é a alma desse blog.
Referências:
https://learn.microsoft.com/en-us/microsoft-copilot-studio/agent-extend-action-rest-api
https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-http-webhook-trigger
Fique bem e até a próxima.
#copilotstudio #azurefunctions #restapi #ia #agentes #datainaction
Hey dataholics! Second to last post in the Tools series and this one is a little special to me, because it brings together two things I've been talking about here for a long time: Azure Functions and agents. In post [2] I took a public API (BrasilAPI) and turned it into a tool. Today the API is yours: I'll take an Azure Function, your serverless code, and turn it into an agent tool. I made a short animation explaining the idea and below it I break down the step by step with the code.
What we'll cover in this post:
Why use a Function as a tool
The Function I picked (with code)
The path: HTTP trigger, OpenAPI, REST API tool
Authentication with a function key
Summary
Why use a Function as a tool
A ready-made connector or a public API are great for reading data from outside, but at some point you'll want the agent to run your logic. Compute a business rule, transform a value, hit an internal database, talk to a system only your company has. That's where the Azure Function fits: it's your code, exposed over HTTP, running serverless (it scales on its own and you pay per use). And best of all, if you already have Functions running, like the ones from my series here on the blog, you can reuse them without rewriting anything.
The Function I picked
To make it concrete, picture a simple Function that returns an order's status by its number. In the new Python model it looks like this, with an HTTP trigger:
import azure.functions as func
import json
app = func.FunctionApp()
@app.route(route="pedido/{id}", auth_level=func.AuthLevel.FUNCTION)
def get_pedido(req: func.HttpRequest) -> func.HttpResponse:
pedido_id = req.route_params.get("id")
# here you would call your real system
dados = {"id": pedido_id, "status": "em transporte", "previsao_dias": 2}
return func.HttpResponse(
json.dumps(dados), mimetype="application/json"
)Notice the auth_level=func.AuthLevel.FUNCTION. It means the Function only responds to whoever sends the function key, and that key is going to be exactly the authentication of our tool further down. Hold on to that.
The path: from the Function to the agent
Here's the good part: the path is the same as post [2]. A Function is nothing more than a REST API, so we use the Copilot Studio REST API wizard. The flow is this:
HTTP trigger: your Function is already exposed over HTTP, with a URL like
https://minhafunc.azurewebsites.net/api/pedido/123.OpenAPI: you describe the Function in an OpenAPI file, just like we did with BrasilAPI. One important detail: Copilot Studio works with OpenAPI 2.0 (Swagger) under the hood. If you upload a 3.0 it converts it on its own, but if you get a weird error, it's worth generating it as 2.0 already.
REST API tool: in the agent, Add a tool, REST API tab, upload the OpenAPI, and follow the same wizard of upload, plugin details, authentication, select tools and publish.
The agent calls it: the tool lands on the Tools tab with Trigger by agent, and the model decides to call your Function when the user asks something that needs it.
One gotcha worth flagging, because it catches a lot of people: when you describe the host in the OpenAPI, put only the domain, without the https://. If you include the scheme (https://minhafunc.azurewebsites.net) the wizard complains. The right way is minhafunc.azurewebsites.net in the host and https goes in the schemes field.
Authentication with a function key
Remember the auth_level=FUNCTION back in the code? Now is when it matters. In the Authentication step of the wizard you choose API key and configure the function key to go in the x-functions-key header (you can also send it as a query ?code=, but the header is cleaner). From then on the agent sends the key on every call, and your Function stays protected, not left open to anyone.
Reginaldo, and what if I want something more enterprise than a key?
Then you go with OAuth and Entra ID, and the path becomes a custom connector in Power Platform instead of the REST API directly. To get started and for an internal scenario, the function key works really well and it's what I'd use at first.
RECAP
An Azure Function with an HTTP trigger is the way to give the agent your logic, not just reading data from outside.
The path is the same as post [2]: describe the Function in an OpenAPI and upload it as a REST API tool.
Copilot Studio uses OpenAPI 2.0 under the hood (it converts 3.0 on its own). In the host, only the domain, without https://.
Authentication with a function key: choose API key in the wizard and send it in the
x-functions-keyheader.For enterprise auth (OAuth / Entra ID), the path becomes a custom connector in Power Platform.
With that the agent already runs your own serverless code. In the last post of the series we take the final step and connect Databricks as a tool, and that finally brings together the world of agents and the world of data, which is the soul of this blog.
References:
https://learn.microsoft.com/en-us/microsoft-copilot-studio/agent-extend-action-rest-api
https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-http-webhook-trigger
Stay well and see you next time.
#copilotstudio #azurefunctions #restapi #ai #agents #datainaction
Gostou? Tem mais no YouTube e no LinkedIn.
Enjoyed it? There's more on YouTube and LinkedIn.