mcpField
O
openserv-agent-sdk

openserv-agent-sdk

github.com/openserv-labsAgent 工作流28148 次安装29 周前更新
代码仓库

关于 openserv-agent-sdk

供 TypeScript 开发者为 OpenServ 平台构建和部署自定义 AI Agent。SDK 支持由平台处理 LLM 调用的能力,也支持自定义运行逻辑、任务管理和文件操作。

主要功能

  1. 01定义可运行与免运行能力
  2. 02委托平台执行 LLM 调用
  3. 03注册并启动 Agent
  4. 04管理任务状态与日志
  5. 05获取、上传和删除文件

适用场景

  1. 01构建调用 API 的自定义 Agent
  2. 02创建由平台处理 AI 调用的能力
  3. 03将 Agent 接入多 Agent 工作流
  4. 04在任务中记录日志并处理文件

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/openserv-labs/skills --skill openserv-agent-sdk

安装后在 Claude Code 中输入/openserv-agent-sdk确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

reference.md
troubleshooting.md
examples/
basic-agent.ts
capability-example.ts
capability-with-agent-methods.ts
env.example
error-handling.ts
file-operations.ts
haiku-poet-agent.ts
multiple-capabilities.ts
task-management.ts

详细介绍

OpenServ Agent SDK

使用 TypeScript 为 OpenServ 平台构建和部署自定义 AI Agent。

为什么要构建 Agent?

OpenServ Agent 是一项运行你编写的代码并将其发布到 OpenServ 平台的服务,因此工作流、其他 Agent 或付费调用(例如 x402)都可以触发它。平台会向你的 Agent 发送任务;你的 Agent 运行其功能(API、工具、文件处理)并返回结果。你不必使用大模型,例如,它可以是一个只返回数据的静态 API。如果需要大模型推理,有两个选项:使用无运行函数(由平台代为处理 AI 调用,无需 API 密钥),或使用 generate()(将大模型调用委托给平台);也可以自带大模型(使用你可以访问的任意提供商)。

工作原理(流程)

  1. 定义 Agent — 系统提示词加上_功能_。功能分为两种:可运行(包含 Zod 架构和 run 处理函数)和无运行函数(只有名称和描述,由平台自动处理 AI 调用)。你也可以在可运行功能中使用 generate(),将大模型调用委托给平台。
  2. 向平台注册 — 你需要拥有平台账户;通常最简单的方式是让 provision() 自动为你创建账户:它会创建钱包并使用该钱包注册(后续运行会重复使用该账户)。调用 provision()(来自 @openserv-labs/client):它会创建或重复使用钱包、注册 Agent,并将 API 密钥和身份验证令牌写入环境变量(或者传入 agent.instance,直接绑定它们)。在开发环境中,你可以跳过设置端点 URL;SDK 可以使用内置隧道连接平台。
  3. 启动 Agent — 调用 run(agent)。Agent 会监听任务、运行其功能(以及你使用的大模型),并作出响应。详情请参阅 reference.md 和 troubleshooting.md;examples/ 中提供了完整的可运行代码。

Agent 能做什么

  • 无运行函数 — 只有名称和描述。平台会自动处理 AI 调用,无需 API 密钥,也无需 run() 函数。你可以选择定义 inputSchema 和 outputSchema,以实现结构化输入和输出。
  • 可运行功能 — Agent 可以运行的工具(例如,搜索、转换数据、调用 API)。每项功能都有名称、描述、inputSchema 和 run() 函数。
  • generate() 方法 — 在任意可运行功能中将大模型调用委托给平台。无需 API 密钥;平台会执行调用并记录用量。支持文本和结构化输出。
  • 任务上下文 — 在任务中运行时,Agent 可以通过 addLogToTask() 和 uploadFile() 等方法向该任务附加日志和上传文件。
  • 多 Agent 工作流 — 你的 Agent 可以与其他 Agent 一同参与工作流;有关 Platform API、工作流和 ERC-8004 链上身份,请参阅 openserv-client 技能。

参考: reference.md(模式) · troubleshooting.md(常见问题) · examples/(完整示例)

快速开始

安装
npm install @openserv-labs/sdk @openserv-labs/client zod

注意: 只有在使用 process() 方法直接调用 OpenAI 时,才需要安装 openai。大多数 Agent 都不需要它,可改用无运行函数或 generate()。

最简 Agent

完整的可运行示例请参阅 examples/basic-agent.ts。

模式很简单:

  1. 创建一个带有系统提示词的 Agent
  2. 使用 agent.addCapability() 添加功能
  3. 调用 provision() 在平台上注册(传入 agent.instance 以绑定凭据)
  4. 调用 run(agent) 启动

完整 Agent 模板

文件结构
my-agent/
├── src/agent.ts
├── .env
├── .gitignore
├── package.json
└── tsconfig.json
依赖项
npm init -y && npm pkg set type=module
npm i @openserv-labs/sdk @openserv-labs/client dotenv zod
npm i -D @types/node tsx typescript

注意: 项目必须在 package.json 中使用 "type": "module"。添加 "dev": "tsx src/agent.ts" 脚本以便在本地开发。只有在使用 process() 方法直接调用 OpenAI 时,才安装 openai。

.env

大多数 Agent 无需 LLM API 密钥——使用 无运行函数的能力 或 generate(),平台会为你处理 LLM 调用。如果使用 process() 直接调用 OpenAI,请设置 OPENAI_API_KEY。其余配置由 provision() 填充。

# Only needed if you use process() for direct OpenAI calls:
# OPENAI_API_KEY=your-openai-key
# ANTHROPIC_API_KEY=your_anthropic_key  # If using Claude directly

# Required for deploy (get from OpenServ platform dashboard)
OPENSERV_USER_API_KEY=your-user-api-key

# Auto-populated by provision():
WALLET_PRIVATE_KEY=
OPENSERV_API_KEY=
OPENSERV_AUTH_TOKEN=
PORT=7378
# Production: skip tunnel and run HTTP server only
# DISABLE_TUNNEL=true
# Force tunnel even when endpointUrl is set
# FORCE_TUNNEL=true

能力

能力分为两种:

无运行函数的能力(推荐用于大多数场景)

无运行函数的能力不需要 run 函数——平台会自动处理 AI 调用。只需提供名称和描述:

// Simplest form — just name + description
agent.addCapability({
  name: 'generate_haiku',
  description: 'Generate a haiku poem (5-7-5 syllables) about the given input.'
})

// With custom input schema
agent.addCapability({
  name: 'translate',
  description: 'Translate text to the target language.',
  inputSchema: z.object({
    text: z.string(),
    targetLanguage: z.string()
  })
})

// With structured output
agent.addCapability({
  name: 'analyze_sentiment',
  description: 'Analyze the sentiment of the given text.',
  outputSchema: z.object({
    sentiment: z.enum(['positive', 'negative', 'neutral']),
    confidence: z.number().min(0).max(1)
  })
})
  • 无需 run 函数 — 平台会执行 LLM 调用
  • 无需 API 密钥 — 平台会处理
  • inputSchema 为可选项 — 如果省略,默认为 z.object({ input: z.string() })
  • outputSchema 为可选项 — 如需平台返回结构化输出,可进行定义

完整的无运行函数示例请参见 examples/haiku-poet-agent.ts。

可运行能力

可运行能力包含用于自定义逻辑的 run 函数。每项能力都需要:

  • name - 唯一标识符
  • description - 功能说明(帮助 AI 判断何时使用)
  • inputSchema - 定义参数的 Zod 架构
  • run - 返回字符串的函数
agent.addCapability({
  name: 'greet',
  description: 'Greet a user by name',
  inputSchema: z.object({ name: z.string() }),
  async run({ args }) {
    return `Hello, ${args.name}!`
  }
})

基础能力请参见 examples/capability-example.ts。

注意: schema 属性仍可作为 inputSchema 的别名使用,但已弃用。新代码请使用 inputSchema。

使用 Agent 方法

在能力中访问 this,即可使用 Agent 方法,例如 addLogToTask()、uploadFile()、generate() 等。

有关日志记录和文件上传模式,请参见 examples/capability-with-agent-methods.ts。


Agent 方法

generate() — 由平台代为执行的 LLM 调用

generate() 方法让你无需 API 密钥即可进行 LLM 调用。平台会执行调用,并将用量记录到工作区。

// Text generation
const poem = await this.generate({
  prompt: `Write a short poem about ${args.topic}`,
  action
})

// Structured output (returns validated object matching the schema)
const metadata = await this.generate({
  prompt: `Suggest a title and 3 tags for: ${poem}`,
  outputSchema: z.object({
    title: z.string(),
    tags: z.array(z.string()).length(3)
  }),
  action
})

// With conversation history
const followUp = await this.generate({
  prompt: 'Suggest a related topic.',
  messages,  // conversation history from run function
  action
})

参数:

  • prompt(字符串)— 提供给 LLM 的提示词
  • action(ActionSchema)— 操作上下文(传入你的 run 函数)
  • outputSchema(Zod 架构,可选)— 提供后将返回经过验证的结构化输出
  • messages(数组,可选)— 多轮生成的对话历史

action 参数为必需项,因为它用于识别计费对应的工作区和任务。请在可运行能力中使用它,此时可从 run 函数的参数中获取 action。

任务管理
await agent.createTask({ workspaceId, assignee, description, body, input, dependencies })
await agent.updateTaskStatus({ workspaceId, taskId, status: 'in-progress' })
await agent.addLogToTask({ workspaceId, taskId, severity: 'info', type: 'text', body: '...' })
await agent.markTaskAsErrored({ workspaceId, taskId, error: 'Something went wrong' })
const task = await agent.getTaskDetail({ workspaceId, taskId })
const tasks = await agent.getTasks({ workspaceId })
文件操作
const files = await agent.getFiles({ workspaceId })
await agent.uploadFile({ workspaceId, path: 'output.txt', file: 'content', taskIds: [taskId] })
await agent.deleteFile({ workspaceId, fileId })

操作上下文

能力中的 action 参数是一个联合类型——只有在 'do-task' 变体中才存在 task。访问 action.task 前,务必先使用类型守卫缩小类型范围:

async run({ args, action }) {
  // action.task does NOT exist on all action types — you must narrow first
  if (action?.type === 'do-task' && action.task) {
    const { workspace, task } = action
    workspace.id        // Workspace ID
    workspace.goal      // Workspace goal
    task.id             // Task ID
    task.description    // Task description
    task.input          // Task input
    action.me.id        // Current agent ID
  }
}

不要在类型守卫之前提取 action?.task?.id——TypeScript 会报错:Property 'task' does not exist on type 'ActionSchema'。


工作流名称和目标

provision() 中的 workflow 对象需要两个重要属性:

  • name(字符串)— 这将成为 ERC-8004 中的 Agent 名称。名称应精炼、有力且令人印象深刻——这是用户看到的对外品牌名称。应像为产品发布命名,而不是给变量命名。例如:'Crypto Alpha Scanner'、'AI Video Studio'、'Instant Blog Machine'。
  • goal(字符串,必填)— 对工作流要完成事项的详细描述。内容必须具体详尽——目标过于简短或含糊会导致 API 调用失败。至少用一个完整句子说明工作流的目的。
workflow: {
  name: 'Haiku Poetry Generator',  // Polished display name — the ERC-8004 agent name users see
  goal: 'Transform any theme or emotion into a beautiful traditional 5-7-5 haiku poem using AI',
  trigger: triggers.x402({ ... }),
  task: { description: 'Generate a haiku about the given topic' }
}

触发器类型

import { triggers } from '@openserv-labs/client'

triggers.webhook({ waitForCompletion: true, timeout: 600 })
triggers.x402({ name: '...', description: '...', price: '0.01', timeout: 600 })
triggers.cron({ schedule: '0 9 * * *' })
triggers.manual()

重要: Webhook 和 x402 触发器的 timeout 始终应至少设为 600 秒(10 分钟)。Agent 处理请求通常需要较长时间,尤其是在进行研究、内容生成或其他复杂工作时。超时时间过短会导致任务过早失败。对于包含多个连续步骤的多 Agent 流水线,可考虑设为 900 秒或更长。

API 密钥:Agent 与用户

provision() 会创建两种凭据。它们不可互换:

  • OPENSERV_API_KEY(Agent API 密钥)——SDK 在接收任务时用于内部身份验证。传入 agent.instance 时,provision() 会自动设置此密钥。不要将此密钥用于 PlatformClient。
  • WALLET_PRIVATE_KEY / OPENSERV_USER_API_KEY(用户凭据)——用于通过 PlatformClient 执行管理调用(列出任务、调试工作流等)。使用 client.authenticate(walletKey) 进行身份验证,或在构造函数中传入 apiKey。

如果需要调试任务或检查工作流,请使用钱包身份验证:

const client = new PlatformClient()
await client.authenticate(process.env.WALLET_PRIVATE_KEY)
const tasks = await client.tasks.list({ workflowId: result.workflowId })

有关 401 错误的详情,请参阅 troubleshooting.md。


部署

本地开发
npm run dev

run() 函数会自动:

  • 启动 Agent HTTP 服务(端口 7378,并自动回退)
  • 通过 WebSocket 连接到 agents-proxy.openserv.ai
  • 将平台请求路由到本地计算机

无需使用 ngrok 或其他隧道工具——run() 会无缝处理这些操作。只需调用 run(agent),平台即可访问本地 Agent。

部署到 OpenServ Cloud

只需一条命令,即可将 Agent 部署到 OpenServ 托管云:

npx @openserv-labs/client deploy [path]

其中 [path] 是包含 Agent 代码的目录(默认为当前目录)。

前提条件
  1. .env 中的 OPENSERV_USER_API_KEY——Agent 目录中的 .env 文件必须包含 OPENSERV_USER_API_KEY。请从 OpenServ 平台仪表板获取此密钥。部署命令(以及 PlatformClient 执行管理操作)都需要此密钥。请注意,provision() 本身不需要此密钥——它会自行创建钱包、进行身份验证,并独立将凭据保存到 .openserv.json。如果存在用户 API 密钥,provision() 后也会将其保存到 .openserv.json。

  2. 先调用 provision()——部署前必须至少运行一次 provision()。它会在平台上注册 Agent,并将凭据保存到 .openserv.json。推荐的 Agent 模板已在 main() 中先调用 provision(),再调用 run(agent),因此只需在本地启动 Agent(npm run dev 或 npx tsx src/agent.ts)即可。如果代码未调用 provision()(例如,只在自定义脚本中调用 run(agent)),则必须显式添加 provision() 调用,并在部署前运行一次。

部署工作流
1. Set OPENSERV_USER_API_KEY in .env
2. Call provision() during local startup (npm run dev) — registers the agent and writes .openserv.json
3. npx @openserv-labs/client deploy .
可自托管的生产环境

部署到 Cloud Run 等托管服务提供商时,请将 DISABLE_TUNNEL=true 设置为环境变量。这样,run() 只会启动 HTTP 服务,而不会打开 WebSocket 隧道——平台会通过 Agent 的公开 URL 直接访问它。

await provision({
  agent: {
    name: 'my-agent',
    description: '...',
    endpointUrl: 'https://my-agent.example.com' // Required for production
  },
  workflow: {
    name: 'Lightning Service Pro',
    goal: 'Describe in detail what this workflow does — be thorough, vague goals cause failures',
    trigger: triggers.webhook({ waitForCompletion: true, timeout: 600 }),
    task: { description: 'Process incoming requests' }
  }
})

// With DISABLE_TUNNEL=true, run() starts only the HTTP server (no tunnel)
await run(agent)

ERC-8004:链上 Agent 身份

完成配置后,通过 Identity Registry 在链上注册你的 Agent,以便他人发现。

需要 Base 上的 ETH。 注册会在 Base 主网(chain 8453) 上调用 ERC-8004 合约的 register(),并消耗 Gas。provision() 创建的钱包初始余额为零。首次尝试注册前,请向该钱包转入少量 Base 上的 ETH。配置过程中会记录钱包地址(Created new wallet: 0x...)。

务必使用 try/catch 包裹,这样注册失败(例如钱包余额不足)不会阻止 run(agent) 启动。

两个重要模式:

  1. 以编程方式使用 dotenv(而不是 import 'dotenv/config'),这样就能在 provision() 写入 WALLET_PRIVATE_KEY 后重新加载 .env。
  2. 在 provision() 后调用 dotenv.config({ override: true }),以便在 ERC-8004 注册前读取刚写入的密钥。
import dotenv from 'dotenv'
dotenv.config()

import { Agent, run } from '@openserv-labs/sdk'
import { provision, triggers, PlatformClient } from '@openserv-labs/client'

// ... define agent and capabilities ...

const result = await provision({
  agent: { instance: agent, name: 'my-agent', description: '...' },
  workflow: {
    name: 'My Service',
    goal: 'Detailed description of what the workflow does',
    trigger: triggers.x402({ name: 'My Service', description: '...', price: '0.01', timeout: 600 }),
    task: { description: 'Process requests' }
  }
})

// Reload .env to pick up WALLET_PRIVATE_KEY written by provision()
dotenv.config({ override: true })

// Register on-chain (non-blocking — requires funded wallet on Base)
try {
  const client = new PlatformClient()
  await client.authenticate(process.env.WALLET_PRIVATE_KEY)

  const erc8004 = await client.erc8004.registerOnChain({
    workflowId: result.workflowId,
    privateKey: process.env.WALLET_PRIVATE_KEY!,
    name: 'My Service',
    description: 'What this agent does'
  })

  console.log(`Agent ID: ${erc8004.agentId}`) // "8453:42"
  console.log(`TX: ${erc8004.blockExplorerUrl}`)
  console.log(`Scan: ${erc8004.scanUrl}`) // "https://www.8004scan.io/agents/base/42"
} catch (error) {
  console.warn('ERC-8004 registration skipped:', error instanceof Error ? error.message : error)
}

await run(agent)
  • 首次运行会铸造一个新的身份 NFT。再次运行会更新 URI——Agent ID 保持不变。
  • **除非你有意创建新的 Agent ID,否则绝不要清除钱包状态。**要更新元数据,只需重新运行。
  • 默认链:Base 主网(8453)。如需使用其他链,请传入 chainId / rpcUrl。

完整的 ERC-8004 API 参考和故障排查,请参阅 openserv-client 技能。


请勿使用

  • 能力内的 this.process()——这是需要 OpenAI API 密钥的旧版方法。请改用 this.generate()(由平台代为执行,无需密钥),或使用无运行时能力
  • doTask 覆盖——SDK 会自动处理任务执行
  • this.completeTask()——任务完成由 Runtime API 处理

更新此技能

此技能可能已过时。OpenServ 团队会定期发布更新,包括新功能、API 更改和错误修复;在你更新之前,这些内容都不会反映在此处。如果遇到问题,或想确保获取最新信息,请先更新技能再继续。

# Check if updates are available
npx skills check

# Update all installed skills to latest versions
npx skills update

或者直接重新安装 OpenServ 技能:

npx skills add openserv-labs/skills

相关技能

  • openserv-client - 完整的 Platform Client API 参考
  • openserv-multi-agent-workflows - 多 Agent 协作模式
  • openserv-launch - 在 Base 区块链上发行代币
  • openserv-ideaboard-api - 在 Ideaboard 上寻找创意并发布 Agent 服务

评论

支持 Markdown