コードによるワークフロー管理
PythonおよびJavaScript SDKでエージェントのワークフローを構築、編集、バージョン管理
概要
ワークフローは、ノードとエッジのグラフとして保存されます。このグラフを手動で記述する場合、エッジID、edge_order リスト、条件オブジェクトの整合性を自分で保つ必要があります。PythonおよびJavaScript SDKの Workflow ビルダーを使うと、同じグラフをメソッドチェーンで記述できます。ビルダーは、agents.create() と agents.update() がそのまま受け取れる workflow 値を生成します。
次の用途に使用できます。
- ワークフローをコードで構築し、ほかのコード変更と同じようにレビューする。
- エージェントのワークフローを読み込み、グラフのほかの部分に影響を与えずに1つのノードだけを変更して反映する。
- ワークフローをJSONとしてバージョン管理に保存し、CIで検証する。
ビルダーはSDK内だけで動作します。新しいAPIエンドポイントは呼び出しません。また、ビルダーで構築したものはすべて ダッシュボードのビジュアルエディターで開いて編集できます。
要件
- Python:
elevenlabsパッケージ。ビルダーはelevenlabs.agent_workflowsからインポートします。 - JavaScript:
@elevenlabs/elevenlabs-jsパッケージ。ビルダーはパッケージルートからエクスポートされます。
ワークフローを構築する
Workflow オブジェクトは開始ノードを表します。各動詞メソッドはノードを追加してそのノードを返すため、そこから次のステップをチェーンできます。
ルーティングメソッドは、次のノードへ進むエッジを決定します。
ワークフロー上で動詞メソッドを直接呼び出すと、無条件エッジによって開始ノードから分岐します。次の例では、発信者を注文検索へ誘導し、検索に失敗した場合は本人確認を再試行し、VIPまたは不満を抱えている発信者を転送します。
build() はグラフ全体を検証し、リクエストモデルを返します。また、次の処理も行います。
- APIで必須のID
start_nodeを開始ノードに付けます。 source__target形式でエッジIDを生成します。- エッジを追加した順に、各ノードの
edge_orderを設定します。 - 位置が指定されていないノードを配置し、ビジュアルエディターでグラフが左から右へ並ぶようにします。
ワークフローを1つのチェーンとして記述する
up() は現在のノードのチェーン元を返すため、各ノードを変数に保持せずに、ワークフロー全体を1つの式で記述できます。単一のチェーン内では渡す変数がないため、ノードIDを指定して go_to() / goTo() を使用します。
wf.node(id) から取得したノードハンドルでは、up() はそのノードに最初に入るエッジの接続元ノードを返します。開始ノードでは、開始ノード自身を返します。
ノードのオプション
オプション設定は、Pythonではキーワード引数、JavaScriptでは末尾のoptionsオブジェクトに指定します。名前はAPIのノードフィールドと一致します。
ノードを自分で配置したい場合は、すべての動詞メソッドで position も指定できます。Pythonの Workflow(prevent_subagent_loops=True)、またはJavaScriptの new Workflow({ preventSubagentLoops: true }) を使用すると、会話が一度訪れたサブエージェントに再び入るのを防止できます。
転送先
条件
when() は、プレーン文字列、Condition、または Expr を受け取ります。
- 文字列はLLM条件です。条件が成立するかどうかをLLMが判断します。
Condition.llm(text, label=...)も同じですが、ビジュアルエディターでエッジにラベルが表示されます。式にラベルを付けるには、Condition.expr(expr, label=...)を使用します。ExprはLLMを呼び出さずに、動的変数に対して評価されます。
式は Expr.variable(name) と Expr.literal(value) から構築します。eq、neq、gt、gte、lt、lte で比較し、add、sub、mul、div で算術演算を行います。all_of / allOf、any_of / anyOf、if_else / ifElse で組み合わせます。プレーンな値は自動的に Expr.literal() でラップされます。Expr.llm(description) は、会話から値を抽出するようLLMに要求します。ブール値ではなく、文字列、数値、または固定された選択肢のいずれかを取得するには、type と enum を渡します。
ループと後方エッジ
APIでは、任意の2つのノード間にどちらか一方向のエッジを1つ作成できます。会話が来た経路を戻れるようにするには、back でエッジに後方条件を指定します。
go_to() / goTo() は、この一般的なケースを自動的に処理します。対象ノードから現在のノードへ進むエッジがすでにある場合、新しいエッジはそのエッジの後方条件になります。最初の例では、failed.go_to(identify) は identify → lookup_order エッジの後方条件として送信されます。同じ2つのノード間にほかの2本目のエッジがある場合や、ノードからそのノード自身へのエッジがある場合は、検証に失敗します。
既存のエージェントを編集する
Workflow.from_agent() / Workflow.fromAgent() は、agents.get() が返したエージェントのワークフローを読み込みます。ノードID、エッジID、エディター上の位置、エッジの順序は維持されるため、再反映しても変更した箇所だけが更新されます。
insert_between() / insertBetween() は、置き換えるエッジの条件を保持するブランチを関数に渡します。関数は最後に追加したノードを返し、そのノードが元の対象ノードに接続されます。このメソッドはそのノードを返します。2つのノード間にエッジがない場合は、None / undefined を返します。
ワークフローをバージョン管理に保存する
to_json_string() / toJSONString() は、APIのワイヤー形式でワークフローを書き出します。キーはsnake_caseで、すべての階層で並べ替えられ、2スペースでインデントされます。REST APIおよびCLIが使用するものと同じ構造です。両方のSDKは同じワークフローに対してバイト単位で同一のファイルを書き出すため、差分を小さく保てます。Workflow.from_json() / Workflow.fromJSON() で再度読み込めます。また、CLIの agent_configs/ ディレクトリ内のファイルなど、workflow キーを持つ完全なエージェント設定も読み込めます。
一般的な設定手順は次のとおりです。
ワークフローを可視化する
CLIはワークフローファイルをフローチャートとして描画するため、ダッシュボードを開かずにコードが構築した内容を確認できます。to_json_string() / toJSONString() で書き出したワークフロー単体のファイル、または workflow キーを持つエージェント設定を読み込めます。
デフォルトでは、ターミナルにボックスと矢印が描画されます。各エッジの条件にはエッジ上で番号が付けられ、下部の凡例に内容が表示されます。代わりにMermaidソースを出力するには --format mermaid を使用します。プルリクエストのコメントなどで、GitHubがレンダリングできるコードブロックとして出力するには --format mermaid-md を使用します。
このコマンドはローカルファイルだけを読み込むため、APIキーは不要で、CIでも実行できます。
検証
チェーンされた呼び出し自体が失敗することはありません。build()、to_json() / toJSON()、to_json_string() / toJSONString() はグラフ全体をチェックし、単一の WorkflowValidationError を発生させます。その issues にはすべての問題が列挙され、各問題には code、message、および関連する node_id / nodeId が含まれます。
エラーには次のものがあります。
- 同じノードのペア間に2つのエッジがある、またはノードからそのノード自身へのエッジがある。
- 開始ノードに入るエッジ、または終了ノードから出るエッジがある。
- ツールノードから出るエッジが成功エッジでも失敗エッジでもない、またはほかの種類のノードから成功エッジや失敗エッジが出ている。
- 同じIDを持つノードが2つある、または存在しないノードへのエッジがある。
開始ノードから到達できないノードは、on_warning / onWarning を通じて警告として報告されますが、ビルドは停止しません。
SDKより新しいノードタイプ
APIまたはファイルから読み込んだワークフローには、使用中のSDKバージョンがまだ認識していないノードタイプが含まれる場合があります。これらは from_json() / fromJSON() と to_json_string() / toJSONString() を通じて変更されずにラウンドトリップされ、build() はそれぞれを警告として報告します。型付きリクエストモデルではこれらを保持できないため、SDKをアップグレードするか、ワイヤー形式を直接送信してください。