Agent SDK
创建 Go 自定义工具
把业务查询封装为类型化工具,注册进程内 MCP 并验证输入与返回值。
让 Agent 调用现有业务函数
Go 自定义工具运行在宿主进程中,通过进程内 MCP 提供给运行时。它适合调用已有服务层、读取当前用户的业务记录,或执行带授权检查的操作,不需要为每个工具启动一个 HTTP 服务。
先设计一个范围明确的工具。名称说明动作,描述说明何时使用,输入只包含完成任务所需字段。不要让模型传入任意 SQL、任意文件路径或任意命令来代替业务接口。
完整示例
下面的工具读取示例订单状态,没有外部网络和写操作。保存为 main.go,在快速开始建立的模块中运行。
package main
import (
"context"
"fmt"
"log"
"time"
"github.com/nexus-research-lab/nexus-agent-sdk-bridge/client"
"github.com/nexus-research-lab/nexus-agent-sdk-bridge/tools"
)
type OrderInput struct {
ID string `json:"id"`
}
func run() error {
lookup, err := tools.NewTyped[OrderInput]("order_status", "查询指定订单的处理状态。",
func(ctx context.Context, input OrderInput, _ *tools.Context) (tools.Result, error) {
if err := ctx.Err(); err != nil { return tools.Result{}, err }
if input.ID != "demo-001" {
return tools.Error("没有找到当前用户可访问的订单。"), nil
}
return tools.Text("订单 demo-001 已发货。"), nil
}, tools.ReadOnly())
if err != nil { return err }
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
defer cancel()
options := client.NewOptions().WithRuntime(client.RuntimeNXS).
WithCustomTools("orders", lookup).
WithAllowedTools("mcp__orders__order_status")
result, err := client.Prompt(ctx, client.PromptRequest{
Prompt: "使用订单工具查询 demo-001 的状态。", Options: options,
})
if err != nil { return err }
if result.IsError { return fmt.Errorf("任务失败:%s", result.Subtype) }
fmt.Println(result.Result)
return nil
}
func main() {
if err := run(); err != nil { log.Fatal(err) }
}
输入类型与业务验证
NewTyped[T] 从 Go 类型推导 JSON Schema,并在调用时解码为 T。它减少手工转换,不替代业务验证:空 ID、超出范围的数量、资源归属和重复请求仍要检查。
有复杂 Schema 时可用 tools.New 显式传入定义。错误应说明哪项输入无效,让模型可以纠正;不要把数据库堆栈或访问令牌放进错误内容。
实际服务中的当前用户应来自宿主可信上下文,而不是让模型传一个 user_id 决定权限。本例只接受 demo-001,是为了让可访问范围可见、可测试。
注册、名称和权限
WithCustomTools("orders", lookup) 建立名为 orders 的进程内服务。运行时使用完整名称 mcp__orders__order_status 调用,因此允许规则要与注册名称一致。添加了工具但调用失败时,先检查服务名、工具名和权限规则,不要扩大成允许全部工具。
需要自行管理服务对象时,使用 tools.CreateSDKMCPServer 与 WithSDKMCPServer。它们与外部 MCP 服务配置不同,详见MCP 接入。
返回结果和失败
tools.Text 返回模型可读文本,tools.Error 返回带错误标记的工具结果。订单不存在等预期业务失败适合返回受控错误文本;连接中断等调用失败可以返回 Go error。失败不能返回“成功”再把错误藏在日志里。
结果应只包含当前任务需要的信息。大量记录应分页或先聚合。工具输出进入模型上下文,不能把内部字段全量序列化给模型。
并发与副作用
ReadOnly 和 Concurrent 是对工具行为的声明,不会自动加锁,也不会把写操作变成安全操作。只有实现确实允许并发时才使用相应选项。
写操作应有宿主授权、幂等键和可核对的结果。运行时重试或用户再次提交任务,都可能触发重复调用。业务状态不能依赖模型保证“只调用一次”。