Coze Studio 深度文档 05:实战教程合集

5 阅读10分钟

本篇是"动手"导向。从零跑通 Bot、从零搭工作流、从零写插件、新加一个工作流节点四个完整流程,所有步骤基于源码确认。

主文档:01 - 原理与使用 系列前篇:02 - 会话与执行 · 03 - 工程化与扩展 · 04 - 生态对比与排错

目录

  1. 实战 1:从零创建一个 Bot
  2. 实战 2:从零搭一个工作流
  3. 实战 3:开发一个自定义插件
  4. 实战 4:二次开发——新增一个工作流节点
  5. 典型场景实现思路

1. 实战 1:从零创建一个 Bot

1.1 启动并注册账号

# 启动完整 Docker 栈
make web

# 等待镜像拉起后访问
http://localhost:8888/sign

注册接口在 idl/passport/passport.thrift:

操作端点必填字段
注册POST /api/passport/web/email/register/v2/email、password
登录POST /api/passport/web/email/login/email、password
当前账户POST /api/passport/account/info/v2/(cookie)

1.2 配置模型(必做,否则 Bot 不能用)

模板位于 backend/conf/model/template/,含 20+ 个 YAML 模板:

model_template_ark.yaml          # 火山方舟(豆包)
model_template_openai.yaml       # OpenAI
model_template_claude.yaml       # Anthropic Claude
model_template_gemini.yaml       # Google Gemini
model_template_qwen.yaml         # 通义千问
model_template_deepseek.yaml     # DeepSeek
model_template_ollama.yaml       # 本地 Ollama
...

步骤

  1. 选一个模板,复制到 backend/conf/model/(去掉 template_)
  2. 填写关键字段(以 Ark 为例):
id: 60001                        # 自己分配的唯一 ID
name: doubao-1-5-pro-32k         # 展示名
meta:
  protocol: ark                  # 协议(ark/openai/claude/gemini/qwen/deepseek/ollama)
  capability:
    function_call: true          # 是否支持工具调用
    input_tokens: 32768
    max_tokens: 4096
  conn_config:
    base_url: https://ark.cn-beijing.volces.com/api/v3/
    api_key: ${ARK_API_KEY}      # 从环境变量读
    model: ep-20240xxxxxxx        # 端点 ID
    temperature: 0.7
default_parameters:
  - { name: temperature, type: float, min: "0", max: "1" }
  - { name: max_tokens, type: int, min: "1", max: "4096" }
  1. 重启 coze-server(docker compose restart coze-servermake server)
  2. 浏览器访问 http://localhost:8888/admin/#model-management,新模型应已显示

1.3 创建 Bot

UI 路径:工作空间 → 创建 → "智能体"

接口(IDL 在 idl/app/intelligence.thriftidl/app/project.thrift):

POST /api/intelligence_api/draft_project/create
{
  "space_id": 7xxx,
  "name": "My First Bot",
  "description": "我的第一个 Bot",
  "icon_uri": "default_icon/agent_default.jpeg"
}

响应里的 project_id 就是 Bot ID。

1.4 Bot 编辑器五大区域

每个区域对应一个或多个前端包:

区域配置内容前端包
Persona人设、风格agent-ide/space-bot/
Prompt系统提示词agent-ide/prompt/ + prompt-adapter
Tools挂插件、工作流agent-ide/tool/agent-ide/tool-config/
Knowledge挂知识库data/knowledge-data-set-for-agent/
Variables全局变量agent-ide/bot-config-area/ 内的 dialogue-config-view

1.5 调试

右侧"预览与调试"面板,组件:BotDebugChatArea,在 agent-ide/chat-debug-area/

1.6 发布到 OpenAPI

  1. Bot 编辑器右上角"发布",选择 API Connector
  2. 进入"API Token"页面,创建一个 PAT(pat_xxx,只显示一次)
  3. 调用:
curl -N -X POST http://localhost:8888/v3/chat \
  -H "Authorization: Bearer pat_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "bot_id": "7xxxxx",
    "user_id": "test_user_001",
    "stream": true,
    "additional_messages": [
      { "role": "user", "type": "question", "content": "你好" }
    ]
  }'

-N 关键:让 curl 不缓冲,SSE 才能实时显示。


2. 实战 2:从零搭一个工作流

2.1 创建

接口在 backend/api/handler/coze/workflow_service.go:

操作端点
创建POST /api/workflow_api/create
保存POST /api/workflow_api/save
获取画布POST /api/workflow_api/canvas
测试运行POST /api/workflow_api/test_run
中断后恢复POST /api/workflow_api/test_resume

UI:工作空间 → 资源 → 工作流 → 创建。

2.2 最简工作流:Entry → LLM → Exit

Entry 节点

  • 类型:NodeTypeEntry(ID=1)
  • 配置:声明输入字段(如 question: string)

LLM 节点

  • 类型:NodeTypeLLM(ID=3)
  • 关键配置:
    • 选模型(从 1.2 配的列表里挑)
    • 系统 Prompt 模板,引用上游变量
    • 用户 Prompt:{{question}}(直接用 Entry 输出的字段)
    • 输出格式:Text / Markdown / JSON

Exit 节点

  • 类型:NodeTypeExit(ID=2)
  • 配置:声明输出字段(如 answer),引用 LLM 节点输出

2.3 变量引用语法

源码:backend/domain/workflow/entity/vo/canvas.go

两种引用方式共存:

方式 1:结构化 ref(画布 JSON 中)

{
  "type": "ref",
  "value": {
    "content": {
      "blockID": "100001",         // 上游节点 ID
      "name": "answer",            // 上游输出字段名
      "source": "block-output"
    }
  }
}

方式 2:模板渲染(字符串字段中)

请基于以下问题作答:{{question}}_{{user_info.name}}

{{xxx}} 由运行时引擎替换为节点入参对应值。

2.4 测试运行

POST /api/workflow_api/test_run
{
  "workflow_id": "7xxxxx",
  "input": {
    "question": "什么是 RAG?"
  }
}

响应是 SSE 流,前端按节点逐个渲染状态。

2.5 工作流挂为 Bot 的工具

  1. 工作流编辑器 → 发布(同 Bot)
  2. 进 Bot 编辑器,Tools 区域 → 添加工作流
  3. LLM 在对话中自动决定何时调用此工作流(走 Function Call)

技术细节:工作流被包装成 Eino BaseTool,作为 LLM 节点的工具集传入 ReAct Agent。代码:backend/domain/workflow/internal/compose/workflow_tool.go


3. 实战 3:开发一个自定义插件

3.1 参考官方模板

backend/conf/plugin/pluginproduct/ 有 18 个示例:

插件用途
bocha_search.yaml博查全网搜索
gaode_map.yaml高德地图(地点、导航)
lark_*.yaml(8 个)飞书全家桶(表格/日历/文档/消息/Wiki…)
library_search.yaml文库检索
image_compression.yaml图片压缩
sky_eye_check.yaml天眼查企业信息
plugin_meta.yaml总注册表(所有官方插件的入口)

3.2 Manifest + OpenAPI 完整字段

- plugin_id: 100         # 自分配 ID
  version: v1.0.0
  manifest:
    schema_version: v1
    name_for_model: weather_query     # LLM 可见名(英文,LLM 通过此匹配)
    name_for_human: 天气查询          # 用户可见名
    description_for_model: 输入城市名,返回该城市当天天气
    auth:
      type: service_http              # none / service_http / oauth
      key: Authorization
      sub_type: token/api_key
      payload: '{"key":"Authorization","service_token":"","location":"Header"}'
    logo_url: my_plugin_icon/weather.png
    api:
      type: openapi
    common_params:
      header:
        - { name: User-Agent, value: Coze/1.0 }
  tools:
    - tool_id: 10001
      method: get
      sub_url: /weather

3.3 OpenAPI Operation(描述每个 tool)

OpenAPI 3.0 标准片段(可单独成 yaml,也可内嵌):

paths:
  /weather:
    get:
      operationId: getWeather
      parameters:
        - name: city
          in: query
          required: true
          schema: { type: string }
          description: 城市名,如"北京"
      responses:
        "200":
          description: 天气信息
          content:
            application/json:
              schema:
                type: object
                properties:
                  temp: { type: number }
                  desc: { type: string }

3.4 三种导入方式(选一)

实现:backend/domain/plugin/internal/openapi/convert_protocol.go

方式函数用法
OpenAPI 3.0 直接导入ToOpenapi3Doc最规范
Swagger 2.0SwaggerToOpenapi3Doc自动转 3.0
cURL 命令CurlToOpenapi3Doc把 curl 粘进去自动反推
Postman 集合PostmanToOpenapi3Doc把 Postman 导出 JSON 粘进去

底层用开源库 getkin/kin-openapi

3.5 OAuth 配置(需要时)

OAuth schema 模板:backend/conf/plugin/common/oauth_schema.json

支持 4 种鉴权模式:

AuthzTypeAuthzSubType说明
none-
api_key-API Key(在 header/query/body)
basic_auth-HTTP Basic
oauthauthorization_code标准三段式 OAuth
oauthclient_credentials服务端凭证

授权码模式所需字段:client_idclient_secretauthorization_urltoken_urlscopeclient_url

3.6 在 UI 中创建/调试

接口在 idl/plugin/plugin_develop.thrift:

操作端点
注册插件POST /api/plugin_api/register
注册元数据POST /api/plugin_api/register_plugin_meta
创建 API(tool)POST /api/plugin_api/create_api
调试 APIPOST /api/plugin_api/debug_api
发布插件POST /api/plugin_api/publish_plugin

UI:工作空间 → 资源 → 插件 → 创建插件 → 选导入方式 → 填鉴权 → 添加 tool → 调试 → 发布。

3.7 在 Bot 中使用

Bot 编辑器 → Tools → 添加插件 → 选刚发布的 → 保存。

LLM 会在对话中按需调用,Function Call 输出的参数自动按 OpenAPI 映射到 path/query/header/body。


4. 实战 4:二次开发——新增一个工作流节点

需求示例:加一个 RegexExtract 节点(用正则从字符串中提取)。

4.1 后端改动

Step 1:注册 NodeType

文件:backend/domain/workflow/entity/node_meta.go

const (
    NodeTypeEntry         NodeType = "Entry"
    // ...
    NodeTypeRegexExtract  NodeType = "RegexExtract"   // 👈 新增
)

var NodeTypeMetas = map[NodeType]*NodeTypeMeta{
    // ...
    NodeTypeRegexExtract: {
        ID:           50,
        Key:          NodeTypeRegexExtract,
        Name:         "正则提取",
        Category:     "utilities",
        SupportBatch: false,
        ExecutableMeta: ExecutableMeta{
            IsComposite:       false,
            PreFillZero:       true,
            PostFillNil:       true,
            IncrementalOutput: false,
        },
    },
}

Step 2:实现节点

新文件:backend/domain/workflow/internal/nodes/regexextract/regex_extract.go

package regexextract

import (
    "context"
    "regexp"

    "coze-studio/backend/domain/workflow/entity"
    "coze-studio/backend/domain/workflow/entity/vo"
    "coze-studio/backend/domain/workflow/internal/schema"
)

// Config: 节点的"设计期"配置(画布 → 后端 schema)
type Config struct {
    Pattern string  // 正则表达式
}

// Adapt: 把前端画布 Node 转成后端 NodeSchema
func (c *Config) Adapt(ctx context.Context, n *vo.Node, others ...any) (*schema.NodeSchema, error) {
    return &schema.NodeSchema{
        Key:     vo.NodeKey(n.ID),
        Type:    entity.NodeTypeRegexExtract,
        Name:    n.Data.Meta.Title,
        Configs: c,
    }, nil
}

// Build: 在执行期把 NodeSchema 实例化为可运行对象
func (c *Config) Build(ctx context.Context, ns *schema.NodeSchema, others ...any) (any, error) {
    re, err := regexp.Compile(c.Pattern)
    if err != nil {
        return nil, err
    }
    return &RegexExtract{re: re}, nil
}

// 运行期对象
type RegexExtract struct {
    re *regexp.Regexp
}

// Invoke: 节点真正执行的代码
func (r *RegexExtract) Invoke(ctx context.Context, input map[string]any) (map[string]any, error) {
    text, _ := input["text"].(string)
    matches := r.re.FindStringSubmatch(text)
    return map[string]any{
        "matched": len(matches) > 0,
        "groups":  matches,
    }, nil
}

Step 3:挂注册表

文件:backend/domain/workflow/internal/canvas/adaptor/to_schema.goinit()

func init() {
    nodes.RegisterNodeAdaptor(entity.NodeTypeLLM, func() nodes.NodeAdaptor {
        return &llm.Config{}
    })
    // ...
    nodes.RegisterNodeAdaptor(entity.NodeTypeRegexExtract, func() nodes.NodeAdaptor {
        return &regexextract.Config{}
    })
}

4.2 前端改动

Step 1:NodeType 枚举

文件:frontend/packages/workflow/base/src/types/node-type.ts

export enum StandardNodeType {
  Start = '1',
  End = '2',
  LLM = '3',
  // ...
  RegexExtract = '50',           // 👈 与后端 ID 对齐
}

Step 2:节点元数据 + 表单

新目录:frontend/packages/workflow/playground/src/node-registries/regex-extract/

regex-extract/
├── index.ts                     # 注册入口
├── meta.ts                      # 节点 meta(图标、分类)
├── form-meta.tsx                # 表单 schema
└── form.tsx                     # 表单 React 组件(可选,默认有)

meta.ts 简化样例:

import { type NodeRegistry } from '@flowgram-adapter/free-layout-editor';
import { StandardNodeType } from '@coze-workflow/base';

export const RegexExtractNodeRegistry: NodeRegistry = {
  type: StandardNodeType.RegexExtract,
  meta: {
    label: 'Regex Extract',
    icon: '/assets/regex.svg',
    description: '正则提取',
    category: 'utilities',
  },
  formMeta: () => import('./form-meta').then(m => m.formMeta),
};

Step 3:加 i18n 文案

文件:frontend/packages/arch/resources/studio-i18n-resource/src/locales/

// zh-CN.json
{ "node_regex_extract": "正则提取", "node_regex_extract_desc": "用正则从字符串中提取" }

// en.json
{ "node_regex_extract": "Regex Extract", "node_regex_extract_desc": "Extract from string by regex" }

Step 4:在节点列表注册

通常在 playground 包的节点注册聚合文件中加一行 RegexExtractNodeRegistry

4.3 验证

  1. make server 重启后端
  2. cd frontend/apps/coze-studio && npm run dev 重启前端
  3. 新建工作流,左侧节点面板应能看到"正则提取"
  4. 拖到画布,配置 pattern,连上 Entry/Exit,测试运行

5. 典型场景实现思路

源码里没有现成的场景模板目录。下列是基于源码能力的推荐方案。

5.1 客服机器人

组件实现
知识来源知识库:产品手册 PDF + FAQ Markdown,索引到 Milvus + ES
角色Bot Persona + Prompt:"你是某产品客服,语气友好,只回答产品相关问题"
实时数据工作流挂订单查询 Plugin(查 OMS API)
上下文用户 ID 作为 user_id 传入,Memory.Variables 存用户偏好
多轮Conversation 自动维护 Section,默认 SSE 流式
兜底Prompt 加"无法回答时,引导转人工"
发布API Connector → 在自家网站接 /v3/chat

5.2 代码审查助手

组件实现
主链路工作流:Entry(代码片段) → LLM(初步审查) → Code(执行 lint/static analyze) → LLM(综合) → Exit
知识知识库挂"代码规范"文档
工具Plugin:对接 GitHub PR API,可直接评论
发布OpenAPI,在 CI 里 curl 调用

5.3 数据分析助手

组件实现
数据源Memory.Database:把分析需要的表导入 Coze 内置库
自然语言查询NL2SQL 节点(infra/nl2sql/)→ Database 节点
可视化LLM 节点输出 markdown 表格,前端渲染
发布WebSDK 嵌入数据看板页面

关键路径速查

主题路径
Passport IDLidl/passport/passport.thrift
Bot/Project IDLidl/app/intelligence.thriftidl/app/project.thrift
Plugin IDLidl/plugin/plugin_develop.thrift
Workflow Handlerbackend/api/handler/coze/workflow_service.go
模型模板backend/conf/model/template/
插件模板backend/conf/plugin/pluginproduct/
OAuth Schemabackend/conf/plugin/common/oauth_schema.json
OpenAPI 解析backend/domain/plugin/internal/openapi/convert_protocol.go
NodeType 枚举backend/domain/workflow/entity/node_meta.go
Node 注册表backend/domain/workflow/internal/canvas/adaptor/to_schema.go
TextProcessor 实现(参考)backend/domain/workflow/internal/nodes/textprocessor/
前端 NodeTypefrontend/packages/workflow/base/src/types/node-type.ts
前端节点注册根frontend/packages/workflow/playground/src/node-registries/
Workflow as Toolbackend/domain/workflow/internal/compose/workflow_tool.go