Skip to content

loadartifactstool breaks Vertex AI session persistence due to []string in function response #668

@will-arxed

Description

@will-arxed

Required Information

Describe the Bug:

loadartifactstool.Run returns []string in its response map, which causes structpb.NewStruct to fail when the Vertex AI session service persists the function response event. structpb only supports []any, not typed slices like []string.

Steps to Reproduce:

  1. Register loadartifactstool.New() on an agent
  2. Register a separate tool that saves artifacts via toolCtx.Artifacts().Save()
  3. Configure the runner with a Vertex AI session service (session/vertexai)
  4. Send a message that causes the agent to call the artifact-saving tool, then load_artifacts
  5. Observe the error when the load_artifacts function response event is persisted:
AGENT_ERROR: failed to add event to session: failed to append event: error creating content: failed to convert function response to structpb: proto: invalid type: []string

Expected Behavior:

The load_artifacts function response event should persist successfully to the Vertex AI session service, and the agent should continue with the loaded artifact content.

Observed Behavior:

The invocation fails when structpb.NewStruct is called on the function response map containing []string (vertexai_client.go line 503).

The root cause is in loadartifactstool.Run (lines 112-114):

result := map[string]any{
    "artifact_names": artifactNames, // artifactNames is []string
}
return result, nil

structpb.NewValue (called internally by structpb.NewStruct) has a type switch that handles []any but not []string — any unmatched type falls through to the default case which returns "invalid type: %T".

Environment Details:

  • ADK Library Version: v0.6.0 (also present in v0.5.0)
  • OS: macOS (Darwin 25.3.0)
  • Go Version: 1.25

Model Information:

  • N/A (the bug is in tool response serialization, not model-specific)

Optional Information

Regression:

Unknown.

How often has this issue occurred?:

Always (100%) — any load_artifacts call triggers it when using the Vertex AI session service.

Minimal Reproduction Code:

package main

import (
	"fmt"
	"google.golang.org/protobuf/types/known/structpb"
)

func main() {
	// Exactly what loadartifactstool.Run returns:
	result := map[string]any{
		"artifact_names": []string{"a.pdf", "b.pdf"},
	}
	_, err := structpb.NewStruct(result)
	fmt.Println(err) // proto: invalid type: []string

	// The fix — use []any instead of []string:
	fixed := map[string]any{
		"artifact_names": []any{"a.pdf", "b.pdf"},
	}
	_, err = structpb.NewStruct(fixed)
	fmt.Println(err) // <nil>
}

Additional Context:

Suggested fix for loadartifactstool.Run — return []any instead of []string:

anyNames := make([]any, len(artifactNames))
for i, name := range artifactNames {
    anyNames[i] = name
}
result := map[string]any{
    "artifact_names": anyNames,
}

There is a secondary issue: even if Run is fixed to return []any, processLoadArtifactsFunctionCall (line 176) does a hard type assertion to []string. After a structpb round-trip (persist then reload), the value comes back as []interface{}, so that assertion would also fail. It should handle both []string and []any.

Metadata

Metadata

Labels

bugSomething isn't working

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions