ronantakizawa/codereview-bench huggingface dataset:
Repository: googleapis/genai-toolbox
File: internal/sources/cloudmonitoring/cloud_monitoring.go (Go)

Code before:
	"github.com/googleapis/genai-toolbox/internal/sources"
	"github.com/googleapis/genai-toolbox/internal/util"
	"go.opentelemetry.io/otel/trace"
	"golang.org/x/oauth2"
	"golang.org/x/oauth2/google"
	monitoring "google.golang.org/api/monitoring/v3"
)

const SourceKind string = "cloud-monitoring"

type userAgentRoundTripper struct {
	userAgent string
	next      http.RoundTripper
}

func (rt *userAgentRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
	newReq := *req
	newReq.Header = make(http.Header)
	for k, v := range req.Header {
		newReq.Header[k] = v
	}
	ua := newReq.Header.Get("User-Agent")
	if ua == "" {
		newReq.Header.Set("User-Agent", rt.userAgent)
	} else {
		newReq.Header.Set("User-Agent", rt.userAgent+" "+ua)
	}
	return rt.next.RoundTrip(&newReq)
}

// validate interface
var _ sources.SourceConfig = Config{}

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

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

type Config struct {
	Name           string `yaml:"name" validate:"required"`
	Kind           string `yaml:"kind" validate:"required"`
	UseClientOAuth bool   `yaml:"useClientOAuth"`

Review comment (bug):
Correct me if I'm wrong but seems like best practice when appending UA is to append to the back instead of the front? 

```suggestion
		newReq.Header.Set("User-Agent", ua+" "+rt.userAgent)
```

Code after:
	"github.com/googleapis/genai-toolbox/internal/sources"
	"github.com/googleapis/genai-toolbox/internal/util"
	"go.opentelemetry.io/otel/trace"
	"golang.org/x/oauth2"
	"golang.org/x/oauth2/google"
	monitoring "google.golang.org/api/monitoring/v3"
)

const SourceKind string = "cloud-monitoring"

type userAgentRoundTripper struct {
	userAgent string
	next      http.RoundTripper
}

func (rt *userAgentRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
	newReq := *req
	newReq.Header = make(http.Header)
	for k, v := range req.Header {
		newReq.Header[k] = v
	}
	ua := newReq.Header.Get("User-Agent")
	if ua == "" {
		newReq.Header.Set("User-Agent", rt.userAgent)
	} else {
		newReq.Header.Set("User-Agent", ua+" "+rt.userAgent)
	}
	return rt.next.RoundTrip(&newReq)
}

// validate interface
var _ sources.SourceConfig = Config{}

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

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

type Config struct {
	Name           string `yaml:"name" validate:"required"`
	Kind           string `yaml:"kind" validate:"required"`
	UseClientOAuth bool   `yaml:"useClientOAuth"`
Repository: googleapis/genai-toolbox
File: tests/prompts/custom/prompts_integration_test.go (Go)

Code before:
// 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 custom_test

import (
	"bytes"
	"context"
	"encoding/json"
	"io"
	"net/http"
	"regexp"
	"testing"
	"time"

	_ "github.com/googleapis/genai-toolbox/internal/prompts/custom"
	"github.com/googleapis/genai-toolbox/internal/server/mcp/jsonrpc"
	"github.com/googleapis/genai-toolbox/internal/testutils"
	"github.com/googleapis/genai-toolbox/tests"
)

func getPromptsConfig() map[string]any {
	return map[string]any{
		"prompts": map[string]any{
			"prompt1": map[string]any{
				"description": "description1.",
				"arguments": []any{
					map[string]any{
						"name":        "arg1",

Review comment (suggestion):
```suggestion
package custom
```

Maybe we can name it the same as the prompt package name? similar to how the source integration tests are done

Code after:
// 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 custom

import (
	"bytes"
	"context"
	"encoding/json"
	"io"
	"net/http"
	"regexp"
	"testing"
	"time"

	_ "github.com/googleapis/genai-toolbox/internal/prompts/custom"
	"github.com/googleapis/genai-toolbox/internal/server/mcp/jsonrpc"
	"github.com/googleapis/genai-toolbox/internal/testutils"
	"github.com/googleapis/genai-toolbox/tests"
)

func getPromptsConfig() map[string]any {
	return map[string]any{
		"prompts": map[string]any{
			"prompt1": map[string]any{
				"description": "description1.",
				"arguments": []any{
					map[string]any{
						"name":        "arg1",
Repository: googleapis/genai-toolbox
File: internal/sources/neo4j/neo4j.go (Go)

Code before:

func (s *Source) SourceKind() string {
	return SourceKind
}

func (s *Source) Neo4jDriver() neo4j.DriverWithContext {
	return s.Driver
}

func (s *Source) Neo4jDatabase() string {
	return s.Database
}

func initNeo4jDriver(ctx context.Context, tracer trace.Tracer, uri, user, password, name string) (neo4j.DriverWithContext, error) {
	//nolint:all // Reassigned ctx
	ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceKind, name)
	defer span.End()

	auth := neo4j.BasicAuth(user, password, "")
	driver, err := neo4j.NewDriverWithContext(uri, auth, func(config *neo4jconf.Config) {
		config.UserAgent = UserAgent
	})
	if err != nil {
		return nil, fmt.Errorf("unable to create connection driver: %w", err)
	}
	return driver, nil
}


Review comment (security):
```suggestion
	userAgent, err := util.UserAgentFromContext(ctx)
	if err != nil {
		return nil, err
	}
	driver, err := neo4j.NewDriverWithContext(uri, auth, func(config *neo4jconf.Config) {
		config.UserAgent = userAgent
	})
```

Code after:

func (s *Source) SourceKind() string {
	return SourceKind
}

func (s *Source) Neo4jDriver() neo4j.DriverWithContext {
	return s.Driver
}

func (s *Source) Neo4jDatabase() string {
	return s.Database
}

func initNeo4jDriver(ctx context.Context, tracer trace.Tracer, uri, user, password, name string) (neo4j.DriverWithContext, error) {
	//nolint:all // Reassigned ctx
	ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceKind, name)
	defer span.End()

	auth := neo4j.BasicAuth(user, password, "")
	userAgent, err := util.UserAgentFromContext(ctx)
	if err != nil {
		return nil, err
	}
	driver, err := neo4j.NewDriverWithContext(uri, auth, func(config *neo4jconf.Config) {
		config.UserAgent = userAgent
	})
	if err != nil {
		return nil, fmt.Errorf("unable to create connection driver: %w", err)
	}
	return driver, nil
}
Repository: googleapis/genai-toolbox
File: internal/tools/neo4j/neo4jexecutecypher/neo4jexecutecypher.go (Go)

Code before:

	return out, nil
}

func (t Tool) ParseParams(data map[string]any, claimsMap map[string]map[string]any) (tools.ParamValues, error) {
	return tools.ParseParams(t.Parameters, data, claimsMap)
}

func (t Tool) Manifest() tools.Manifest {
	return t.manifest
}

func (t Tool) McpManifest() tools.McpManifest {
	return t.mcpManifest
}

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

func (t Tool) RequiresClientAuthorization() bool {
	return false
}

// Recursive function to add plan children
func (t Tool) addPlanChildren(p neo4j.Plan) []map[string]any {
	var children []map[string]any
	for _, child := range p.Children() {
		childMap := map[string]any{
			"operator":       child.Operator(),
			"arguments":      child.Arguments(),
			"identifiers":    child.Identifiers(),
			"children_count": len(child.Children()),
		}
		if len(child.Children()) > 0 {
			childMap["children"] = t.addPlanChildren(child)
		}
		children = append(children, childMap)
	}
	return children
}


Review comment (suggestion):
```suggestion
func addPlanChildren(p neo4j.Plan) []map[string]any {
```

doesn't seem like this function will need to access the state of the Tool struct.

Code after:

	return out, nil
}

func (t Tool) ParseParams(data map[string]any, claimsMap map[string]map[string]any) (tools.ParamValues, error) {
	return tools.ParseParams(t.Parameters, data, claimsMap)
}

func (t Tool) Manifest() tools.Manifest {
	return t.manifest
}

func (t Tool) McpManifest() tools.McpManifest {
	return t.mcpManifest
}

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

func (t Tool) RequiresClientAuthorization() bool {
	return false
}

// Recursive function to add plan children
func addPlanChildren(p neo4j.Plan) []map[string]any {
	var children []map[string]any
	for _, child := range p.Children() {
		childMap := map[string]any{
			"operator":       child.Operator(),
			"arguments":      child.Arguments(),
			"identifiers":    child.Identifiers(),
			"children_count": len(child.Children()),
		}
		if len(child.Children()) > 0 {
			childMap["children"] = addPlanChildren(child)
		}
		children = append(children, childMap)
	}
	return children
}
Repository: googleapis/genai-toolbox
File: internal/tools/looker/lookerrundashboard/lookerrundashboard.go (Go)

Code before:
	logger.DebugContext(ctx, "data = ", data)

	return data, nil
}

func (t Tool) ParseParams(data map[string]any, claims map[string]map[string]any) (tools.ParamValues, error) {
	return tools.ParseParams(t.Parameters, data, claims)
}

func (t Tool) Manifest() tools.Manifest {
	return t.manifest
}

func (t Tool) McpManifest() tools.McpManifest {
	return t.mcpManifest
}

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

func (t Tool) RequiresClientAuthorization() bool {
	return t.UseClientOAuth
}

func TileQueryWorker(ctx context.Context, sdk *v4.LookerSDK, options *rtl.ApiSettings, index int, element v4.DashboardElement) <-chan map[string]any {
	out := make(chan map[string]any)

	data := make(map[string]any)
	data["index"] = index
	if element.Title != nil {
		data["title"] = *element.Title
	}
	if element.TitleText != nil {
		data["title_text"] = *element.TitleText
	}
	if element.SubtitleText != nil {
		data["subtitle_text"] = *element.SubtitleText
	}
	if element.BodyText != nil {
		data["body_text"] = *element.BodyText
	}

	var q v4.Query
	if element.Query != nil {
		data["element_type"] = "query"
		q = *element.Query
	} else if element.Look != nil {
		data["element_type"] = "look"
		q = *element.Look.Query
	} else {

Review comment (suggestion):
```suggestion
func tileQueryWorker(ctx context.Context, sdk *v4.LookerSDK, options *rtl.ApiSettings, index int, element v4.DashboardElement) <-chan map[string]any {
```

Code after:
	logger.DebugContext(ctx, "data = ", data)

	return data, nil
}

func (t Tool) ParseParams(data map[string]any, claims map[string]map[string]any) (tools.ParamValues, error) {
	return tools.ParseParams(t.Parameters, data, claims)
}

func (t Tool) Manifest() tools.Manifest {
	return t.manifest
}

func (t Tool) McpManifest() tools.McpManifest {
	return t.mcpManifest
}

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

func (t Tool) RequiresClientAuthorization() bool {
	return t.UseClientOAuth
}

func tileQueryWorker(ctx context.Context, sdk *v4.LookerSDK, options *rtl.ApiSettings, index int, element v4.DashboardElement) <-chan map[string]any {
	out := make(chan map[string]any)

	go func() {
		defer close(out)

		data := make(map[string]any)
		data["index"] = index
		if element.Title != nil {
			data["title"] = *element.Title
		}
		if element.TitleText != nil {
			data["title_text"] = *element.TitleText
		}
		if element.SubtitleText != nil {
			data["subtitle_text"] = *element.SubtitleText
		}
		if element.BodyText != nil {
			data["body_text"] = *element.BodyText
		}

		var q v4.Query
		if element.Query != nil {
			data["element_type"] = "query"
			q = *element.Query
		} else if element.Look != nil {
Repository: googleapis/genai-toolbox
File: internal/tools/looker/lookerrundashboard/lookerrundashboard.go (Go)

Code before:
	logger.DebugContext(ctx, "params = ", params)
	paramsMap := params.AsMap()

	dashboard_id := paramsMap["dashboard_id"].(string)

	sdk, err := lookercommon.GetLookerSDK(t.UseClientOAuth, t.ApiSettings, t.Client, accessToken)
	if err != nil {
		return nil, fmt.Errorf("error getting sdk: %w", err)
	}
	dashboard, err := sdk.Dashboard(dashboard_id, "", t.ApiSettings)
	if err != nil {
		return nil, fmt.Errorf("error getting dashboard: %w", err)
	}

	data := make(map[string]any)
	data["tiles"] = make([]any, 0)
	if dashboard.Title != nil {
		data["title"] = *dashboard.Title
	}
	if dashboard.Description != nil {
		data["description"] = *dashboard.Description
	}

	channels := make([]<-chan map[string]any, len(*dashboard.DashboardElements))
	for i, element := range *dashboard.DashboardElements {
		channels[i] = TileQueryWorker(ctx, sdk, t.ApiSettings, i, element)
	}
	
	for resp := range merge(channels...) {
		data["tiles"] = append(data["tiles"].([]any), resp)
	}

	logger.DebugContext(ctx, "data = ", data)

	return data, nil
}

func (t Tool) ParseParams(data map[string]any, claims map[string]map[string]any) (tools.ParamValues, error) {
	return tools.ParseParams(t.Parameters, data, claims)
}

func (t Tool) Manifest() tools.Manifest {
	return t.manifest
}

func (t Tool) McpManifest() tools.McpManifest {
	return t.mcpManifest
}

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

Review comment (suggestion):
```suggestion
		channels[i] = tileQueryWorker(ctx, sdk, t.ApiSettings, i, element)
```

Code after:
	logger.DebugContext(ctx, "params = ", params)
	paramsMap := params.AsMap()

	dashboard_id := paramsMap["dashboard_id"].(string)

	sdk, err := lookercommon.GetLookerSDK(t.UseClientOAuth, t.ApiSettings, t.Client, accessToken)
	if err != nil {
		return nil, fmt.Errorf("error getting sdk: %w", err)
	}
	dashboard, err := sdk.Dashboard(dashboard_id, "", t.ApiSettings)
	if err != nil {
		return nil, fmt.Errorf("error getting dashboard: %w", err)
	}

	data := make(map[string]any)
	data["tiles"] = make([]any, 0)
	if dashboard.Title != nil {
		data["title"] = *dashboard.Title
	}
	if dashboard.Description != nil {
		data["description"] = *dashboard.Description
	}

	channels := make([]<-chan map[string]any, len(*dashboard.DashboardElements))
	for i, element := range *dashboard.DashboardElements {
		channels[i] = tileQueryWorker(ctx, sdk, t.ApiSettings, i, element)
	}

	for resp := range merge(channels...) {
		data["tiles"] = append(data["tiles"].([]any), resp)
	}

	logger.DebugContext(ctx, "data = ", data)

	return data, nil
}

func (t Tool) ParseParams(data map[string]any, claims map[string]map[string]any) (tools.ParamValues, error) {
	return tools.ParseParams(t.Parameters, data, claims)
}

func (t Tool) Manifest() tools.Manifest {
	return t.manifest
}

func (t Tool) McpManifest() tools.McpManifest {
	return t.mcpManifest
}

func (t Tool) Authorized(verifiedAuthServices []string) bool {
	return tools.IsAuthorized(t.AuthRequired, verifiedAuthServices)
Repository: googleapis/genai-toolbox
File: internal/server/mcp.go (Go)

Code before:
		attribute.String("mcp.transport.type", transportType),
	)

	// Set network protocol version if available
	if networkProtocolVersion != "" {
		span.SetAttributes(attribute.String("network.protocol.version", networkProtocolVersion))
	}

	// Set MCP protocol version if available
	if protocolVersion != "" {
		span.SetAttributes(attribute.String("mcp.protocol.version", protocolVersion))
	}

	// Set request ID
	if baseMessage.Id != nil {
		if idStr, ok := baseMessage.Id.(string); ok {
			span.SetAttributes(attribute.String("jsonrpc.request.id", idStr))
		} else if idNum, ok := baseMessage.Id.(float64); ok {
			span.SetAttributes(attribute.String("jsonrpc.request.id", fmt.Sprintf("%v", idNum)))
		}
	}

	// Set toolset name if available
	if toolsetName != "" {
		span.SetAttributes(attribute.String("toolset.name", toolsetName))
	}

	// Extract tool/prompt name for gen_ai attributes
	switch baseMessage.Method {
	case "tools/call":
		var req struct {
			Params struct {
				Name string `json:"name"`
			} `json:"params"`
		}
		if json.Unmarshal(body, &req) == nil && req.Params.Name != "" {
			span.SetAttributes(
				attribute.String("gen_ai.tool.name", req.Params.Name),
				attribute.String("gen_ai.operation.name", "execute_tool"),
			)
		}
	case "prompts/get":
		var req struct {
			Params struct {
				Name string `json:"name"`
			} `json:"params"`
		}
		if json.Unmarshal(body, &req) == nil && req.Params.Name != "" {
			span.SetAttributes(attribute.String("gen_ai.prompt.name", req.Params.Name))
		}
	}

Review comment (suggestion):
```suggestion
	span.SetAttributes(attribute.String("toolset.name", toolsetName))
```
Let's set the toolset name regardless~ the default toolset name is an empty string --`""`

Code after:
		}
		span.SetAttributes(attribute.String("mcp.protocol.version", version))
		return version, result, err
	default:
		toolset, ok := s.ResourceMgr.GetToolset(toolsetName)
		if !ok {
			err := fmt.Errorf("toolset does not exist")
			rpcErr := jsonrpc.NewError(baseMessage.Id, jsonrpc.INVALID_REQUEST, err.Error(), nil)
			span.SetStatus(codes.Error, err.Error())
			span.SetAttributes(attribute.String("error.type", rpcErr.Error.String()))
			return "", rpcErr, err
		}
		promptset, ok := s.ResourceMgr.GetPromptset(promptsetName)
		if !ok {
			err := fmt.Errorf("promptset does not exist")
			rpcErr := jsonrpc.NewError(baseMessage.Id, jsonrpc.INVALID_REQUEST, err.Error(), nil)
			span.SetStatus(codes.Error, err.Error())
			span.SetAttributes(attribute.String("error.type", rpcErr.Error.String()))
			return "", rpcErr, err
		}
		result, err := mcp.ProcessMethod(ctx, protocolVersion, baseMessage.Id, baseMessage.Method, toolset, promptset, s.ResourceMgr, body, header)
		if err != nil {
			span.SetStatus(codes.Error, err.Error())
			// Set error.type based on JSON-RPC error code
			if rpcErr, ok := result.(jsonrpc.JSONRPCError); ok {
				span.SetAttributes(attribute.Int("jsonrpc.error.code", rpcErr.Error.Code))
				span.SetAttributes(attribute.String("error.type", rpcErr.Error.String()))
			}
		}
		return "", result, err
	}
}
Repository: googleapis/genai-toolbox
File: docs/en/samples/pre_post_processing/python/langchain/agent.py (Python)

Code before:
            model=model,
            tools=tools,
            middleware=[enforce_business_rules, enrich_response],
        )

        user_input = "Book hotel with id 3."
        response = await agent.ainvoke(
            {"messages": [{"role": "user", "content": user_input}]}
        )

        print("-" * 50)
        print("Final Client Response:")
        last_ai_msg = response["messages"][-1].content
        print(f"AI: {last_ai_msg}")

        # Test Pre-processing
        print("-" * 50)
        user_input = "Update my hotel with id 3 with checkin date 2025-01-18 and checkout date 2025-01-20"
        response = await agent.ainvoke(
            {"messages": [{"role": "user", "content": user_input}]}
        )
        last_ai_msg = response["messages"][-1].content
        print(f"AI: {last_ai_msg}")


if __name__ == "__main__":
    asyncio.run(main())


Review comment (suggestion):
Not sure how much comments we want for this docs but I'm thinking it might be helpful to add comments explaining what is going on/what is expected for the results. This way, users don't necessarily have to run this code.

Code after:

    return result


async def main():
    async with ToolboxClient("http://127.0.0.1:5000") as client:
        tools = await client.aload_toolset("my-toolset")
        model = ChatVertexAI(model="gemini-2.5-flash")
        agent = create_agent(
            system_prompt=system_prompt,
            model=model,
            tools=tools,
            # add any pre and post processing methods
            middleware=[enforce_business_rules, enrich_response],
        )

        user_input = "Book hotel with id 3."
        response = await agent.ainvoke(
            {"messages": [{"role": "user", "content": user_input}]}
        )

        print("-" * 50)
        last_ai_msg = response["messages"][-1].content
        print(f"AI: {last_ai_msg}")

        # Test Pre-processing
        print("-" * 50)
        user_input = "Update my hotel with id 3 with checkin date 2025-01-18 and checkout date 2025-01-20"
        response = await agent.ainvoke(
            {"messages": [{"role": "user", "content": user_input}]}
        )
        last_ai_msg = response["messages"][-1].content
        print(f"AI: {last_ai_msg}")


if __name__ == "__main__":
    asyncio.run(main())
Repository: googleapis/genai-toolbox
File: internal/util/errors.go (Go)

Code before:
	Category() ErrorCategory
	Error() string
	Unwrap() error
}

// Agent Errors return 200 to the sender
type AgentError struct {
	Msg   string
	Cause error
}

var _ ToolboxError = &AgentError{}

func (e *AgentError) Error() string { return e.Msg }

func (e *AgentError) Category() ErrorCategory { return CategoryAgent }

func (e *AgentError) Unwrap() error { return e.Cause }

func NewAgentError(msg string, cause error) *AgentError {
	return &AgentError{Msg: msg, Cause: cause}
}

var _ ToolboxError = &AgentError{}

// ClientServerError returns 4XX/5XX error code
type ClientServerError struct {
	Msg   string
	Code  int
	Cause error
}

var _ ToolboxError = &ClientServerError{}

func (e *ClientServerError) Error() string { return fmt.Sprintf("%s: %v", e.Msg, e.Cause) }

func (e *ClientServerError) Category() ErrorCategory { return CategoryServer }

func (e *ClientServerError) Unwrap() error { return e.Cause }

func NewClientServerError(msg string, code int, cause error) *ClientServerError {
	return &ClientServerError{Msg: msg, Code: code, Cause: cause}
}


Review comment (refactor):
```suggestion
// ClientServerError returns 4XX/5XX error code
```

Duplicated~ 

Code after:
	Category() ErrorCategory
	Error() string
	Unwrap() error
}

// Agent Errors return 200 to the sender
type AgentError struct {
	Msg   string
	Cause error
}

var _ ToolboxError = &AgentError{}

func (e *AgentError) Error() string {
	if e.Cause != nil {
		return fmt.Sprintf("%s: %v", e.Msg, e.Cause)
	}
	return e.Msg
}

func (e *AgentError) Category() ErrorCategory { return CategoryAgent }

func (e *AgentError) Unwrap() error { return e.Cause }

func NewAgentError(msg string, cause error) *AgentError {
	return &AgentError{Msg: msg, Cause: cause}
}

// ClientServerError returns 4XX/5XX error code
type ClientServerError struct {
	Msg   string
	Code  int
	Cause error
}

var _ ToolboxError = &ClientServerError{}

func (e *ClientServerError) Error() string {
	if e.Cause != nil {
		return fmt.Sprintf("%s: %v", e.Msg, e.Cause)
	}
	return e.Msg
}

func (e *ClientServerError) Category() ErrorCategory { return CategoryServer }

func (e *ClientServerError) Unwrap() error { return e.Cause }

func NewClientServerError(msg string, code int, cause error) *ClientServerError {
	return &ClientServerError{Msg: msg, Code: code, Cause: cause}
}