关于 migrate-bluejay
用于将 Bluejay 配置和实体迁移到 Coval 的引导式技能。它盘点源数据、映射相互依赖的实体、检查重复项并处理失败;创建的计划运行会保持禁用,供审核后启用。
主要功能
- 01盘点 Bluejay 实体
- 02映射指标、角色和 Agent
- 03创建 Coval 测试集与测试用例
- 04迁移运行模板和计划任务
- 05检查重复项并报告进度
适用场景
- 01将 Bluejay 配置迁移至 Coval
- 02创建依赖资源前核对实体映射
- 03部分失败后查看进度并继续迁移
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ coval-ai/ coval-external-skills --skill migrate-bluejay安装后在 Claude Code 中输入/migrate-bluejay确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/bluejay-api.mdcoval-api.mdentity-mapping.mdmetric-type-mapping.md详细介绍
Bluejay → Coval 迁移
为 $ARGUMENTS 将所有配置从 Bluejay 迁移到 Coval。
API 参考
- references/bluejay-api.md — Bluejay 端点、身份验证、分页
- references/coval-api.md — Coval 端点、身份验证、请求架构
- references/entity-mapping.md — 逐字段映射表
- references/metric-type-mapping.md — Bluejay response_type → Coval metric_type
步骤 0:迁移前检查
收集 API 密钥
解析 $ARGUMENTS 中的两个位置参数:[bluejay-api-key] [coval-api-key]。
如果未提供,请分别向用户询问每个密钥。
验证 Bluejay 密钥
curl -s -o /dev/null -w "%{http_code}" \
-H "X-API-Key: <BLUEJAY_KEY>" \
"https://api.getbluejay.ai/v1/all-agents"
预期为 200。如果返回 401/403,请告知用户密钥无效。
验证 Coval 密钥
curl -s -o /dev/null -w "%{http_code}" \
-H "X-API-Key: <COVAL_KEY>" \
"https://api.coval.dev/v1/agents?page_size=1"
预期为 200。如果返回 401,请告知用户密钥无效。
获取 Coval 语音目录
curl -s -H "X-API-Key: <COVAL_KEY>" \
"https://api.coval.dev/v1/personas/voices"
保存语音列表,以便在步骤 4 中映射角色。响应格式:
{ "voices": [{ "voice_name": "aria", "supported_languages": ["en-US", ...] }] }
步骤 1:盘点
获取所有 Bluejay 实体。使用 references/bluejay-api.md 中的端点。
尽可能并行获取以下数据:
| 实体 | 端点 |
|---|---|
| Agents | GET /v1/all-agents |
| 模拟 | GET /v1/get-all-simulations |
| 自定义指标 | GET /v1/custom-metrics?page=1&page_size=100(分页) |
| 社区 | GET /v1/communities |
| 计划 | 从模拟中推导(没有列出所有计划的端点——检查每个模拟) |
| 客户角色 | 按 Agent 获取:GET /v1/customer-personas-by-agent/{agent_id} |
| 文件夹 | GET /v1/all-folders |
对于每个 Agent,还要获取:
- 最新提示词:
GET /v1/agents/{agent_id}/prompts/versions?page_size=1(最新版本) - 最新知识库:
GET /v1/agents/{agent_id}/knowledge-bases/versions?page_size=1 - 数字人:按模拟获取:
GET /v1/digital-humans-by-simulation/{simulation_id}
向用户展示摘要:
Found:
- X agents
- Y digital humans (across Z simulations)
- N custom metrics
- M communities
- P customer personas
- Q schedules
- R folders
Proceed with migration?
继续之前,请等待用户确认。
步骤 2:检查现有 Coval 状态
获取现有 Coval 实体,以支持幂等操作:
# Agents
curl -s -H "X-API-Key: <COVAL_KEY>" "https://api.coval.dev/v1/agents?page_size=100"
# Personas
curl -s -H "X-API-Key: <COVAL_KEY>" "https://api.coval.dev/v1/personas?page_size=100"
# Test Sets
curl -s -H "X-API-Key: <COVAL_KEY>" "https://api.coval.dev/v1/test-sets?page_size=100"
# Metrics
curl -s -H "X-API-Key: <COVAL_KEY>" "https://api.coval.dev/v1/metrics?page_size=100"
# Run Templates
curl -s -H "X-API-Key: <COVAL_KEY>" "https://api.coval.dev/v1/run-templates?page_size=100"
# Scheduled Runs
curl -s -H "X-API-Key: <COVAL_KEY>" "https://api.coval.dev/v1/scheduled-runs?page_size=100"
如果存在 next_page_token,则进行分页。
为每种实体类型构建 display_name → ID 查找映射。检查重复项时:
- 如果实体的元数据中包含
bluejay_migration: true→ 跳过(已迁移) - 如果名称与非迁移实体冲突 → 询问用户是跳过还是重命名
阶段 1:独立实体(步骤 3–5)
这些实体没有交叉引用。按顺序执行,但每个步骤彼此独立。
步骤 3:迁移指标
将 Bluejay 自定义指标映射为 Coval 指标。
对于每个 Bluejay 指标,使用 references/metric-type-mapping.md 中的映射。
对于每个指标:
- 根据 Bluejay
response_type确定metric_type - 使用 Bluejay
scoring_guidance+description构建prompt - 对于
qualitative→ 向用户询问类别列表 - 对于
quantitative→ 如果存在则使用 Bluejaymin_value/max_value,否则询问用户 - 对于
enum→ 使用enum_options作为categories - 如果
eval_route == "AUDIO"→ 使用METRIC_AUDIO_LLM_*变体 - 对于
json→ 使用METRIC_LLM_BINARY,并提醒用户这只是近似方案
curl -s -X POST "https://api.coval.dev/v1/metrics" \
-H "X-API-Key: <COVAL_KEY>" \
-H "Content-Type: application/json" \
-d '{
"metric_name": "<bluejay_metric_name>",
"description": "<bluejay_description>",
"metric_type": "<mapped_type>",
"prompt": "<from_scoring_guidance>",
"metadata": {
"bluejay_migration": true,
"bluejay_original_id": "<bluejay_metric_id>"
}
}'
根据映射表添加特定类型的字段(categories、min_value、max_value)。
记录:bluejay_metric_id → coval_metric_id
步骤 4:迁移角色
将 Bluejay 数字人(语音/行为)和客户角色映射为 Coval 角色。
数字人 → Persona
对于每个唯一的数字人:
-
语音映射 — 向用户展示 Bluejay 语音配置:
Bluejay Digital Human: "<name>" Gender: <gender> Accent: <accent> Language: <language> Available Coval voices: aria, asteria, athena, luna, ... Which Coval voice should map to this configuration?缓存语音映射 — 如果再次出现相同的性别、口音和语言组合,则重复使用该映射,无需询问。
-
将
language映射为language_code(例如,en→en-US,es→es-ES) -
将
background_noise映射为background_sound(参见实体映射参考) -
根据
role_description、traits和行为字段构建persona_prompt
curl -s -X POST "https://api.coval.dev/v1/personas" \
-H "X-API-Key: <COVAL_KEY>" \
-H "Content-Type: application/json" \
-d '{
"name": "<digital_human_name>",
"voice_name": "<mapped_coval_voice>",
"language_code": "<mapped_language_code>",
"persona_prompt": "<built_from_role_description_and_traits>",
"background_sound": "<mapped_background_noise>",
"conversation_initiation": "<from_speaks_first_config>",
"metadata": {
"bluejay_migration": true,
"bluejay_original_id": "<digital_human_id>"
}
}'
记录:bluejay_digital_human_id → coval_persona_id
客户 Persona → Persona
对于每个 Bluejay 客户 Persona:
curl -s -X POST "https://api.coval.dev/v1/personas" \
-H "X-API-Key: <COVAL_KEY>" \
-H "Content-Type: application/json" \
-d '{
"name": "<customer_persona_name>",
"voice_name": "aria",
"language_code": "en-US",
"persona_prompt": "Name: <name>\nDescription: <description>\nGoal: <goal>",
"metadata": {
"bluejay_migration": true,
"bluejay_original_id": "<customer_persona_id>",
"bluejay_entity_type": "customer_persona"
}
}'
询问用户客户 Persona 应使用哪种语音(默认为 aria)。
步骤 5:迁移 Agent
将 Bluejay Agent 映射为 Coval Agent。
对于每个 Bluejay Agent:
- 确定
model_type:Bluejaymode=VOICE→MODEL_TYPE_VOICE,mode=TEXT→MODEL_TYPE_TEXT - 根据以下内容构建
prompt:最新版本 Prompt 的prompt_text+ Agent 的goals(以编号列表形式追加) - 如果 Agent 有
system_prompt,则将其添加到提示词前面 - 将
knowledge_base内容存储在 Agent 元数据中 - 如果 Agent 有
folder,则在display_name前加上文件夹名称:"[FolderName] AgentName"
curl -s -X POST "https://api.coval.dev/v1/agents" \
-H "X-API-Key: <COVAL_KEY>" \
-H "Content-Type: application/json" \
-d '{
"display_name": "<folder_prefix><agent_name>",
"model_type": "<MODEL_TYPE_VOICE|MODEL_TYPE_TEXT>",
"prompt": "<system_prompt + latest_prompt + goals>",
"metadata": {
"bluejay_migration": true,
"bluejay_original_id": "<bluejay_agent_id>",
"knowledge_base": "<kb_text_content>",
"bluejay_connection_type": "<connection_type>",
"bluejay_phone_number": "<phone_number>"
}
}'
记录:bluejay_agent_id → coval_agent_id
阶段 2:依赖阶段 1(步骤 6–7)
步骤 6:迁移测试集
将 Bluejay 模拟 + 社区映射为 Coval 测试集。
模拟 → 测试集
对于每个 Bluejay 模拟:
curl -s -X POST "https://api.coval.dev/v1/test-sets" \
-H "X-API-Key: <COVAL_KEY>" \
-H "Content-Type: application/json" \
-d '{
"display_name": "<simulation_name>",
"description": "Migrated from Bluejay simulation <simulation_id>",
"test_set_type": "SCENARIO",
"test_set_metadata": {
"bluejay_migration": true,
"bluejay_original_id": "<simulation_id>",
"bluejay_entity_type": "simulation"
}
}'
记录:bluejay_simulation_id → coval_test_set_id
社区 → 测试集
对于每个 Bluejay 社区:
curl -s -X POST "https://api.coval.dev/v1/test-sets" \
-H "X-API-Key: <COVAL_KEY>" \
-H "Content-Type: application/json" \
-d '{
"display_name": "<community_title>",
"description": "<community_description>",
"test_set_type": "SCENARIO",
"test_set_metadata": {
"bluejay_migration": true,
"bluejay_original_id": "<community_id>",
"bluejay_entity_type": "community"
}
}'
记录:bluejay_community_id → coval_test_set_id
步骤 7:迁移测试用例
将 Bluejay 数字人意图映射为 Coval 测试用例。
对于与模拟关联的每个数字人:
- 使用
intent→input_str - 使用
success_criteria→expected_behaviors(如果有多行,则拆分为数组) - 从模拟映射中查找
coval_test_set_id(步骤 6) - 如果存在
scripted_responses,则设置input_type: "SCRIPT",并使用simulation_metadata_input.script_turns
curl -s -X POST "https://api.coval.dev/v1/test-cases" \
-H "X-API-Key: <COVAL_KEY>" \
-H "Content-Type: application/json" \
-d '{
"test_set_id": "<coval_test_set_id>",
"input_str": "<digital_human_intent>",
"expected_behaviors": ["<success_criteria_line_1>", "<success_criteria_line_2>"],
"description": "<digital_human_name>: <digital_human_tag>",
"input_type": "SCENARIO",
"metadata": {
"bluejay_migration": true,
"bluejay_original_id": "<digital_human_id>"
}
}'
对于脚本化测试用例:
curl -s -X POST "https://api.coval.dev/v1/test-cases" \
-H "X-API-Key: <COVAL_KEY>" \
-H "Content-Type: application/json" \
-d '{
"test_set_id": "<coval_test_set_id>",
"input_str": "<digital_human_intent>",
"expected_behaviors": ["<success_criteria>"],
"input_type": "SCRIPT",
"simulation_metadata_input": {
"script_turns": ["<turn_1>", "<turn_2>", "..."]
},
"metadata": {
"bluejay_migration": true,
"bluejay_original_id": "<digital_human_id>"
}
}'
记录:bluejay_digital_human_id → coval_test_case_id
阶段 3:依赖阶段 1 + 2(步骤 8)
步骤 8:迁移运行模板
将 Bluejay 模拟映射为 Coval 运行模板。
对于每个 Bluejay 模拟,创建一个运行模板,将迁移后的资源关联起来:
- 根据
bluejay_agent_id查找coval_agent_id(该模拟的 Agent) - 选择此模拟中由数字人映射得到的第一个 Persona,或询问用户
- 从模拟映射中查找
coval_test_set_id - 收集与 Agent 关联的
coval_metric_ids
curl -s -X POST "https://api.coval.dev/v1/run-templates" \
-H "X-API-Key: <COVAL_KEY>" \
-H "Content-Type: application/json" \
-d '{
"display_name": "<simulation_name> Template",
"description": "Migrated from Bluejay simulation <simulation_id>",
"agent_id": "<coval_agent_id>",
"persona_id": "<coval_persona_id>",
"test_set_id": "<coval_test_set_id>",
"metric_ids": ["<coval_metric_id_1>", "<coval_metric_id_2>"],
"iteration_count": 1,
"concurrency": 5,
"metadata": {
"bluejay_migration": true,
"bluejay_original_id": "<simulation_id>"
}
}'
记录:bluejay_simulation_id → coval_run_template_id
阶段 4:依赖阶段 3(步骤 9)
步骤 9:迁移计划运行
将 Bluejay 计划映射为 Coval 计划运行。
为安全起见,所有计划运行均创建为 DISABLED。 客户必须在审核后手动启用它们。
对于每个 Bluejay 计划:
- 从模拟映射中查找
coval_run_template_id - 转换计划格式:
- Bluejay
cron表达式 → Covalcron(...)格式 - Bluejay
every_n_minutes→rate(<n> minutes) - Bluejay
every_n_hours→rate(<n> hours) - Bluejay 每日 HH:MM →
cron(<MM> <HH> ? * * *) - Bluejay 每周 →
cron(<MM> <HH> ? * <DAY> *) - Bluejay 每月 →
cron(<MM> <HH> <DOM> * ? *)
- Bluejay
curl -s -X POST "https://api.coval.dev/v1/scheduled-runs" \
-H "X-API-Key: <COVAL_KEY>" \
-H "Content-Type: application/json" \
-d '{
"display_name": "<simulation_name> Schedule",
"run_template_id": "<coval_run_template_id>",
"schedule_expression": "<converted_schedule>",
"enabled": false,
"metadata": {
"bluejay_migration": true,
"bluejay_original_id": "<schedule_id>"
}
}'
记录:bluejay_schedule_id → coval_scheduled_run_id
步骤 10:迁移报告
打印最终摘要:
## Migration Complete
### Created Entities
| Type | Count | Details |
|------|-------|---------|
| Metrics | N | bluejay_id → coval_id for each |
| Personas | N | ... |
| Agents | N | ... |
| Test Sets | N | ... |
| Test Cases | N | ... |
| Run Templates | N | ... |
| Scheduled Runs | N | (all disabled) |
### Skipped (Already Existed)
- List any entities skipped due to idempotency
### Warnings
- List any ambiguous mappings or approximations made
- Note any `json` metrics mapped to METRIC_LLM_BINARY
- Note any voice mappings that may need review
### Next Steps
1. Review migrated entities in the Coval dashboard: https://app.coval.dev
2. Enable scheduled runs after verifying configuration
3. Run a test evaluation from a migrated Run Template to verify
4. Review persona voice assignments and adjust if needed
错误处理
- HTTP 429(速率受限):等待 5 秒后重试。每个请求最多重试 3 次。
- HTTP 400(错误请求):向用户显示错误详情。询问用户是修正输入后重试,还是跳过此实体。
- HTTP 401/403(身份验证错误):停止操作,并请用户核验 API key。
- HTTP 500(服务器错误):显示错误,跳过此实体并继续处理其他实体。
- 网络错误:等待 3 秒后重试一次。如果仍然失败,则停止并报告目前已创建的内容。
发生任何故障后,始终向用户显示目前已成功创建的内容,以便用户继续操作。
幂等性规则
- 创建任何实体之前,先执行步骤 2 中的名称查找
- 如果实体存在,且其元数据中
bluejay_migration: true→ 静默跳过 - 如果名称与非迁移实体冲突 → 询问用户:“名为 '' 的 Coval <entity_type> 已存在,但并非由 Bluejay 迁移创建。要跳过、重命名还是覆盖?”
- 所有已创建的实体都添加以下元数据:
{ "bluejay_migration": true, "bluejay_original_id": "<id>" } - 如果没有任何更改,重新运行迁移不应创建任何新实体