Os callbacks são um recurso avançado que oferece um mecanismo eficiente para se conectar ao processo de execução de um agente específico usando código Python. Eles permitem observar, personalizar e até mesmo controlar o comportamento do agente em pontos específicos e predefinidos.
Há vários tipos de callbacks que podem ser usados, e cada um deles é executado em um ponto específico da rodada de conversa. Esses tipos são descritos nas seções abaixo.
Ambiente de execução e classes do Python
No código de callback do Python, você tem acesso a determinadas classes e funções que ajudam a escrever o código. Para mais informações, consulte a referência do ambiente de execução do Python.
Limitações de sandbox e rede
O código de callback do Python é executado em um ambiente de sandbox. Esse ambiente tem as seguintes limitações:
- Sem acesso à rede privada (PNA): os callbacks não podem acessar diretamente endereços IP privados nem resolver domínios DNS particulares, mesmo que o Diretório de serviços esteja configurado. Se você precisar acessar recursos em uma rede privada, use um tipo de ferramenta que ofereça suporte ao acesso à rede privada (como ferramentas OpenAPI ou MCP).
- Acesso à Internet pública: os callbacks só podem acessar endpoints que estão disponíveis publicamente na Internet.
Tipos de callback
Dependendo do tipo de callback, a função de callback principal precisa ter um nome específico. Isso permite definir funções auxiliares de qualquer nome no código de callback.
Cada tipo de callback é executado em um ponto específico da rodada de conversa:

Se você definir vários callbacks de um tipo específico, eles serão executados na ordem em que forem definidos.
As seções abaixo descrevem cada tipo de callback, com as seguintes informações para cada tipo:
| X | X |
|---|---|
| Nome | Nome da função de callback obrigatória |
| Execução | Ponto de execução na rodada de conversa. |
| Finalidade | Cenários úteis para usar o callback. |
| Argumentos | Argumentos de entrada para a função. |
| Retornar | Valor de retorno para a função. |
| Callback do ADK | Link para a documentação de callback do ADK correspondente. |
Antes do início do agente (before_agent_callback)
| X | X |
|---|---|
| Nome | before_agent_callback |
| Execução | Chamado antes da invocação do agente. |
| Finalidade | Útil para configurar recursos ou estados necessários para o agente, realizar verificações de validação no estado da sessão ou evitar a invocação do agente. |
| Argumentos | CallbackContext |
| Retornar | Conteúdo(opcional): se definido, o agente não será invocado, e a resposta fornecida será usada. |
| Callback do ADK | before agent callback |
Exemplo de código:
import random
def before_agent_callback(
callback_context: CallbackContext
) -> Optional[Content]:
username = callback_context.variables.get("username", None)
if not username:
# default user
final_name = "Default Name"
else:
# add a random integer to the username
final_name = f"{username} {random.randint(1,10)}"
# update the username variable
callback_context.variables["username"] = final_name
Depois que o agente termina (after_agent_callback)
| X | X |
|---|---|
| Nome | after_agent_callback |
| Execução | Chamado depois que o agente é concluído. |
| Finalidade | Útil para tarefas de limpeza, validação pós-execução, modificação do estado final ou atualização da resposta do agente. |
| Argumentos | CallbackContext |
| Retornar | Conteúdo(opcional): se definido, substitui a saída do agente pela saída fornecida. |
| Callback do ADK | after agent callback |
Exemplo de código:
def after_agent_callback(
callback_context: CallbackContext
) -> Optional[Content]:
if callback_context.agent_name == "Routing Agent":
counter = callback_context.variables.get("counter", 0)
counter += 1
# increment the invoked counter for this agent
callback_context.variables["counter"] = int(counter)
Antes da chamada do LLM (before_model_callback)
| X | X |
|---|---|
| Nome | before_model_callback |
| Execução | Chamado antes da solicitação do modelo. |
| Finalidade | Útil para inspeção/modificação da solicitação do modelo ou para evitar o uso do modelo. |
| Argumentos | CallbackContext, LlmRequest |
| Retornar | LlmResponse: se definido, a chamada do modelo será ignorada, e a resposta será usada como se viesse do modelo. |
| Callback do ADK | before model callback |
Exemplo de código:
def before_model_callback(
callback_context: CallbackContext,
llm_request: LlmRequest
) -> Optional[LlmResponse]:
"""
This callback executes *before* a request is sent to the LLM.
By returning an `LlmResponse` object, we are intercepting the call to the
LLM. The LLM will *not* be called, and the framework will instead use the
`LlmResponse` we provide as if it came from the model.
This is the core mechanism for implementing input guardrails, prompt
validation, or serving responses from a cache. Here, we force the agent to
call a function instead of thinking with the LLM.
"""
# Modify the shared session state.
callback_context.variables['foo'] = 'baz'
# Skip the LLM call and return a custom response telling the agent to
# execute a specific function.
return LlmResponse(
content=Content(parts=[Part(
function_call=FunctionCall(
name="function_name", args={"arg_name": "arg_value"}))],
role="model"))
Depois da chamada do LLM (after_model_callback)
| X | X |
|---|---|
| Nome | after_model_callback |
| Execução | Chamado depois que uma resposta do modelo é recebida. |
| Finalidade | Útil para reformatar respostas do modelo, censurar informações sensíveis geradas pelo modelo, analisar dados estruturados do modelo para uso em variáveis e tratamento de erros do modelo. |
| Argumentos | CallbackContext, LlmResponse |
| Retornar | LlmResponse: se definido, substitui a resposta do modelo pela resposta fornecida. |
| Callback do ADK | after model callback |
Exemplo de código:
def after_model_callback(
callback_context: CallbackContext,
llm_response: LlmResponse
) -> Optional[LlmResponse]:
"""
This callback executes *after* a response has been received from the LLM,
but before the agent processes it.
The `llm_response` parameter contains the actual data from the LLM.
By returning `None`, we are approving this response and allowing the agent
to use it as-is.
If we returned a new `LlmResponse` object, it would *replace* the original,
which is useful for redacting sensitive information, enforcing output
formatting, or adding disclaimers.
"""
# Returning None allows the LLM's actual response to be used.
return None
Antes da chamada de ferramenta (before_tool_callback)
| X | X |
|---|---|
| Nome | before_tool_callback |
| Execução | Chamado antes das chamadas de ferramenta. |
| Finalidade | Útil para inspeção e modificação de argumentos de ferramentas, verificações de autorização antes da execução da ferramenta ou implementação de armazenamento em cache no nível da ferramenta. |
| Argumentos | Ferramenta, Dict[str,Any]: entradas de ferramenta, CallbackContext |
| Retornar | Dict[str,Any] : se definido, a execução da ferramenta será ignorada, e essa saída será fornecida ao modelo. |
| Callback do ADK | before tool callback |
Exemplo de código:
def before_tool_callback(
tool: Tool,
input: dict[str, Any],
callback_context: CallbackContext
) -> Optional[dict[str, Any]]:
"""
This callback executes *before* a specific tool is called by the agent.
Here, we modify the input arguments intended for the tool and then return
a dictionary. By returning a dictionary instead of `None`, we are
overriding the default behavior. The actual tool function will *not* be
executed. Instead, the dictionary we return will be treated as the
llm.tool's result and passed back to the LLM for the next step.
This is ideal for validating tool inputs, applying policies, or returning
mocked/cached data for testing.
"""
# Modify the shared session state.
callback_context.variables['foo'] = 'baz'
# Modify the arguments for the tool call in-place.
input['input_arg'] = 'updated_val1'
input['additional_arg'] = 'updated_val2'
# Override the tool call and return a mocked result.
return {"result": "ok"}
Depois da chamada de ferramenta (after_tool_callback)
| X | X |
|---|---|
| Nome | after_tool_callback |
| Execução | Chamado após a conclusão da ferramenta. |
| Finalidade | Útil para inspeção e modificação da resposta da ferramenta antes de enviá-la de volta ao modelo, pós-processamento dos resultados da ferramenta ou salvamento de partes específicas de uma resposta da ferramenta em variáveis. |
| Argumentos | Ferramenta, Dict[str,Any]: entradas de ferramenta, CallbackContext, Dict[str,Any]: resposta da ferramenta |
| Retornar | Dict[str,Any]: se definido, substitui a resposta da ferramenta fornecida ao modelo. |
| Callback do ADK | after tool callback |
Exemplo de código:
# Previous tool was named `get_user_info`
# Previous tool returned the payload:
# {"username": "Patrick", "fave_food": ["pizza"]}
def after_tool_callback(
tool: Tool,
input: dict[str, Any],
callback_context: CallbackContext,
tool_response: dict
) -> Optional[dict]:
if tool.name == "get_user_info":
tool_response["username"] = "Gary"
tool_response["pet"] = "dog"
# Override tool response
return tool_response
Crie um callback
Para criar um callback:
- Abra as configurações do agente.
- Clique em Adicionar código.
- Selecione um tipo de callback.
- Forneça o código Python.
- Clique em Salvar.
Payloads personalizados (custom_payloads)
Os payloads personalizados facilitam a inclusão de dados estruturados suplementares não textuais (normalmente formatados como JSON) na resposta de um agente. Esse payload é fundamental para direcionar ou aumentar a interação do agente com sistemas externos ou aplicativos cliente.
O valor do payload não fica visível para o modelo de linguagem grande (LLM). Ele é usado apenas para gerar a resposta final.
Os payloads personalizados são gerados e definidos usando callbacks, especificamente before_model_callback ou after_model_callback.
O payload personalizado pode ser usado para várias finalidades, geralmente centradas na ativação de interações estruturadas e avançadas:
- Escalonamento/transferência de agente: é usado com frequência para transferir uma interação para um agente humano fornecendo instruções de roteamento (por exemplo, a fila específica para rotear).
- Conteúdo avançado e ações do lado do cliente:
oferece suporte à incorporação de widgets avançados e outros conteúdos avançados
diretamente em experiências de chat,
o que é especialmente útil para integrações de chat personalizadas.
- Os exemplos incluem a exibição de URLs de imagens ou chips e opções de resposta rápida para um cliente usando uma interface como o Call Companion.
- Composição de respostas:
os payloads personalizados podem ser configurados para serem retornados de várias maneiras:
- Retorne apenas o payload explícito de forma determinística.
- Retorne o payload com uma resposta de texto gerada pelo LLM.
- Retorne o payload com uma resposta de texto estático
Configuração do agente
Os payloads personalizados só podem ser gerados e definidos usando callbacks.
O payload é definido como um
blob
com um mime_type de application/json.
Part.from_json(data=payload_string)
Exemplo de after_model_callback
Este é um exemplo de after_model_callback que retorna a resposta do modelo com outra resposta de payload personalizada.
import json
def after_model_callback(callback_context: CallbackContext, llm_response: LlmResponse) -> Optional[LlmResponse]:
"""
Adds a custom payload to every model response which is a text
"""
if (llm_response.content.parts[0].text is not None):
# construct payload
payload_dict = { "custom_payload_key": "custom_payload_value"}
payload_json_string = json.dumps(payload_dict)
new_parts = []
# Keep the origial agent response part, as model only sees text in the historical context.
new_parts.append(Part(text=llm_response.content.parts[0].text))
# Append custom payload
new_parts.append(Part.from_json(data=payload_json_string))
return LlmResponse(content=Content(parts=new_parts))
Exemplo de before_model_callback
Este é um exemplo de before_model_callback que retorna um payload personalizado adicional depois que uma determinada ferramenta é acionada.
import json
def has_escalate(llm_request: LlmRequest) -> bool:
for content in llm_request.contents:
for part in content.parts:
if part.function_call and part.function_call.name == 'escalate':
return True
return False
def before_model_callback(callback_context: CallbackContext, llm_request: LlmRequest) -> Optional[LlmResponse]:
# checks if `escalate` tool is being called
if not has_escalate(llm_request):
return None
payload_dict = { "escalate": "user ask for escalation"}
payload_json_string = json.dumps(payload_dict)
return LlmResponse(content=Content(parts=[Part(text="ESCALATE!!!"), Part.from_json(data=payload_json_string)]))
Verificar o payload no ambiente de execução na resposta
O payload é preenchido como uma estrutura no campo payload para
RunSession
e
BidiRunSession.
O valor do payload não fica visível para o LLM.