migrate-bluejay

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Bluejay → Coval Migration

Bluejay → Coval 迁移指南

Migrate all configuration from Bluejay to Coval for
$ARGUMENTS
.
$ARGUMENTS
将所有配置从Bluejay迁移至Coval。

API References

API 参考文档

  • references/bluejay-api.md — Bluejay endpoints, auth, pagination
  • references/coval-api.md — Coval endpoints, auth, request schemas
  • references/entity-mapping.md — Field-by-field mapping tables
  • references/metric-type-mapping.md — Bluejay response_type → Coval metric_type
  • references/bluejay-api.md — Bluejay接口、鉴权、分页机制
  • references/coval-api.md — Coval接口、鉴权、请求 schema
  • references/entity-mapping.md — 字段级映射表
  • references/metric-type-mapping.md — Bluejay response_type → Coval metric_type 映射

Step 0: Pre-flight

步骤0:预检查

Collect API Keys

收集API密钥

Parse
$ARGUMENTS
for two positional args:
[bluejay-api-key] [coval-api-key]
.
If not provided, ask the user for each key individually.
$ARGUMENTS
中解析两个位置参数:
[bluejay-api-key] [coval-api-key]
如果未提供,分别向用户索要每个密钥。

Validate Bluejay Key

验证Bluejay密钥

bash
curl -s -o /dev/null -w "%{http_code}" \
  -H "X-API-Key: <BLUEJAY_KEY>" \
  "https://api.getbluejay.ai/v1/all-agents"
Expect
200
. On
401
/
403
, tell user key is invalid.
bash
curl -s -o /dev/null -w "%{http_code}" \
  -H "X-API-Key: <BLUEJAY_KEY>" \
  "https://api.getbluejay.ai/v1/all-agents"
预期返回
200
。若返回
401
/
403
,告知用户密钥无效。

Validate Coval Key

验证Coval密钥

bash
curl -s -o /dev/null -w "%{http_code}" \
  -H "X-API-Key: <COVAL_KEY>" \
  "https://api.coval.dev/v1/agents?page_size=1"
Expect
200
. On
401
, tell user key is invalid.
bash
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
,告知用户密钥无效。

Fetch Coval Voice Catalog

获取Coval语音库

bash
curl -s -H "X-API-Key: <COVAL_KEY>" \
  "https://api.coval.dev/v1/personas/voices"
Store the voice list for persona mapping in Step 4. Response shape:
json
{ "voices": [{ "voice_name": "aria", "supported_languages": ["en-US", ...] }] }
bash
curl -s -H "X-API-Key: <COVAL_KEY>" \
  "https://api.coval.dev/v1/personas/voices"
存储语音列表,用于步骤4中的角色映射。响应格式:
json
{ "voices": [{ "voice_name": "aria", "supported_languages": ["en-US", ...] }] }

Step 1: Inventory

步骤1:资源盘点

Fetch all Bluejay entities. Use the endpoints in references/bluejay-api.md.
Fetch these in parallel where possible:
EntityEndpoint
Agents
GET /v1/all-agents
Simulations
GET /v1/get-all-simulations
Custom Metrics
GET /v1/custom-metrics?page=1&page_size=100
(paginate)
Communities
GET /v1/communities
SchedulesDerive from simulations (no list-all endpoint — check each simulation)
Customer PersonasFetch per agent:
GET /v1/customer-personas-by-agent/{agent_id}
Folders
GET /v1/all-folders
For each agent, also fetch:
  • Latest prompt:
    GET /v1/agents/{agent_id}/prompts/versions?page_size=1
    (latest version)
  • Latest knowledge base:
    GET /v1/agents/{agent_id}/knowledge-bases/versions?page_size=1
  • Digital humans: Fetch per simulation:
    GET /v1/digital-humans-by-simulation/{simulation_id}
Present summary to user:
Found:
  - X agents
  - Y digital humans (across Z simulations)
  - N custom metrics
  - M communities
  - P customer personas
  - Q schedules
  - R folders

Proceed with migration?
Wait for user confirmation before continuing.
获取所有Bluejay实体,使用references/bluejay-api.md中的接口。
尽可能并行获取以下资源:
实体接口
Agents
GET /v1/all-agents
Simulations
GET /v1/get-all-simulations
Custom Metrics
GET /v1/custom-metrics?page=1&page_size=100
(分页获取)
Communities
GET /v1/communities
Schedules从Simulations中提取(无批量获取接口——需逐个检查模拟场景)
Customer Personas按Agent获取:
GET /v1/customer-personas-by-agent/{agent_id}
Folders
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}
向用户展示汇总信息:
已发现:
  - X个Agent
  - Y个数字人(分布在Z个模拟场景中)
  - N个自定义指标
  - M个社区
  - P个客户角色
  - Q个调度任务
  - R个文件夹

是否继续迁移?
等待用户确认后再继续。

Step 2: Check Existing Coval State

步骤2:检查Coval现有状态

Fetch existing Coval entities to enable idempotency:
bash
undefined
获取Coval现有实体以实现幂等性:
bash
undefined

Agents

Agents

curl -s -H "X-API-Key: <COVAL_KEY>" "https://api.coval.dev/v1/agents?page_size=100"
curl -s -H "X-API-Key: <COVAL_KEY>" "https://api.coval.dev/v1/agents?page_size=100"

Personas

Personas

curl -s -H "X-API-Key: <COVAL_KEY>" "https://api.coval.dev/v1/personas?page_size=100"
curl -s -H "X-API-Key: <COVAL_KEY>" "https://api.coval.dev/v1/personas?page_size=100"

Test Sets

Test Sets

curl -s -H "X-API-Key: <COVAL_KEY>" "https://api.coval.dev/v1/test-sets?page_size=100"
curl -s -H "X-API-Key: <COVAL_KEY>" "https://api.coval.dev/v1/test-sets?page_size=100"

Metrics

Metrics

curl -s -H "X-API-Key: <COVAL_KEY>" "https://api.coval.dev/v1/metrics?page_size=100"
curl -s -H "X-API-Key: <COVAL_KEY>" "https://api.coval.dev/v1/metrics?page_size=100"

Run Templates

Run Templates

curl -s -H "X-API-Key: <COVAL_KEY>" "https://api.coval.dev/v1/run-templates?page_size=100"
curl -s -H "X-API-Key: <COVAL_KEY>" "https://api.coval.dev/v1/run-templates?page_size=100"

Scheduled Runs

Scheduled Runs

curl -s -H "X-API-Key: <COVAL_KEY>" "https://api.coval.dev/v1/scheduled-runs?page_size=100"

Paginate if `next_page_token` is present.

Build a lookup map of `display_name → ID` for each entity type. When checking for duplicates:
- If entity exists with `bluejay_migration: true` in metadata → **skip** (already migrated)
- If name collision with non-migrated entity → **ask user** whether to skip or rename
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` → **跳过**(已完成迁移)
- 若与非迁移实体重名 → **询问用户**是否跳过或重命名

Phase 1: Independent Entities (Steps 3–5)

第一阶段:独立实体(步骤3–5)

These have no cross-references. Execute in order but each step is independent.
这些实体无交叉引用,可按顺序执行,且每个步骤相互独立。

Step 3: Migrate Metrics

步骤3:迁移指标

Map Bluejay Custom Metrics → Coval Metrics.
For each Bluejay metric, use the mapping in references/metric-type-mapping.md.
For each metric:
  1. Determine
    metric_type
    from Bluejay
    response_type
  2. Build
    prompt
    from Bluejay
    scoring_guidance
    +
    description
  3. For
    qualitative
    → ask user for category list
  4. For
    quantitative
    → use Bluejay
    min_value
    /
    max_value
    if present, else ask
  5. For
    enum
    → use
    enum_options
    as
    categories
  6. If
    eval_route == "AUDIO"
    → use
    METRIC_AUDIO_LLM_*
    variants
  7. For
    json
    → use
    METRIC_LLM_BINARY
    , warn user this is an approximation
bash
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>"
    }
  }'
Add type-specific fields (
categories
,
min_value
,
max_value
) per the mapping table.
Record:
bluejay_metric_id → coval_metric_id
将Bluejay自定义指标映射至Coval指标。
对于每个Bluejay指标,使用references/metric-type-mapping.md中的映射规则。
每个指标的处理步骤:
  1. 根据Bluejay的
    response_type
    确定
    metric_type
  2. 从Bluejay的
    scoring_guidance
    +
    description
    构建
    prompt
  3. 若为
    qualitative
    类型 → 向用户询问分类列表
  4. 若为
    quantitative
    类型 → 若存在Bluejay的
    min_value
    /
    max_value
    则使用,否则询问用户
  5. 若为
    enum
    类型 → 将
    enum_options
    作为
    categories
  6. eval_route == "AUDIO"
    → 使用
    METRIC_AUDIO_LLM_*
    变体
  7. 若为
    json
    类型 → 使用
    METRIC_LLM_BINARY
    ,并告知用户这是近似处理
bash
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

Step 4: Migrate Personas

步骤4:迁移角色

Map Bluejay Digital Humans (voice/behavior) AND Customer Personas → Coval Personas.
将Bluejay数字人(语音/行为)和客户角色映射至Coval角色。

Digital Human → Persona

数字人 → 角色

For each unique digital human:
  1. Voice mapping — Present the Bluejay voice config to the user:
    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?
    Cache voice mappings — if same gender+accent+language combo appears again, reuse the mapping without asking.
  2. Map
    language
    language_code
    (e.g.,
    en
    en-US
    ,
    es
    es-ES
    )
  3. Map
    background_noise
    background_sound
    (see entity mapping reference)
  4. Build
    persona_prompt
    from
    role_description
    +
    traits
    + behavioral fields
bash
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>"
    }
  }'
Record:
bluejay_digital_human_id → coval_persona_id
对于每个唯一的数字人:
  1. 语音映射 — 向用户展示Bluejay语音配置:
    Bluejay数字人:"<name>"
      性别: <gender>
      口音: <accent>
      语言: <language>
    
    可用Coval语音:aria, asteria, athena, luna, ...
    
    该配置应映射到哪个Coval语音?
    缓存语音映射 — 若相同性别+口音+语言组合再次出现,直接复用映射无需询问。
  2. language
    映射为
    language_code
    (例如:
    en
    en-US
    es
    es-ES
  3. background_noise
    映射为
    background_sound
    (参考实体映射文档)
  4. role_description
    +
    traits
    + 行为字段构建
    persona_prompt
bash
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

Customer Persona → Persona

客户角色 → 角色

For each Bluejay Customer Persona:
bash
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"
    }
  }'
Ask user which voice to use for customer personas (default to
aria
).
对于每个Bluejay客户角色:
bash
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"
    }
  }'
询问用户客户角色使用的语音(默认使用
aria
)。

Step 5: Migrate Agents

步骤5:迁移Agent

Map Bluejay Agents → Coval Agents.
For each Bluejay agent:
  1. Determine
    model_type
    : Bluejay
    mode=VOICE
    MODEL_TYPE_VOICE
    ,
    mode=TEXT
    MODEL_TYPE_TEXT
  2. Build
    prompt
    from: latest Prompt version
    prompt_text
    + agent
    goals
    (append as numbered list)
  3. If agent has a
    system_prompt
    , prepend it to the prompt
  4. Store
    knowledge_base
    content in agent metadata
  5. If agent has a
    folder
    , prefix
    display_name
    with folder name:
    "[FolderName] AgentName"
bash
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>"
    }
  }'
Record:
bluejay_agent_id → coval_agent_id
将Bluejay Agent映射至Coval Agent。
对于每个Bluejay Agent:
  1. 确定
    model_type
    :Bluejay
    mode=VOICE
    MODEL_TYPE_VOICE
    mode=TEXT
    MODEL_TYPE_TEXT
  2. 构建
    prompt
    :最新提示词版本的
    prompt_text
    + Agent的
    goals
    (以编号列表追加)
  3. 若Agent存在
    system_prompt
    ,将其前置到prompt中
  4. 将知识库内容存储在Agent元数据中
  5. 若Agent属于某个文件夹,在
    display_name
    前添加文件夹名称:
    "[FolderName] AgentName"
bash
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

Phase 2: Dependent on Phase 1 (Steps 6–7)

第二阶段:依赖第一阶段(步骤6–7)

Step 6: Migrate Test Sets

步骤6:迁移测试集

Map Bluejay Simulations + Communities → Coval Test Sets.
将Bluejay Simulations + Communities映射至Coval Test Sets。

Simulation → Test Set

模拟场景 → 测试集

For each Bluejay simulation:
bash
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"
    }
  }'
Record:
bluejay_simulation_id → coval_test_set_id
对于每个Bluejay模拟场景:
bash
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": "从Bluejay模拟场景<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

Community → Test Set

社区 → 测试集

For each Bluejay community:
bash
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"
    }
  }'
Record:
bluejay_community_id → coval_test_set_id
对于每个Bluejay社区:
bash
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

Step 7: Migrate Test Cases

步骤7:迁移测试用例

Map Bluejay Digital Human intents → Coval Test Cases.
For each digital human associated with a simulation:
  1. Use
    intent
    input_str
  2. Use
    success_criteria
    expected_behaviors
    (split into array if multi-line)
  3. Look up
    coval_test_set_id
    from the simulation mapping (Step 6)
  4. If
    scripted_responses
    present → set
    input_type: "SCRIPT"
    with
    simulation_metadata_input.script_turns
bash
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>"
    }
  }'
For scripted test cases:
bash
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>"
    }
  }'
Record:
bluejay_digital_human_id → coval_test_case_id
将Bluejay数字人意图映射至Coval测试用例。
对于每个与模拟场景关联的数字人:
  1. 使用
    intent
    作为
    input_str
  2. 使用
    success_criteria
    作为
    expected_behaviors
    (若为多行则拆分为数组)
  3. 从步骤6的模拟场景映射中查找
    coval_test_set_id
  4. 若存在
    scripted_responses
    → 设置
    input_type: "SCRIPT"
    并传入
    simulation_metadata_input.script_turns
bash
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>"
    }
  }'
对于脚本化测试用例:
bash
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

Phase 3: Depends on Phase 1 + 2 (Step 8)

第三阶段:依赖第一、二阶段(步骤8)

Step 8: Migrate Run Templates

步骤8:迁移运行模板

Map Bluejay Simulations → Coval Run Templates.
For each Bluejay simulation, create a Run Template that ties together the migrated resources:
  1. Look up
    coval_agent_id
    from
    bluejay_agent_id
    (the simulation's agent)
  2. Pick the first persona mapped from a digital human in this simulation, or ask the user
  3. Look up
    coval_test_set_id
    from the simulation mapping
  4. Collect
    coval_metric_ids
    from the agent's associated metrics
bash
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>"
    }
  }'
Record:
bluejay_simulation_id → coval_run_template_id
将Bluejay Simulations映射至Coval Run Templates。
对于每个Bluejay模拟场景,创建一个关联已迁移资源的运行模板:
  1. bluejay_agent_id
    (模拟场景关联的Agent)查找
    coval_agent_id
  2. 选择该模拟场景中数字人映射的第一个角色,或询问用户
  3. 从模拟场景映射中查找
    coval_test_set_id
  4. 收集Agent关联指标对应的
    coval_metric_ids
bash
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": "从Bluejay模拟场景<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

Phase 4: Depends on Phase 3 (Step 9)

第四阶段:依赖第三阶段(步骤9)

Step 9: Migrate Scheduled Runs

步骤9:迁移调度任务

Map Bluejay Schedules → Coval Scheduled Runs.
All scheduled runs are created DISABLED for safety. The customer must manually enable them after review.
For each Bluejay schedule:
  1. Look up
    coval_run_template_id
    from the simulation mapping
  2. Convert schedule format:
    • Bluejay
      cron
      expression → Coval
      cron(...)
      format
    • Bluejay
      every_n_minutes
      rate(<n> minutes)
    • Bluejay
      every_n_hours
      rate(<n> hours)
    • Bluejay
      daily
      at HH:MM →
      cron(<MM> <HH> ? * * *)
    • Bluejay
      weekly
      cron(<MM> <HH> ? * <DAY> *)
    • Bluejay
      monthly
      cron(<MM> <HH> <DOM> * ? *)
bash
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>"
    }
  }'
Record:
bluejay_schedule_id → coval_scheduled_run_id
将Bluejay Schedules映射至Coval Scheduled Runs。
**出于安全考虑,所有创建的调度任务默认处于禁用状态。**客户需在审核后手动启用。
对于每个Bluejay调度任务:
  1. 从模拟场景映射中查找
    coval_run_template_id
  2. 转换调度格式:
    • Bluejay
      cron
      表达式 → Coval
      cron(...)
      格式
    • Bluejay
      every_n_minutes
      rate(<n> minutes)
    • Bluejay
      every_n_hours
      rate(<n> hours)
    • Bluejay
      daily
      于HH:MM →
      cron(<MM> <HH> ? * * *)
    • Bluejay
      weekly
      cron(<MM> <HH> ? * <DAY> *)
    • Bluejay
      monthly
      cron(<MM> <HH> <DOM> * ? *)
bash
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

Step 10: Migration Report

步骤10:迁移报告

Print a final summary:
undefined
打印最终汇总:
undefined

Migration Complete

迁移完成

Created Entities

创建的实体

TypeCountDetails
MetricsNbluejay_id → coval_id for each
PersonasN...
AgentsN...
Test SetsN...
Test CasesN...
Run TemplatesN...
Scheduled RunsN(all disabled)
类型数量详情
MetricsN每个实体的bluejay_id → coval_id映射
PersonasN...
AgentsN...
Test SetsN...
Test CasesN...
Run TemplatesN...
Scheduled RunsN(全部禁用)

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
  • 列出所有模糊映射或近似处理的内容
  • 记录所有映射为METRIC_LLM_BINARY的json类型指标
  • 记录所有需审核的语音映射

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
undefined
  1. 在Coval控制台查看已迁移实体:https://app.coval.dev
  2. 验证配置后启用调度任务
  3. 运行一个迁移后的运行模板进行测试验证
  4. 审核角色语音分配并按需调整
undefined

Error Handling

错误处理

  • HTTP 429 (Rate Limited): Wait 5 seconds and retry. Max 3 retries per request.
  • HTTP 400 (Bad Request): Show the error details to the user. Ask whether to fix the input and retry, or skip this entity.
  • HTTP 401/403 (Auth Error): Stop and ask user to verify their API key.
  • HTTP 500 (Server Error): Show error, skip entity, continue with others.
  • Network Error: Retry once after 3 seconds. If still failing, stop and report what was created so far.
After any failure, always show what has been successfully created so far so the user can resume.
  • HTTP 429(请求限流):等待5秒后重试,每个请求最多重试3次。
  • HTTP 400(请求错误):向用户展示错误详情,询问是否修正输入后重试,或跳过该实体。
  • HTTP 401/403(鉴权错误):停止操作并要求用户验证API密钥。
  • HTTP 500(服务器错误):展示错误信息,跳过该实体,继续处理其他内容。
  • 网络错误:等待3秒后重试一次。若仍失败,停止操作并报告已成功创建的内容。
无论发生何种失败,均需向用户展示已成功创建的内容,以便用户可以恢复迁移。

Idempotency Rules

幂等性规则

  1. Before creating any entity, check the name lookup from Step 2
  2. If entity exists with
    bluejay_migration: true
    in metadata → skip silently
  3. If name collision with non-migrated entity → ask user: "A Coval <entity_type> named '<name>' already exists but wasn't from a Bluejay migration. Skip, rename, or overwrite?"
  4. All created entities get metadata:
    { "bluejay_migration": true, "bluejay_original_id": "<id>" }
  5. Re-running the migration should produce zero new entities if nothing changed
  1. 创建任何实体前,检查步骤2中的名称查找映射
  2. 若实体元数据中存在
    bluejay_migration: true
    → 静默跳过
  3. 若与非迁移实体重名 → 询问用户:“名为'<name>'的Coval <entity_type>已存在,但并非来自Bluejay迁移。是否跳过、重命名或覆盖?”
  4. 所有创建的实体均添加元数据:
    { "bluejay_migration": true, "bluejay_original_id": "<id>" }
  5. 若未发生任何变更,重新运行迁移不应创建新实体