Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
e93adfc
Add lookup entry tool
AnujJhunjhunwala Jul 25, 2025
0f4cb2f
Add aspect types parameter
AnujJhunjhunwala Jul 25, 2025
da9b407
Update descriptions
AnujJhunjhunwala Jul 25, 2025
f2910d5
Merge branch 'googleapis:main' into tool/dataplex-lookup-entry
AnujJhunjhunwala Jul 25, 2025
4471807
Merge branch 'googleapis:main' into tool/dataplex-lookup-entry
AnujJhunjhunwala Jul 26, 2025
fb03632
Add integration tests
AnujJhunjhunwala Jul 26, 2025
520447d
Remove references of unimplemented tools
AnujJhunjhunwala Jul 28, 2025
ec99481
Rephrase prebuilt dataplex yaml
AnujJhunjhunwala Jul 28, 2025
586791f
Rephrase view and aspectTypes arg desc
AnujJhunjhunwala Jul 28, 2025
b90bf4d
add agent instructions to gitignore
AnujJhunjhunwala Jul 28, 2025
a31d916
Add advanced example to lookup entry test
AnujJhunjhunwala Jul 29, 2025
0f55479
Remove name parmeter from initialization
AnujJhunjhunwala Jul 29, 2025
ad39bdc
Update integration tests with arg related tc
AnujJhunjhunwala Jul 29, 2025
305df98
Merge branch 'googleapis:main' into tool/dataplex-lookup-entry
AnujJhunjhunwala Jul 29, 2025
54639c4
Merge branch 'googleapis:main' into tool/dataplex-lookup-entry
AnujJhunjhunwala Jul 30, 2025
e6a8812
Remove instructions from .gitignore
AnujJhunjhunwala Jul 30, 2025
79767cb
Fix indentation in dataplex.md
AnujJhunjhunwala Jul 30, 2025
940933d
Add arg format and allowed values
AnujJhunjhunwala Jul 30, 2025
cf1c868
Rephrasing aspect types arg desc
AnujJhunjhunwala Jul 30, 2025
a115149
Update naming of tool struct
AnujJhunjhunwala Jul 31, 2025
2ca7d8e
Update case in dataplex.md
AnujJhunjhunwala Jul 31, 2025
a055631
Merge branch 'googleapis:main' into tool/dataplex-lookup-entry
AnujJhunjhunwala Jul 31, 2025
1897507
Merge branch 'main' into tool/dataplex-lookup-entry
duwenxin99 Jul 31, 2025
5e3328a
Add auth tcs to integration-tests
AnujJhunjhunwala Aug 1, 2025
65ca4c9
Merge branch 'main' into tool/dataplex-lookup-entry
duwenxin99 Aug 1, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 0 additions & 20 deletions cmd/BUILD

This file was deleted.

1 change: 1 addition & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import (
_ "github.com/googleapis/genai-toolbox/internal/tools/bigquery/bigquerysql"
_ "github.com/googleapis/genai-toolbox/internal/tools/bigtable"
_ "github.com/googleapis/genai-toolbox/internal/tools/couchbase"
_ "github.com/googleapis/genai-toolbox/internal/tools/dataplex/dataplexlookupentry"
_ "github.com/googleapis/genai-toolbox/internal/tools/dataplex/dataplexsearchentries"
_ "github.com/googleapis/genai-toolbox/internal/tools/dgraph"
_ "github.com/googleapis/genai-toolbox/internal/tools/duckdbsql"
Expand Down
2 changes: 1 addition & 1 deletion cmd/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1250,7 +1250,7 @@ func TestPrebuiltTools(t *testing.T) {
wantToolset: server.ToolsetConfigs{
"dataplex-tools": tools.ToolsetConfig{
Name: "dataplex-tools",
ToolNames: []string{"dataplex_search_entries"},
ToolNames: []string{"dataplex_search_entries", "dataplex_lookup_entry"},
},
},
},
Expand Down
226 changes: 217 additions & 9 deletions docs/en/resources/sources/dataplex.md

Large diffs are not rendered by default.

60 changes: 60 additions & 0 deletions docs/en/resources/tools/dataplex/dataplex-lookup-entry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
---
title: "dataplex-lookup-entry"
type: docs
weight: 1
description: >
A "dataplex-lookup-entry" tool returns details of a particular entry in Dataplex Catalog.
aliases:
- /resources/tools/dataplex-lookup-entry
---

## About

A `dataplex-lookup-entry` tool returns details of a particular entry in Dataplex Catalog.
It's compatible with the following sources:

- [dataplex](../sources/dataplex.md)

`dataplex-lookup-entry` takes a required `name` parameter which contains the project and location to which the request should be attributed in the following form: projects/{project}/locations/{location} and also a required `entry` parameter which is the resource name of the entry in the following form: projects/{project}/locations/{location}/entryGroups/{entryGroup}/entries/{entry}. It also optionally accepts following parameters:
- `view` - View to control which parts of an entry the service should return. It takes integer values from 1-4 corresponding to type of view - BASIC, FULL, CUSTOM, ALL
- `aspectTypes` - Limits the aspects returned to the provided aspect types in the format `projects/{project}/locations/{location}/aspectTypes/{aspectType}`. It only works for CUSTOM view.
- `paths` - Limits the aspects returned to those associated with the provided paths within the Entry. It only works for CUSTOM view.

## Requirements

### IAM Permissions

Dataplex uses [Identity and Access Management (IAM)][iam-overview] to control
user and group access to Dataplex resources. Toolbox will use your
[Application Default Credentials (ADC)][adc] to authorize and authenticate when
interacting with [Dataplex][dataplex-docs].

In addition to [setting the ADC for your server][set-adc], you need to ensure
the IAM identity has been given the correct IAM permissions for the tasks you
intend to perform. See [Dataplex Universal Catalog IAM permissions][iam-permissions]
and [Dataplex Universal Catalog IAM roles][iam-roles] for more information on
applying IAM permissions and roles to an identity.

[iam-overview]: https://cloud.google.com/dataplex/docs/iam-and-access-control
[adc]: https://cloud.google.com/docs/authentication#adc
[set-adc]: https://cloud.google.com/docs/authentication/provide-credentials-adc
[iam-permissions]: https://cloud.google.com/dataplex/docs/iam-permissions
[iam-roles]: https://cloud.google.com/dataplex/docs/iam-roles

## Example

```yaml
tools:
lookup_entry:
kind: dataplex-lookup-entry
source: my-dataplex-source
description: Use this tool to retrieve a specific entry in Dataplex Catalog.
```

## Reference

| **field** | **type** | **required** | **description** |
|-------------|:------------------------------------------:|:------------:|--------------------------------------------------------------------------------------------------|
| kind | string | true | Must be "dataplex-lookup-entry". |
| source | string | true | Name of the source the tool should execute on. |
| description | string | true | Description of the tool that is passed to the LLM. |
10 changes: 7 additions & 3 deletions internal/prebuiltconfigs/tools/dataplex.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,13 @@ tools:
dataplex_search_entries:
kind: dataplex-search-entries
source: dataplex-source
description: |
Use this tool to search for entries in Dataplex Catalog that represent data assets (e.g. tables, views, models) based on the provided search query.
description: Use this tool to search for entries in Dataplex Catalog based on the provided search query.
dataplex_lookup_entry:
kind: dataplex-lookup-entry
source: dataplex-source
description: Use this tool to retrieve a specific entry from Dataplex Catalog.

toolsets:
dataplex-tools:
- dataplex_search_entries
- dataplex_search_entries
- dataplex_lookup_entry
183 changes: 183 additions & 0 deletions internal/tools/dataplex/dataplexlookupentry/dataplexlookupentry.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package dataplexlookupentry

import (
"context"
"fmt"

dataplexapi "cloud.google.com/go/dataplex/apiv1"
dataplexpb "cloud.google.com/go/dataplex/apiv1/dataplexpb"
"github.com/goccy/go-yaml"
"github.com/googleapis/genai-toolbox/internal/sources"
dataplexds "github.com/googleapis/genai-toolbox/internal/sources/dataplex"
"github.com/googleapis/genai-toolbox/internal/tools"
)

const kind string = "dataplex-lookup-entry"

func init() {
if !tools.Register(kind, newConfig) {
panic(fmt.Sprintf("tool kind %q already registered", kind))
}
}

func newConfig(ctx context.Context, name string, decoder *yaml.Decoder) (tools.ToolConfig, error) {
actual := Config{Name: name}
if err := decoder.DecodeContext(ctx, &actual); err != nil {
return nil, err
}
return actual, nil
}

type compatibleSource interface {
CatalogClient() *dataplexapi.CatalogClient
}

// validate compatible sources are still compatible
var _ compatibleSource = &dataplexds.Source{}

var compatibleSources = [...]string{dataplexds.SourceKind}

type Config struct {
Name string `yaml:"name" validate:"required"`
Kind string `yaml:"kind" validate:"required"`
Source string `yaml:"source" validate:"required"`
Description string `yaml:"description"`
AuthRequired []string `yaml:"authRequired"`
Parameters tools.Parameters `yaml:"parameters"`
}

// validate interface
var _ tools.ToolConfig = Config{}

func (cfg Config) ToolConfigKind() string {
return kind
}

func (cfg Config) Initialize(srcs map[string]sources.Source) (tools.Tool, error) {
// Initialize the search configuration with the provided sources
rawS, ok := srcs[cfg.Source]
if !ok {
return nil, fmt.Errorf("no source named %q configured", cfg.Source)
}
// verify the source is compatible
s, ok := rawS.(compatibleSource)
if !ok {
return nil, fmt.Errorf("invalid source for %q tool: source kind must be one of %q", kind, compatibleSources)
}

viewDesc := `
## Argument: view

**Type:** Integer

**Description:** Specifies the parts of the entry and its aspects to return.

**Possible Values:**

* 1 (BASIC): Returns entry without aspects.
* 2 (FULL): Return all required aspects and the keys of non-required aspects. (Default)
* 3 (CUSTOM): Return the entry and aspects requested in aspect_types field (at most 100 aspects). Always use this view when aspect_types is not empty.
* 4 (ALL): Return the entry and both required and optional aspects (at most 100 aspects)
`

name := tools.NewStringParameter("name", "The project to which the request should be attributed in the following form: projects/{project}/locations/{location}.")
view := tools.NewIntParameterWithDefault("view", 2, viewDesc)
aspectTypes := tools.NewArrayParameterWithDefault("aspectTypes", []any{}, "Limits the aspects returned to the provided aspect types. It only works when used together with CUSTOM view.", tools.NewStringParameter("aspectType", "The types of aspects to be included in the response in the format `projects/{project}/locations/{location}/aspectTypes/{aspectType}`."))
entry := tools.NewStringParameter("entry", "The resource name of the Entry in the following form: projects/{project}/locations/{location}/entryGroups/{entryGroup}/entries/{entry}.")
parameters := tools.Parameters{name, view, aspectTypes, entry}

mcpManifest := tools.McpManifest{
Name: cfg.Name,
Description: cfg.Description,
InputSchema: parameters.McpManifest(),
}

t := &Tool{
Name: cfg.Name,
Kind: kind,
Parameters: parameters,
AuthRequired: cfg.AuthRequired,
CatalogClient: s.CatalogClient(),
manifest: tools.Manifest{
Description: cfg.Description,
Parameters: parameters.Manifest(),
AuthRequired: cfg.AuthRequired,
},
mcpManifest: mcpManifest,
}
return t, nil
}

type Tool struct {
Name string
Kind string
Parameters tools.Parameters
AuthRequired []string
CatalogClient *dataplexapi.CatalogClient
manifest tools.Manifest
mcpManifest tools.McpManifest
}

func (t *Tool) Authorized(verifiedAuthServices []string) bool {
return tools.IsAuthorized(t.AuthRequired, verifiedAuthServices)
}

func (t *Tool) Invoke(ctx context.Context, params tools.ParamValues) (any, error) {
paramsMap := params.AsMap()
viewMap := map[int]dataplexpb.EntryView{
1: dataplexpb.EntryView_BASIC,
2: dataplexpb.EntryView_FULL,
3: dataplexpb.EntryView_CUSTOM,
4: dataplexpb.EntryView_ALL,
}
name, _ := paramsMap["name"].(string)
entry, _ := paramsMap["entry"].(string)
view, _ := paramsMap["view"].(int)
aspectTypeSlice, err := tools.ConvertAnySliceToTyped(paramsMap["aspectTypes"].([]any), "string")
if err != nil {
return nil, fmt.Errorf("can't convert aspectTypes to array of strings: %s", err)
}
aspectTypes := aspectTypeSlice.([]string)

req := &dataplexpb.LookupEntryRequest{
Name: name,
View: viewMap[view],
AspectTypes: aspectTypes,
Entry: entry,
}

result, err := t.CatalogClient.LookupEntry(ctx, req)
if err != nil {
return nil, err
}
return result, nil
}

func (t *Tool) ParseParams(data map[string]any, claims map[string]map[string]any) (tools.ParamValues, error) {
// Parse parameters from the provided data
return tools.ParseParams(t.Parameters, data, claims)
}

func (t *Tool) Manifest() tools.Manifest {
// Returns the tool manifest
return t.manifest
}

func (t *Tool) McpManifest() tools.McpManifest {
// Returns the tool MCP manifest
return t.mcpManifest
}
Loading
Loading