* Deleted redundant files. * Deleted redundant files. * Deleted redundant files. * Deleted redundant files. * Deleted redundant files. * Deleted redundant files. * Delete .gitignore Deleted redundant files. * Delete .gitignore Deleted redundant files. * Delete .gitignore * Delete .gitignore * Delete .gitignore * Revert changes to .gitignore * Revert changes to .gitignore * Revert changes to .gitignore * Revert changes to .gitignore * Revert changes to .gitignore * Revert changes to .gitignore * Add MCP Tools TS example * Removed unnecessary changes * Removed extra slashes * Added the custom agent sample. * Corrected an error in the package.json file. * Updated custom-agent.md * Made small fixes. * Add Session TS examples * Added the typescript code snippets for multi agent. * added the code sample for loop agent * Added the code sample for loop agent * Added the code sample for parallel agent * Fixed a few issues and bugs * Added the code sample for sequential agent * Renamed run back to runAsync * Updated the capital agent code sample. * Corrected the snippet * Renamed run() to runAsync() * Add Runtime TS examples * Fixed the snippets after library updates. * Fixed the sample code after library changes. * Added final touchups and fixes. * Updated the code based on recent library changes. * Updated package.json * Updated package.json * Updated package.json * Updated the code with runAsync and package.json * Updated the typescript sample. * Updated after_tool_callback.ts with runAsync * Updated after_model_callback.ts * Updated before_model_callback.ts * Updated before_tool_callback.ts * Created before_agent_callback.ts * Update before_agent_callback.ts Changed the condition * Update before_model_callback.ts Changed the condition * Update after_model_callback.ts Changed the condition * Update after_tool_callback.ts Changed the condition * Update after_agent_callback.ts Changed the condition * Update callback_basic.ts Changed the condition * Update storyflow_agent.ts Changed the condition * Update sequential_agent_code_development_agent.ts Changed the condition * Updated before_agent_callback.ts * Removed unnecessary comment. * Updated comment * Renamed run to runAsync * Added artifact code snippets. * Fixed .link-checker-config.json * Added tsconfig.json * Update .gitignore with node modules files * Added 7 typescript code snippets * Cleaned up and corrected the snippets for plugins * Update index.md Undid the changes in artifacts/index.md * Escaped properly. * Add Long Running Function Tool TS examples * Resolved code review feedback * Fixed the code sample per git comments. * Fixed the code per git comments. * Fixed the md file per git comments. * Fixed the issues per git comments. * Fixed issues per github comments. * Fixed the issues per PR comments. * Fixed issues per PR comments. * Added a code sample for HITL * Fixed the indentations in the typescript code * Used createPartFromBase64 when appropriate. * Switched to use createUserContent. * docs: Add JavaScript Quickstart, short unified format * Added a simulated user delay to the code sample. * Made some cosmetic improvements * Added the code snippet with HITL with policy * Made cosmetic modifications to multi-agents.md * Added more tutorial for the HITL with policy * Modularized the main function and added helper functions. * Resolved code review feedback * Resolved code review feedback * Resolved code review feedback * Fixed minor things in the typescript code per PR comments. * Fixed the import for Event and used createEventActions. * Simplified functionResponse code. * Corrected the Event import and used createEventActions. * Updated ADK versions in package.json. * Final review of all changes & Add Safety TS example * Make tsconfig.json files consistent * Generated the API Reference for typescript * Resolved code review feedback * feat: Add Typescript API reference to docs This commit adds the generated TypeDoc documentation for the Typescript ADK to the documentation site. It also updates the main API reference page to include a link to the new Typescript API reference. * docs: update TypeScript quickstart * docs: Add version tags for Build Agents topics - add version tags - move TS content to second position (after Python) * docs: Add MCP Toolbox for databases TS SDK Documentation * Update mcp-toolbox-for-databases.md * use typescript code block * minor changes * Update mcp-toolbox-for-databases.md * Auto generated the typescript API reference. * Added the TS code snippets for context. * Fixed TS code snippets for context. * Modified the sample based on the comment. * docs: adding TypeScript language tags (2 of 3) - Update all Run Agents section topics - change all TS tags to v0.2.0 per eng agreement * docs: Add TypeScript language support tags, Components (3 of 3) - add TS language support tags - re-order TS examples to be second - minor fixes: remove trailing spaces * Added callback samples for typescript to the markdown files. * Updated adk version in quickstart * Updated google/adk version for typescript. --------- Co-authored-by: manchan <manchan@google.com> Co-authored-by: Mandy Chan <75594070+slothwriter@users.noreply.github.com> Co-authored-by: Joe Fernandez <joefernandez@google.com> Co-authored-by: Joe Fernandez <joefernandez@users.noreply.github.com> Co-authored-by: Twisha Bansal <58483338+twishabansal@users.noreply.github.com>
8.4 KiB
Callbacks: Observe, Customize, and Control Agent Behavior
Callbacks are a cornerstone feature of ADK, providing a powerful mechanism to hook into an agent's execution process. They allow you to observe, customize, and even control the agent's behavior at specific, predefined points without modifying the core ADK framework code.
What are they? In essence, callbacks are standard functions that you define. You then associate these functions with an agent when you create it. The ADK framework automatically calls your functions at key stages, letting you observe or intervene. Think of it like checkpoints during the agent's process:
- Before the agent starts its main work on a request, and after it finishes: When you ask an agent to do something (e.g., answer a question), it runs its internal logic to figure out the response.
- The
Before Agentcallback executes right before this main work begins for that specific request. - The
After Agentcallback executes right after the agent has finished all its steps for that request and has prepared the final result, but just before the result is returned. - This "main work" encompasses the agent's entire process for handling that single request. This might involve deciding to call an LLM, actually calling the LLM, deciding to use a tool, using the tool, processing the results, and finally putting together the answer. These callbacks essentially wrap the whole sequence from receiving the input to producing the final output for that one interaction.
- The
- Before sending a request to, or after receiving a response from, the Large Language Model (LLM): These callbacks (
Before Model,After Model) allow you to inspect or modify the data going to and coming from the LLM specifically. - Before executing a tool (like a Python function or another agent) or after it finishes: Similarly,
Before ToolandAfter Toolcallbacks give you control points specifically around the execution of tools invoked by the agent.
Why use them? Callbacks unlock significant flexibility and enable advanced agent capabilities:
- Observe & Debug: Log detailed information at critical steps for monitoring and troubleshooting.
- Customize & Control: Modify data flowing through the agent (like LLM requests or tool results) or even bypass certain steps entirely based on your logic.
- Implement Guardrails: Enforce safety rules, validate inputs/outputs, or prevent disallowed operations.
- Manage State: Read or dynamically update the agent's session state during execution.
- Integrate & Enhance: Trigger external actions (API calls, notifications) or add features like caching.
!!! tip When implementing security guardrails and policies, use ADK Plugins for better modularity and flexibility than Callbacks. For more details, see Callbacks and Plugins for Security Guardrails.
How are they added:
??? "Code" === "Python"
```python
--8<-- "examples/python/snippets/callbacks/callback_basic.py:callback_basic"
```
=== "Typescript"
```typescript
--8<-- "examples/typescript/snippets/callbacks/callback_basic.ts:callback_basic"
```
=== "Go"
```go
--8<-- "examples/go/snippets/callbacks/main.go:imports"
--8<-- "examples/go/snippets/callbacks/main.go:callback_basic"
```
=== "Java"
```java
--8<-- "examples/java/snippets/src/main/java/callbacks/AgentWithBeforeModelCallback.java:init"
```
The Callback Mechanism: Interception and Control
When the ADK framework encounters a point where a callback can run (e.g., just before calling the LLM), it checks if you provided a corresponding callback function for that agent. If you did, the framework executes your function.
Context is Key: Your callback function isn't called in isolation. The framework provides special context objects (CallbackContext or ToolContext) as arguments. These objects contain vital information about the current state of the agent's execution, including the invocation details, session state, and potentially references to services like artifacts or memory. You use these context objects to understand the situation and interact with the framework. (See the dedicated "Context Objects" section for full details).
Controlling the Flow (The Core Mechanism): The most powerful aspect of callbacks lies in how their return value influences the agent's subsequent actions. This is how you intercept and control the execution flow:
-
return None(Allow Default Behavior):- The specific return type can vary depending on the language. In Java, the equivalent return type is
Optional.empty(). Refer to the API documentation for language specific guidance. - This is the standard way to signal that your callback has finished its work (e.g., logging, inspection, minor modifications to mutable input arguments like
llm_request) and that the ADK agent should proceed with its normal operation. - For
before_*callbacks (before_agent,before_model,before_tool), returningNonemeans the next step in the sequence (running the agent logic, calling the LLM, executing the tool) will occur. - For
after_*callbacks (after_agent,after_model,after_tool), returningNonemeans the result just produced by the preceding step (the agent's output, the LLM's response, the tool's result) will be used as is.
- The specific return type can vary depending on the language. In Java, the equivalent return type is
-
return <Specific Object>(Override Default Behavior):- Returning a specific type of object (instead of
None) is how you override the ADK agent's default behavior. The framework will use the object you return and skip the step that would normally follow or replace the result that was just generated. before_agent_callback→types.Content: Skips the agent's main execution logic (_run_async_impl/_run_live_impl). The returnedContentobject is immediately treated as the agent's final output for this turn. Useful for handling simple requests directly or enforcing access control.before_model_callback→LlmResponse: Skips the call to the external Large Language Model. The returnedLlmResponseobject is processed as if it were the actual response from the LLM. Ideal for implementing input guardrails, prompt validation, or serving cached responses.before_tool_callback→dictorMap: Skips the execution of the actual tool function (or sub-agent). The returneddictis used as the result of the tool call, which is then typically passed back to the LLM. Perfect for validating tool arguments, applying policy restrictions, or returning mocked/cached tool results.after_agent_callback→types.Content: Replaces theContentthat the agent's run logic just produced.after_model_callback→LlmResponse: Replaces theLlmResponsereceived from the LLM. Useful for sanitizing outputs, adding standard disclaimers, or modifying the LLM's response structure.after_tool_callback→dictorMap: Replaces thedictresult returned by the tool. Allows for post-processing or standardization of tool outputs before they are sent back to the LLM.
- Returning a specific type of object (instead of
Conceptual Code Example (Guardrail):
This example demonstrates the common pattern for a guardrail using before_model_callback.
??? "Code" === "Python"
```python
--8<-- "examples/python/snippets/callbacks/before_model_callback.py"
```
=== "Typescript"
```typescript
--8<-- "examples/typescript/snippets/callbacks/before_model_callback.ts"
```
=== "Go"
```go
--8<-- "examples/go/snippets/callbacks/main.go:imports"
--8<-- "examples/go/snippets/callbacks/main.go:guardrail_init"
```
=== "Java"
```java
--8<-- "examples/java/snippets/src/main/java/callbacks/BeforeModelGuardrailExample.java:init"
```
By understanding this mechanism of returning None versus returning specific objects, you can precisely control the agent's execution path, making callbacks an essential tool for building sophisticated and reliable agents with ADK.
