agentsdk

package module
v1.7.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 10, 2026 License: MIT Imports: 11 Imported by: 0

README

Agent SDK

AI Agent 运行时框架 — 通过可插拔的 Skill(技能)、SubAgent(子代理)与 MCP 工具协议实现领域能力的动态扩展

Go Version Zero Dependencies License


目录


特性

  • 零外部依赖 — 仅使用 Go 标准库,无第三方依赖
  • SubAgent 子代理 — 声明式配置子代理,LLM 自动编排多 Agent 协作
  • Plan 编排 — LLM 生成多步执行计划,支持顺序和 DAG 并行两种模式
  • Skill 插件化 — 技能以目录包形式组织,支持热发现与动态加载
  • 多种文件系统 — 内置 MemFS、ZipFS,支持任意 fs.FS 实现
  • MCP 协议 — 支持 stdio/SSE 两种传输方式,连接外部工具服务器
  • 内置工具集 — 提供 Bash、HTTP、文件读取、Web 搜索等基础工具
  • 脚本工具 — 自动将技能包内的 .py/.js/.sh 脚本注册为工具
  • 对话摘要 — LLM 驱动的多级对话压缩,自动控制上下文长度

安装

go get github.com/opentoys/agentsdk

要求 Go 1.23 或更高版本。


快速开始

基本用法
package main

import (
    "context"
    "fmt"
    "os"

    "github.com/opentoys/agentsdk"
    "github.com/opentoys/agentsdk/modules/aichat"
    "github.com/opentoys/agentsdk/modules/log"
    "github.com/opentoys/agentsdk/tool"
    "github.com/opentoys/agentsdk/types"
)

func main() {
    chatClient := aichat.New(
        aichat.WithKey(os.Getenv("OPENAI_API_KEY")),
        aichat.WithBase(os.Getenv("OPENAI_API_BASE")),
        aichat.WithModel(os.Getenv("OPENAI_API_MODEL")),
    )

    skillsFS := os.DirFS("/path/to/skills")

    agent := agentsdk.New(types.Config{
        SkillsFS:   skillsFS,
        Debug:      &log.DefaultLog{},
        ChatClient: chatClient,
        Tools: []types.Tool{
            tool.DefineBashTool(),
            tool.DefineHTTPTool(),
        },
    })

    resp, err := agent.Run(context.Background(), "帮我分析这个数据")
    if err != nil {
        panic(err)
    }
    fmt.Println(resp)
}
使用 SubAgent
agent := agentsdk.New(types.Config{
    ChatClient: chatClient,
    SubAgents: []types.SubAgentConfig{
        {Name: "researcher", Description: "搜索和研究信息的子代理"},
        {Name: "writer",     Description: "撰写内容的子代理"},
    },
    Tools: []types.Tool{tool.DefineBashTool()},
})

// LLM 自动选择并调用子代理
agent.Run(ctx, "帮我调研 AI 趋势并写报告")
使用 Plan 编排
agent := agentsdk.New(types.Config{
    ChatClient: chatClient,
    SubAgents: []types.SubAgentConfig{
        {Name: "researcher", Description: "搜索和研究信息"},
        {Name: "writer",     Description: "撰写内容"},
        {Name: "reviewer",   Description: "审查和改进内容"},
    },
    Tools: []types.Tool{tool.DefineHTTPTool()},
})

// LLM 生成计划 → 按步骤自动执行
agent.RunWithPlan(ctx, "调研 AI 趋势,写一份报告,并审查质量")
使用 VFS 内存文件系统
mem := vfs.NewMem()
mem.WriteFile("my-skill/SKILL.md", []byte(skillContent))
mem.WriteFile("my-skill/scripts/run.py", []byte(scriptContent))

agent := agentsdk.New(types.Config{
    SkillsFS:   mem,
    ChatClient: chatClient,
})
使用 MCP 外部工具
config, _ := mcp.LoadConfig("mcp_config.json")
mcpClient := mcp.NewClient(ctx, config)
defer mcpClient.Close()

agent := agentsdk.New(types.Config{
    ChatClient:  chatClient,
    McpSessions: mcpClient,
    SkillsFS:   os.DirFS("./skills"),
})

核心架构

设计理念

Agent 不硬编码任何领域知识,而是通过四层工具体系 + SubAgent + 可插拔模块获取能力:

                      ┌──────────────┐
                      │   Agent      │  ◄── 入口 / 协调者
                      │   Run/Plan   │
                      └──────┬───────┘
                             │
      ┌──────────┬───────────┼───────────┬──────────┐
      ▼          ▼           ▼           ▼          ▼
┌──────────┐ ┌────────┐ ┌────────┐ ┌─────────┐ ┌──────────┐
│ SubAgent │ │ skill/ │ │ tool/  │ │ MCP     │ │ Custom   │
│ 子代理   │ │ parser │ │ 内置   │ │ 远程    │ │ Tool     │
│ (声明式) │ │ +gen   │ │        │ │         │ │ (NewTool)│
└──────────┘ └────────┘ └────────┘ └─────────┘ └──────────┘
     │            │          │          │           │
  Agent实例    技能包      Bash/     MCP服务器    自定义
  (独立LLM)   (脚本)     HTTP/Read  (SSE/stdio)  Exec函数
四层工具体系
层级 来源 说明 示例
SubAgent Config.SubAgents 声明式子代理配置,每个子代理拥有独立的 Agent 实例和消息历史 researcher, writer, dealer
BaseTools Config.Tools 通用基础能力,也可通过 NewTool() 自定义 bash, http, read, search
Script Tools 技能包 scripts/ 目录 技能专属的 .py/.ts/.js/.sh 脚本,自动或手动定义为工具 run_query.py, run_deploy.sh
MCP Tools 外部 MCP 服务器 通过 Model Context Protocol 连接的远程服务工具 组件查询, 数据库操作
执行流程
用户输入 userPrompt
        │
        ▼
┌─ Run() ──────────────────────────────────────────────┐
│  loadSkill(SkillsFS) → ParseSkillPackages              │
│  ├─ 0 个技能: runWithSkill(nil)                         │
│  ├─ 1 个技能: runWithSkill(skill)                       │
│  └─ N 个技能: selectSkill() → LLM 选择 → runWithSkill   │
└────────────────────────────────────────────────────────┘
        │
        ▼
┌─ runWithSkill() ─────────────────────────────────────┐
│  合并工具: SubAgent tools + Base tools + Script + MCP  │
│                                                        │
│  工具调用循环 (最多 20 轮):                              │
│  ├─ LLM 决定调用哪个工具                                │
│  ├─ SubAgent → tool.Exec() → 子 Agent.Run()            │
│  ├─ 含 "__" → McpSessions.CallTool (MCP)               │
│  ├─ 在 Tools 中 → tool.Exec() (内置/自定义)             │
│  ├─ 在 scriptMap 中 → bash() (脚本工具)                 │
│  └─ 无 tool_calls → 返回最终文本                        │
└────────────────────────────────────────────────────────┘

SubAgent 子代理

SubAgent 是框架内置的多 Agent 协作机制。通过声明式配置,将多个子 Agent 注册为父 Agent 可调用的 Tool,由 LLM 自动编排调用。

Agent-as-Tool 模式

最常用的模式:每个子代理是一个拥有独立消息历史和 SystemPrompt 的 Agent,被包装为 Tool 注册到父 Agent。LLM 在工具调用循环中自动决定何时调用哪个子代理。

agent := agentsdk.New(types.Config{
    ChatClient: chatClient,
    SubAgents: []types.SubAgentConfig{
        {
            Name:         "dealer",
            Description:  "荷官,负责发牌和判定胜负",
            SystemPrompt: "你是德州扑克荷官...",
        },
        {
            Name:         "xiaoming",
            Description:  "松凶型玩家",
            SystemPrompt: "你是玩家小明,松凶型风格...",
        },
    },
})

// 一行启动,LLM 自动编排子代理间的交互
agent.Run(ctx, "开始一局德州扑克")

工作原理:

父 Agent 收到 "开始一局德州扑克"
  │
  ├─ LLM: "调用 dealer 发牌"
  │     └─ dealer 子代理执行 → 返回发牌结果
  ├─ LLM: "调用 xiaoming 做决策"
  │     └─ xiaoming 子代理执行 → 返回决策
  ├─ LLM: "调用 xiaohong 做决策"
  │     └─ xiaohong 子代理执行 → 返回决策
  └─ ... LLM 持续编排直到游戏结束
Plan 编排模式

通过 RunWithPlan() 实现。LLM 先生成多步骤执行计划(顺序或 DAG),然后框架按计划依次调用子代理,支持步骤间传递中间结果。

agent := agentsdk.New(types.Config{
    ChatClient: chatClient,
    SubAgents: []types.SubAgentConfig{
        {Name: "researcher", Description: "搜索和研究信息"},
        {Name: "writer",     Description: "撰写内容"},
        {Name: "reviewer",   Description: "审查内容"},
    },
    Tools: []types.Tool{tool.DefineHTTPTool()},
})

// LLM 自动生成计划并按步骤执行
agent.RunWithPlan(ctx, "调研 AI 趋势并写报告")

LLM 生成的计划示例:

{
  "setps": [
    {"name": "researcher", "input": "调研 2024 年 AI 领域重大突破"},
    {"name": "writer",     "input": "基于 {{result:researcher}} 撰写一份报告"},
    {"name": "reviewer",   "input": "审查 {{result:writer}} 的质量和准确性", "after": ["writer"]}
  ]
}
  • 步骤间通过 {{result:步骤名}} 引用前序步骤的输出
  • after 字段定义依赖关系,无依赖的步骤可并行执行
  • 无子代理时自动退化为普通 Run()
SubAgentConfig 配置
字段 类型 必填 说明
Name string 是 子代理名称,同时作为注册到父 Agent 的 Tool 名称
Description string 是 能力描述,LLM 依据此描述决定何时调用该子代理
SystemPrompt string 否 系统提示词,定义子代理的角色和行为准则
SkillsFS fs.FS 否 子代理专属技能文件系统,nil 时复用父 Agent 的
Tools []Tool 否 子代理专属工具集,nil 时复用父 Agent 的
McpSessions ClientSessioner 否 子代理专属 MCP 会话,nil 时复用父 Agent 的
Parameters map[string]any 否 自定义 Tool 参数 Schema,nil 时使用默认的 input 字段
PlanStep 结构
字段 类型 说明
Name string 步骤名称,对应子代理名或工具名
Input string 传递给该步骤的自然语言输入
After []string 前置依赖步骤名称列表(DAG 模式)

API 参考

Agent
Config 结构体
字段 类型 必填 说明
ChatClient types.OpenAIChatClient 是 LLM 聊天客户端
SkillsFS fs.FS 否 技能文件系统
Debug types.Logger 否 日志接口实现
McpSessions types.ClientSessioner 否 MCP 会话管理器
History []types.ChatCompletionMessage 否 初始消息历史
Tools []Tool 否 自定义工具集合
SubAgents []SubAgentConfig 否 声明式子代理配置列表
核心方法
方法 签名 说明
New New(cfg types.Config) *Agent 创建并初始化 Agent(含子代理注册)
Run (a *Agent) Run(ctx, prompt string) (string, error) 主入口:技能选择 + 工具调用循环,LLM 自动编排子代理
RunWithPlan (a *Agent) RunWithPlan(ctx, prompt string) (string, error) Plan 模式:LLM 生成计划 → DAG/顺序执行子代理
CallTool (a *Agent) CallTool(ctx, name, args string) (string, error) 通过名称调用已注册的工具(含子代理)
注册函数
函数 签名 说明
NewTool NewTool(cfg types.ToolConfig) Tool 创建自定义 Tool(快捷构造)
WarpSkill WarpSkill(sk *SkillPackage, a *Agent) Tool 将 SkillPackage 包装为 Tool
RegisterExec RegisterExec(ext, exec string) 注册脚本执行器(如 .py → python3)
RegisterBash RegisterBash(f func(context.Context, string) (string, error)) 覆盖默认的 Bash 执行函数
ToolConfig 结构体

用于 NewTool() 快捷创建自定义工具:

t := agentsdk.NewTool(types.ToolConfig{
    Name:        "my_tool",
    Description: "工具描述",
    Exec: func(ctx context.Context, in string) (string, error) {
        return "result", nil
    },
})
字段 类型 必填 说明
Name string 是 工具名称
Description string 是 工具描述
Parameters map[string]any 否 自定义参数 Schema
Exec func(ctx, in string) (out string, e error) 是 执行函数

默认脚本执行器映射:

扩展名 执行命令
.py python3
.js node
.tengo tengo

Skill 系统
Skill Package 结构

每个技能是一个包含 SKILL.md(或 skill.md)的目录:

my-skill/
├── SKILL.md           # 技能元数据 + 指令
├── scripts/           # 可选:脚本工具
│   ├── run.py
│   └── deploy.sh
└── resources/         # 可选:资源文件
SKILL.md 格式

支持 Claude Code 和 OpenAI 双格式解析。使用 YAML frontmatter 定义元数据:

---
name: my-skill
description: 描述技能的功能
allowedTools:
  - bash
  - http
---

# 技能指令

这里是技能的详细指令内容...
Skill 元数据字段
字段 类型 说明
Name string 技能名称(唯一标识)
Description string 技能描述
AllowedTools []string 允许使用的工具列表
Model string 推荐使用的模型
Author string 作者
Version string 版本号
License string 许可证
Tools []ToolDefinition 自定义工具定义

Tool 系统
Tool 结构体
type Tool struct {
    Prompt   string                    // 可选:附加提示信息(不序列化到 API)
    Type     string                    // 工具类型,默认 "function"
    Function *FunctionDefinition       // 函数定义(名称、描述、参数 Schema)
    Exec     func(ctx context.Context, in string) (string, error) // 执行函数
}
内置工具
工具名 创建函数 功能说明 安全特性
bash DefineBashTool() Shell 命令执行 危险命令拦截 + 2 分钟超时
http_request DefineHTTPTool() HTTP 请求(curl兼容) JSON 自动美化输出
read_local DefineReadLocal(fsys fs.FS) 文件/目录读取 基于 fs.FS,支持任意文件系统
tavily_search DefineTavilySearch() Tavily AI 搜索 默认上限 20 条
Bash 工具

支持环境变量 $WORKDIR 作为命令的工作根目录。

危险命令拦截列表:rm -rf /、rm -rf /*、> /dev/sd、> /dev/null、mkfs、dd if=

result, err := tool.Bash("ls -la")                              // 默认 2 分钟超时
result, err = tool.BashWithTimeout("sleep 5", 10*time.Second)   // 自定义超时

VFS 虚拟文件系统

技能加载通过 fs.FS 接口抽象,内置多种虚拟文件系统实现。

MemFS — 内存文件系统

适用于动态构建技能内容或测试场景。

mem := vfs.NewMem()                    // 创建内存 FS
mem.WriteFile("calc/SKILL.md", data)   // 写入文件(自动创建目录)
mem.Remove("calc/old.md")              // 删除文件
mem.Export(zipWriter)                  // 导出为 ZIP
mem.Merge("prefix/", otherFS)          // 合并其他 FS
ZipFS — ZIP 文件系统
zipFS := vfs.NewZip()
r, _ := vfs.ZipReadFile("skills.zip")     // 本地文件
r, _ := vfs.ZipReadURL("https://...")      // 远程 URL
zipFS.Add("my-skill", r)
工具函数
函数 签名 说明
ZipReadFile ZipReadFile(name string) (*zip.Reader, error) 读取本地 ZIP 文件
ZipReadURL ZipReadURL(url string) (*zip.Reader, error) 从 URL 读取 ZIP
ZipCreate ZipCreate(content map[string]string) *zip.Reader 从内存创建 ZIP
CreateZip CreateZip(w io.Writer, files map[string][]byte) error 写入 ZIP 到 Writer
ParseZip ParseZip(data []byte) (map[string][]byte, error) 解析 ZIP 到内存 Map

Memory 系统

LLM 驱动的多级对话摘要系统,用于控制上下文长度。

三级摘要策略
策略 触发条件 行为
Leaf 单个对话片段 增量摘要
Condensed D1 多个 leaf 合并 压缩为单节点
Condensed D2 多 session 合并 更高层级压缩
自动升级策略
normal policy → 检查 token 是否超预算 (150%)
    ↓ 超出
aggressive policy → 再检查
    ↓ 还超出
deterministicFallback → 截断到目标长度
summarizer := &memory.LLMSummarizer{
    Generate: func(ctx context.Context, prompt string) (string, error) {
        return llmClient.Generate(prompt)
    },
}
summary, err := memory.BuildSummarize(ctx, summarizer, messages, memory.SummarizeOptions{
    TargetTokens: 4000,
    IsCondenced: true,
    Depth:        1,
})

模块系统

aichat — OpenAI Chat 客户端

路径:modules/aichat/

基于 HTTP 直连 OpenAI 兼容 API 的轻量级客户端,采用 函数选项模式 配置。

client := aichat.New(
    aichat.WithKey("sk-xxx"),
    aichat.WithBase("https://api.openai.com/v1"),
    aichat.WithModel("gpt-4o"),
)
选项 说明 默认值
WithKey API Key 无(必填)
WithBase Base URL https://api.deepseek.com/v1
WithModel 默认模型 deepseek-v4-flash

mcp — MCP 协议客户端

路径:modules/mcp/

支持 stdio / SSE 两种传输方式,内建连接重试与指数退避机制。

config, _ := mcp.LoadConfig("servers.json")
client := mcp.NewClient(ctx, config)
defer client.Close()

// 工具名格式: serverName__toolName(自动添加前缀避免冲突)
tools, _ := client.ListTools(ctx)
result, _ := client.CallTool(ctx, "serverName__toolName", map[string]any{"arg": "value"})

log — 日志模块

路径:modules/log/

实现 types.Logger 接口,用于 Agent 调试输出。

agent := agentsdk.New(types.Config{
    Debug: &log.DefaultLog{},
})

dag — DAG 执行引擎

路径:modules/dag/

有向无环图(DAG)执行引擎,用于 RunWithPlan 的计划编排。

g := dag.New()
g.AddNode("step1", "输入描述1")
g.AddNode("step2", "输入描述2")
g.AddEdge("step1", "step2") // step2 依赖 step1

g.Run(ctx, func(ctx context.Context, name, prompt string) error {
    // 执行节点逻辑
    dag.SetResultKV(ctx, name, result) // 存储结果
    return nil
})

results := dag.GetResult(ctx) // map[string]string

也支持从 JSON 构建:

g := dag.NewJson([]byte(`{"setps": [
    {"name": "research", "input": "调研AI趋势"},
    {"name": "write",    "input": "写报告", "after": ["research"]}
]}`))

设计模式

模式 应用位置 说明
Strategy OpenAIChatClient, Summarizer 接口 可替换 LLM 后端和摘要引擎
Plugin Skill Package + SubAgent 技能/子代理作为插件热发现和注册
Pipeline 发现 → 选择 → 执行 Agent 的核心流水线
Adapter MCP Client, aichat 将外部格式适配为统一的 Tool 接口
Option aichat.New 函数选项模式,灵活配置客户端
Delegate SubAgent (Agent-as-Tool) 父 Agent 委托子 Agent 处理子任务
Orchestrate RunWithPlan (DAG) LLM 生成计划,框架按 DAG 编排

参考项目

  • goskills — Reference skills implementation
  • anna — Reference memory implementation
  • go-mcp — Downgrading MCP to Go 1.23

License

MIT

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewTool added in v1.7.1

func NewTool(cfg types.ToolConfig) (tool types.Tool)

func RegisterExec added in v0.2.3

func RegisterExec(ext string, exec types.Runner)

func WarpSkill added in v1.7.0

func WarpSkill(sk *skill.SkillPackage, a *Agent) types.Tool

Types

type Agent

type Agent struct {
	// contains filtered or unexported fields
}

func New

func New(cfg types.Config) *Agent

func (*Agent) Run

func (s *Agent) Run(ctx context.Context, in string) (out string, e error)

func (*Agent) RunWithPlan added in v1.7.1

func (s *Agent) RunWithPlan(ctx context.Context, input string) (string, error)

RunWithPlan 让 LLM 生成多步骤执行计划,然后按计划调度子代理执行 支持顺序执行和 DAG 并行执行两种模式,由 LLM 根据任务复杂度自动选择

Directories

Path Synopsis
examples
cards command
cli command
multi command
modules
dag
log
mcp

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL