Skip to content

Design Patterns and Best Practices for Callbacks

回调的设计模式和最佳实践

Callbacks offer powerful hooks into the agent lifecycle. Here are common design patterns illustrating how to leverage them effectively in ADK, followed by best practices for implementation.

回调提供了强大的智能体生命周期钩子。以下展示了常见的设计模式,说明如何在 ADK 中有效利用它们,以及实现的最佳实践。

Design Patterns

设计模式

These patterns demonstrate typical ways to enhance or control agent behavior using callbacks:

这些模式展示了使用回调增强或控制智能体行为的典型方式:

1. Guardrails & Policy Enforcement

1. 防护栏与策略执行

Pattern Overview: 模式概述: Intercept requests before they reach the LLM or tools to enforce rules.

在请求到达 LLM 或工具之前拦截请求以强制执行规则。

Implementation: 实现: - Use before_model_callback to inspect the LlmRequest prompt 使用 before_model_callback 检查 LlmRequest 提示 - Use before_tool_callback to inspect tool arguments 使用 before_tool_callback 检查工具参数 - If a policy violation is detected (e.g., forbidden topics, profanity): 如果检测到策略违规(例如,禁止的主题,亵渎语言): - Return a predefined response (LlmResponse or dict/Map) to block the operation 返回预定义的响应(LlmResponsedict/Map)以阻止操作 - Optionally update context.state to log the violation 可选地更新 context.state 以记录违规

Example Use Case: 示例用例: A before_model_callback checks llm_request.contents for sensitive keywords and returns a standard "Cannot process this request" LlmResponse if found, preventing the LLM call.

before_model_callback 检查 llm_request.contents 中的敏感关键字,如果找到则返回标准的"无法处理此请求"LlmResponse,从而阻止 LLM 调用。

2. Dynamic State Management

2. 动态状态管理

Pattern Overview: 模式概述: Read from and write to session state within callbacks to make agent behavior context-aware and pass data between steps.

在回调中从会话状态读取和写入数据,使智能体行为具有上下文感知能力,并在步骤之间传递数据。

Implementation: 实现: - Access callback_context.state or tool_context.state 访问 callback_context.statetool_context.state - Modifications (state['key'] = value) are automatically tracked in the subsequent Event.actions.state_delta 修改(state['key'] = value)会在后续的 Event.actions.state_delta 中自动跟踪 - Changes are persisted by the SessionService 更改由 SessionService 持久化

Example Use Case: 示例用例: An after_tool_callback saves a transaction_id from the tool's result to tool_context.state['last_transaction_id']. A later before_agent_callback might read state['user_tier'] to customize the agent's greeting.

after_tool_callback 将工具结果中的 transaction_id 保存到 tool_context.state['last_transaction_id']。随后的 before_agent_callback 可能会读取 state['user_tier'] 来自定义智能体的问候。

3. Logging and Monitoring

3. 日志记录和监控

Pattern Overview: 模式概述: Add detailed logging at specific lifecycle points for observability and debugging.

在特定的生命周期点添加详细的日志记录,以实现可观察性和调试。

Implementation: 实现: - Implement callbacks (e.g., before_agent_callback, after_tool_callback, after_model_callback) 实现回调(例如,before_agent_callbackafter_tool_callbackafter_model_callback) - Print or send structured logs containing: 打印或发送包含以下内容的结构化日志: - Agent name 智能体名称 - Tool name 工具名称 - Invocation ID 调用 ID - Relevant data from the context or arguments 来自上下文或参数的相关数据

Example Use Case: 示例用例: Log messages like INFO: [Invocation: e-123] Before Tool: search_api - Args: {'query': 'ADK'}.

记录类似 INFO: [Invocation: e-123] Before Tool: search_api - Args: {'query': 'ADK'} 的日志消息。

4. Caching

4. 缓存

Pattern Overview: 模式概述: Avoid redundant LLM calls or tool executions by caching results.

通过缓存结果来避免冗余的 LLM 调用或工具执行。

Implementation Steps: 实现步骤: 1. Before Operation: In before_model_callback or before_tool_callback: 操作之前:before_model_callbackbefore_tool_callback 中: - Generate a cache key based on the request/arguments 根据请求/参数生成缓存键 - Check context.state (or an external cache) for this key 在 context.state(或外部缓存)中检查此键 - If found, return the cached LlmResponse or result directly 如果找到,直接返回缓存的 LlmResponse 或结果

  1. After Operation: If cache miss occurred: 操作之后: 如果缓存未命中:
  2. Use the corresponding after_ callback to store the new result in the cache using the key 使用相应的 after_ 回调使用键将新结果存储在缓存中

Example Use Case: 示例用例: before_tool_callback for get_stock_price(symbol) checks state[f"cache:stock:{symbol}"]. If present, returns the cached price; otherwise, allows the API call and after_tool_callback saves the result to the state key.

get_stock_price(symbol)before_tool_callback 检查 state[f"cache:stock:{symbol}"]。如果存在,则返回缓存的价格;否则,允许 API 调用,after_tool_callback 将结果保存到状态键。

5. Request/Response Modification

5. 请求/响应修改

Pattern Overview: 模式概述: Alter data just before it's sent to the LLM/tool or just after it's received.

在发送到 LLM/工具之前或接收之后立即修改数据。

Implementation Options: 实现选项: - before_model_callback: Modify llm_request (e.g., add system instructions based on state) 修改 llm_request(例如,基于 state 添加系统指令) - after_model_callback: Modify the returned LlmResponse (e.g., format text, filter content) 修改返回的 LlmResponse(例如,格式化文本,过滤内容) - before_tool_callback: Modify the tool args dictionary (or Map in Java) 修改工具 args 字典(或 Java 中的 Map) - after_tool_callback: Modify the tool_response dictionary (or Map in Java) 修改 tool_response 字典(或 Java 中的 Map)

Example Use Case: 示例用例: before_model_callback appends "User language preference: Spanish" to llm_request.config.system_instruction if context.state['lang'] == 'es'.

如果 context.state['lang'] == 'es',before_model_callback 会将"用户语言偏好:西班牙语"附加到 llm_request.config.system_instruction

6. Conditional Skipping of Steps

6. 条件跳过步骤

Pattern Overview: 模式概述: Prevent standard operations (agent run, LLM call, tool execution) based on certain conditions.

根据某些条件阻止标准操作(智能体运行、LLM 调用、工具执行)。

Implementation: 实现: - Return a value from a before_ callback to skip the normal execution: 从 before_ 回调返回一个值以跳过正常执行: - Content from before_agent_callback 来自 before_agent_callbackContent - LlmResponse from before_model_callback 来自 before_model_callbackLlmResponse - dict from before_tool_callback 来自 before_tool_callbackdict - The framework interprets this returned value as the result for that step 框架将此返回值解释为该步骤的结果

Example Use Case: 示例用例: before_tool_callback checks tool_context.state['api_quota_exceeded']. If True, it returns {'error': 'API quota exceeded'}, preventing the actual tool function from running.

before_tool_callback 检查 tool_context.state['api_quota_exceeded']。如果为 True,它返回 {'error': 'API quota exceeded'},从而阻止实际工具函数运行。

7. Tool-Specific Actions (Authentication & Summarization Control)

7. 工具特定操作(身份验证和摘要控制)

Pattern Overview: 模式概述: Handle actions specific to the tool lifecycle, primarily authentication and controlling LLM summarization of tool results.

处理特定于工具生命周期的操作,主要是身份验证和控制 LLM 对工具结果的摘要。

Implementation: 实现: Use ToolContext within tool callbacks (before_tool_callback, after_tool_callback):

在工具回调(before_tool_callbackafter_tool_callback)中使用 ToolContext:

  • Authentication: Call tool_context.request_credential(auth_config) in before_tool_callback if credentials are required but not found (e.g., via tool_context.get_auth_response or state check). This initiates the auth flow. 身份验证: 如果需要但未找到凭据(例如,通过 tool_context.get_auth_response 或状态检查),则在 before_tool_callback 中调用 tool_context.request_credential(auth_config)。这会启动身份验证流程。
  • Summarization: Set tool_context.actions.skip_summarization = True if the raw dictionary output of the tool should be passed back to the LLM or potentially displayed directly, bypassing the default LLM summarization step. 摘要: 如果工具的原始字典输出应该传递回 LLM 或可能直接显示,绕过默认的 LLM 摘要步骤,则设置 tool_context.actions.skip_summarization = True

Example Use Case: 示例用例: A before_tool_callback for a secure API checks for an auth token in state; if missing, it calls request_credential. An after_tool_callback for a tool returning structured JSON might set skip_summarization = True.

安全 API 的 before_tool_callback 检查状态中的身份验证令牌;如果缺少,则调用 request_credential。返回结构化 JSON 的工具的 after_tool_callback 可能会设置 skip_summarization = True

8. Artifact Handling

8. 工件处理

Pattern Overview: 模式概述: Save or load session-related files or large data blobs during the agent lifecycle.

在智能体生命周期中保存或加载与会话相关的文件或大型数据块。

Implementation: 实现: - Saving: Use callback_context.save_artifact / await tool_context.save_artifact to store data: 保存: 使用 callback_context.save_artifact / await tool_context.save_artifact 存储数据: - Generated reports 生成的报告 - Logs 日志 - Intermediate data 中间数据 - Loading: Use load_artifact to retrieve previously stored artifacts 加载: 使用 load_artifact 检索先前存储的工件 - Tracking: Changes are tracked via Event.actions.artifact_delta 跟踪: 更改通过 Event.actions.artifact_delta 跟踪

Example Use Case: 示例用例: An after_tool_callback for a "generate_report" tool saves the output file using await tool_context.save_artifact("report.pdf", report_part). A before_agent_callback might load a configuration artifact using callback_context.load_artifact("agent_config.json").

"generate_report" 工具的 after_tool_callback 使用 await tool_context.save_artifact("report.pdf", report_part) 保存输出文件。before_agent_callback 可能使用 callback_context.load_artifact("agent_config.json") 加载配置工件。

Best Practices for Callbacks

回调的最佳实践

Design Principles

设计原则

Keep Focused: 保持专注: Design each callback for a single, well-defined purpose (e.g., just logging, just validation). Avoid monolithic callbacks.

为每个回调设计单一、明确定义的目的(例如,仅日志记录、仅验证)。避免庞大的回调。

Mind Performance: 注意性能: Callbacks execute synchronously within the agent's processing loop. Avoid long-running or blocking operations (network calls, heavy computation). Offload if necessary, but be aware this adds complexity.

回调在智能体的处理循环中同步执行。避免长时间运行或阻塞操作(网络调用、繁重计算)。如果需要,请卸载,但请注意这会增加复杂性。

Error Handling

错误处理

Handle Errors Gracefully: 优雅地处理错误: - Use try...except/catch blocks within your callback functions 在回调函数中使用 try...except/catch 块 - Log errors appropriately 适当地记录错误 - Decide if the agent invocation should halt or attempt recovery 决定智能体调用是否应停止或尝试恢复 - Don't let callback errors crash the entire process 不要让回调错误使整个进程崩溃

State Management

状态管理

Manage State Carefully: 谨慎管理状态: - Be deliberate about reading from and writing to context.state 有意地从 context.state 读取和写入 - Changes are immediately visible within the current invocation and persisted at the end of the event processing 更改在当前调用中立即可见,并在事件处理结束时持久化 - Use specific state keys rather than modifying broad structures to avoid unintended side effects 使用特定的状态键而不是修改广泛的结构以避免意外的副作用 - Consider using state prefixes (State.APP_PREFIX, State.USER_PREFIX, State.TEMP_PREFIX) for clarity, especially with persistent SessionService implementations 考虑使用状态前缀(State.APP_PREFIXState.USER_PREFIXState.TEMP_PREFIX)以保持清晰,特别是在持久化的 SessionService 实现中

Reliability

可靠性

Consider Idempotency: 考虑幂等性: If a callback performs actions with external side effects (e.g., incrementing an external counter), design it to be idempotent (safe to run multiple times with the same input) if possible, to handle potential retries in the framework or your application.

如果回调执行具有外部副作用的操作(例如,增加外部计数器),请尽可能设计为幂等性(可以安全地使用相同输入多次运行),以处理框架或应用程序中的潜在重试。

Testing & Documentation

测试和文档

Test Thoroughly: 彻底测试: - Unit test your callback functions using mock context objects 使用模拟上下文对象对回调函数进行单元测试 - Perform integration tests to ensure callbacks function correctly within the full agent flow 执行集成测试以确保回调在完整的智能体流中正确运行

Ensure Clarity: 确保清晰: - Use descriptive names for your callback functions 为回调函数使用描述性名称 - Add clear docstrings explaining their purpose, when they run, and any side effects (especially state modifications) 添加清晰的文档字符串,解释其目的、运行时间以及任何副作用(特别是状态修改)

Use Correct Context Type: 使用正确的上下文类型: Always use the specific context type provided (CallbackContext for agent/model, ToolContext for tools) to ensure access to the appropriate methods and properties.

始终使用提供的特定上下文类型(智能体/模型使用 CallbackContext,工具使用 ToolContext)以确保访问适当的方法和属性。

By applying these patterns and best practices, you can effectively use callbacks to create more robust, observable, and customized agent behaviors in ADK.

通过应用这些模式和最佳实践,您可以有效地使用回调在 ADK 中创建更强大、可观察和自定义的智能体行为。