Register and share your invite link to earn from video plays and referrals.

Search results for ADK
ADK community
One keyword maps to one global community path.
Create community
People
Not Found
Tweets including ADK
Trace Adkins details being shot by his ex-wife during heated argument: ‘Totally uncalled for’
# Practical and Useful Patterns with ADK ## 🎨 Battle-Tested Callback Patterns for Production ADK Agents You know how callbacks work — but how do you actually use them in production? Master ADK's **Callback Design Patterns** for logging, caching, security, and more! 💪 ## 📌 Title Callback Patterns (Design Patterns and Best Practices) ## 🔗 URL ## 🧩 Overview ADK callbacks have well-established patterns that recur in production systems: logging, caching, state management, security guardrails, request/response modification, conditional skipping, and artifact handling. The documentation also defines best practices — single responsibility, performance awareness, idempotency, and error handling — to keep callbacks robust. A critical guideline: **for cross-agent security guardrails, prefer Plugins over Callbacks**. ## 🛠 How to Use **Pattern 1: Logging & Monitoring** `logging_before_tool(ctx, tool, args)` logs the `ctx.invocation_id`, ` and `args` via ` then returns `None` to observe without altering the flow. `logging_after_model(ctx, response)` logs the length of ` with the invocation ID, and likewise returns `None`. **Pattern 2: Caching Strategy** `cache_before_tool(ctx, tool, args)` builds a cache key from ` and `hash(str(args))`, then checks `ctx.state.get(cache_key)`. On a cache hit, it returns the cached value to skip tool execution. On a miss, it returns `None` to proceed. `cache_after_tool(ctx, tool, args, tool_ctx, result)` stores the result in `ctx.state[cache_key]` using the same key, then returns `None` to continue without modification. **Pattern 3: State Management** `state_aware_callback(ctx, req)` retrieves the user tier from `ctx.state.get("user:tier", "free")`, and if the tier is `"premium"`, appends additional instructions to `req.config.system_instruction`. It returns `None` to continue the normal flow. ## 🏗 Practical Usage **Multi-layer defense pattern for production:** As a security guardrail (Plugins are preferred for cross-agent use), `security_before_model(ctx, req)` extracts user input from `req.contents[-1].parts[0].text`, runs `detect_pii()` to check for personal information, and if found, calls `audit_log()` and returns an `LlmResponse` with a rejection message to skip the LLM call. It also runs `detect_injection()` for prompt injection detection, blocking with a similar `LlmResponse` if detected. If neither check triggers, it returns `None` to continue. For tool argument sanitization, `sanitize_before_tool(ctx, tool, args)` checks if ` is `"database_query"` and whether `args.get("query", "")` contains `"DROP"`, returning an error dictionary to block dangerous queries. For artifact persistence, `save_artifact_after_agent(ctx)` calls `generate_report(ctx)` and saves the result via `"execution_report.json", report)`, returning `None`. ## 💡 Use Cases - 📊 **Structured logging**: Emit structured logs with invocation IDs at every execution point - 💾 **API cost reduction**: Cache tool results with before/after patterns to avoid redundant calls - 🔐 **Layered security**: Place PII detection, injection prevention, and SQL sanitization at different layers - 📦 **Artifact management**: Auto-save execution results and reports as artifacts - 🎚️ **Dynamic behavior**: Adjust instructions dynamically based on user tier or session state ## ⚠️ Caveats - **Single responsibility**: Give each callback one purpose — don't mix logging with validation - **Performance**: Callbacks execute synchronously; avoid blocking I/O or heavy computation - **Idempotency**: Design callbacks with external side effects to be safe when retried - **Error handling**: Always wrap in try-except to prevent callback errors from crashing the process - **Prefer Plugins**: For cross-agent security policies, consider **Plugins** over per-agent callbacks ## ✨ Closing Knowing callback patterns dramatically levels up your ADK skills. Combine logging, caching, security, and state management patterns to build robust, cost-efficient agents. And for cross-cutting security concerns, don't forget Plugins! #ADK# #AIAgent#
Show more
# Useful but Little-Known Features of ADK 2.0 🌍 Ever had an AI agent fail mid-workflow because of a transient API hiccup, forcing you to manually re-run everything? ADK 2.0 introduces RetryConfig, a framework-level automatic retry mechanism. Define your retry strategy declaratively — no more manual try-catch blocks scattered throughout your agent code. 📌 Title: Automatic Retry (RetryConfig) 🔗 URL: 🧩 Overview RetryConfig lets the framework automatically manage retries when transient errors occur during agent or tool execution. By simply specifying max_attempts, you can automate recovery from network timeouts, API rate limits, and other temporary failures. This eliminates the need for developers to implement retry logic individually, dramatically improving agent robustness. 🛠 How to use it Just attach a RetryConfig to your agent — automatic retries are immediately enabled. ```python from adk import Agent, RetryConfig agent = Agent( name="api_caller", model="gemini-2.0-flash", instruction="Fetch data from the external API", retry_config=RetryConfig(max_attempts=3), ) ``` When the framework detects an error, it automatically retries up to the specified number of attempts. No manual try-except blocks needed. 🏗 Building it into production ・Always configure RetryConfig for agents that call external APIs ・Set max_attempts appropriately based on target API rate limits and SLAs ・Design with a clear distinction between transient and permanent errors ・Monitor retry counts and error details in logs to identify root causes 💡 Use cases 🌐 Automatic recovery from external API rate limits and timeouts 🗄️ Handling temporary database connection drops ☁️ Building resilience against brief cloud service outages 🔄 Improving stability at intermediate steps in multi-step workflows ⚠️ Watch out Broad `except Exception:` blocks will break the framework's retry mechanism by swallowing errors before the framework can handle them. Catching `BaseException` is even worse — it traps `NodeInterruptedError`, which breaks Human-in-the-Loop (HITL) flows. Also, be careful not to waste retries on non-recoverable errors like authentication failures. ✨ With RetryConfig, you can free yourself from manual error handling and build robust agents that run reliably in production environments. #ADK# #AIAgent#
Show more
# Practical and Useful Patterns with ADK ## 🎛️ Take Full Control of Agent Behavior with Callbacks Want to add guardrails before LLM calls? Validate tool inputs? Cache responses? ADK's **Callbacks** let you hook into every critical execution point! 🔧 ## 📌 Title Callbacks ## 🔗 URL ## 🧩 Overview Callbacks are functions you attach to agents to observe, customize, and control behavior at specific execution points. The ADK framework automatically invokes them at key stages without requiring core framework modifications. Six callback types are available: - **before_agent / after_agent**: Before and after agent execution - **before_model / after_model**: Before and after LLM calls - **before_tool / after_tool**: Before and after tool execution The key mechanism is **flow control via return values**: return `None` to continue normally, or return a specific object to skip the subsequent step entirely. ## 🛠 How to Use **Skip LLM call (input guardrail / cache) — return `LlmResponse`:** Define a `before_model_callback` function that accepts `CallbackContext` and `LlmRequest` and returns `Optional[LlmResponse]`. It extracts the user's last message via `llm_request.contents[-1].parts[0].text`, checks for a forbidden topic, and if found, returns an `LlmResponse` wrapping `Content(role="model")` with a rejection message to skip the LLM call. If the input is acceptable, it returns `None` to proceed normally. **Skip tool execution (validation / mock) — return `Dict`:** Define a `before_tool_callback` that takes `context`, `tool`, and `args`, returning `Optional[Dict]`. It calls `validate_args(args)` and if validation fails, returns `{"error": "Invalid arguments"}` to skip tool execution. Otherwise, it returns `None` to proceed normally. **Skip agent execution — return `Content`:** Define a `before_agent_callback` that takes `context` and returns `Optional[Content]`. It checks `is_authorized(context)`, and if the user lacks permission, returns `Content(role="model", parts=[Part(text="Access denied")])` to skip agent execution. If authorized, it returns `None` to continue. ## 🏗 Practical Usage **Combined input guardrail + response cache:** Define a `smart_before_model` function taking `ctx` and `req`, returning `Optional[LlmResponse]`. In Step 1, it extracts user input from `req.contents[-1].parts[0].text` and checks for PII using `contains_pii()`. If PII is detected, it returns an `LlmResponse` with a rejection message to skip the LLM call. In Step 2, it generates a `cache_key` via `hash(user_input)` and looks up `ctx.state.get(f"cache:{cache_key}")`. On a cache hit, it returns the cached text wrapped in an `LlmResponse`. On a cache miss, it returns `None` to proceed to the LLM. Finally, an `LlmAgent` is created with `name="SecureAgent"`, `model="gemini-2.0-flash"`, and `before_model_callback=smart_before_model` to register this callback. ## 💡 Use Cases - 🛡️ **Input guardrails**: Block inappropriate inputs or prompt injection before LLM calls - 💾 **Response caching**: Serve cached responses for repeated queries to cut costs - 🔍 **Debug logging**: Record requests/responses at each execution point - ✅ **Tool validation**: Pre-validate tool arguments to prevent errors - 🧪 **Test mocking**: Return mock responses instead of calling real tools ## ⚠️ Caveats - Callbacks execute synchronously; avoid heavy operations like external API calls - Returning a value from `before_*` completely skips downstream processing — be intentional - For cross-agent security guardrails, consider **Plugins** instead of per-agent callbacks - Always wrap callback logic in try-except to prevent callback errors from crashing the entire agent ## ✨ Closing ADK Callbacks provide surgical control over agent execution flow. Guardrails, caching, logging, validation — implement any cross-cutting concern without polluting core logic. Start with `before_model_callback` and build from there! #ADK# #AIAgent#
Show more
# Useful but Little-Known Features of ADK 2.0 🌍 Do you know the different types of callbacks in ADK 2.0 and when to use each one? ADK 2.0 provides callbacks across three layers: agent lifecycle, LLM calls, and tool execution. The Before/After pattern at each layer lets you flexibly inject validation, guardrails, logging, and more. 📌 Title: Types and Patterns of Callbacks 🔗 URL: 🧩 Overview ADK 2.0 callbacks fall into three categories. Agent lifecycle callbacks (`BeforeAgentCallback` / `AfterAgentCallback`) insert processing before and after agent execution — useful for validation and cleanup. LLM callbacks (`BeforeModelCallback` / `AfterModelCallback`) operate around model calls for request modification and guardrails. Tool callbacks (`BeforeToolCallback` / `AfterToolCallback`) handle validation and result processing around tool execution. 🛠 How to use it Callbacks are specified when defining an agent. In Python, exact parameter names (`callback_context`, `llm_request`, `tool_context`) are required. ```python from adk import Agent async def before_agent(callback_context) -> None: """Validate before agent execution.""" print(f"Agent starting: {callback_context.agent_name}") # Return None to continue, return a value to skip async def before_model(callback_context, llm_request): """Guardrails before model call.""" if contains_sensitive_info(llm_request): return block_response() # returning a value skips the model call return None # continue with normal model call async def after_tool(callback_context, tool_context, tool_response): """Log after tool execution.""" log_tool_usage(tool_context.tool_name, tool_response) return None agent = Agent( name="my_agent", model="gemini-3.5-flash", before_agent_callback=before_agent, before_model_callback=before_model, after_tool_callback=after_tool, ) ``` Before callbacks that return a value skip subsequent processing; returning None continues normal execution. 🏗 Building it into production ・Use `BeforeAgentCallback` for input validation and auth checks to reject bad requests early ・Apply guardrails (PII detection, harmful content filters) in `BeforeModelCallback` ・Validate model output format and policy compliance in `AfterModelCallback` ・Record tool execution results in `AfterToolCallback` for audit trails 💡 Use cases 🛡 Block prompts containing personal information with `BeforeModelCallback` 📝 Record agent execution results to a database with `AfterAgentCallback` ✅ Validate tool call parameters with `BeforeToolCallback` 🔍 Verify JSON format of model output in `AfterModelCallback` and trigger retries ⚠️ Watch out In Python, callback function parameter names must be exact — `callback_context`, `llm_request`, `tool_context`, etc. Mismatched names will cause silent failures. Be careful not to accidentally return a value from Before callbacks, as this skips model calls or tool execution. Also remember that callbacks execute after plugins in the processing order. ✨ Using the right callbacks at the right layer gives you fine-grained control over agent behavior. Combine callbacks across layers to meet your security, quality assurance, and audit requirements. #ADK# #AIAgent#
Show more
# Practical and Useful Patterns with ADK ## 🧠 Keep Long Sessions Cost-Efficient with Context Compaction As agent conversations grow longer, context balloons and so do costs and latency. ADK's **Context Compaction** automatically summarizes old events, keeping your context lean and your wallet happy! 🎯 ## 📌 Title Context Compaction ## 🔗 URL ## 🧩 Overview Context Compaction reduces processing overhead by automatically summarizing older workflow event data during agent execution. Using a sliding window approach, it keeps recent events intact while compressing older ones, optimizing both cost and latency. Configure it with `EventsCompactionConfig` by setting the `compaction_interval` (how often compression triggers) and `overlap_size` (how many previous events carry over into the next compression batch). ## 🛠 How to Use Set up `EventsCompactionConfig` at the App level: Import `App` and `EventsCompactionConfig` from ` Pass `EventsCompactionConfig(compaction_interval=3, overlap_size=1)` to the `App`'s `events_compaction_config` parameter, which triggers compression every 3 events while keeping 1 event of overlap from the previous batch. In TypeScript, you can use token-threshold-based compaction with `TokenBasedContextCompactor`: ```typescript const agent = new LlmAgent({ name: 'my-agent', model: 'gemini-flash-latest', contextCompactors: [ new TokenBasedContextCompactor({ tokenThreshold: 1000, eventRetentionSize: 1, summarizer: new LlmSummarizer({ llm: new Gemini({model: 'gemini-flash-latest'}) }) }) ] }); ``` ## 🏗 Practical Usage **Customer support bot example:** In long support conversations that span dozens of turns, Context Compaction delivers: 1. **Cost reduction**: Auto-summarize old dialogue to dramatically cut tokens sent per LLM call 2. **Faster responses**: Smaller context means faster LLM processing 3. **Maintained accuracy**: Recent exchanges stay intact, preserving conversational flow With `compaction_interval=5, overlap_size=2`, compression fires every 5 turns while carrying 2 turns of context into the next window. **Custom summarizers:** Use domain-specific summarization prompts to ensure critical business information (order numbers, customer IDs, etc.) is always preserved in summaries. ## 💡 Use Cases - 📞 **Customer support**: Prevent context explosion in lengthy support tickets - 📝 **Document authoring**: Summarize past discussions while keeping the latest direction in long writing sessions - 🔍 **Data analysis agents**: Compress intermediate results across multi-step analysis pipelines - 🎮 **Game NPCs**: Summarize past events to maintain memory over long play sessions ## ⚠️ Caveats - Compaction is irreversible; fine-grained details may be lost in summarization - Too small an `overlap_size` can cause context discontinuity - Custom summarizer models add their own cost overhead - Too-frequent compression intervals increase processing overhead ## ✨ Closing Context Compaction breaks the assumption that "long sessions = high costs." With a single configuration, old events are auto-summarized while fresh context stays intact, optimizing both cost and latency. If your agents handle long-running conversations, this feature is a must-have! #ADK# #AIAgent#
Show more
# Useful but Little-Known Features of ADK 2.0 🌍 What if you could hook into the entire agent execution lifecycle — observing, intervening, and amending — without touching agent code? ADK 2.0's Plugin system lets you extend `BasePlugin` and register it on a Runner to apply lifecycle callbacks globally across all agents. Unlike per-agent callbacks, plugins operate at the runner level with cross-cutting scope. 📌 Title: Plugins 🔗 URL: 🧩 Overview Plugins extend `BasePlugin` and are registered on the Runner. Unlike agent-specific callbacks, they apply globally across all agents. Lifecycle hooks cover the full span: user message receipt, runner start, agent execution, model calls, tool execution, event processing, and runner end. Plugins operate in three modes: Observe (monitoring only), Intervene (modify or block processing), and Amend (modify results after the fact). Plugin callbacks run BEFORE agent callbacks in the execution order. 🛠 How to use it Extend `BasePlugin` and override the lifecycle hooks you need. ```python from adk.plugins import BasePlugin class LoggingPlugin(BasePlugin): def __init__(self): super().__init__(name="logging_plugin") async def on_before_model_call(self, callback_context, llm_request): print(f"Model call: {llm_request.model}") return None # returning None continues normal processing async def on_after_tool_call(self, tool_context, tool_response): print(f"Tool executed: {tool_context.tool_name}") return None # Register on Runner runner = Runner( agent=my_agent, plugins=[LoggingPlugin()] ) ``` In Intervene mode, return a value from the callback to replace the normal processing. In Amend mode, modify results after event processing. 🏗 Building it into production ・Implement logging and metrics collection as Observe-mode plugins to keep agent code clean ・Build guardrails and content filtering as Intervene-mode plugins to block inappropriate I/O ・Add analytics data collection as Amend-mode post-processing ・Leverage prebuilt plugins (Reflect/Retry, BigQuery Analytics, Context Filtering, Global Instructions) to accelerate development 💡 Use cases 📊 Log all model calls and tool executions across every agent to BigQuery 🛡 Centralize input guardrails in a plugin to block harmful requests system-wide 🔄 Implement retry logic for failed model calls using the Reflect/Retry plugin 📋 Apply global instructions (compliance rules, etc.) to all agents via the Global Instructions plugin ⚠️ Watch out Plugin callbacks execute before agent callbacks — if a plugin blocks processing, the agent callback won't fire. Returning incorrect values in Intervene mode can break agent behavior, so understand the expected return types and semantics before using it. Plugin execution order depends on registration order in the Runner. ✨ Plugins let you separate cross-cutting concerns (logging, security, analytics) from agent core logic, enabling highly maintainable systems. #ADK# #AIAgent#
Show more
# Practical and Useful Patterns with ADK Sending the same system prompts and tool definitions over and over? Context Caching dramatically reduces repeated prefix token costs 💰 📌 **Title**: Context Caching 🔗 **URL**: ## 🧩 Overview Context Caching caches the static portions of context sent to the LLM (system instructions, tool definitions, etc.) to reduce repeated token costs. By configuring `ContextCacheConfig`, instead of resending the same prefix tokens with every request, the agent references cached context. The cost optimization impact is especially significant in multi-user environments where many users share the same agent with identical prompts and tool definitions. ## 🛠 How to Use Import `Agent` from `google.adk` and `ContextCacheConfig` from `google.adk.agents`. Create a cache configuration with `ContextCacheConfig(max_entries=100, ttl_seconds=3600)` to set the maximum number of cache entries and the time-to-live in seconds. Pass this `cache_config` to the `Agent`'s `context_cache_config` parameter so that the static portions of the `instruction` (your long system prompt) and `tools` definitions (e.g., `search_kb`, `create_ticket`, `escalate`) are cached, reducing repeated token costs. ## 🏗 Practical Usage **Large-scale customer support optimization:** In a customer support agent, these elements are common across all users: - System instructions (response guidelines, tone, prohibited actions) - Tool definitions (knowledge base search, ticket creation, escalation) - Few-shot examples These static contexts can amount to thousands of tokens per request. For a support bot handling 10,000 requests daily, Context Caching delivers massive token savings. **RAG pipeline optimization:** When tool definitions include knowledge base schemas and search parameter descriptions, caching these optimizes per-query costs. **Multi-tenant SaaS:** When sharing the same agent definition across multiple tenants, only tenant-specific information becomes the dynamic portion while common prompts and tool definitions are shared via cache. ## 💡 Use Cases - 💰 Cost reduction: Cut costs from repeatedly sending long system prompts - 🚀 Latency improvement: Faster prefill processing on cache hits - 👥 Multi-user optimization: Share cache across multiple users with the same prompts - 🏢 Multi-tenant: Efficiently cache tenant-common context portions - 📚 Large tool definitions: Optimize tool definition costs for agents with many tools ## ⚠️ Caveats - Context Caching depends on model provider support. Verify available models in advance - TTL too short reduces hit rates; too long consumes memory. Tune based on access patterns - Benefits are limited if system prompts or tool definitions change frequently - Caching itself may incur costs. Check provider pricing and evaluate total cost - Dynamic context (user-specific information, etc.) is not cacheable. Design clear separation between static and dynamic portions ✨ Context Caching implements "don't repeat yourself" at the infrastructure level. It delivers major cost optimization benefits in multi-user environments! #ADK# #AIAgent#
Show more