统一接口规范 - Run/Job Contract
定义 Node/LangGraph/n8n/Flowise 之间的标准通信协议
文档信息
| 属性 | 值 |
|---|---|
| 版本 | v1.0 |
| 创建日期 | 2024-12-14 |
| 状态 | 设计完成,待实施 |
| 目标 | 统一 Run(工作流运行)与 Job(外部任务)的接口形状 |
一、核心概念
1.1 Run vs Job
┌─────────────────────────────────────────────────────────────────────────────┐
│ Run(工作流运行单元) │
│ │
│ 代表一次完整的工作流执行,从 start 到 completed/failed │
│ 所有者:Node.js Task 表 │
│ 生命周期:pending → running → completed / failed / cancelled │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ 可以包含多个 Job │ │
│ │ │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │ Job 1 │ │ Job 2 │ │ Job 3 │ │ Job 4 │ │ │
│ │ │ n8n │ │ LangGraph│ │ Suno │ │ Flowise │ │ │
│ │ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘1.2 状态流转
Run 状态:
pending ─────────► running ─────────► completed
│ │
│ │
▼ ▼
failed cancelled
Job 状态:
pending ─────────► running ─────────► completed
│ │
│ │
▼ ▼
failed timeout二、Run 接口规范
2.1 Run 数据结构
typescript
/**
* Run - 工作流运行单元
* 对应 Node.js Task 表的一条记录
*/
interface Run {
// ===== 核心标识 =====
run_id: string; // UUID,主键
workflow_id: string; // 工作流 ID,如 "voiceover_video"
// ===== 状态 =====
status: RunStatus; // 运行状态
progress: number; // 进度百分比 0-100
// ===== 输入输出 =====
inputs: Record<string, any>; // 输入参数
outputs: Record<string, any> | null; // 输出结果(完成后才有)
// ===== 追踪 =====
trace: TraceStep[]; // 执行步骤记录
jobs: JobReference[]; // 关联的外部任务
// ===== 上下文 =====
user_context: {
user_id: number;
username?: string;
};
project_context?: {
project_id: string;
project_name?: string;
strategy_task_id?: string;
};
// ===== 触发信息 =====
trigger: 'manual' | 'scheduler' | 'webhook' | 'api';
triggered_by?: string; // 触发者标识
// ===== 时间戳 =====
created_at: string; // ISO 8601
started_at?: string; // 开始执行时间
updated_at: string; // 最后更新时间
completed_at?: string; // 完成时间
// ===== 错误信息 =====
error?: RunError;
}
type RunStatus =
| 'pending' // 等待执行
| 'running' // 执行中
| 'completed' // 成功完成
| 'failed' // 执行失败
| 'cancelled' // 已取消
| 'paused'; // 暂停(等待人工介入)
interface RunError {
code: string; // 错误码,如 "TIMEOUT", "AGENT_ERROR"
message: string; // 人类可读的错误信息
step_id?: string; // 出错的步骤 ID
details?: any; // 详细错误信息
}2.2 TraceStep 结构
typescript
/**
* TraceStep - 执行步骤记录
* 用于追踪、调试、回放
*/
interface TraceStep {
step_id: string; // 步骤 ID
step_name: string; // 步骤名称,如 "generate_script"
agent: string; // 执行的 Agent,如 "writing"
// ===== 执行信息 =====
status: 'pending' | 'running' | 'completed' | 'failed' | 'skipped';
inputs: Record<string, any>; // 步骤输入
outputs?: Record<string, any>;// 步骤输出
// ===== 时间 =====
started_at: string;
completed_at?: string;
duration_ms?: number; // 执行耗时(毫秒)
// ===== 质量指标 =====
confidence?: number; // Agent 置信度 0-1
tokens_used?: number; // 消耗的 Token 数
cost_usd?: number; // 成本(美元)
// ===== 错误 =====
error?: {
code: string;
message: string;
};
}2.3 JobReference 结构
typescript
/**
* JobReference - Run 中关联的 Job 引用
*/
interface JobReference {
job_id: string;
type: JobType;
status: JobStatus;
created_at: string;
resolved_at?: string;
}三、Job 接口规范
3.1 Job 数据结构
typescript
/**
* Job - 外部异步任务
* 用于跟踪 n8n/Suno/RunningHub 等外部系统的异步调用
*/
interface Job {
// ===== 核心标识 =====
job_id: string; // UUID,主键
run_id: string; // 关联的 Run ID
// ===== 类型 =====
type: JobType; // 任务类型
// ===== 状态 =====
status: JobStatus;
// ===== 请求信息 =====
request: {
url?: string; // 请求 URL
method?: string; // HTTP 方法
payload: any; // 请求负载
};
// ===== 回调配置 =====
callback: {
url: string; // 回调 URL
signature?: string; // 签名(用于验证)
};
// ===== 结果 =====
result: any | null; // 任务结果(完成后才有)
error?: {
code: string;
message: string;
details?: any;
};
// ===== 重试 =====
retry_count: number; // 已重试次数
max_retries: number; // 最大重试次数
// ===== 时间戳 =====
created_at: string;
timeout_at: string; // 超时时间
resolved_at?: string; // 完成/失败时间
}
type JobType =
| 'n8n' // n8n 工作流
| 'langgraph' // LangGraph 运行
| 'flowise' // Flowise 对话
| 'suno' // Suno 音乐生成
| 'runninghub' // RunningHub 视频生成
| 'fish_audio' // Fish Audio 语音合成
| 'tikhub'; // TikHub 视频解析
type JobStatus =
| 'pending' // 等待执行
| 'running' // 执行中
| 'completed' // 成功完成
| 'failed' // 执行失败
| 'timeout'; // 超时四、API 规范
4.1 启动工作流 - POST /api/workflow/start
请求
json
{
"workflow": "voiceover_video",
"project_id": "uuid-xxx",
"inputs": {
"topic": "美业账号如何做选题",
"platform": "douyin",
"style": "tutorial"
}
}响应(成功)
json
{
"success": true,
"run_id": "run-uuid-xxx",
"workflow": "voiceover_video",
"status": "pending",
"message": "Workflow started successfully"
}响应(失败)
json
{
"success": false,
"error": {
"code": "WORKFLOW_NOT_FOUND",
"message": "Workflow 'xxx' not found in registry"
}
}4.2 查询状态 - GET /api/workflow/status/:runId
响应
json
{
"success": true,
"run_id": "run-uuid-xxx",
"workflow": "voiceover_video",
"status": "running",
"progress": 45,
"current_step": "generate_visual",
"created_at": "2024-12-14T10:00:00Z",
"updated_at": "2024-12-14T10:02:30Z"
}4.3 获取结果 - GET /api/workflow/result/:runId
响应(进行中)
json
{
"success": true,
"run_id": "run-uuid-xxx",
"status": "running",
"message": "Workflow is still in progress",
"progress": 45
}响应(完成)
json
{
"success": true,
"run_id": "run-uuid-xxx",
"status": "completed",
"outputs": {
"script": "这里是生成的脚本内容...",
"title": "3个美业选题技巧",
"thumbnail_prompt": "beauty salon interior, professional lighting...",
"hooks": ["你知道吗?", "今天教你..."]
},
"trace": [
{
"step_id": "generate_script",
"agent": "writing",
"status": "completed",
"duration_ms": 3500
},
...
]
}4.4 获取追踪 - GET /api/workflow/trace/:runId
响应
json
{
"success": true,
"run_id": "run-uuid-xxx",
"trace": [
{
"step_id": "generate_script",
"step_name": "生成脚本",
"agent": "writing",
"status": "completed",
"inputs": { "topic": "..." },
"outputs": { "script": "..." },
"started_at": "2024-12-14T10:00:05Z",
"completed_at": "2024-12-14T10:00:09Z",
"duration_ms": 3500,
"confidence": 0.92,
"tokens_used": 1250
},
{
"step_id": "generate_visual",
"step_name": "生成封面提示词",
"agent": "visual",
"status": "completed",
...
}
]
}4.5 取消工作流 - POST /api/workflow/cancel/:runId
响应
json
{
"success": true,
"run_id": "run-uuid-xxx",
"status": "cancelled",
"message": "Workflow cancelled successfully"
}4.6 恢复工作流 - POST /api/workflow/resume/:runId
请求
json
{
"input": {
"user_feedback": "请使用更口语化的表达"
}
}响应
json
{
"success": true,
"run_id": "run-uuid-xxx",
"status": "running",
"message": "Workflow resumed successfully"
}五、回调规范
5.1 LangGraph → Node 回调
URL: POST /api/webhooks/langgraph-callback
请求
json
{
"run_id": "run-uuid-xxx",
"job_id": "job-uuid-xxx",
"status": "completed",
"outputs": {
"script": "...",
"title": "..."
},
"trace": [...],
"metadata": {
"total_tokens": 5000,
"total_cost_usd": 0.05,
"duration_ms": 12000
}
}签名验证
X-Signature: sha256=xxxxxx5.2 n8n → Node 回调
URL: POST /api/webhooks/n8n-callback
请求
json
{
"job_id": "job-uuid-xxx",
"workflow_name": "suno_music_generation",
"status": "completed",
"result": {
"audio_url": "https://...",
"duration": 30,
"style": "lofi"
}
}5.3 Suno/RunningHub → Node 回调
URL: POST /api/webhooks/ai-callback
请求
json
{
"job_id": "job-uuid-xxx",
"type": "suno",
"status": "completed",
"result": {
"audio_url": "https://...",
"cover_url": "https://..."
}
}六、错误码规范
6.1 通用错误码(1xxx)
| 错误码 | 名称 | 说明 |
|---|---|---|
| 1000 | UNKNOWN_ERROR | 未知错误 |
| 1001 | VALIDATION_ERROR | 参数校验失败 |
| 1002 | AUTHENTICATION_ERROR | 认证失败 |
| 1003 | AUTHORIZATION_ERROR | 权限不足 |
| 1004 | NOT_FOUND | 资源不存在 |
| 1005 | RATE_LIMIT_EXCEEDED | 请求频率超限 |
6.2 工作流错误码(2xxx)
| 错误码 | 名称 | 说明 |
|---|---|---|
| 2000 | WORKFLOW_NOT_FOUND | 工作流不存在 |
| 2001 | WORKFLOW_ALREADY_RUNNING | 工作流已在运行 |
| 2002 | WORKFLOW_TIMEOUT | 工作流执行超时 |
| 2003 | WORKFLOW_CANCELLED | 工作流被取消 |
| 2004 | WORKFLOW_STEP_FAILED | 步骤执行失败 |
| 2005 | WORKFLOW_INVALID_STATE | 工作流状态无效 |
6.3 Agent 错误码(3xxx)
| 错误码 | 名称 | 说明 |
|---|---|---|
| 3000 | AGENT_NOT_FOUND | Agent 不存在 |
| 3001 | AGENT_EXECUTION_FAILED | Agent 执行失败 |
| 3002 | AGENT_TIMEOUT | Agent 执行超时 |
| 3003 | AGENT_INVALID_OUTPUT | Agent 输出格式无效 |
| 3004 | AGENT_TOOL_FAILED | Agent 工具调用失败 |
6.4 外部服务错误码(4xxx)
| 错误码 | 名称 | 说明 |
|---|---|---|
| 4000 | EXTERNAL_SERVICE_ERROR | 外部服务错误 |
| 4001 | N8N_WEBHOOK_FAILED | n8n Webhook 调用失败 |
| 4002 | LANGGRAPH_RUNNER_ERROR | LangGraph Runner 错误 |
| 4003 | FLOWISE_ERROR | Flowise 调用失败 |
| 4004 | SUNO_API_ERROR | Suno API 错误 |
| 4005 | RUNNINGHUB_ERROR | RunningHub 错误 |
| 4006 | CALLBACK_VERIFICATION_FAILED | 回调签名验证失败 |
6.5 资源错误码(5xxx)
| 错误码 | 名称 | 说明 |
|---|---|---|
| 5000 | RESOURCE_EXHAUSTED | 资源耗尽 |
| 5001 | QUOTA_EXCEEDED | 配额超限 |
| 5002 | CREDITS_INSUFFICIENT | 积分不足 |
| 5003 | STORAGE_FULL | 存储空间已满 |
七、重试策略
7.1 Run 级别重试
| 场景 | 策略 | 说明 |
|---|---|---|
| 网络超时 | 自动重试 3 次 | 间隔 1s/2s/4s 指数退避 |
| Agent 失败 | 自动重试 2 次 | 可配置 |
| 外部服务错误 | 不自动重试 | 人工介入 |
7.2 Job 级别重试
| Job 类型 | 最大重试 | 超时时间 | 退避策略 |
|---|---|---|---|
| n8n | 3 | 60s | 指数 |
| langgraph | 2 | 120s | 指数 |
| flowise | 2 | 30s | 固定 |
| suno | 0 | 300s | 无 |
| runninghub | 0 | 600s | 无 |
7.3 降级策略
typescript
// 当外部服务不可用时的降级
const degradationConfig = {
flowise: {
enabled: true,
fallback: 'local_prompt' // 使用本地 prompt 模板
},
n8n: {
enabled: true,
fallback: 'node_scheduler' // 回退到 Node setInterval
},
langgraph: {
enabled: true,
fallback: 'workflow_engine' // 回退到现有 WorkflowEngine
}
};八、监控与告警
8.1 关键指标
| 指标 | 说明 | 告警阈值 |
|---|---|---|
| run_success_rate | Run 成功率 | < 95% |
| run_avg_duration | Run 平均耗时 | > 60s |
| job_timeout_rate | Job 超时率 | > 5% |
| agent_error_rate | Agent 错误率 | > 10% |
| callback_delay | 回调延迟 | > 5s |
8.2 日志格式
json
{
"timestamp": "2024-12-14T10:00:00.000Z",
"level": "info",
"service": "workflow-service",
"run_id": "run-uuid-xxx",
"job_id": "job-uuid-xxx",
"event": "step_completed",
"step_id": "generate_script",
"agent": "writing",
"duration_ms": 3500,
"tokens_used": 1250
}九、版本兼容
9.1 API 版本
- 当前版本:v1
- URL 前缀:
/api/workflow/*(无版本号,默认 v1) - 未来版本:
/api/v2/workflow/*
9.2 向后兼容承诺
- 新增字段:不破坏现有客户端
- 删除字段:提前 2 个版本标记 deprecated
- 类型变更:不允许,必须新增字段
十、相关文档
- KKMUSIC_ARCHITECTURE_BLUEPRINT.md - 整体架构蓝图
- WORKFLOW_MIGRATION_ROADMAP.md - 迁移路线
文档维护者:一刻工坊技术团队
最后更新:2024-12-14