mirror of
https://github.com/google/adk-docs.git
synced 2026-09-14 16:16:59 +08:00
8da5856bc5
* Add Kotlin snippet for filtering a toolset's tools
The Toolsets section had no Kotlin. ToolFilter and ToolPredicate arrived in
adk-kotlin 0.7.0 and give Kotlin something the other languages do not have: a
filter that receives the ReadonlyContext, so a toolset's tool list can depend on
session state or the current user.
The Python tab in the Simple Math Toolset example only gestures at this, in a
commented-out branch inside get_tools(). This snippet implements it, showing all
three states: no filter selects everything, allowList selects by name, and a
Predicate decides per invocation.
Placed in its own subsection rather than as a fourth tab on the Simple Math
Toolset example. That group is one worked example explained by five bullets --
an agent, a greet tool, name prefixing, a tool_context.state write and close() --
and a filtering snippet satisfies none of them. Kotlin cannot satisfy the prefix
bullet at all, since BaseTool.name is a val and adk-kotlin has no prefix
mechanism. A tab there would have left readers with four bullets that do not
describe the code above them.
Transcluded, so CI compiles and lints it. Verified beyond compiling: the tools
are generated by KSP, filtering returns the expected sets for all three cases,
and the tool bodies run -- addNumbers(7,3) -> {result=10}.
* feat: add Kotlin code snippets for tool definition and usage examples to ADK documentation
* refactor: move doc snippet markers above imports in Kotlin tool examples
* Match ExternalApprovalTool to the 0.8.0 BaseTool.run signature
adk-kotlin 0.8.0 widened `BaseTool.run`'s args from `Map<String, Any>` to
`Map<String, Any?>`, so the override in this snippet overrides nothing and the
class no longer implements its abstract member. `compileKotlin` fails with
"'run' overrides nothing" at MultiAgentExample.kt:61.
The break arrived on main with the 0.8.0 bump in #2143, not from this branch.
It surfaces here because the snippet runner builds the whole examples project,
while that PR's own check only compiled the files it changed - and it changed
no .kt files at all. Fixing it here because it blocks this PR; it is one
character and unrelated to the toolset filtering content.
* Correct the tool badges and drop the exclusivity from the filter heading
Four things from joefernandez's review:
- Heading shortened to "Filter tools in toolsets" as suggested.
- That shorter heading is conceptual, and the subsection carries a Kotlin-only
badge, which would repeat the exclusivity claim his b/548652184 is about.
Python, Java and TypeScript all filter toolsets by name or by a
context-aware predicate on BaseToolset, so the section now says so in a
sentence and the badge's title scopes the version to the Kotlin ToolFilter
API rather than to filtering as a concept.
- Page badge Kotlin v0.7.0 -> v0.1.0, and the Toolsets badge likewise. @Tool,
ToolContext and Toolset all exist at the v0.1.0 tag; only ToolFilter is new
in v0.7.0, and function-tools.md already carries v0.1.0.
- The Toolsets badge's bare "Java" span now reads v0.3.0, the first adk-java
release containing BaseToolset (added in a211ac4c, tagged v0.3.0).
59 lines
2.2 KiB
Kotlin
59 lines
2.2 KiB
Kotlin
/*
|
|
* Copyright 2026 Google LLC
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package com.google.adk.kt.examples.tools.overview
|
|
|
|
// --8<-- [start:example]
|
|
|
|
import com.google.adk.kt.annotations.Param
|
|
import com.google.adk.kt.annotations.Tool
|
|
import com.google.adk.kt.tools.ToolContext
|
|
|
|
class UserPreferenceTools {
|
|
/**
|
|
* Updates a user-specific preference.
|
|
*/
|
|
@Tool
|
|
fun updateUserPreference(
|
|
@Param("The name of the preference to update.") preference: String,
|
|
@Param("The value to set the preference to.") value: String,
|
|
context: ToolContext,
|
|
): Map<String, String> {
|
|
// One key per preference, so each write stands on its own. The "user:"
|
|
// prefix scopes the value to this user across all their sessions.
|
|
val userPrefsKey = "user:preferences:$preference"
|
|
|
|
// Read through the readonly view of the context.
|
|
val previous = context.context.state[userPrefsKey] as? String
|
|
|
|
// Kotlin has no mutable `state` on ToolContext. Writing through
|
|
// actions.stateDelta is what puts the change on the resulting event, which
|
|
// is the same effect as assigning to `tool_context.state` in Python.
|
|
context.actions.stateDelta[userPrefsKey] = value
|
|
|
|
println("Tool: Updated user preference '$preference' from '$previous' to '$value'")
|
|
return mapOf("status" to "success", "updated_preference" to preference)
|
|
}
|
|
}
|
|
|
|
// In an agent:
|
|
// LlmAgent(..., tools = UserPreferenceTools().generatedTools())
|
|
//
|
|
// When the LLM calls updateUserPreference(preference = "theme", value = "dark"),
|
|
// the delta is written to the session state and travels on the resulting tool
|
|
// response event as actions.stateDelta.
|
|
// --8<-- [end:example]
|