├── examples ├── tools │ ├── loadartifacts │ │ └── animal_picture.png │ └── multipletools │ │ └── main.go ├── README.md ├── quickstart │ └── main.go ├── workflowagents │ ├── loop │ │ └── main.go │ ├── sequential │ │ └── main.go │ └── parallel │ │ └── main.go ├── rest │ └── main.go └── web │ ├── agents │ └── image_generator.go │ └── main.go ├── .gitignore ├── agent ├── doc.go ├── remoteagent │ └── doc.go ├── llmagent │ ├── doc.go │ └── testdata │ │ └── TestLLMAgent_healthy_backend.httprr ├── run_config.go ├── workflowagents │ ├── sequentialagent │ │ └── agent.go │ └── loopagent │ │ └── agent.go ├── loader_test.go ├── loader.go └── context.go ├── server ├── adka2a │ ├── doc.go │ └── executor_context.go ├── doc.go └── adkrest │ ├── internal │ ├── services │ │ ├── doc.go │ │ └── apiserverspanexporter.go │ ├── models │ │ ├── models.go │ │ ├── runtime.go │ │ ├── session.go │ │ └── event.go │ └── routers │ │ ├── apps.go │ │ ├── eval.go │ │ ├── runtime.go │ │ ├── routers.go │ │ ├── debug.go │ │ ├── artifacts.go │ │ └── sessions.go │ ├── controllers │ ├── errors.go │ ├── apps.go │ └── handlers.go │ └── handler.go ├── session ├── doc.go └── service.go ├── .github ├── workflows │ ├── nightly.yml │ └── go.yml ├── actions │ └── setup │ │ └── action.yml └── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── internal ├── utils │ └── utils_test.go ├── version │ └── version.go ├── sessioninternal │ ├── session.go │ └── mutablesession.go ├── cli │ └── util │ │ ├── text_helpers.go │ │ ├── doc.go │ │ ├── flagset_helpers.go │ │ └── oscmd.go ├── toolinternal │ ├── tool.go │ ├── context_test.go │ ├── toolutils │ │ └── toolutils.go │ └── context.go ├── agent │ ├── state.go │ ├── runconfig │ │ └── run_config.go │ └── parentmap │ │ ├── map.go │ │ └── map_test.go ├── memory │ └── memory.go ├── llminternal │ ├── googlellm │ │ └── variant.go │ ├── file_uploads_processor.go │ ├── agent.go │ ├── other_processors.go │ ├── converters │ │ └── converters.go │ └── clone_test.go ├── context │ ├── context_test.go │ ├── readonly_context.go │ └── invocation_context.go ├── httprr │ └── LICENSE ├── converters │ └── map_structure.go ├── typeutil │ └── convert.go ├── artifact │ ├── artifacts.go │ └── artifacts_test.go ├── testutil │ └── genai.go ├── sessionutils │ └── utils.go └── style_test.go ├── cmd ├── adkgo │ ├── adkgo.go │ └── internal │ │ ├── root │ │ └── root.go │ │ └── deploy │ │ └── deploy.go └── launcher │ ├── prod │ └── prod.go │ ├── full │ └── full.go │ ├── web │ └── webui │ │ └── distr │ │ ├── chunk-2WH2EVR6.js │ │ ├── assets │ │ ├── audio-processor.js │ │ └── ADK-512-color.svg │ │ └── adk_favicon.svg │ └── launcher.go ├── artifact ├── inmemory_test.go └── artifact_key_test.go ├── telemetry └── telemetry.go ├── model ├── gemini │ └── testdata │ │ ├── TestModel_GenerateStream_ok.httprr │ │ ├── TestModel_Generate_ok.httprr │ │ └── TestModel_TrackingHeaders_verifies_headers_are_set.httprr └── llm.go ├── tool ├── exitlooptool │ └── tool.go ├── geminitool │ ├── google_search.go │ ├── tool.go │ └── tool_test.go ├── tool.go └── tool_test.go ├── .golangci.yml ├── util └── instructionutil │ └── instruction.go ├── memory └── service.go └── README.md /examples/tools/loadartifacts/animal_picture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/adk-go/HEAD/examples/tools/loadartifacts/animal_picture.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # .gitignore is restricted to the artifacts produced by go build and test. 2 | # for personal setup you can use personal .gitignore: `git config --global core.excludesfile ~/.gitignore` 3 | 4 | # Binaries for programs and plugins 5 | *.exe 6 | *.exe~ 7 | *.dll 8 | *.so 9 | *.dylib 10 | 11 | # Test binary, built with `go test -c` 12 | *.test 13 | 14 | # Code coverage profiles and other test artifacts 15 | *.out 16 | coverage.* 17 | *.coverprofile 18 | profile.cov 19 | 20 | # Go workspace file 21 | go.work 22 | go.work.sum 23 | -------------------------------------------------------------------------------- /agent/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package agent provides entities to build agents using ADK. 16 | package agent 17 | -------------------------------------------------------------------------------- /server/adka2a/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package adka2a allows to expose ADK agents via A2A. 16 | package adka2a 17 | -------------------------------------------------------------------------------- /agent/remoteagent/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package remoteagent allows to use a remote ADK agents. 16 | package remoteagent 17 | -------------------------------------------------------------------------------- /server/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package server hosts protocol implementations to expose and serve ADK agents. 16 | package server 17 | -------------------------------------------------------------------------------- /session/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package session provides types to manage user sessions and their states. 16 | package session 17 | -------------------------------------------------------------------------------- /.github/workflows/nightly.yml: -------------------------------------------------------------------------------- 1 | name: Nightly 2 | 3 | on: 4 | schedule: 5 | - cron: '0 2 * * *' # 2 AM UTC daily 6 | 7 | workflow_dispatch: 8 | 9 | jobs: 10 | test: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 14 | 15 | - name: Setup 16 | uses: ./.github/actions/setup 17 | 18 | - name: Nightly Test 19 | run: go test -race -mod=readonly -v -count=1 -shuffle=on ./... 20 | 21 | vulncheck: 22 | runs-on: ubuntu-latest 23 | steps: 24 | - name: Run govulncheck 25 | uses: golang/govulncheck-action@b625fbe08f3bccbe446d94fbf87fcc875a4f50ee # v1.0.4 26 | with: 27 | go-version-file: go.mod 28 | repo-checkout: true -------------------------------------------------------------------------------- /server/adkrest/internal/services/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package services contains services defined for the ADK-Web REST API. 16 | package services 17 | -------------------------------------------------------------------------------- /internal/utils/utils_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package utils_test 16 | 17 | import "testing" 18 | 19 | func TestNothing(t *testing.T) { 20 | // To make it buildable. 21 | } 22 | -------------------------------------------------------------------------------- /internal/version/version.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package version 16 | 17 | // Version exposes the current ADK Go version, used for llm request tagging 18 | const Version string = "0.3.0" 19 | -------------------------------------------------------------------------------- /internal/sessioninternal/session.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package tool defines internal-only interfaces and logic for tools. 16 | package sessioninternal 17 | 18 | type MutableState interface { 19 | Set(string, any) error 20 | } 21 | -------------------------------------------------------------------------------- /.github/actions/setup/action.yml: -------------------------------------------------------------------------------- 1 | name: Setup 2 | description: Setup the environment 3 | 4 | outputs: 5 | go-version: 6 | description: 'Go version' 7 | value: ${{ steps.setup-go.outputs.go-version }} 8 | 9 | runs: 10 | using: 'composite' 11 | steps: 12 | - name: Set up Go 13 | id: setup-go 14 | uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 15 | with: 16 | go-version-file: 'go.mod' 17 | cache: false # wrapper for actions/cache that doesn't support all functionality 18 | 19 | - name: Load Go cache 20 | uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 21 | with: 22 | path: | 23 | ~/.cache/go-build 24 | ~/go/pkg/mod 25 | key: ${{ runner.os }}-go-build-${{ hashFiles('**/go.mod', '**/go.sum') }} 26 | restore-keys: ${{ runner.os }}-go-build- 27 | -------------------------------------------------------------------------------- /internal/cli/util/text_helpers.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package util 16 | 17 | import "strings" 18 | 19 | func CenterString(s string, w int) string { 20 | sw := w - len(s) 21 | lw := sw / 2 22 | rw := sw - lw 23 | return strings.Repeat(" ", lw) + s + strings.Repeat(" ", rw) 24 | } 25 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | ** Please make sure you read the contribution guide and file the issues in the right place. ** 11 | [Contribution guide.](https://google.github.io/adk-docs/contributing-guide/) 12 | 13 | **Is your feature request related to a problem? Please describe.** 14 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 15 | 16 | **Describe the solution you'd like** 17 | A clear and concise description of what you want to happen. 18 | 19 | **Describe alternatives you've considered** 20 | A clear and concise description of any alternative solutions or features you've considered. 21 | 22 | **Additional context** 23 | Add any other context or screenshots about the feature request here. 24 | -------------------------------------------------------------------------------- /internal/cli/util/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package util provides helper functions for execution of commands and presenting their stderr and stdout in uniform way. 16 | // Provides also a way to capture text generated by FlagSet as command line arguments' documentation (PrintDefaults) 17 | package util 18 | -------------------------------------------------------------------------------- /cmd/adkgo/adkgo.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // adkgo is a CLI tool to help deploy and test an ADK application. 16 | package main 17 | 18 | import ( 19 | _ "google.golang.org/adk/cmd/adkgo/internal/deploy/cloudrun" 20 | "google.golang.org/adk/cmd/adkgo/internal/root" 21 | ) 22 | 23 | func main() { 24 | root.Execute() 25 | } 26 | -------------------------------------------------------------------------------- /agent/llmagent/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package llmagent provides an LLM-based agent. 16 | // LLM agents use large language models to perform tasks based on instructions, user input, 17 | // deciding on actions to take, and executing actions using available tools or 18 | // delegating to sub agents. 19 | package llmagent 20 | -------------------------------------------------------------------------------- /server/adkrest/internal/models/models.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package models defines the data structures for the REST API. 16 | package models 17 | 18 | import "reflect" 19 | 20 | // IsZeroValue checks if the val is the zero-ed value. 21 | func IsZeroValue(val any) bool { 22 | return val == nil || reflect.DeepEqual(val, reflect.Zero(reflect.TypeOf(val)).Interface()) 23 | } 24 | -------------------------------------------------------------------------------- /internal/cli/util/flagset_helpers.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package util 16 | 17 | import ( 18 | "flag" 19 | "strings" 20 | ) 21 | 22 | // FormatFlagUsage returns a string containing the usage information for the given FlagSet. 23 | func FormatFlagUsage(fs *flag.FlagSet) string { 24 | var b strings.Builder 25 | o := fs.Output() 26 | fs.SetOutput(&b) 27 | fs.PrintDefaults() 28 | fs.SetOutput(o) 29 | return b.String() 30 | } 31 | -------------------------------------------------------------------------------- /artifact/inmemory_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package artifact_test 16 | 17 | import ( 18 | "testing" 19 | 20 | "google.golang.org/adk/artifact" 21 | "google.golang.org/adk/internal/artifact/tests" 22 | ) 23 | 24 | func TestInMemoryArtifactService(t *testing.T) { 25 | factory := func(t *testing.T) (artifact.Service, error) { 26 | return artifact.InMemoryService(), nil 27 | } 28 | tests.TestArtifactService(t, "InMemory", factory) 29 | } 30 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # ADK GO samples 2 | This folder hosts examples to test different features. The examples are usually minimal and simplistic to test one or a few scenarios. 3 | 4 | 5 | **Note**: This is different from the [google/adk-samples](https://github.com/google/adk-samples) repo, which hosts more complex e2e samples for customers to use or modify directly. 6 | 7 | 8 | # Launcher 9 | In many examples you can see such lines: 10 | ```go 11 | l := full.NewLauncher() 12 | err = l.ParseAndRun(ctx, config, os.Args[1:], universal.ErrorOnUnparsedArgs) 13 | if err != nil { 14 | log.Fatalf("run failed: %v\n\n%s", err, l.FormatSyntax()) 15 | } 16 | ``` 17 | 18 | it allows to decide, which launching options are supported in the run-time. 19 | `full.NewLauncher()` includes all major ways you can run the example: 20 | * console 21 | * restapi 22 | * a2a 23 | * webui (it can run standalone or with restapi or a2a). 24 | 25 | Run `go run ./example/quickstart/main.go help` for details 26 | 27 | As an alternative, you may want to use `prod.NewLauncher()` which only builds-in restapi and a2a launchers. 28 | -------------------------------------------------------------------------------- /server/adkrest/controllers/errors.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package controllers 16 | 17 | type statusError struct { 18 | Err error 19 | Code int 20 | } 21 | 22 | func newStatusError(err error, code int) statusError { 23 | return statusError{Err: err, Code: code} 24 | } 25 | 26 | // Error returns an associated error 27 | func (se statusError) Error() string { 28 | return se.Err.Error() 29 | } 30 | 31 | // Status returns an associated status code 32 | func (se statusError) Status() int { 33 | return se.Code 34 | } 35 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | ** Please make sure you read the contribution guide and file the issues in the right place. ** 11 | [Contribution guide.](https://google.github.io/adk-docs/contributing-guide/) 12 | 13 | **Describe the bug** 14 | A clear and concise description of what the bug is. 15 | 16 | **To Reproduce** 17 | Please share a minimal code and data to reproduce your problem. 18 | Steps to reproduce the behavior: 19 | 1. Install '...' 20 | 2. Run '....' 21 | 3. Open '....' 22 | 4. Provide error or a stacktrace 23 | 24 | **Expected behavior** 25 | A clear and concise description of what you expected to happen. 26 | 27 | **Screenshots** 28 | If applicable, add screenshots to help explain your problem. 29 | 30 | **Desktop (please complete the following information):** 31 | - OS: [e.g. macOS, Linux, Windows] 32 | - Go version: 33 | - ADK version: 34 | 35 | **Model Information:** 36 | - Which model is being used (e.g. gemini-2.5-pro) 37 | 38 | **Additional context** 39 | Add any other context about the problem here. 40 | -------------------------------------------------------------------------------- /internal/toolinternal/tool.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package tool defines internal-only interfaces and logic for tools. 16 | package toolinternal 17 | 18 | import ( 19 | "google.golang.org/genai" 20 | 21 | "google.golang.org/adk/model" 22 | "google.golang.org/adk/tool" 23 | ) 24 | 25 | type FunctionTool interface { 26 | tool.Tool 27 | Declaration() *genai.FunctionDeclaration 28 | Run(ctx tool.Context, args any) (result map[string]any, err error) 29 | } 30 | 31 | type RequestProcessor interface { 32 | ProcessRequest(ctx tool.Context, req *model.LLMRequest) error 33 | } 34 | -------------------------------------------------------------------------------- /artifact/artifact_key_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package artifact 16 | 17 | import ( 18 | "testing" 19 | 20 | "github.com/google/go-cmp/cmp" 21 | ) 22 | 23 | func TestArtifactKey(t *testing.T) { 24 | key := artifactKey{ 25 | AppName: "testapp", 26 | UserID: "testuser", 27 | SessionID: "testsession", 28 | FileName: "testfile", 29 | Version: 123, 30 | } 31 | var key2 artifactKey 32 | err := key2.Decode(key.Encode()) 33 | if err != nil { 34 | t.Fatalf("error decoding key:%s", err) 35 | } 36 | if diff := cmp.Diff(key, key2); diff != "" { 37 | t.Errorf("key mismatch (-want +got):\n%s", diff) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /internal/agent/state.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package agent 16 | 17 | // holds Agent internal state 18 | type Agent interface { 19 | internal() *State 20 | } 21 | 22 | type State struct { 23 | AgentType Type 24 | Config any 25 | } 26 | 27 | type Type string 28 | 29 | const ( 30 | TypeLLMAgent Type = "LLMAgent" 31 | TypeLoopAgent Type = "LoopAgent" 32 | TypeSequentialAgent Type = "SequentialAgent" 33 | TypeParallelAgent Type = "ParallelAgent" 34 | TypeCustomAgent Type = "CustomAgent" 35 | ) 36 | 37 | func (s *State) internal() *State { return s } 38 | 39 | func Reveal(a Agent) *State { return a.internal() } 40 | -------------------------------------------------------------------------------- /cmd/adkgo/internal/root/root.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package root handles command line parameters 16 | package root 17 | 18 | import ( 19 | "os" 20 | 21 | "github.com/spf13/cobra" 22 | ) 23 | 24 | // RootCmd represents the base command when called without any subcommands 25 | var RootCmd = &cobra.Command{ 26 | Use: "adkgo", 27 | Short: "CLI tool for use with ADK-GO", 28 | Long: `adkgo is a CLI tool which allows developer to quickly deploy and test an agentic application`, 29 | } 30 | 31 | // Execute adds all child commands to the root command and sets flags appropriately. 32 | func Execute() { 33 | err := RootCmd.Execute() 34 | if err != nil { 35 | os.Exit(1) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /cmd/adkgo/internal/deploy/deploy.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package deploy allows to run deployment-related subcommands. 16 | package deploy 17 | 18 | import ( 19 | "github.com/spf13/cobra" 20 | 21 | "google.golang.org/adk/cmd/adkgo/internal/root" 22 | ) 23 | 24 | // DeployCmd represents the deploy command. 25 | var DeployCmd = &cobra.Command{ 26 | Use: "deploy", 27 | Short: "Makes deployment to various platforms easy", 28 | Long: `Please see subcommands for details`, 29 | RunE: func(cmd *cobra.Command, args []string) error { 30 | if len(args) == 0 { 31 | return cmd.Help() 32 | } 33 | return nil 34 | }, 35 | } 36 | 37 | func init() { 38 | root.RootCmd.AddCommand(DeployCmd) 39 | } 40 | -------------------------------------------------------------------------------- /internal/memory/memory.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package memory 16 | 17 | import ( 18 | "context" 19 | 20 | "google.golang.org/adk/memory" 21 | "google.golang.org/adk/session" 22 | ) 23 | 24 | type Memory struct { 25 | Service memory.Service 26 | SessionID string 27 | UserID string 28 | AppName string 29 | } 30 | 31 | func (a *Memory) AddSession(ctx context.Context, session session.Session) error { 32 | return a.Service.AddSession(ctx, session) 33 | } 34 | 35 | func (a *Memory) Search(ctx context.Context, query string) (*memory.SearchResponse, error) { 36 | return a.Service.Search(ctx, &memory.SearchRequest{ 37 | AppName: a.AppName, 38 | UserID: a.UserID, 39 | Query: query, 40 | }) 41 | } 42 | -------------------------------------------------------------------------------- /server/adkrest/controllers/apps.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package controllers 16 | 17 | import ( 18 | "net/http" 19 | 20 | "google.golang.org/adk/agent" 21 | ) 22 | 23 | // AppsAPIController is the controller for the Apps API. 24 | type AppsAPIController struct { 25 | agentLoader agent.Loader 26 | } 27 | 28 | // NewAppsAPIController creates a controller for Apps API. 29 | func NewAppsAPIController(agentLoader agent.Loader) *AppsAPIController { 30 | return &AppsAPIController{agentLoader: agentLoader} 31 | } 32 | 33 | // ListAppsHandler handles listing all loaded agents. 34 | func (c *AppsAPIController) ListAppsHandler(rw http.ResponseWriter, req *http.Request) { 35 | apps := c.agentLoader.ListAgents() 36 | EncodeJSONResponse(apps, http.StatusOK, rw) 37 | } 38 | -------------------------------------------------------------------------------- /internal/llminternal/googlellm/variant.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package googlellm 16 | 17 | import ( 18 | "os" 19 | "slices" 20 | ) 21 | 22 | const ( 23 | // For using credentials from Google Vertex AI 24 | GoogleLLMVariantVertexAI = "VERTEX_AI" 25 | // For using API Key from Google AI Studio 26 | GoogleLLMVariantGeminiAPI = "GEMINI_API" 27 | ) 28 | 29 | // GetGoogleLLMVariant returns the Google LLM variant to use. 30 | // see https://google.github.io/adk-docs/get-started/quickstart/#set-up-the-model 31 | func GetGoogleLLMVariant() string { 32 | useVertexAI, _ := os.LookupEnv("GOOGLE_GENAI_USE_VERTEXAI") 33 | if slices.Contains([]string{"1", "true"}, useVertexAI) { 34 | return GoogleLLMVariantVertexAI 35 | } 36 | return GoogleLLMVariantGeminiAPI 37 | } 38 | -------------------------------------------------------------------------------- /cmd/launcher/prod/prod.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package prod provides easy way to play with ADK with all available options without 16 | // development support (no console, no ADK Web UI) including only production 17 | // options like the REST API and A2A support. 18 | package prod 19 | 20 | import ( 21 | "google.golang.org/adk/cmd/launcher" 22 | "google.golang.org/adk/cmd/launcher/universal" 23 | "google.golang.org/adk/cmd/launcher/web" 24 | "google.golang.org/adk/cmd/launcher/web/a2a" 25 | "google.golang.org/adk/cmd/launcher/web/api" 26 | ) 27 | 28 | // NewLauncher returns a launcher capable of serving ADK REST API and A2A. 29 | func NewLauncher() launcher.Launcher { 30 | return universal.NewLauncher(web.NewLauncher(api.NewLauncher(), a2a.NewLauncher())) 31 | } 32 | -------------------------------------------------------------------------------- /internal/agent/runconfig/run_config.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package runconfig 16 | 17 | import "context" 18 | 19 | type StreamingMode string 20 | 21 | const ( 22 | StreamingModeNone StreamingMode = "none" 23 | StreamingModeSSE StreamingMode = "sse" 24 | StreamingModeBidi StreamingMode = "bidi" 25 | ) 26 | 27 | type RunConfig struct { 28 | StreamingMode StreamingMode 29 | } 30 | 31 | func ToContext(ctx context.Context, cfg *RunConfig) context.Context { 32 | return context.WithValue(ctx, runConfigCtxKey, cfg) 33 | } 34 | 35 | func FromContext(ctx context.Context) *RunConfig { 36 | m, ok := ctx.Value(runConfigCtxKey).(*RunConfig) 37 | if !ok { 38 | return nil 39 | } 40 | return m 41 | } 42 | 43 | type ctxKey int 44 | 45 | const runConfigCtxKey ctxKey = 0 46 | -------------------------------------------------------------------------------- /cmd/launcher/full/full.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package full provides easy way to play with ADK with all available options 16 | package full 17 | 18 | import ( 19 | "google.golang.org/adk/cmd/launcher" 20 | "google.golang.org/adk/cmd/launcher/console" 21 | "google.golang.org/adk/cmd/launcher/universal" 22 | "google.golang.org/adk/cmd/launcher/web" 23 | "google.golang.org/adk/cmd/launcher/web/a2a" 24 | "google.golang.org/adk/cmd/launcher/web/api" 25 | "google.golang.org/adk/cmd/launcher/web/webui" 26 | ) 27 | 28 | // NewLauncher returnes the most versatile universal launcher with all options built-in. 29 | func NewLauncher() launcher.Launcher { 30 | return universal.NewLauncher(console.NewLauncher(), web.NewLauncher(api.NewLauncher(), a2a.NewLauncher(), webui.NewLauncher())) 31 | } 32 | -------------------------------------------------------------------------------- /telemetry/telemetry.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package telemetry allows to set up custom telemetry processors that the ADK events 16 | // will be emitted to. 17 | package telemetry 18 | 19 | import ( 20 | sdktrace "go.opentelemetry.io/otel/sdk/trace" 21 | 22 | internaltelemetry "google.golang.org/adk/internal/telemetry" 23 | ) 24 | 25 | // RegisterSpanProcessor registers the span processor to local trace provider instance. 26 | // Any processor should be registered BEFORE any of the events are emitted, otherwise 27 | // the registration will be ignored. 28 | // In addition to the RegisterSpanProcessor function, global trace provider configs 29 | // are respected. 30 | func RegisterSpanProcessor(processor sdktrace.SpanProcessor) { 31 | internaltelemetry.AddSpanProcessor(processor) 32 | } 33 | -------------------------------------------------------------------------------- /agent/run_config.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package agent 16 | 17 | // StreamingMode defines the streaming mode for agent execution. 18 | type StreamingMode string 19 | 20 | const ( 21 | // StreamingModeNone indicates no streaming. 22 | StreamingModeNone StreamingMode = "none" 23 | // StreamingModeSSE enables server-sent events streaming, one-way, where 24 | // LLM response parts are streamed immediately as they are generated. 25 | StreamingModeSSE StreamingMode = "sse" 26 | ) 27 | 28 | // RunConfig controls runtime behavior of an agent. 29 | type RunConfig struct { 30 | // StreamingMode defines the streaming mode for an agent. 31 | StreamingMode StreamingMode 32 | // If true, ADK runner will save each part of the user input that is a blob 33 | // (e.g., images, files) as an artifact. 34 | SaveInputBlobsAsArtifacts bool 35 | } 36 | -------------------------------------------------------------------------------- /.github/workflows/go.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a golang project 2 | # For more information see: 3 | # - https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go 4 | # - https://golangci-lint.run/usage/configuration/ 5 | 6 | name: Go 7 | 8 | on: 9 | push: 10 | branches: [ "main" ] 11 | 12 | pull_request: 13 | branches: [ "main" ] 14 | 15 | workflow_dispatch: 16 | 17 | concurrency: 18 | group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} 19 | cancel-in-progress: true 20 | 21 | jobs: 22 | test: 23 | runs-on: ubuntu-latest 24 | steps: 25 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 26 | 27 | - name: Setup 28 | uses: ./.github/actions/setup 29 | 30 | - name: Tidy 31 | run: go mod tidy -diff 32 | 33 | - name: Build 34 | run: go build -mod=readonly -v ./... 35 | 36 | - name: Test 37 | run: go test -mod=readonly -v ./... 38 | 39 | lint: 40 | runs-on: ubuntu-latest 41 | steps: 42 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 43 | 44 | - name: Setup 45 | uses: ./.github/actions/setup 46 | 47 | - name: Lint 48 | uses: golangci/golangci-lint-action@4afd733a84b1f43292c63897423277bb7f4313a9 # v8.0.0 49 | with: 50 | install-mode: goinstall 51 | version: 5256574b81bcedfbcae9099f745f6aee9335da10 # v2.3.1 52 | -------------------------------------------------------------------------------- /server/adkrest/internal/routers/apps.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package routers 16 | 17 | import ( 18 | "net/http" 19 | 20 | "google.golang.org/adk/server/adkrest/controllers" 21 | ) 22 | 23 | // AppsAPIRouter defines the routes for the Apps API. 24 | type AppsAPIRouter struct { 25 | appsController *controllers.AppsAPIController 26 | } 27 | 28 | // NewAppsAPIRouter creates a new AppsAPIRouter. 29 | func NewAppsAPIRouter(controller *controllers.AppsAPIController) *AppsAPIRouter { 30 | return &AppsAPIRouter{appsController: controller} 31 | } 32 | 33 | // Routes returns the routes for the Apps API. 34 | func (r *AppsAPIRouter) Routes() Routes { 35 | return Routes{ 36 | Route{ 37 | Name: "ListApps", 38 | Methods: []string{http.MethodGet}, 39 | Pattern: "/list-apps", 40 | HandlerFunc: r.appsController.ListAppsHandler, 41 | }, 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /internal/toolinternal/context_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package toolinternal 16 | 17 | import ( 18 | "testing" 19 | 20 | "google.golang.org/adk/agent" 21 | contextinternal "google.golang.org/adk/internal/context" 22 | "google.golang.org/adk/session" 23 | ) 24 | 25 | func TestToolContext(t *testing.T) { 26 | inv := contextinternal.NewInvocationContext(t.Context(), contextinternal.InvocationContextParams{}) 27 | toolCtx := NewToolContext(inv, "fn1", &session.EventActions{}) 28 | 29 | if _, ok := toolCtx.(agent.ReadonlyContext); !ok { 30 | t.Errorf("ToolContext(%+T) is unexpectedly not a ReadonlyContext", toolCtx) 31 | } 32 | if _, ok := toolCtx.(agent.CallbackContext); !ok { 33 | t.Errorf("ToolContext(%+T) is unexpectedly not a CallbackContext", toolCtx) 34 | } 35 | if got, ok := toolCtx.(agent.InvocationContext); ok { 36 | t.Errorf("ToolContext(%+T) is unexpectedly an InvocationContext", got) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /internal/context/context_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package context 16 | 17 | import ( 18 | "testing" 19 | 20 | "google.golang.org/adk/agent" 21 | ) 22 | 23 | func TestReadonlyContext(t *testing.T) { 24 | inv := NewInvocationContext(t.Context(), InvocationContextParams{}) 25 | readonly := NewReadonlyContext(inv) 26 | 27 | if got, ok := readonly.(agent.InvocationContext); ok { 28 | t.Errorf("ReadonlyContext(%+T) is unexpectedly an InvocationContext", got) 29 | } 30 | } 31 | 32 | func TestCallbackContext(t *testing.T) { 33 | inv := NewInvocationContext(t.Context(), InvocationContextParams{}) 34 | callback := NewCallbackContext(inv) 35 | 36 | if _, ok := callback.(agent.ReadonlyContext); !ok { 37 | t.Errorf("CallbackContext(%+T) is unexpectedly not a ReadonlyContext", callback) 38 | } 39 | if got, ok := callback.(agent.InvocationContext); ok { 40 | t.Errorf("CallbackContext(%+T) is unexpectedly an InvocationContext", got) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /internal/httprr/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 The Go Authors. All rights reserved. 2 | Redistribution and use in source and binary forms, with or without 3 | modification, are permitted provided that the following conditions are 4 | met: 5 | * Redistributions of source code must retain the above copyright 6 | notice, this list of conditions and the following disclaimer. 7 | * Redistributions in binary form must reproduce the above 8 | copyright notice, this list of conditions and the following disclaimer 9 | in the documentation and/or other materials provided with the 10 | distribution. 11 | * Neither the name of Google Inc. nor the names of its 12 | contributors may be used to endorse or promote products derived from 13 | this software without specific prior written permission. 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 15 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 16 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 18 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 20 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /model/gemini/testdata/TestModel_GenerateStream_ok.httprr: -------------------------------------------------------------------------------- 1 | httprr trace v1 2 | 375 1028 3 | POST https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:streamGenerateContent?alt=sse HTTP/1.1 4 | Host: generativelanguage.googleapis.com 5 | User-Agent: Go-http-client/1.1 6 | Content-Length: 129 7 | Content-Type: application/json 8 | 9 | {"contents":[{"parts":[{"text":"What is the capital of France? One word."}],"role":"user"}],"generationConfig":{"temperature":0}}HTTP/2.0 200 OK 10 | Connection: close 11 | Content-Disposition: attachment 12 | Content-Type: text/event-stream 13 | Date: Mon, 18 Aug 2025 13:55:15 GMT 14 | Server: scaffolding on HTTPServer2 15 | Server-Timing: gfet4t7; dur=327 16 | Vary: Origin 17 | Vary: X-Origin 18 | Vary: Referer 19 | X-Content-Type-Options: nosniff 20 | X-Frame-Options: SAMEORIGIN 21 | X-Xss-Protection: 0 22 | 23 | data: {"candidates": [{"content": {"parts": [{"text": "Paris"}],"role": "model"}}],"usageMetadata": {"promptTokenCount": 11,"totalTokenCount": 11,"promptTokensDetails": [{"modality": "TEXT","tokenCount": 11}]},"modelVersion": "gemini-2.0-flash","responseId": "wzCjaPa4As7shMIP2Mei0AI"} 24 | 25 | data: {"candidates": [{"content": {"parts": [{"text": "\n"}],"role": "model"},"finishReason": "STOP"}],"usageMetadata": {"promptTokenCount": 10,"candidatesTokenCount": 2,"totalTokenCount": 12,"promptTokensDetails": [{"modality": "TEXT","tokenCount": 10}],"candidatesTokensDetails": [{"modality": "TEXT","tokenCount": 2}]},"modelVersion": "gemini-2.0-flash","responseId": "wzCjaPa4As7shMIP2Mei0AI"} 26 | 27 | -------------------------------------------------------------------------------- /model/gemini/testdata/TestModel_Generate_ok.httprr: -------------------------------------------------------------------------------- 1 | httprr trace v1 2 | 361 954 3 | POST https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent HTTP/1.1 4 | Host: generativelanguage.googleapis.com 5 | User-Agent: Go-http-client/1.1 6 | Content-Length: 129 7 | Content-Type: application/json 8 | 9 | {"contents":[{"parts":[{"text":"What is the capital of France? One word."}],"role":"user"}],"generationConfig":{"temperature":0}}HTTP/2.0 200 OK 10 | Content-Type: application/json; charset=UTF-8 11 | Date: Mon, 18 Aug 2025 13:55:14 GMT 12 | Server: scaffolding on HTTPServer2 13 | Server-Timing: gfet4t7; dur=394 14 | Vary: Origin 15 | Vary: X-Origin 16 | Vary: Referer 17 | X-Content-Type-Options: nosniff 18 | X-Frame-Options: SAMEORIGIN 19 | X-Xss-Protection: 0 20 | 21 | { 22 | "candidates": [ 23 | { 24 | "content": { 25 | "parts": [ 26 | { 27 | "text": "Paris\n" 28 | } 29 | ], 30 | "role": "model" 31 | }, 32 | "finishReason": "STOP", 33 | "avgLogprobs": -0.00055273278849199414 34 | } 35 | ], 36 | "usageMetadata": { 37 | "promptTokenCount": 10, 38 | "candidatesTokenCount": 2, 39 | "totalTokenCount": 12, 40 | "promptTokensDetails": [ 41 | { 42 | "modality": "TEXT", 43 | "tokenCount": 10 44 | } 45 | ], 46 | "candidatesTokensDetails": [ 47 | { 48 | "modality": "TEXT", 49 | "tokenCount": 2 50 | } 51 | ] 52 | }, 53 | "modelVersion": "gemini-2.0-flash", 54 | "responseId": "wjCjaI3AI7mokdUPn8Gf2Ac" 55 | } 56 | -------------------------------------------------------------------------------- /internal/llminternal/file_uploads_processor.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package llminternal 16 | 17 | import ( 18 | "google.golang.org/adk/agent" 19 | "google.golang.org/adk/internal/llminternal/googlellm" 20 | "google.golang.org/adk/model" 21 | ) 22 | 23 | // The Gemini API (non-Vertex) backend does not support the display_name parameter for file uploads, 24 | // so it must be removed to prevent request failures. 25 | func removeDisplayNameIfExists(ctx agent.InvocationContext, req *model.LLMRequest) error { 26 | if req.Contents == nil { 27 | return nil 28 | } 29 | for _, content := range req.Contents { 30 | if content.Parts == nil { 31 | continue 32 | } 33 | if googlellm.GetGoogleLLMVariant() == googlellm.GoogleLLMVariantGeminiAPI { 34 | for _, part := range content.Parts { 35 | if part.InlineData != nil { 36 | part.InlineData.DisplayName = "" 37 | } 38 | if part.FileData != nil { 39 | part.FileData.DisplayName = "" 40 | } 41 | } 42 | } 43 | } 44 | return nil 45 | } 46 | -------------------------------------------------------------------------------- /model/gemini/testdata/TestModel_TrackingHeaders_verifies_headers_are_set.httprr: -------------------------------------------------------------------------------- 1 | httprr trace v1 2 | 309 994 3 | POST https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent HTTP/1.1 4 | Host: generativelanguage.googleapis.com 5 | User-Agent: Go-http-client/1.1 6 | Content-Length: 78 7 | Content-Type: application/json 8 | 9 | {"contents":[{"parts":[{"text":"ping"}],"role":"user"}],"generationConfig":{}}HTTP/2.0 200 OK 10 | Content-Type: application/json; charset=UTF-8 11 | Date: Thu, 06 Nov 2025 11:23:18 GMT 12 | Server: scaffolding on HTTPServer2 13 | Server-Timing: gfet4t7; dur=585 14 | Vary: Origin 15 | Vary: X-Origin 16 | Vary: Referer 17 | X-Content-Type-Options: nosniff 18 | X-Frame-Options: SAMEORIGIN 19 | X-Xss-Protection: 0 20 | 21 | { 22 | "candidates": [ 23 | { 24 | "content": { 25 | "parts": [ 26 | { 27 | "text": "Pong! \n\nIs there anything I can help you with?\n" 28 | } 29 | ], 30 | "role": "model" 31 | }, 32 | "finishReason": "STOP", 33 | "avgLogprobs": -0.35232135227748324 34 | } 35 | ], 36 | "usageMetadata": { 37 | "promptTokenCount": 1, 38 | "candidatesTokenCount": 14, 39 | "totalTokenCount": 15, 40 | "promptTokensDetails": [ 41 | { 42 | "modality": "TEXT", 43 | "tokenCount": 1 44 | } 45 | ], 46 | "candidatesTokensDetails": [ 47 | { 48 | "modality": "TEXT", 49 | "tokenCount": 14 50 | } 51 | ] 52 | }, 53 | "modelVersion": "gemini-2.0-flash", 54 | "responseId": "JYUMaciaHZ7hnsEP9amb6Qg" 55 | } 56 | -------------------------------------------------------------------------------- /server/adkrest/internal/models/runtime.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package models 16 | 17 | import ( 18 | "fmt" 19 | 20 | "google.golang.org/genai" 21 | ) 22 | 23 | type RunAgentRequest struct { 24 | AppName string `json:"appName"` 25 | 26 | UserId string `json:"userId"` 27 | 28 | SessionId string `json:"sessionId"` 29 | 30 | NewMessage genai.Content `json:"newMessage"` 31 | 32 | Streaming bool `json:"streaming,omitempty"` 33 | 34 | StateDelta *map[string]any `json:"stateDelta,omitempty"` 35 | } 36 | 37 | // AssertRunAgentRequestRequired checks if the required fields are not zero-ed 38 | func (req RunAgentRequest) AssertRunAgentRequestRequired() error { 39 | elements := map[string]any{ 40 | "appName": req.AppName, 41 | "userId": req.UserId, 42 | "sessionId": req.SessionId, 43 | "newMessage": req.NewMessage, 44 | } 45 | for name, el := range elements { 46 | if isZero := IsZeroValue(el); isZero { 47 | return fmt.Errorf("%s is required", name) 48 | } 49 | } 50 | 51 | return nil 52 | } 53 | -------------------------------------------------------------------------------- /tool/exitlooptool/tool.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package exitlooptool provides a tool that allows an agent to exit a loop. 16 | package exitlooptool 17 | 18 | import ( 19 | "fmt" 20 | 21 | "google.golang.org/adk/tool" 22 | "google.golang.org/adk/tool/functiontool" 23 | ) 24 | 25 | // EmptyArgs is an empty struct used as an argument for the exitLoop tool. 26 | type EmptyArgs struct{} 27 | 28 | func exitLoop(ctx tool.Context, myArgs EmptyArgs) (map[string]string, error) { 29 | ctx.Actions().Escalate = true 30 | ctx.Actions().SkipSummarization = true 31 | return map[string]string{}, nil 32 | } 33 | 34 | // New creates an instance of an exitLoop tool. 35 | func New() (tool.Tool, error) { 36 | exitLoopTool, err := functiontool.New(functiontool.Config{ 37 | Name: "exit_loop", 38 | Description: "Exits the loop.\nCall this function only when you are instructed to do so.\n", 39 | }, exitLoop) 40 | if err != nil { 41 | return nil, fmt.Errorf("error creating exit loop tool: %w", err) 42 | } 43 | return exitLoopTool, nil 44 | } 45 | -------------------------------------------------------------------------------- /server/adkrest/internal/routers/eval.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package routers 16 | 17 | import ( 18 | "net/http" 19 | 20 | "google.golang.org/adk/server/adkrest/controllers" 21 | ) 22 | 23 | // EvalAPIRouter defines the routes for the Eval API. 24 | type EvalAPIRouter struct{} 25 | 26 | // Routes returns the routes for the Apps API. 27 | func (r *EvalAPIRouter) Routes() Routes { 28 | return Routes{ 29 | Route{ 30 | Name: "ListEvalSets", 31 | Methods: []string{http.MethodGet}, 32 | Pattern: "/apps/{app_name}/eval_sets", 33 | HandlerFunc: controllers.Unimplemented, 34 | }, 35 | Route{ 36 | Name: "ListEvalSets", 37 | Methods: []string{http.MethodPost, http.MethodOptions}, 38 | Pattern: "/apps/{app_name}/eval_sets/{eval_set_name}", 39 | HandlerFunc: controllers.Unimplemented, 40 | }, 41 | Route{ 42 | Name: "ListEvalResults", 43 | Methods: []string{http.MethodGet}, 44 | Pattern: "/apps/{app_name}/eval_results", 45 | HandlerFunc: controllers.Unimplemented, 46 | }, 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /internal/llminternal/agent.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package llminternal 16 | 17 | import ( 18 | "google.golang.org/genai" 19 | 20 | "google.golang.org/adk/agent" 21 | "google.golang.org/adk/model" 22 | "google.golang.org/adk/tool" 23 | ) 24 | 25 | // holds LLMAgent internal state 26 | type Agent interface { 27 | internal() *State 28 | } 29 | 30 | type State struct { 31 | Model model.LLM 32 | 33 | Tools []tool.Tool 34 | Toolsets []tool.Toolset 35 | 36 | IncludeContents string 37 | 38 | GenerateContentConfig *genai.GenerateContentConfig 39 | 40 | Instruction string 41 | InstructionProvider InstructionProvider 42 | GlobalInstruction string 43 | GlobalInstructionProvider InstructionProvider 44 | 45 | DisallowTransferToParent bool 46 | DisallowTransferToPeers bool 47 | 48 | InputSchema *genai.Schema 49 | OutputSchema *genai.Schema 50 | 51 | OutputKey string 52 | } 53 | 54 | type InstructionProvider func(ctx agent.ReadonlyContext) (string, error) 55 | 56 | func (s *State) internal() *State { return s } 57 | 58 | func Reveal(a Agent) *State { return a.internal() } 59 | -------------------------------------------------------------------------------- /agent/llmagent/testdata/TestLLMAgent_healthy_backend.httprr: -------------------------------------------------------------------------------- 1 | httprr trace v1 2 | 508 945 3 | POST https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent HTTP/1.1 4 | Host: generativelanguage.googleapis.com 5 | User-Agent: Go-http-client/1.1 6 | Content-Length: 276 7 | Content-Type: application/json 8 | 9 | {"contents":[{"parts":[{"text":"Handle the requests as specified in the System Instruction."}],"role":"user"}],"generationConfig":{},"systemInstruction":{"parts":[{"text":"Answer as precisely as possible."},{"text":"Roll the dice and report only the result."}],"role":"user"}}HTTP/2.0 200 OK 10 | Content-Type: application/json; charset=UTF-8 11 | Date: Mon, 29 Sep 2025 08:03:49 GMT 12 | Server: scaffolding on HTTPServer2 13 | Server-Timing: gfet4t7; dur=618 14 | Vary: Origin 15 | Vary: X-Origin 16 | Vary: Referer 17 | X-Content-Type-Options: nosniff 18 | X-Frame-Options: SAMEORIGIN 19 | X-Xss-Protection: 0 20 | 21 | { 22 | "candidates": [ 23 | { 24 | "content": { 25 | "parts": [ 26 | { 27 | "text": "6\n" 28 | } 29 | ], 30 | "role": "model" 31 | }, 32 | "finishReason": "STOP", 33 | "avgLogprobs": -0.2207629382610321 34 | } 35 | ], 36 | "usageMetadata": { 37 | "promptTokenCount": 25, 38 | "candidatesTokenCount": 2, 39 | "totalTokenCount": 27, 40 | "promptTokensDetails": [ 41 | { 42 | "modality": "TEXT", 43 | "tokenCount": 25 44 | } 45 | ], 46 | "candidatesTokensDetails": [ 47 | { 48 | "modality": "TEXT", 49 | "tokenCount": 2 50 | } 51 | ] 52 | }, 53 | "modelVersion": "gemini-2.0-flash", 54 | "responseId": "ZD3aaI7bIqenkdUPq4ONQA" 55 | } 56 | -------------------------------------------------------------------------------- /tool/geminitool/google_search.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package geminitool 16 | 17 | import ( 18 | "google.golang.org/genai" 19 | 20 | "google.golang.org/adk/model" 21 | "google.golang.org/adk/tool" 22 | ) 23 | 24 | // GoogleSearch is a built-in tool that is automatically invoked by Gemini 2 25 | // models to retrieve search results from Google Search. 26 | // The tool operates internally within the model and does not require or 27 | // perform local code execution. 28 | type GoogleSearch struct{} 29 | 30 | // Name implements tool.Tool. 31 | func (s GoogleSearch) Name() string { 32 | return "google_search" 33 | } 34 | 35 | // Description implements tool.Tool. 36 | func (s GoogleSearch) Description() string { 37 | return "Performs a Google search to retrieve information from the web." 38 | } 39 | 40 | // ProcessRequest adds the GoogleSearch tool to the LLM request. 41 | func (s GoogleSearch) ProcessRequest(ctx tool.Context, req *model.LLMRequest) error { 42 | return setTool(req, &genai.Tool{ 43 | GoogleSearch: &genai.GoogleSearch{}, 44 | }) 45 | } 46 | 47 | // IsLongRunning implements tool.Tool. 48 | func (t GoogleSearch) IsLongRunning() bool { 49 | return false 50 | } 51 | -------------------------------------------------------------------------------- /cmd/launcher/web/webui/distr/chunk-2WH2EVR6.js: -------------------------------------------------------------------------------- 1 | var q=Object.create;var m=Object.defineProperty,r=Object.defineProperties,s=Object.getOwnPropertyDescriptor,t=Object.getOwnPropertyDescriptors,u=Object.getOwnPropertyNames,j=Object.getOwnPropertySymbols,v=Object.getPrototypeOf,n=Object.prototype.hasOwnProperty,p=Object.prototype.propertyIsEnumerable;var l=(b,a)=>(a=Symbol[b])?a:Symbol.for("Symbol."+b),w=b=>{throw TypeError(b)};var o=(b,a,c)=>a in b?m(b,a,{enumerable:!0,configurable:!0,writable:!0,value:c}):b[a]=c,z=(b,a)=>{for(var c in a||={})n.call(a,c)&&o(b,c,a[c]);if(j)for(var c of j(a))p.call(a,c)&&o(b,c,a[c]);return b},A=(b,a)=>r(b,t(a));var B=(b,a)=>{var c={};for(var d in b)n.call(b,d)&&a.indexOf(d)<0&&(c[d]=b[d]);if(b!=null&&j)for(var d of j(b))a.indexOf(d)<0&&p.call(b,d)&&(c[d]=b[d]);return c};var C=(b,a)=>()=>(a||b((a={exports:{}}).exports,a),a.exports);var x=(b,a,c,d)=>{if(a&&typeof a=="object"||typeof a=="function")for(let e of u(a))!n.call(b,e)&&e!==c&&m(b,e,{get:()=>a[e],enumerable:!(d=s(a,e))||d.enumerable});return b};var D=(b,a,c)=>(c=b!=null?q(v(b)):{},x(a||!b||!b.__esModule?m(c,"default",{value:b,enumerable:!0}):c,b));var E=(b,a,c)=>new Promise((d,e)=>{var f=g=>{try{i(c.next(g))}catch(k){e(k)}},h=g=>{try{i(c.throw(g))}catch(k){e(k)}},i=g=>g.done?d(g.value):Promise.resolve(g.value).then(f,h);i((c=c.apply(b,a)).next())}),y=function(b,a){this[0]=b,this[1]=a};var F=b=>{var a=b[l("asyncIterator")],c=!1,d,e={};return a==null?(a=b[l("iterator")](),d=f=>e[f]=h=>a[f](h)):(a=a.call(b),d=f=>e[f]=h=>{if(c){if(c=!1,f==="throw")throw h;return h}return c=!0,{done:!1,value:new y(new Promise(i=>{var g=a[f](h);g instanceof Object||w("Object expected"),i(g)}),1)}}),e[l("iterator")]=()=>e,d("next"),"throw"in a?d("throw"):e.throw=f=>{throw f},"return"in a&&d("return"),e};export{z as a,A as b,B as c,C as d,D as e,E as f,F as g}; 2 | -------------------------------------------------------------------------------- /server/adkrest/internal/routers/runtime.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package routers 16 | 17 | import ( 18 | "net/http" 19 | 20 | "google.golang.org/adk/server/adkrest/controllers" 21 | ) 22 | 23 | // RuntimeAPIRouter defines the routes for the Runtime API. 24 | type RuntimeAPIRouter struct { 25 | runtimeController *controllers.RuntimeAPIController 26 | } 27 | 28 | // NewRuntimeAPIRouter creates a new RuntimeAPIRouter. 29 | func NewRuntimeAPIRouter(controller *controllers.RuntimeAPIController) *RuntimeAPIRouter { 30 | return &RuntimeAPIRouter{runtimeController: controller} 31 | } 32 | 33 | // Routes returns the routes for the Runtime API. 34 | func (r *RuntimeAPIRouter) Routes() Routes { 35 | return Routes{ 36 | Route{ 37 | Name: "RunAgent", 38 | Methods: []string{http.MethodPost, http.MethodOptions}, 39 | Pattern: "/run", 40 | HandlerFunc: controllers.NewErrorHandler(r.runtimeController.RunHandler), 41 | }, 42 | Route{ 43 | Name: "RunAgentSse", 44 | Methods: []string{http.MethodPost, http.MethodOptions}, 45 | Pattern: "/run_sse", 46 | HandlerFunc: controllers.NewErrorHandler(r.runtimeController.RunSSEHandler), 47 | }, 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | version: "2" 2 | 3 | formatters: 4 | enable: 5 | - goimports 6 | - gofumpt 7 | 8 | settings: 9 | goimports: 10 | local-prefixes: 11 | - google.golang.org/adk 12 | gofumpt: 13 | extra-rules: true 14 | module-path: google.golang.org/adk 15 | 16 | linters: 17 | enable: 18 | - goheader 19 | 20 | settings: 21 | 22 | goheader: 23 | values: 24 | const: 25 | COMPANY: Google LLC 26 | regexp: 27 | YEAR: 20\d\d 28 | template: |- 29 | Copyright {{ YEAR }} {{ COMPANY }} 30 | 31 | Licensed under the Apache License, Version 2.0 (the "License"); 32 | you may not use this file except in compliance with the License. 33 | You may obtain a copy of the License at 34 | 35 | http://www.apache.org/licenses/LICENSE-2.0 36 | 37 | Unless required by applicable law or agreed to in writing, software 38 | distributed under the License is distributed on an "AS IS" BASIS, 39 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 40 | See the License for the specific language governing permissions and 41 | limitations under the License. 42 | 43 | staticcheck: 44 | checks: 45 | # The default config: 46 | - all 47 | - -ST1000 48 | - -ST1003 49 | - -ST1016 50 | - -ST1020 51 | - -ST1021 52 | - -ST1022 53 | # Changes to the default config: 54 | - -QF1001 # Exclude "Apply De Morgan's law" 55 | - -QF1008 # Exclude "Omit embedded fields from selector expression" 56 | 57 | exclusions: 58 | rules: 59 | - path: 'internal/httprr/.*' 60 | linters: 61 | - goheader 62 | - errcheck 63 | - staticcheck 64 | -------------------------------------------------------------------------------- /internal/converters/map_structure.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package converters 16 | 17 | import ( 18 | "encoding/json" 19 | ) 20 | 21 | // ToMapStructure converts any to map[string]any. 22 | // We can't use mapstructure library in a way compatible with ADK-python, because genai type fields 23 | // don't have proper field tags. 24 | // TODO(yarolegovich): field annotation PR for genai types. 25 | func ToMapStructure(data any) (map[string]any, error) { 26 | bytes, err := json.Marshal(data) 27 | if err != nil { 28 | return nil, err 29 | } 30 | 31 | var result map[string]any 32 | if err := json.Unmarshal(bytes, &result); err != nil { 33 | return nil, err 34 | } 35 | return result, nil 36 | } 37 | 38 | // FromMapStructure converts map[string]any to the type parameter T. 39 | // We can't use mapstructure library in a way compatible with ADK-python, because genai type fields 40 | // don't have proper field tags. 41 | // TODO(yarolegovich): field annotation PR for genai types. 42 | func FromMapStructure[T any](data map[string]any) (*T, error) { 43 | bytes, err := json.Marshal(data) 44 | if err != nil { 45 | return nil, err 46 | } 47 | 48 | var zero T 49 | if err := json.Unmarshal(bytes, &zero); err != nil { 50 | return nil, err 51 | } 52 | return &zero, nil 53 | } 54 | -------------------------------------------------------------------------------- /internal/typeutil/convert.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package typeutil is a collection of type handling utility functions. 16 | package typeutil 17 | 18 | import ( 19 | "encoding/json" 20 | 21 | "github.com/google/jsonschema-go/jsonschema" 22 | ) 23 | 24 | // ConvertToWithJSONSchema converts the given value to another type using json marshal/unmarshal. 25 | // If non-nil resolvedSchema is provided, validation against the resolvedSchema will run 26 | // during the conversion. 27 | func ConvertToWithJSONSchema[From, To any](v From, resolvedSchema *jsonschema.Resolved) (To, error) { 28 | var zero To 29 | rawArgs, err := json.Marshal(v) 30 | if err != nil { 31 | return zero, err 32 | } 33 | if resolvedSchema != nil { 34 | // See https://github.com/google/jsonschema-go/issues/23: in order to 35 | // validate, we must validate against a map[string]any. Struct validation 36 | // does not work as it cannot account for `omitempty` or custom marshalling. 37 | var m map[string]any 38 | if err := json.Unmarshal(rawArgs, &m); err != nil { 39 | return zero, err 40 | } 41 | if err := resolvedSchema.Validate(m); err != nil { 42 | return zero, err 43 | } 44 | } 45 | var typed To 46 | if err := json.Unmarshal(rawArgs, &typed); err != nil { 47 | return zero, err 48 | } 49 | return typed, nil 50 | } 51 | -------------------------------------------------------------------------------- /server/adkrest/internal/routers/routers.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package routers defines the HTTP routes for the ADK REST API. 16 | package routers 17 | 18 | import ( 19 | "net/http" 20 | 21 | "github.com/gorilla/mux" 22 | ) 23 | 24 | // A Route defines the parameters for an api endpoint 25 | type Route struct { 26 | Name string 27 | Methods []string 28 | Pattern string 29 | HandlerFunc http.HandlerFunc 30 | } 31 | 32 | // Routes is a list of defined api endpoints 33 | type Routes []Route 34 | 35 | // Router defines the required methods for retrieving api routes 36 | type Router interface { 37 | Routes() Routes 38 | } 39 | 40 | // NewRouter creates a new router for any number of api routers 41 | func NewRouter(routers ...Router) *mux.Router { 42 | router := mux.NewRouter().StrictSlash(true) 43 | SetupSubRouters(router) 44 | return router 45 | } 46 | 47 | // SetupSubRouters adds routes from subrouter to the naub router 48 | func SetupSubRouters(router *mux.Router, subrouters ...Router) { 49 | for _, api := range subrouters { 50 | for _, route := range api.Routes() { 51 | var handler http.Handler = route.HandlerFunc 52 | 53 | router. 54 | Methods(route.Methods...). 55 | Path(route.Pattern). 56 | Name(route.Name). 57 | Handler(handler) 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /agent/workflowagents/sequentialagent/agent.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package sequentialagent provides an agent that runs its sub-agents in a sequence. 16 | package sequentialagent 17 | 18 | import ( 19 | "fmt" 20 | 21 | "google.golang.org/adk/agent" 22 | "google.golang.org/adk/agent/workflowagents/loopagent" 23 | agentinternal "google.golang.org/adk/internal/agent" 24 | ) 25 | 26 | // New creates a SequentialAgent. 27 | // 28 | // SequentialAgent executes its sub-agents once, in the order they are listed. 29 | // 30 | // Use the SequentialAgent when you want the execution to occur in a fixed, 31 | // strict order. 32 | func New(cfg Config) (agent.Agent, error) { 33 | sequentialAgent, err := loopagent.New(loopagent.Config{ 34 | AgentConfig: cfg.AgentConfig, 35 | MaxIterations: 1, 36 | }) 37 | if err != nil { 38 | return nil, err 39 | } 40 | 41 | internalAgent, ok := sequentialAgent.(agentinternal.Agent) 42 | if !ok { 43 | return nil, fmt.Errorf("internal error: failed to convert to internal agent") 44 | } 45 | state := agentinternal.Reveal(internalAgent) 46 | state.AgentType = agentinternal.TypeSequentialAgent 47 | state.Config = cfg 48 | 49 | return sequentialAgent, nil 50 | } 51 | 52 | // Config defines the configuration for a SequentialAgent. 53 | type Config struct { 54 | // Basic agent setup. 55 | AgentConfig agent.Config 56 | } 57 | -------------------------------------------------------------------------------- /server/adkrest/internal/routers/debug.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package routers 16 | 17 | import ( 18 | "net/http" 19 | 20 | "google.golang.org/adk/server/adkrest/controllers" 21 | ) 22 | 23 | // DebugAPIRouter defines the routes for the Debug API. 24 | type DebugAPIRouter struct { 25 | runtimeController *controllers.DebugAPIController 26 | } 27 | 28 | // NewDebugAPIRouter creates a new DebugAPIRouter. 29 | func NewDebugAPIRouter(controller *controllers.DebugAPIController) *DebugAPIRouter { 30 | return &DebugAPIRouter{runtimeController: controller} 31 | } 32 | 33 | // Routes returns the routes for the Debug API. 34 | func (r *DebugAPIRouter) Routes() Routes { 35 | return Routes{ 36 | Route{ 37 | Name: "GetTraceDict", 38 | Methods: []string{http.MethodGet}, 39 | Pattern: "/debug/trace/{event_id}", 40 | HandlerFunc: r.runtimeController.TraceDictHandler, 41 | }, 42 | Route{ 43 | Name: "GetEventGraph", 44 | Methods: []string{http.MethodGet}, 45 | Pattern: "/apps/{app_name}/users/{user_id}/sessions/{session_id}/events/{event_id}/graph", 46 | HandlerFunc: r.runtimeController.EventGraphHandler, 47 | }, 48 | Route{ 49 | Name: "GetSessionTrace", 50 | Methods: []string{http.MethodGet}, 51 | Pattern: "/debug/trace/session/{session_id}", 52 | HandlerFunc: controllers.Unimplemented, 53 | }, 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /cmd/launcher/web/webui/distr/assets/audio-processor.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2025 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | class AudioProcessor extends AudioWorkletProcessor { 18 | constructor() { 19 | super(); 20 | this.targetSampleRate = 22000; // Change to your desired rate 21 | this.originalSampleRate = sampleRate; // Browser's sample rate 22 | this.resampleRatio = this.originalSampleRate / this.targetSampleRate; 23 | } 24 | 25 | process(inputs, outputs, parameters) { 26 | const input = inputs[0]; 27 | if (input.length > 0) { 28 | let audioData = input[0]; // Get first channel's data 29 | 30 | if (this.resampleRatio !== 1) { 31 | audioData = this.resample(audioData); 32 | } 33 | 34 | this.port.postMessage(audioData); 35 | } 36 | return true; // Keep processor alive 37 | } 38 | 39 | resample(audioData) { 40 | const newLength = Math.round(audioData.length / this.resampleRatio); 41 | const resampled = new Float32Array(newLength); 42 | 43 | for (let i = 0; i < newLength; i++) { 44 | const srcIndex = Math.floor(i * this.resampleRatio); 45 | resampled[i] = audioData[srcIndex]; // Nearest neighbor resampling 46 | } 47 | return resampled; 48 | } 49 | } 50 | 51 | registerProcessor('audio-processor', AudioProcessor); 52 | -------------------------------------------------------------------------------- /internal/llminternal/other_processors.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package llminternal 16 | 17 | import ( 18 | "google.golang.org/adk/agent" 19 | "google.golang.org/adk/model" 20 | ) 21 | 22 | func identityRequestProcessor(ctx agent.InvocationContext, req *model.LLMRequest) error { 23 | // TODO: implement (adk-python src/google/adk/flows/llm_flows/identity.py) 24 | return nil 25 | } 26 | 27 | func nlPlanningRequestProcessor(ctx agent.InvocationContext, req *model.LLMRequest) error { 28 | // TODO: implement (adk-python src/google/adk/flows/llm_flows/_nl_plnning.py) 29 | return nil 30 | } 31 | 32 | func codeExecutionRequestProcessor(ctx agent.InvocationContext, req *model.LLMRequest) error { 33 | // TODO: implement (adk-python src/google/adk/flows/llm_flows/_code_execution.py) 34 | return nil 35 | } 36 | 37 | func authPreprocessor(ctx agent.InvocationContext, req *model.LLMRequest) error { 38 | // TODO: implement (adk-python src/google/adk/auth/auth_preprocessor.py) 39 | return nil 40 | } 41 | 42 | func nlPlanningResponseProcessor(ctx agent.InvocationContext, req *model.LLMRequest, resp *model.LLMResponse) error { 43 | // TODO: implement (adk-python src/google/adk/_nl_planning.py) 44 | return nil 45 | } 46 | 47 | func codeExecutionResponseProcessor(ctx agent.InvocationContext, req *model.LLMRequest, resp *model.LLMResponse) error { 48 | // TODO: implement (adk-python src/google/adk_code_execution.py) 49 | return nil 50 | } 51 | -------------------------------------------------------------------------------- /util/instructionutil/instruction.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package instructionutil provides utilities to work with agent instructions. 16 | package instructionutil 17 | 18 | import ( 19 | "fmt" 20 | 21 | "google.golang.org/adk/agent" 22 | icontext "google.golang.org/adk/internal/context" 23 | "google.golang.org/adk/internal/llminternal" 24 | ) 25 | 26 | // InjectSessionState populates values in the instruction template, e.g. state, 27 | // artifact, etc. 28 | // - There can be placeholders like {key_name} that will be resolved by ADK 29 | // at runtime using session state and context. 30 | // - key_name must match "^[a-zA-Z_][a-zA-Z0-9_]*$", otherwise it will be 31 | // treated as a literal. 32 | // - {artifact.key_name} can be used to insert the text content of the 33 | // artifact named key_name. 34 | // 35 | // If the state variable or artifact does not exist, the agent will raise an 36 | // error. If you want to ignore the error, you can append a ? to the 37 | // variable name as in {var?}. 38 | // 39 | // This method is intended to be used in InstructionProvider based Instruction 40 | // and GlobalInstruction which are called with ReadonlyContext. 41 | func InjectSessionState(ctx agent.ReadonlyContext, template string) (string, error) { 42 | ictx, ok := ctx.(*icontext.ReadonlyContext) 43 | if !ok { 44 | return "", fmt.Errorf("unexpected context type: %T", ctx) 45 | } 46 | return llminternal.InjectSessionState(ictx.InvocationContext, template) 47 | } 48 | -------------------------------------------------------------------------------- /server/adkrest/controllers/handlers.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package controllers contains the controllers for the ADK REST API. 16 | package controllers 17 | 18 | import ( 19 | "encoding/json" 20 | "net/http" 21 | ) 22 | 23 | // TODO: Move to an internal package, controllers doesn't have to be public API. 24 | 25 | // EncodeJSONResponse uses the json encoder to write an interface to the http response with an optional status code 26 | func EncodeJSONResponse(i any, status int, w http.ResponseWriter) { 27 | wHeader := w.Header() 28 | wHeader.Set("Content-Type", "application/json; charset=UTF-8") 29 | 30 | w.WriteHeader(status) 31 | 32 | if i != nil { 33 | err := json.NewEncoder(w).Encode(i) 34 | if err != nil { 35 | http.Error(w, err.Error(), http.StatusInternalServerError) 36 | } 37 | } 38 | } 39 | 40 | type errorHandler func(http.ResponseWriter, *http.Request) error 41 | 42 | // NewErrorHandler writes the error code returned from the http handler. 43 | func NewErrorHandler(fn errorHandler) http.HandlerFunc { 44 | return func(w http.ResponseWriter, r *http.Request) { 45 | err := fn(w, r) 46 | if err != nil { 47 | if statusErr, ok := err.(statusError); ok { 48 | http.Error(w, statusErr.Error(), statusErr.Status()) 49 | } else { 50 | http.Error(w, err.Error(), http.StatusInternalServerError) 51 | } 52 | } 53 | } 54 | } 55 | 56 | // Unimplemented returns 501 - Status Not Implemented error 57 | func Unimplemented(rw http.ResponseWriter, req *http.Request) { 58 | rw.WriteHeader(http.StatusNotImplemented) 59 | } 60 | -------------------------------------------------------------------------------- /examples/quickstart/main.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package provides a quickstart ADK agent. 16 | package main 17 | 18 | import ( 19 | "context" 20 | "log" 21 | "os" 22 | 23 | "google.golang.org/genai" 24 | 25 | "google.golang.org/adk/agent" 26 | "google.golang.org/adk/agent/llmagent" 27 | "google.golang.org/adk/cmd/launcher" 28 | "google.golang.org/adk/cmd/launcher/full" 29 | "google.golang.org/adk/model/gemini" 30 | "google.golang.org/adk/tool" 31 | "google.golang.org/adk/tool/geminitool" 32 | ) 33 | 34 | func main() { 35 | ctx := context.Background() 36 | 37 | model, err := gemini.NewModel(ctx, "gemini-2.5-flash", &genai.ClientConfig{ 38 | APIKey: os.Getenv("GOOGLE_API_KEY"), 39 | }) 40 | if err != nil { 41 | log.Fatalf("Failed to create model: %v", err) 42 | } 43 | 44 | a, err := llmagent.New(llmagent.Config{ 45 | Name: "weather_time_agent", 46 | Model: model, 47 | Description: "Agent to answer questions about the time and weather in a city.", 48 | Instruction: "Your SOLE purpose is to answer questions about the current time and weather in a specific city. You MUST refuse to answer any questions unrelated to time or weather.", 49 | Tools: []tool.Tool{ 50 | geminitool.GoogleSearch{}, 51 | }, 52 | }) 53 | if err != nil { 54 | log.Fatalf("Failed to create agent: %v", err) 55 | } 56 | 57 | config := &launcher.Config{ 58 | AgentLoader: agent.NewSingleLoader(a), 59 | } 60 | 61 | l := full.NewLauncher() 62 | if err = l.Execute(ctx, config, os.Args[1:]); err != nil { 63 | log.Fatalf("Run failed: %v\n\n%s", err, l.CommandLineSyntax()) 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /memory/service.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package memory defines the entities to interact with agent memory (long-term knowledge). 16 | package memory 17 | 18 | import ( 19 | "context" 20 | "time" 21 | 22 | "google.golang.org/genai" 23 | 24 | "google.golang.org/adk/session" 25 | ) 26 | 27 | // Service is a definition of the memory service. 28 | // 29 | // The service ingests sessions into memory so that it can be used for 30 | // user queries across user-scoped sessions. 31 | type Service interface { 32 | // AddSession adds a session to the memory service. 33 | // 34 | // A session can be added multiple times during its lifetime. 35 | AddSession(ctx context.Context, s session.Session) error 36 | // Search returns memory entries relevant to the given query. 37 | // Empty slice is returned if there are no matches. 38 | Search(ctx context.Context, req *SearchRequest) (*SearchResponse, error) 39 | } 40 | 41 | // SearchRequest represents a request for memory search. 42 | type SearchRequest struct { 43 | Query string 44 | UserID string 45 | AppName string 46 | } 47 | 48 | // SearchResponse represents the response from a memory search. 49 | type SearchResponse struct { 50 | Memories []Entry 51 | } 52 | 53 | // Entry represents a single memory entry. 54 | type Entry struct { 55 | // Content contains the main content of the memory. 56 | Content *genai.Content 57 | // Author of the memory. 58 | Author string 59 | // Timestamp shows when the original content of this memory happened. 60 | // This string will be forwarded to LLM. Preferred format is ISO 8601 format. 61 | Timestamp time.Time 62 | } 63 | -------------------------------------------------------------------------------- /internal/artifact/artifacts.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package artifact 16 | 17 | import ( 18 | "context" 19 | 20 | "google.golang.org/genai" 21 | 22 | "google.golang.org/adk/agent" 23 | "google.golang.org/adk/artifact" 24 | ) 25 | 26 | // Artifacts implements Artifacts 27 | type Artifacts struct { 28 | Service artifact.Service 29 | AppName string 30 | UserID string 31 | SessionID string 32 | } 33 | 34 | func (a *Artifacts) Save(ctx context.Context, name string, data *genai.Part) (*artifact.SaveResponse, error) { 35 | return a.Service.Save(ctx, &artifact.SaveRequest{ 36 | AppName: a.AppName, 37 | UserID: a.UserID, 38 | SessionID: a.SessionID, 39 | FileName: name, 40 | Part: data, 41 | }) 42 | } 43 | 44 | func (a *Artifacts) Load(ctx context.Context, name string) (*artifact.LoadResponse, error) { 45 | return a.Service.Load(ctx, &artifact.LoadRequest{ 46 | AppName: a.AppName, 47 | UserID: a.UserID, 48 | SessionID: a.SessionID, 49 | FileName: name, 50 | }) 51 | } 52 | 53 | func (a *Artifacts) LoadVersion(ctx context.Context, name string, version int) (*artifact.LoadResponse, error) { 54 | return a.Service.Load(ctx, &artifact.LoadRequest{ 55 | AppName: a.AppName, 56 | UserID: a.UserID, 57 | SessionID: a.SessionID, 58 | FileName: name, 59 | Version: int64(version), 60 | }) 61 | } 62 | 63 | func (a *Artifacts) List(ctx context.Context) (*artifact.ListResponse, error) { 64 | return a.Service.List(ctx, &artifact.ListRequest{ 65 | AppName: a.AppName, 66 | UserID: a.UserID, 67 | SessionID: a.SessionID, 68 | }) 69 | } 70 | 71 | var _ agent.Artifacts = (*Artifacts)(nil) 72 | -------------------------------------------------------------------------------- /internal/testutil/genai.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package testutil 16 | 17 | import ( 18 | "bytes" 19 | "encoding/json" 20 | "fmt" 21 | "net/http" 22 | "strings" 23 | 24 | "google.golang.org/adk/internal/httprr" 25 | ) 26 | 27 | // NewGeminiTransport returns the genai.ClientConfig configured for record and replay. 28 | func NewGeminiTransport(rrfile string) (http.RoundTripper, error) { 29 | rr, err := httprr.Open(rrfile, http.DefaultTransport) 30 | if err != nil { 31 | return nil, fmt.Errorf("httprr.Open(%q) failed: %w", rrfile, err) 32 | } 33 | rr.ScrubReq(scrubGeminiRequest) 34 | return rr, nil 35 | } 36 | 37 | func scrubGeminiRequest(req *http.Request) error { 38 | delete(req.Header, "x-goog-api-key") // genai does not canonicalize 39 | req.Header.Del("X-Goog-Api-Key") // in case it starts 40 | delete(req.Header, "x-goog-api-client") // contains version numbers 41 | req.Header.Del("X-Goog-Api-Client") 42 | delete(req.Header, "user-agent") // contains google-genai-sdk and gl-go version numbers 43 | req.Header.Del("User-Agent") 44 | 45 | if ctype := req.Header.Get("Content-Type"); ctype == "application/json" || strings.HasPrefix(ctype, "application/json;") { 46 | // Canonicalize JSON body. 47 | // google.golang.org/protobuf/internal/encoding.json 48 | // goes out of its way to randomize the JSON encodings 49 | // of protobuf messages by adding or not adding spaces 50 | // after commas. Derandomize by compacting the JSON. 51 | b := req.Body.(*httprr.Body) 52 | var buf bytes.Buffer 53 | if err := json.Compact(&buf, b.Data); err == nil { 54 | b.Data = buf.Bytes() 55 | } 56 | } 57 | return nil 58 | } 59 | -------------------------------------------------------------------------------- /internal/context/readonly_context.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package context 16 | 17 | import ( 18 | "context" 19 | 20 | "google.golang.org/genai" 21 | 22 | "google.golang.org/adk/agent" 23 | "google.golang.org/adk/session" 24 | ) 25 | 26 | func NewReadonlyContext(ctx agent.InvocationContext) agent.ReadonlyContext { 27 | return &ReadonlyContext{ 28 | Context: ctx, 29 | InvocationContext: ctx, 30 | } 31 | } 32 | 33 | type ReadonlyContext struct { 34 | context.Context 35 | InvocationContext agent.InvocationContext 36 | } 37 | 38 | // AppName implements agent.ReadonlyContext. 39 | func (c *ReadonlyContext) AppName() string { 40 | return c.InvocationContext.Session().AppName() 41 | } 42 | 43 | // Branch implements agent.ReadonlyContext. 44 | func (c *ReadonlyContext) Branch() string { 45 | return c.InvocationContext.Branch() 46 | } 47 | 48 | // SessionID implements agent.ReadonlyContext. 49 | func (c *ReadonlyContext) SessionID() string { 50 | return c.InvocationContext.Session().ID() 51 | } 52 | 53 | // UserID implements agent.ReadonlyContext. 54 | func (c *ReadonlyContext) UserID() string { 55 | return c.InvocationContext.Session().UserID() 56 | } 57 | 58 | func (c *ReadonlyContext) AgentName() string { 59 | return c.InvocationContext.Agent().Name() 60 | } 61 | 62 | func (c *ReadonlyContext) ReadonlyState() session.ReadonlyState { 63 | return c.InvocationContext.Session().State() 64 | } 65 | 66 | func (c *ReadonlyContext) InvocationID() string { 67 | return c.InvocationContext.InvocationID() 68 | } 69 | 70 | func (c *ReadonlyContext) UserContent() *genai.Content { 71 | return c.InvocationContext.UserContent() 72 | } 73 | -------------------------------------------------------------------------------- /model/llm.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package model defines the interfaces and data structures for interacting with LLMs. 16 | package model 17 | 18 | import ( 19 | "context" 20 | "iter" 21 | 22 | "google.golang.org/genai" 23 | ) 24 | 25 | // LLM provides the access to the underlying LLM. 26 | type LLM interface { 27 | Name() string 28 | GenerateContent(ctx context.Context, req *LLMRequest, stream bool) iter.Seq2[*LLMResponse, error] 29 | } 30 | 31 | // LLMRequest is the raw LLM request. 32 | type LLMRequest struct { 33 | Model string 34 | Contents []*genai.Content 35 | Config *genai.GenerateContentConfig 36 | 37 | Tools map[string]any `json:"-"` 38 | } 39 | 40 | // LLMResponse is the raw LLM response. 41 | // It provides the first candidate response from the model if available. 42 | type LLMResponse struct { 43 | Content *genai.Content 44 | CitationMetadata *genai.CitationMetadata 45 | GroundingMetadata *genai.GroundingMetadata 46 | UsageMetadata *genai.GenerateContentResponseUsageMetadata 47 | CustomMetadata map[string]any 48 | LogprobsResult *genai.LogprobsResult 49 | // Partial indicates whether the content is part of a unfinished content stream. 50 | // Only used for streaming mode and when the content is plain text. 51 | Partial bool 52 | // Indicates whether the response from the model is complete. 53 | // Only used for streaming mode. 54 | TurnComplete bool 55 | // Flag indicating that LLM was interrupted when generating the content. 56 | // Usually it is due to user interruption during a bidi streaming. 57 | Interrupted bool 58 | ErrorCode string 59 | ErrorMessage string 60 | FinishReason genai.FinishReason 61 | AvgLogprobs float64 62 | } 63 | -------------------------------------------------------------------------------- /internal/toolinternal/toolutils/toolutils.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package tool defines internal-only interfaces and logic for tools. 16 | package toolutils 17 | 18 | import ( 19 | "fmt" 20 | 21 | "google.golang.org/genai" 22 | 23 | "google.golang.org/adk/model" 24 | ) 25 | 26 | type Tool interface { 27 | Name() string 28 | Declaration() *genai.FunctionDeclaration 29 | } 30 | 31 | // The PackTool ensures that in case there is a usage of multiple function tools, 32 | // all of them are consolidated into one genai tool that has all the function declarations 33 | // provided by the tools. So, if there is already a tool with a function declaration, 34 | // it appends another to it; otherwise, it creates a new genai tool. 35 | func PackTool(req *model.LLMRequest, tool Tool) error { 36 | if req.Tools == nil { 37 | req.Tools = make(map[string]any) 38 | } 39 | 40 | name := tool.Name() 41 | 42 | if _, ok := req.Tools[name]; ok { 43 | return fmt.Errorf("duplicate tool: %q", name) 44 | } 45 | req.Tools[name] = tool 46 | 47 | if req.Config == nil { 48 | req.Config = &genai.GenerateContentConfig{} 49 | } 50 | if decl := tool.Declaration(); decl == nil { 51 | return nil 52 | } 53 | // Find an existing genai.Tool with FunctionDeclarations 54 | var funcTool *genai.Tool 55 | for _, tool := range req.Config.Tools { 56 | if tool != nil && tool.FunctionDeclarations != nil { 57 | funcTool = tool 58 | break 59 | } 60 | } 61 | if funcTool == nil { 62 | req.Config.Tools = append(req.Config.Tools, &genai.Tool{ 63 | FunctionDeclarations: []*genai.FunctionDeclaration{tool.Declaration()}, 64 | }) 65 | } else { 66 | funcTool.FunctionDeclarations = append(funcTool.FunctionDeclarations, tool.Declaration()) 67 | } 68 | return nil 69 | } 70 | -------------------------------------------------------------------------------- /internal/llminternal/converters/converters.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package converters 16 | 17 | import ( 18 | "google.golang.org/genai" 19 | 20 | "google.golang.org/adk/model" 21 | ) 22 | 23 | func Genai2LLMResponse(res *genai.GenerateContentResponse) *model.LLMResponse { 24 | usageMetadata := res.UsageMetadata 25 | if len(res.Candidates) > 0 && res.Candidates[0] != nil { 26 | candidate := res.Candidates[0] 27 | if candidate.Content != nil && len(candidate.Content.Parts) > 0 { 28 | return &model.LLMResponse{ 29 | Content: candidate.Content, 30 | GroundingMetadata: candidate.GroundingMetadata, 31 | FinishReason: candidate.FinishReason, 32 | CitationMetadata: candidate.CitationMetadata, 33 | AvgLogprobs: candidate.AvgLogprobs, 34 | LogprobsResult: candidate.LogprobsResult, 35 | UsageMetadata: usageMetadata, 36 | } 37 | } 38 | return &model.LLMResponse{ 39 | ErrorCode: string(candidate.FinishReason), 40 | ErrorMessage: candidate.FinishMessage, 41 | GroundingMetadata: candidate.GroundingMetadata, 42 | FinishReason: candidate.FinishReason, 43 | CitationMetadata: candidate.CitationMetadata, 44 | AvgLogprobs: candidate.AvgLogprobs, 45 | LogprobsResult: candidate.LogprobsResult, 46 | UsageMetadata: usageMetadata, 47 | } 48 | 49 | } 50 | if res.PromptFeedback != nil { 51 | return &model.LLMResponse{ 52 | ErrorCode: string(res.PromptFeedback.BlockReason), 53 | ErrorMessage: res.PromptFeedback.BlockReasonMessage, 54 | UsageMetadata: usageMetadata, 55 | } 56 | } 57 | return &model.LLMResponse{ 58 | ErrorCode: "UNKNOWN_ERROR", 59 | ErrorMessage: "Unknown error.", 60 | UsageMetadata: usageMetadata, 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /server/adkrest/handler.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package adkrest 16 | 17 | import ( 18 | "net/http" 19 | "time" 20 | 21 | "github.com/gorilla/mux" 22 | sdktrace "go.opentelemetry.io/otel/sdk/trace" 23 | 24 | "google.golang.org/adk/cmd/launcher" 25 | "google.golang.org/adk/internal/telemetry" 26 | "google.golang.org/adk/server/adkrest/controllers" 27 | "google.golang.org/adk/server/adkrest/internal/routers" 28 | "google.golang.org/adk/server/adkrest/internal/services" 29 | ) 30 | 31 | // NewHandler creates and returns an http.Handler for the ADK REST API. 32 | func NewHandler(config *launcher.Config, sseWriteTimeout time.Duration) http.Handler { 33 | adkExporter := services.NewAPIServerSpanExporter() 34 | telemetry.AddSpanProcessor(sdktrace.NewSimpleSpanProcessor(adkExporter)) 35 | 36 | router := mux.NewRouter().StrictSlash(true) 37 | // TODO: Allow taking a prefix to allow customizing the path 38 | // where the ADK REST API will be served. 39 | setupRouter(router, 40 | routers.NewSessionsAPIRouter(controllers.NewSessionsAPIController(config.SessionService)), 41 | routers.NewRuntimeAPIRouter(controllers.NewRuntimeAPIController(config.SessionService, config.AgentLoader, config.ArtifactService, sseWriteTimeout)), 42 | routers.NewAppsAPIRouter(controllers.NewAppsAPIController(config.AgentLoader)), 43 | routers.NewDebugAPIRouter(controllers.NewDebugAPIController(config.SessionService, config.AgentLoader, adkExporter)), 44 | routers.NewArtifactsAPIRouter(controllers.NewArtifactsAPIController(config.ArtifactService)), 45 | &routers.EvalAPIRouter{}, 46 | ) 47 | return router 48 | } 49 | 50 | func setupRouter(router *mux.Router, subrouters ...routers.Router) *mux.Router { 51 | routers.SetupSubRouters(router, subrouters...) 52 | return router 53 | } 54 | -------------------------------------------------------------------------------- /cmd/launcher/web/webui/distr/assets/ADK-512-color.svg: -------------------------------------------------------------------------------- 1 | 10 | -------------------------------------------------------------------------------- /server/adkrest/internal/routers/artifacts.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package routers 16 | 17 | import ( 18 | "net/http" 19 | 20 | "google.golang.org/adk/server/adkrest/controllers" 21 | ) 22 | 23 | // ArtifactsAPIRouter defines the routes for the Artifacts API. 24 | type ArtifactsAPIRouter struct { 25 | artifactsController *controllers.ArtifactsAPIController 26 | } 27 | 28 | // NewArtifactsAPIRouter creates a new ArtifactsAPIRouter. 29 | func NewArtifactsAPIRouter(controller *controllers.ArtifactsAPIController) *ArtifactsAPIRouter { 30 | return &ArtifactsAPIRouter{artifactsController: controller} 31 | } 32 | 33 | // Routes returns the routes for the Artifacts API. 34 | func (r *ArtifactsAPIRouter) Routes() Routes { 35 | return Routes{ 36 | Route{ 37 | Name: "ListArtifacts", 38 | Methods: []string{http.MethodGet}, 39 | Pattern: "/apps/{app_name}/users/{user_id}/sessions/{session_id}/artifacts", 40 | HandlerFunc: r.artifactsController.ListArtifactsHandler, 41 | }, 42 | Route{ 43 | Name: "LoadArtifact", 44 | Methods: []string{http.MethodGet}, 45 | Pattern: "/apps/{app_name}/users/{user_id}/sessions/{session_id}/artifacts/{artifact_name}", 46 | HandlerFunc: r.artifactsController.LoadArtifactHandler, 47 | }, 48 | Route{ 49 | Name: "LoadArtifact", 50 | Methods: []string{http.MethodGet}, 51 | Pattern: "/apps/{app_name}/users/{user_id}/sessions/{session_id}/artifacts/{artifact_name}/versions/{version}", 52 | HandlerFunc: r.artifactsController.LoadArtifactVersionHandler, 53 | }, 54 | Route{ 55 | Name: "DeleteArtifact", 56 | Methods: []string{http.MethodDelete, http.MethodOptions}, 57 | Pattern: "/apps/{app_name}/users/{user_id}/sessions/{session_id}/artifacts/{artifact_name}", 58 | HandlerFunc: r.artifactsController.DeleteArtifactHandler, 59 | }, 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /examples/workflowagents/loop/main.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package demonstrates a workflow agent that runs a loop agent. 16 | package main 17 | 18 | import ( 19 | "context" 20 | "iter" 21 | "log" 22 | "os" 23 | 24 | "google.golang.org/genai" 25 | 26 | "google.golang.org/adk/agent" 27 | "google.golang.org/adk/agent/workflowagents/loopagent" 28 | "google.golang.org/adk/cmd/launcher" 29 | "google.golang.org/adk/cmd/launcher/full" 30 | "google.golang.org/adk/model" 31 | "google.golang.org/adk/session" 32 | ) 33 | 34 | func CustomAgentRun(ctx agent.InvocationContext) iter.Seq2[*session.Event, error] { 35 | return func(yield func(*session.Event, error) bool) { 36 | yield(&session.Event{ 37 | LLMResponse: model.LLMResponse{ 38 | Content: &genai.Content{ 39 | Parts: []*genai.Part{ 40 | { 41 | Text: "Hello from MyAgent!\n", 42 | }, 43 | }, 44 | }, 45 | }, 46 | }, nil) 47 | } 48 | } 49 | 50 | func main() { 51 | ctx := context.Background() 52 | 53 | customAgent, err := agent.New(agent.Config{ 54 | Name: "my_custom_agent", 55 | Description: "A custom agent that responds with a greeting.", 56 | Run: CustomAgentRun, 57 | }) 58 | if err != nil { 59 | log.Fatalf("Failed to create agent: %v", err) 60 | } 61 | 62 | loopAgent, err := loopagent.New(loopagent.Config{ 63 | MaxIterations: 3, 64 | AgentConfig: agent.Config{ 65 | Name: "loop_agent", 66 | Description: "A loop agent that runs sub-agents", 67 | SubAgents: []agent.Agent{customAgent}, 68 | }, 69 | }) 70 | if err != nil { 71 | log.Fatalf("Failed to create agent: %v", err) 72 | } 73 | 74 | config := &launcher.Config{ 75 | AgentLoader: agent.NewSingleLoader(loopAgent), 76 | } 77 | 78 | l := full.NewLauncher() 79 | if err = l.Execute(ctx, config, os.Args[1:]); err != nil { 80 | log.Fatalf("Run failed: %v\n\n%s", err, l.CommandLineSyntax()) 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /tool/geminitool/tool.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package geminitool provides access to Gemini native tools. You can use any 16 | // tool from genai with geminitool.New(). 17 | // 18 | // For example, to create a Gemini retrieval tool: 19 | // 20 | // geminitool.New("data_retrieval", &genai.Tool{ 21 | // Retrieval: &genai.Retrieval{ 22 | // ExternalAPI: &genai.ExternalAPI{ 23 | // Endpoint: , 24 | // AuthConfig: 25 | // }, 26 | // }, 27 | // }) 28 | // 29 | // Package also provides default tools like GoogleSearch. 30 | package geminitool 31 | 32 | import ( 33 | "fmt" 34 | 35 | "google.golang.org/genai" 36 | 37 | "google.golang.org/adk/model" 38 | "google.golang.org/adk/tool" 39 | ) 40 | 41 | // New creates gemini API tool. 42 | func New(name string, t *genai.Tool) tool.Tool { 43 | return &geminiTool{ 44 | name: name, 45 | value: t, 46 | } 47 | } 48 | 49 | // geminiTool is a wrapper around a genai.Tool. 50 | type geminiTool struct { 51 | name string 52 | value *genai.Tool 53 | } 54 | 55 | // ProcessRequest adds the Gemini tool to the LLM request. 56 | func (t *geminiTool) ProcessRequest(ctx tool.Context, req *model.LLMRequest) error { 57 | return setTool(req, t.value) 58 | } 59 | 60 | // Name implements tool.Tool. 61 | func (t *geminiTool) Name() string { 62 | return t.name 63 | } 64 | 65 | // Description implements tool.Tool. 66 | func (t *geminiTool) Description() string { 67 | return "Performs a Google search to retrieve information from the web." 68 | } 69 | 70 | // IsLongRunning implements tool.Tool. 71 | func (t *geminiTool) IsLongRunning() bool { 72 | return false 73 | } 74 | 75 | func setTool(req *model.LLMRequest, t *genai.Tool) error { 76 | if req == nil { 77 | return fmt.Errorf("llm request is nil") 78 | } 79 | 80 | if req.Config == nil { 81 | req.Config = &genai.GenerateContentConfig{} 82 | } 83 | 84 | req.Config.Tools = append(req.Config.Tools, t) 85 | return nil 86 | } 87 | -------------------------------------------------------------------------------- /internal/context/invocation_context.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package context 16 | 17 | import ( 18 | "context" 19 | 20 | "github.com/google/uuid" 21 | "google.golang.org/genai" 22 | 23 | "google.golang.org/adk/agent" 24 | "google.golang.org/adk/session" 25 | ) 26 | 27 | type InvocationContextParams struct { 28 | Artifacts agent.Artifacts 29 | Memory agent.Memory 30 | Session session.Session 31 | 32 | Branch string 33 | Agent agent.Agent 34 | 35 | UserContent *genai.Content 36 | RunConfig *agent.RunConfig 37 | EndInvocation bool 38 | } 39 | 40 | func NewInvocationContext(ctx context.Context, params InvocationContextParams) agent.InvocationContext { 41 | return &InvocationContext{ 42 | Context: ctx, 43 | params: params, 44 | invocationID: "e-" + uuid.NewString(), 45 | } 46 | } 47 | 48 | type InvocationContext struct { 49 | context.Context 50 | 51 | params InvocationContextParams 52 | invocationID string 53 | } 54 | 55 | func (c *InvocationContext) Artifacts() agent.Artifacts { 56 | return c.params.Artifacts 57 | } 58 | 59 | func (c *InvocationContext) Agent() agent.Agent { 60 | return c.params.Agent 61 | } 62 | 63 | func (c *InvocationContext) Branch() string { 64 | return c.params.Branch 65 | } 66 | 67 | func (c *InvocationContext) InvocationID() string { 68 | return c.invocationID 69 | } 70 | 71 | func (c *InvocationContext) Memory() agent.Memory { 72 | return c.params.Memory 73 | } 74 | 75 | func (c *InvocationContext) Session() session.Session { 76 | return c.params.Session 77 | } 78 | 79 | func (c *InvocationContext) UserContent() *genai.Content { 80 | return c.params.UserContent 81 | } 82 | 83 | func (c *InvocationContext) RunConfig() *agent.RunConfig { 84 | return c.params.RunConfig 85 | } 86 | 87 | func (c *InvocationContext) EndInvocation() { 88 | c.params.EndInvocation = true 89 | } 90 | 91 | func (c *InvocationContext) Ended() bool { 92 | return c.params.EndInvocation 93 | } 94 | -------------------------------------------------------------------------------- /server/adkrest/internal/routers/sessions.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package routers 16 | 17 | import ( 18 | "net/http" 19 | 20 | "google.golang.org/adk/server/adkrest/controllers" 21 | ) 22 | 23 | // SessionsAPIRouter defines the routes for the Sessions API. 24 | type SessionsAPIRouter struct { 25 | sessionController *controllers.SessionsAPIController 26 | } 27 | 28 | // NewSessionsAPIRouter creates a new SessionsAPIRouter. 29 | func NewSessionsAPIRouter(controller *controllers.SessionsAPIController) *SessionsAPIRouter { 30 | return &SessionsAPIRouter{sessionController: controller} 31 | } 32 | 33 | // Routes returns the routes for the Sessions API. 34 | func (r *SessionsAPIRouter) Routes() Routes { 35 | return Routes{ 36 | Route{ 37 | Name: "GetSession", 38 | Methods: []string{http.MethodGet}, 39 | Pattern: "/apps/{app_name}/users/{user_id}/sessions/{session_id}", 40 | HandlerFunc: r.sessionController.GetSessionHandler, 41 | }, 42 | Route{ 43 | Name: "CreateSession", 44 | Methods: []string{http.MethodPost}, 45 | Pattern: "/apps/{app_name}/users/{user_id}/sessions", 46 | HandlerFunc: r.sessionController.CreateSessionHandler, 47 | }, 48 | Route{ 49 | Name: "CreateSessionWithId", 50 | Methods: []string{http.MethodPost}, 51 | Pattern: "/apps/{app_name}/users/{user_id}/sessions/{session_id}", 52 | HandlerFunc: r.sessionController.CreateSessionHandler, 53 | }, 54 | Route{ 55 | Name: "DeleteSession", 56 | Methods: []string{http.MethodDelete, http.MethodOptions}, 57 | Pattern: "/apps/{app_name}/users/{user_id}/sessions/{session_id}", 58 | HandlerFunc: r.sessionController.DeleteSessionHandler, 59 | }, 60 | Route{ 61 | Name: "ListSessions", 62 | Methods: []string{http.MethodGet}, 63 | Pattern: "/apps/{app_name}/users/{user_id}/sessions", 64 | HandlerFunc: r.sessionController.ListSessionsHandler, 65 | }, 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /internal/agent/parentmap/map.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package parentmap 16 | 17 | import ( 18 | "context" 19 | "fmt" 20 | 21 | "google.golang.org/adk/agent" 22 | ) 23 | 24 | type Map map[string]agent.Agent 25 | 26 | // New creates parent map allowing to fetch agent's parent. 27 | // It ensures that agent can have at most one parent. 28 | // It ensures that the root node name is not referenced again in the agent tree 29 | func New(root agent.Agent) (Map, error) { 30 | res := make(map[string]agent.Agent) 31 | rootName := root.Name() 32 | pointerMap := map[agent.Agent]string{root: "is root agent"} 33 | 34 | var f func(cur agent.Agent) error 35 | f = func(cur agent.Agent) error { 36 | for _, subAgent := range cur.SubAgents() { 37 | if p, ok := pointerMap[subAgent]; ok { 38 | return fmt.Errorf("%q agent cannot have >1 parents, found: %q, %q", subAgent.Name(), p, cur.Name()) 39 | } 40 | if _, ok := res[subAgent.Name()]; ok || subAgent.Name() == rootName { 41 | return fmt.Errorf("agent names must be unique in the agent tree, found duplicate: %q", subAgent.Name()) 42 | } 43 | res[subAgent.Name()] = cur 44 | pointerMap[subAgent] = cur.Name() 45 | 46 | if err := f(subAgent); err != nil { 47 | return err 48 | } 49 | } 50 | return nil 51 | } 52 | 53 | return res, f(root) 54 | } 55 | 56 | // RootAgent returns the root of the agent tree. 57 | func (m Map) RootAgent(cur agent.Agent) agent.Agent { 58 | if cur == nil { 59 | return nil 60 | } 61 | for { 62 | parent := m[cur.Name()] 63 | if parent == nil { 64 | return cur 65 | } 66 | cur = parent 67 | } 68 | } 69 | 70 | func ToContext(ctx context.Context, parents Map) context.Context { 71 | return context.WithValue(ctx, mapCtxKey, parents) 72 | } 73 | 74 | func FromContext(ctx context.Context) Map { 75 | m, ok := ctx.Value(mapCtxKey).(Map) 76 | if !ok { 77 | return nil 78 | } 79 | return m 80 | } 81 | 82 | type ctxKey int 83 | 84 | const mapCtxKey ctxKey = 0 85 | -------------------------------------------------------------------------------- /internal/sessioninternal/mutablesession.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package sessioninternal 16 | 17 | import ( 18 | "fmt" 19 | "iter" 20 | "time" 21 | 22 | "google.golang.org/adk/session" 23 | ) 24 | 25 | // MutableSession implements session.Session 26 | type MutableSession struct { 27 | service session.Service 28 | storedSession session.Session 29 | } 30 | 31 | // NewMutableSession creates and returns session.Session implementation. 32 | func NewMutableSession(service session.Service, storedSession session.Session) *MutableSession { 33 | return &MutableSession{ 34 | service: service, 35 | storedSession: storedSession, 36 | } 37 | } 38 | 39 | func (s *MutableSession) State() session.State { 40 | return s 41 | } 42 | 43 | func (s *MutableSession) AppName() string { 44 | return s.storedSession.AppName() 45 | } 46 | 47 | func (s *MutableSession) UserID() string { 48 | return s.storedSession.UserID() 49 | } 50 | 51 | func (s *MutableSession) ID() string { 52 | return s.storedSession.ID() 53 | } 54 | 55 | func (s *MutableSession) Events() session.Events { 56 | return s.storedSession.Events() 57 | } 58 | 59 | func (s *MutableSession) LastUpdateTime() time.Time { 60 | return s.storedSession.LastUpdateTime() 61 | } 62 | 63 | func (s *MutableSession) Get(key string) (any, error) { 64 | value, err := s.storedSession.State().Get(key) 65 | if err != nil { 66 | return nil, fmt.Errorf("failed to get key %q from state: %w", key, err) 67 | } 68 | return value, nil 69 | } 70 | 71 | func (s *MutableSession) All() iter.Seq2[string, any] { 72 | return s.storedSession.State().All() 73 | } 74 | 75 | func (s *MutableSession) Set(key string, value any) error { 76 | mutableState, ok := s.storedSession.State().(MutableState) 77 | if !ok { 78 | return fmt.Errorf("this session state is not mutable") 79 | } 80 | if err := mutableState.Set(key, value); err != nil { 81 | return fmt.Errorf("failed to set key %q in state: %w", key, err) 82 | } 83 | return nil 84 | } 85 | -------------------------------------------------------------------------------- /cmd/launcher/launcher.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package launcher provides ways to interact with agents. 16 | package launcher 17 | 18 | import ( 19 | "context" 20 | 21 | "github.com/a2aproject/a2a-go/a2asrv" 22 | 23 | "google.golang.org/adk/agent" 24 | "google.golang.org/adk/artifact" 25 | "google.golang.org/adk/memory" 26 | "google.golang.org/adk/session" 27 | ) 28 | 29 | // Launcher is the main interface for running an ADK application. 30 | // It is responsible for parsing command-line arguments and executing the 31 | // corresponding logic. 32 | type Launcher interface { 33 | // Execute parses command-line arguments and runs the launcher. 34 | Execute(ctx context.Context, config *Config, args []string) error 35 | // CommandLineSyntax returns a string describing the command-line flags and arguments. 36 | CommandLineSyntax() string 37 | } 38 | 39 | // SubLauncher is an interface for launchers that can be composed within a parent 40 | // launcher, like the universal launcher. Each SubLauncher corresponds to a 41 | // specific mode of operation (e.g., 'console' or 'web'). 42 | type SubLauncher interface { 43 | // Keyword returns the command-line keyword that activates this sub-launcher. 44 | Keyword() string 45 | // Parse parses the arguments for the sub-launcher. It should return any unparsed arguments. 46 | Parse(args []string) ([]string, error) 47 | // CommandLineSyntax returns a string describing the command-line flags and arguments for the sub-launcher. 48 | CommandLineSyntax() string 49 | // SimpleDescription provides a brief, one-line description of the sub-launcher's function. 50 | SimpleDescription() string 51 | // Run executes the sub-launcher's main logic. 52 | Run(ctx context.Context, config *Config) error 53 | } 54 | 55 | // Config contains parameters for web & console execution: sessions, artifacts, agents etc 56 | type Config struct { 57 | SessionService session.Service 58 | ArtifactService artifact.Service 59 | MemoryService memory.Service 60 | AgentLoader agent.Loader 61 | A2AOptions []a2asrv.RequestHandlerOption 62 | } 63 | -------------------------------------------------------------------------------- /internal/sessionutils/utils.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package sessionutils 16 | 17 | import ( 18 | "maps" 19 | "strings" 20 | ) 21 | 22 | const ( 23 | appPrefix = "app:" 24 | userPrefix = "user:" 25 | tempPrefix = "temp:" 26 | ) 27 | 28 | // ExtractStateDeltas splits a single state delta map into three separate maps 29 | // for app, user, and session states based on key prefixes. 30 | // Temporary keys (starting with TempStatePrefix) are ignored. 31 | func ExtractStateDeltas(delta map[string]any) ( 32 | appStateDelta, userStateDelta, sessionStateDelta map[string]any, 33 | ) { 34 | // Initialize the maps to be returned. 35 | appStateDelta = make(map[string]any) 36 | userStateDelta = make(map[string]any) 37 | sessionStateDelta = make(map[string]any) 38 | 39 | if delta == nil { 40 | return appStateDelta, userStateDelta, sessionStateDelta 41 | } 42 | 43 | for key, value := range delta { 44 | if cleanKey, found := strings.CutPrefix(key, appPrefix); found { 45 | appStateDelta[cleanKey] = value 46 | } else if cleanKey, found := strings.CutPrefix(key, userPrefix); found { 47 | userStateDelta[cleanKey] = value 48 | } else if !strings.HasPrefix(key, tempPrefix) { 49 | // This key belongs to the session state, as long as it's not temporary. 50 | sessionStateDelta[key] = value 51 | } 52 | } 53 | return appStateDelta, userStateDelta, sessionStateDelta 54 | } 55 | 56 | // MergeStates combines app, user, and session state maps into a single map 57 | // for client-side responses, adding the appropriate prefixes back. 58 | func MergeStates(appState, userState, sessionState map[string]any) map[string]any { 59 | // Pre-allocate map capacity for efficiency. 60 | totalSize := len(appState) + len(userState) + len(sessionState) 61 | mergedState := make(map[string]any, totalSize) 62 | 63 | maps.Copy(mergedState, sessionState) 64 | 65 | for key, value := range appState { 66 | mergedState[appPrefix+key] = value 67 | } 68 | 69 | for key, value := range userState { 70 | mergedState[userPrefix+key] = value 71 | } 72 | 73 | return mergedState 74 | } 75 | -------------------------------------------------------------------------------- /tool/geminitool/tool_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package geminitool_test 16 | 17 | import ( 18 | "testing" 19 | 20 | "github.com/google/go-cmp/cmp" 21 | "google.golang.org/genai" 22 | 23 | "google.golang.org/adk/internal/toolinternal" 24 | "google.golang.org/adk/model" 25 | "google.golang.org/adk/tool/geminitool" 26 | ) 27 | 28 | func TestGeminiTool_ProcessRequest(t *testing.T) { 29 | testCases := []struct { 30 | name string 31 | inputTool *genai.Tool 32 | req *model.LLMRequest 33 | wantTools []*genai.Tool 34 | wantErr bool 35 | }{ 36 | { 37 | name: "add to empty request", 38 | inputTool: &genai.Tool{ 39 | GoogleSearch: &genai.GoogleSearch{}, 40 | }, 41 | req: &model.LLMRequest{}, 42 | wantTools: []*genai.Tool{ 43 | {GoogleSearch: &genai.GoogleSearch{}}, 44 | }, 45 | }, 46 | { 47 | name: "add to existing tools", 48 | inputTool: &genai.Tool{ 49 | GoogleSearch: &genai.GoogleSearch{}, 50 | }, 51 | req: &model.LLMRequest{ 52 | Config: &genai.GenerateContentConfig{ 53 | Tools: []*genai.Tool{ 54 | { 55 | GoogleMaps: &genai.GoogleMaps{}, 56 | }, 57 | }, 58 | }, 59 | }, 60 | wantTools: []*genai.Tool{ 61 | {GoogleMaps: &genai.GoogleMaps{}}, 62 | {GoogleSearch: &genai.GoogleSearch{}}, 63 | }, 64 | }, 65 | { 66 | name: "error on nil request", 67 | wantErr: true, 68 | }, 69 | } 70 | 71 | for _, tt := range testCases { 72 | t.Run(tt.name, func(t *testing.T) { 73 | geminiTool := geminitool.New("test_tool", tt.inputTool) 74 | 75 | requestProcessor, ok := geminiTool.(toolinternal.RequestProcessor) 76 | if !ok { 77 | t.Fatal("geminiTool does not implement RequestProcessor") 78 | } 79 | 80 | err := requestProcessor.ProcessRequest(nil, tt.req) 81 | if (err != nil) != tt.wantErr { 82 | t.Fatalf("ProcessRequest() error = %v, wantErr %v", err, tt.wantErr) 83 | } 84 | if tt.wantErr { 85 | return 86 | } 87 | 88 | if diff := cmp.Diff(tt.wantTools, tt.req.Config.Tools); diff != "" { 89 | t.Errorf("ProcessRequest returned unexpected tools (-want +got):\n%s", diff) 90 | } 91 | }) 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /agent/loader_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package agent 16 | 17 | import ( 18 | "iter" 19 | "testing" 20 | 21 | "google.golang.org/adk/session" 22 | ) 23 | 24 | var _ Agent = (*testAgent)(nil) 25 | 26 | type testAgent struct { 27 | name string 28 | } 29 | 30 | func (a *testAgent) Name() string { 31 | return a.name 32 | } 33 | 34 | func (a *testAgent) Description() string { 35 | panic("not implemented") 36 | } 37 | 38 | func (a *testAgent) Run(InvocationContext) iter.Seq2[*session.Event, error] { 39 | panic("not implemented") 40 | } 41 | 42 | func (a *testAgent) SubAgents() []Agent { 43 | panic("not implemented") 44 | } 45 | 46 | func (a *testAgent) internal() *agent { 47 | panic("not implemented") 48 | } 49 | 50 | func TestDuplicateName(t *testing.T) { 51 | agent1 := &testAgent{name: "weather_time_agent"} 52 | // duplicate name 53 | agent2 := &testAgent{name: "weather_time_agent"} 54 | agent3 := &testAgent{name: "unique"} 55 | 56 | tests := []struct { 57 | name string 58 | root Agent 59 | agents []Agent 60 | wantErr bool 61 | }{ 62 | { 63 | name: "root only", 64 | root: agent1, 65 | agents: []Agent{}, 66 | wantErr: false, 67 | }, 68 | { 69 | name: "root duplicate object", 70 | root: agent1, 71 | agents: []Agent{agent1}, 72 | wantErr: true, 73 | }, 74 | { 75 | name: "root duplicate name", 76 | root: agent1, 77 | agents: []Agent{agent2}, 78 | wantErr: true, 79 | }, 80 | { 81 | name: "non-root duplicate name", 82 | root: agent3, 83 | agents: []Agent{agent1, agent2}, 84 | wantErr: true, 85 | }, 86 | { 87 | name: "non-root duplicate object", 88 | root: agent3, 89 | agents: []Agent{agent1, agent1}, 90 | wantErr: true, 91 | }, 92 | { 93 | name: "no duplicates", 94 | root: agent1, 95 | agents: []Agent{agent3}, 96 | wantErr: false, 97 | }, 98 | } 99 | for _, tt := range tests { 100 | _, err := NewMultiLoader(tt.root, tt.agents...) 101 | if (err != nil) != tt.wantErr { 102 | t.Errorf("NewMultiLoader() name=%v, error = %v, wantErr %v", tt.name, err, tt.wantErr) 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /server/adkrest/internal/services/apiserverspanexporter.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | package services 16 | 17 | import ( 18 | "context" 19 | "strings" 20 | 21 | sdktrace "go.opentelemetry.io/otel/sdk/trace" 22 | ) 23 | 24 | // APIServerSpanExporter is a custom SpanExporter that stores relevant span data. 25 | // Stores attributes of specific spans (call_llm, send_data, execute_tool) keyed by `gcp.vertex.agent.event_id`. 26 | // This is used for debugging individual events. 27 | // APIServerSpanExporter implements sdktrace.SpanExporter interface. 28 | type APIServerSpanExporter struct { 29 | traceDict map[string]map[string]string 30 | } 31 | 32 | // NewAPIServerSpanExporter returns a APIServerSpanExporter instance 33 | func NewAPIServerSpanExporter() *APIServerSpanExporter { 34 | return &APIServerSpanExporter{ 35 | traceDict: make(map[string]map[string]string), 36 | } 37 | } 38 | 39 | // GetTraceDict returns stored trace informations 40 | func (s *APIServerSpanExporter) GetTraceDict() map[string]map[string]string { 41 | return s.traceDict 42 | } 43 | 44 | // ExportSpans implements custom export function for sdktrace.SpanExporter. 45 | func (s *APIServerSpanExporter) ExportSpans(ctx context.Context, spans []sdktrace.ReadOnlySpan) error { 46 | for _, span := range spans { 47 | if span.Name() == "call_llm" || span.Name() == "send_data" || strings.HasPrefix(span.Name(), "execute_tool") { 48 | spanAttributes := span.Attributes() 49 | attributes := make(map[string]string) 50 | for _, attribute := range spanAttributes { 51 | key := string(attribute.Key) 52 | attributes[key] = attribute.Value.AsString() 53 | } 54 | attributes["trace_id"] = span.SpanContext().TraceID().String() 55 | attributes["span_id"] = span.SpanContext().SpanID().String() 56 | if eventID, ok := attributes["gcp.vertex.agent.event_id"]; ok { 57 | s.traceDict[eventID] = attributes 58 | } 59 | } 60 | } 61 | return nil 62 | } 63 | 64 | // Shutdown is a function that sdktrace.SpanExporter has, should close the span exporter connections. 65 | // Since APIServerSpanExporter holds only in-memory dictionary, no additional logic required. 66 | func (s *APIServerSpanExporter) Shutdown(ctx context.Context) error { 67 | return nil 68 | } 69 | 70 | var _ sdktrace.SpanExporter = (*APIServerSpanExporter)(nil) 71 | -------------------------------------------------------------------------------- /examples/workflowagents/sequential/main.go: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Google LLC 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // Package demonstrates a workflow agent that runs sub-agents sequentially. 16 | package main 17 | 18 | import ( 19 | "context" 20 | "fmt" 21 | "iter" 22 | "log" 23 | "os" 24 | 25 | "google.golang.org/genai" 26 | 27 | "google.golang.org/adk/agent" 28 | "google.golang.org/adk/agent/workflowagents/sequentialagent" 29 | "google.golang.org/adk/cmd/launcher" 30 | "google.golang.org/adk/cmd/launcher/full" 31 | "google.golang.org/adk/model" 32 | "google.golang.org/adk/session" 33 | ) 34 | 35 | type myAgent struct { 36 | id int 37 | } 38 | 39 | func (a myAgent) Run(ctx agent.InvocationContext) iter.Seq2[*session.Event, error] { 40 | return func(yield func(*session.Event, error) bool) { 41 | yield(&session.Event{ 42 | LLMResponse: model.LLMResponse{ 43 | Content: &genai.Content{ 44 | Parts: []*genai.Part{ 45 | { 46 | Text: fmt.Sprintf("Hello from MyAgent id: %v!\n", a.id), 47 | }, 48 | }, 49 | }, 50 | }, 51 | }, nil) 52 | } 53 | } 54 | 55 | func main() { 56 | ctx := context.Background() 57 | 58 | myAgent1, err := agent.New(agent.Config{ 59 | Name: "my_custom_agent_1", 60 | Description: "A custom agent that responds with a greeting.", 61 | Run: myAgent{id: 1}.Run, 62 | }) 63 | if err != nil { 64 | log.Fatalf("Failed to create agent: %v", err) 65 | } 66 | 67 | myAgent2, err := agent.New(agent.Config{ 68 | Name: "my_custom_agent_2", 69 | Description: "A custom agent that responds with a greeting.", 70 | Run: myAgent{id: 2}.Run, 71 | }) 72 | if err != nil { 73 | log.Fatalf("Failed to create agent: %v", err) 74 | } 75 | 76 | sequentialAgent, err := sequentialagent.New(sequentialagent.Config{ 77 | AgentConfig: agent.Config{ 78 | Name: "sequential_agent", 79 | Description: "A sequential agent that runs sub-agents", 80 | SubAgents: []agent.Agent{myAgent1, myAgent2}, 81 | }, 82 | }) 83 | if err != nil { 84 | log.Fatalf("Failed to create agent: %v", err) 85 | } 86 | 87 | config := &launcher.Config{ 88 | AgentLoader: agent.NewSingleLoader(sequentialAgent), 89 | } 90 | 91 | l := full.NewLauncher() 92 | if err = l.Execute(ctx, config, os.Args[1:]); err != nil { 93 | log.Fatalf("Run failed: %v\n\n%s", err, l.CommandLineSyntax()) 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Agent Development Kit (ADK) for Go 2 | 3 | [](LICENSE) 4 | [](https://pkg.go.dev/google.golang.org/adk) 5 | [](https://github.com/google/adk-go/actions/workflows/nightly.yml) 6 | [](https://www.reddit.com/r/agentdevelopmentkit/) 7 | [](https://codewiki.google/github.com/google/adk-go) 8 | 9 | 10 |
12 |