mcpField
M
makers-migration

makers-migration

github.com/tencentedgeone開発1.8k152 回インストール3 週間前に更新
リポジトリ

makers-migration について

AI エージェントプロジェクトを EdgeOne Makers に移行するためのガイドです。Python と Node/TypeScript のフレームワーク別変更点に加え、共通のプラットフォーム規約と検証手順を扱います。

主な機能

  1. 01フレームワーク別の移行手順
  2. 02Python と Node/TypeScript の解説
  3. 03環境変数と API の適応
  4. 04ツールと会話ストアの置き換え
  5. 05SSE レスポンスへの変換

活用シーン

  1. 01CrewAI プロジェクトの移行
  2. 02LangGraph エージェントの移行
  3. 03API ルートの Makers 対応
  4. 04デプロイ前の移行確認

MCP 対応

Claude Agent SDK プロジェクトの MCP ツールを `context.tools.toClaudeMcpServer()` で Makers に接続する方法を説明します。移行時に独自 MCP ツールを置き換える手順も扱います。

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/tencentedgeone/edgeone-makers-tools --skill makers-migration

インストール後、Claude Code で/makers-migrationを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
api-route-to-makers.md
claude-agent-sdk-to-makers.md
crewai-to-makers.md
deepagents-to-makers.md
langgraph-to-makers.md
openai-agents-to-makers.md

詳細

EdgeOne Makers 移行ガイド

既存の AI エージェントプロジェクトを EdgeOne Makers プラットフォーム形式に移行します。構造の変換、API の適応、プラットフォーム機能の注入を扱います。


移行判断ツリー

What type of project are you migrating?
├── Python project
│   ├── Using CrewAI → See §2 CrewAI
│   ├── Using LangChain/LangGraph/DeepAgents → See §3 LangGraph (Python)
│   ├── Using OpenAI Agents SDK → See §4 OpenAI Agents (Python)
│   └── Using Claude Agent SDK → See §5 Claude SDK (Python)
└── Node/TS project
    ├── Using Express/Next.js API routes → See §6 Express → Makers
    ├── Using LangGraph/DeepAgents → See §3 LangGraph (Node)
    ├── Using OpenAI Agents SDK → See §4 OpenAI Agents (Node)
    └── Using Claude Agent SDK → See §5 Claude SDK (Node)

⚠️ 移行チェックリスト(すべてのフレームワーク共通)

フレームワーク固有の変更を始める前に、以下の共通項目を確認してください。

  • agents.framework と buildCommand/outputDirectory が正しく設定された edgeone.json を作成する
  • バックエンドコードを Express のルート/Next.js の API ルートから agents/ ディレクトリに移動する
  • process.env/os.environ を context.env/ctx.env に置き換える
  • req.headers.get('x') を context.request.headers['x'](Node)または通常の辞書アクセス(Python)に置き換える
  • await req.json() を context.request.body(すでに解析済み)に置き換える
  • モデル API の直接呼び出し(OpenAI、Anthropic)を AI_GATEWAY_* 環境変数に置き換える
  • AI エンドポイントに SSE ストリーミングを追加する(res.json()/return {"data": ...} を置き換える)
  • フロントエンドの fetch 呼び出しに makers-conversation-id ヘッダーを追加する
  • 独自のツール実装ではなく、context.tools 経由でプラットフォームツールを接続する
  • インメモリまたは独自の DB ではなく、context.store 経由で会話履歴を接続する
  • web_search を使用する場合は、WSA_API_KEY 環境変数を設定し、context.tools.get("web_search") を使用する
  • ローカル開発用に edgeone makers dev を設定する

§1. 標準 API ルート → Makers ハンドラー

これは最も一般的な移行パターンです。Express/Next.js の API ルート、通常の HTTP ハンドラーなどに適用されます。

Node(Express/Next.js → Makers)
// ❌ Before: Next.js API route (app/api/chat/route.ts)
export async function POST(req: Request) {
  const body = await req.json();
  const headers = req.headers;
  const apiKey = process.env.OPENAI_API_KEY;
  // ... LLM call ...
  return Response.json({ data: result });
}

// ✅ After: Makers agent handler (agents/chat/index.ts)
export async function onRequest(context: any) {
  const body = context.request.body;               // already parsed
  const conversationId = context.conversation_id;   // auto-injected from header
  const env = context.env;                          // context.env, never process.env
  // ... LLM call via AI_GATEWAY_* ...
  return new Response(JSON.stringify({ data: result }), {
    headers: { 'Content-Type': 'application/json' },
  });
}
Python(Flask/FastAPI → Makers)
# ❌ Before: Flask route
@app.route('/chat', methods=['POST'])
def chat():
    body = request.get_json()
    api_key = os.environ.get('OPENAI_API_KEY')
    # ... LLM call ...
    return jsonify({'data': result})

# ✅ After: Makers agent handler (agents/chat/index.py)
async def handler(ctx):
    body = ctx.request.body
    conversation_id = ctx.conversation_id
    api_key = ctx.env.get("AI_GATEWAY_API_KEY")
    # ... LLM call via AI_GATEWAY_* ...
    return {"data": result}

§2. CrewAI(Python)

主な変更点
変更前変更後
os.environ.get("OPENAI_API_KEY")ctx.env.get("AI_GATEWAY_API_KEY")
LLM(provider="openai", ...) — LiteLLM によるディスパッチLLM(provider="openai", base_url=ctx.env["AI_GATEWAY_BASE_URL"], ...) — LiteLLM を経由しない
Crew で memory=Truememory=False + ctx.store を使用
verbose=Trueverbose=False(イベントは crewai_event_bus 経由)
crew.kickoff()(ブロッキング)await asyncio.to_thread(crew.kickoff)
カスタム検索ツールctx.tools.to_crewai_tools(BaseTool) を使用
Flask/FastAPI ハンドラーasync def handler(ctx): → ctx.utils.stream_sse(gen())
edgeone.json
{
  "buildCommand": "",
  "outputDirectory": "",
  "agents": {
    "framework": "crewai"
  }
}
要件
crewai>=1.14.5
openai>=1.50.0
移行手順
  1. Flask/FastAPI のエントリーポイントを async def handler(ctx): に置き換える
  2. 環境変数は ctx.env から読み取り、os.environ は使用しない
  3. LLM(provider="openai", api_key=ctx.env["AI_GATEWAY_API_KEY"], base_url=ctx.env["AI_GATEWAY_BASE_URL"]) を使用する
  4. Crew(memory=False, verbose=False) を設定する
  5. crew.kickoff() を asyncio.to_thread() でラップする
  6. カスタムツールを ctx.tools.to_crewai_tools(BaseTool) に置き換える
  7. ctx.utils.stream_sse(gen()) を介して SSE を返す

完全なパターンについては、makers-agents/skills/python-frameworks/crewai.md を参照してください。 変更前/変更後の詳細については、references/crewai-to-makers.md を参照してください。


§3. LangGraph / DeepAgents(Node + Python)

主な変更点
変更前変更後
モデルを直接作成(new ChatOpenAI(...))apiKey/baseURL に AI_GATEWAY_* を使用
MemorySaver(インメモリのチェックポインター)context.store.langgraphCheckpointer(永続化)
カスタムツール関数context.tools.toLangChainTools(tool)
agent.stream()createSSEResponse(gen, signal) による SSE(Node)、または ctx.utils.stream_sse(gen())(Python)
thread_id の手動管理thread_id = context.conversation_id
Node — edgeone.json
{
  "agents": {
    "framework": "langgraph"
  }
}
Python — edgeone.json
{
  "buildCommand": "",
  "outputDirectory": "",
  "agents": {
    "framework": "langgraph"
  }
}
移行手順
  1. ハンドラーを agents/<name>/index.ts(または .py)に移動します
  2. モデルの初期化を置き換えます。AI_GATEWAY_API_KEY と AI_GATEWAY_BASE_URL を使用します
  3. チェックポインターを置き換えます。MemorySaver の代わりに context.store.langgraphCheckpointer を使用します
  4. ストアを置き換えます。context.store.langgraphStore を使用します
  5. ツールを置き換えます。カスタムツール関数の代わりに context.tools.toLangChainTools(tool) を使用します
  6. thread_id を設定します。{ configurable: { thread_id: context.conversation_id } }
  7. レスポンスを SSE ストリーミングのパターンに置き換えます

Node:makers-agents/skills/node-frameworks/langgraph.md Python:makers-agents/skills/python-frameworks/langgraph.md DeepAgents:makers-agents/skills/node-frameworks/deepagents.md 移行前後の詳細:references/langgraph-to-makers.md、references/deepagents-to-makers.md


§4. OpenAI Agents SDK(Node + Python)

主な変更点
BeforeAfter
new OpenAI({ apiKey, baseURL })context.env / ctx.env から AI_GATEWAY_* を読み込みます
Runner.run(agent, input, { tools })context.tools.all() からツールを取得します(OpenAI の関数形式に変換済み)
セッション管理context.store.openaiSession(convId)(Node)
Express ルートのレスポンスcreateSSEResponse(gen, signal)(Node)または ctx.utils.stream_sse(gen())(Python)による SSE
モデル名のハードコード`ctx.env.AI_GATEWAY_MODEL
Node — edgeone.json
{
  "agents": {
    "framework": "openai-agents-sdk"
  }
}
Python — edgeone.json
{
  "buildCommand": "",
  "outputDirectory": "",
  "agents": {
    "framework": "openai-agents-sdk"
  }
}
移行手順
  1. ハンドラーを agents/<name>/index.ts(または .py)に移動します
  2. process.env ではなく context.env から OpenAI クライアントを作成します
  3. ツールを context.tools.all() に置き換えます(OpenAI の関数形式のツールを返します)
  4. セッションには context.store.openaiSession(conversationId) を使用します(Node)
  5. ストリームイベントを SSE に対応付けます。output_text_delta → ai_response、tool_called → tool_call

Node:makers-agents/skills/node-frameworks/openai-agents.md Python:makers-agents/skills/python-frameworks/openai-agents.md 移行前後の詳細:references/openai-agents-to-makers.md


§5. Claude Agent SDK(Node + Python)

主な変更点
BeforeAfter
ANTHROPIC_API_KEY 環境変数collectGatewayEnv() によって AI_GATEWAY_* からマッピングされます
process.envquery().options.env に注入される context.env
カスタム MCP ツールcontext.tools.toClaudeMcpServer()
セッションcontext.store.claudeSessionStore()(Node)
Stdout の EPIPE クラッシュprocess.stdout の EPIPE を無視します(Node)
書き込み可能な設定ディレクトリがないCLAUDE_CONFIG_DIR=/tmp/claude-agent-sdk、CLAUDE_CODE_TMPDIR=/tmp を設定します
Node — edgeone.json
{
  "agents": {
    "framework": "claude-agent-sdk"
  }
}
Python — edgeone.json
{
  "buildCommand": "",
  "outputDirectory": "",
  "agents": {
    "framework": "claude-agent-sdk"
  }
}
移行手順
  1. ハンドラーを agents/<name>/index.ts(または .py)に移動します
  2. collectGatewayEnv(context.env) を使って AI_GATEWAY_* → ANTHROPIC_* にマッピングします
  3. 環境変数を query({ options: { env: collectGatewayEnv(...) } }) に注入します
  4. MCP ツールを置き換えます。context.tools.toClaudeMcpServer('edgeone', { alwaysLoad: true })
  5. Node のみ:process.stdout の EPIPE を無視します
  6. 書き込み可能な設定ディレクトリを設定します。CLAUDE_CONFIG_DIR=/tmp/claude-agent-sdk、CLAUDE_CODE_TMPDIR=/tmp

Node:makers-agents/skills/node-frameworks/claude-sdk.md Python:makers-agents/skills/python-frameworks/claude-sdk.md 移行前後の詳細:references/claude-agent-sdk-to-makers.md


§6. Express / Next.js API Routes(Node)

Express ベースまたは Next.js API ルートを使用するエージェント向けの一般的な移行手順です。

7 ステップでの変換
ステップ変換前変換後
1. ファイルの場所app/api/chat/route.ts または server/routes/chat.tsagents/chat/index.ts
2. エントリーシグネチャexport async function POST(req) または app.post('/chat', handler)export async function onRequest(context)
3. ボディの解析await req.json()context.request.body(すでに解析済み)
4. ヘッダーreq.headers.get('x-foo')context.request.headers['x-foo']
5. 中断シグナルreq.signalcontext.request.signal(AbortSignal)
6. モデルへのアクセスprocess.env.OPENAI_API_KEY → 直接呼び出しcontext.env.AI_GATEWAY_* → AI Gateway
7. レスポンスres.json() または return Response.json()createSSEResponse(gen, signal) による SSE ストリーム
例:Next.js API ルートから Makers への移行
// ❌ Before: Next.js (app/api/chat/route.ts)
import { NextRequest } from 'next/server';
import OpenAI from 'openai';

export async function POST(req: NextRequest) {
  const { message } = await req.json();
  const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
  const response = await client.chat.completions.create({
    model: 'gpt-4o',
    messages: [{ role: 'user', content: message }],
    stream: true,
  });
  // ... stream back as Response
}

// ✅ After: EdgeOne Makers (agents/chat/index.ts)
import { createLogger, sseEvent, createSSEResponse } from '../_shared';

export async function onRequest(context: any) {
  const { message } = context.request.body ?? {};
  if (!message) return new Response('Missing message', { status: 400 });

  const signal = context.request.signal as AbortSignal;

  return createSSEResponse(async function* (sig) {
    const response = await fetch(context.env.AI_GATEWAY_BASE_URL + '/v1/chat/completions', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${context.env.AI_GATEWAY_API_KEY}`,
      },
      body: JSON.stringify({
        model: context.env.AI_GATEWAY_MODEL || '@makers/deepseek-v4-flash',
        messages: [{ role: 'user', content: message }],
        stream: true,
      }),
      signal: sig,
    });
    // ... proxy SSE chunks ...
    yield 'data: [DONE]\n\n';
  }, signal);
}

§7. クライアント側の移行

フロントエンドの fetch 呼び出し
// ❌ Before: plain fetch without conversation-id
const response = await fetch('/api/chat', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ message }),
});

// ✅ After: with makers-conversation-id header
const conversationId = getOrCreateConversationId(); // crypto.randomUUID() + localStorage
const response = await fetch('/chat', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'makers-conversation-id': conversationId,  // ⭐ required for all AI endpoints
  },
  body: JSON.stringify({ message }),
});
/stop エンドポイント
// ✅ Always pass conversation_id in body for /stop
await fetch('/stop', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ conversation_id: conversationId }),
});
SSE の解析
const reader = response.body!.getReader();
const decoder = new TextDecoder();
let buffer = '';

while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  buffer += decoder.decode(value, { stream: true });

  const lines = buffer.split('\n\n');
  buffer = lines.pop() || '';
  for (const line of lines) {
    if (line.startsWith('data: ')) {
      const data = line.slice(6);
      if (data === '[DONE]') return;
      try {
        const event = JSON.parse(data);
        if (event.type === 'ai_response') { /* display text */ }
        if (event.type === 'tool_call') { /* show tool call */ }
        if (event.type === 'ping') { /* ignore heartbeat */ }
      } catch { /* skip non-JSON */ }
    }
  }
}

§8. 移行後の検証

移行後、デプロイする前に以下の項目を確認してください。

  • edgeone makers dev がエラーなく起動する
  • /chat エンドポイントが SSE ストリーム(JSON ではない)を返す
  • AI の応答がエンドツーエンドで動作する(フロントエンド → エージェント → モデル → フロントエンド)
  • すべての箇所で context.env が使用されている(process.env / os.environ を grep し、残っていないことを確認する)
  • edgeone.json の agents.framework が正しく設定されている
  • プラットフォームツール(context.tools)が少なくとも 1 つのフレームワークで動作する
  • 会話履歴がリクエスト間で保持される(context.store 経由)
  • /stop エンドポイントが実行中の処理をキャンセルする
  • フロントエンドが makers-conversation-id ヘッダーを送信する

関連項目

変換前/変換後の詳細なリファレンスファイル

コメント