mcpField
C
camunda-ai-agents

camunda-ai-agents

github.com/camundaエージェントワークフロー26115 回インストール1 日前に更新
リポジトリ

camunda-ai-agents について

camunda-ai-agentsは、Camunda 8.8以降でエージェント型AIプロセスを設計するスキルです。AI Agentコネクタの設定、BPMNツールとプロンプトの定義、エージェントのコンテキストと応答の扱いを説明します。

主な機能

  1. 01アドホックサブプロセスでのエージェント設計
  2. 02AI Agentコネクタテンプレートの設定
  3. 03BPMNアクティビティによるツール定義
  4. 04fromAi()によるツール入力の宣言
  5. 05プロンプトと応答処理の設定
  6. 06v1・v2テンプレートの移行対応

活用シーン

  1. 01LLMエージェントを呼び出すプロセスの構築
  2. 02REST呼び出しのエージェントツール化
  3. 03生成パラメーターのBPMNアクティビティへの受け渡し
  4. 04AI Agentテンプレートのv1からv2への更新

インストール

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

$npx skills add https://github.com/camunda/skills --skill camunda-ai-agents

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

同梱ファイル

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

portability.json
references/
ai-agent-task.md
fromai.md
tool-modeling.md
v1-to-v2-upgrade.md

詳細

Camunda AI エージェント

Camunda 8.8+ でエージェント型 AI プロセスを構築します。LLM ドライバー(AI Agent コネクターのサブプロセスバリアント)を、ツールを BPMN アクティビティとしてモデル化したアドホックサブプロセスに適用します。構成、プロンプト、fromAi() を使ったツールのモデル化、サブフローツール、複数ターンにわたるエージェントのコンテキストを扱います。

旧来のタスクバリアント(サービスタスク上の AI Agent コネクターを、外部のマルチインスタンスアドホックサブプロセスおよび明示的なフィードバックループと組み合わせる方式)については、すべてのツール呼び出しを監査またはインターセプトする必要があるニッチなケース向けに、references/ai-agent-task.md で説明しています。それ以外のすべてのケースにはサブプロセスバリアントを推奨します。このスキルの以降の内容でも、サブプロセスバリアントを扱います。

前提条件

  • Camunda 8.8+ クラスター(AI Agent コネクターは 8.8+ に付属します)
  • c8ctl CLI がインストールされ、プロファイルが設定されていること — camunda-c8ctl を参照してください
  • プロバイダー、正確なモデル識別子、および既存のコネクターシークレット名。これらはユーザーから提供されます。シークレット値は Camunda クラスターシークレットとして保存し、BPMN ファイルには決して保存しないでください。ローカルの c8run については、シークレットのブートストラップ手順を camunda-c8ctl で確認してください。

プロバイダーの設定

BPMN の作成または編集を始める前に、プロバイダー、正確なモデル識別子、および必要な既存コネクターシークレット名をすべて確認してください。不足している情報があれば、ユーザーに確認し、確認が取れるまで作業を停止してください。デフォルトのプロバイダーやモデルを選択したり、シークレット名を作り出したり、シークレット値を尋ねたりしないでください。選択したテンプレートを調べ、プロバイダー固有のモデルおよび認証フィールドを確認してください。

Camunda ホスト型コネクターを使う Camunda SaaS では、Console でシークレット値を設定してください。確認済みのシークレット名を BPMN 内で {{secrets.NAME}} の参照として使用します。

関連項目

  • camunda-bpmn:BPMN の基本、アドホックサブプロセス要素、名前空間、必須の lint ループ。
  • camunda-connectors:AI Agent テンプレートの適用に使う基盤の c8ctl element-template ワークフロー(およびツールとしてよく使われる REST コネクター)。
  • camunda-feel:プロンプト、fromAi() 呼び出し、結果式、型変換に使う FEEL 構文。
  • camunda-process-mgmt:プロセスのデプロイ、インスタンスの開始、エージェント呼び出しに起因するインシデントの調査。

参照資料

テンプレートの世代:v1 と v2

Camunda 8.10 では、v2 の AI Agent 要素テンプレート(ID のサフィックスは .v2。例:io.camunda.connectors.agenticai.ai-agent-subprocess.v2)が導入され (8.10 以降)、v1(例:io.camunda.connectors.agenticai.aiagent.jobworker.v1)は非推奨になりました。これらはジョブタイプが異なる別々のテンプレートです。v1 は現在も動作しますが、非推奨であり、新しいプロバイダー機能は追加されません。

v2 では、推論/思考の設定、プロンプトキャッシュ、プロバイダーとバックエンドの選択の分離(例:AWS Bedrock Mantle または Foundry 上の Anthropic)、カスタムチャットモデルプロバイダーが追加されています。

  • 新しいエージェント、8.10 以降のクラスター:v2。
  • 8.10 未満のクラスター、または 5.51.0 未満の Desktop Modeler:v1 — v2 には 8.10 のエンジンが必要で、古い Modeler では 見つかりません と表示されます。
  • 既存の v1 要素、8.10 以降のクラスター:v2 にアップグレードしてください — v1 は非推奨です。v1 は引き続き動作するため、アップグレードは後回しにできます。v1 のままで更新する(--to を指定しない)のは一時的な対処にすぎません。リファレンスを参照してください。

切り替えは再デプロイごとに適用されます。実行中のインスタンスは、引き続き v1 のジョブワーカーで実行されます。

c8ctl element-template search "ai agent" は両方の世代を返します。以下の適用例にあるプロバイダーの --set パスは v1 の形式です。v2 では認証情報が backend.<type> の下にネストされます(例:provider.anthropic.backend.anthropic.apiKey)。選択したテンプレートについては、c8ctl element-template get-properties <id> を参照してください。

v1 から v2 への移行については、references/v1-to-v2-upgrade.md をお読みください。

AI Agent Connector の適用

アドホックサブプロセスだけでは AI エージェントになりません。AI Agent Sub-process コネクターテンプレートを適用してください。汎用サブプロセスやサービスタスクで代用しないでください。

例 — プロバイダー/プロンプト/メモリの多数のフィールドを手作業で記述するのではなく、c8ctl を使ってテンプレートを適用します。

# 0. One-time per environment: sync the OOTB catalog. search,
#    get-properties, and OOTB-ID apply need this to have run at
#    least once. Skip on subsequent runs.
c8ctl element-template sync

# 1. Find the current template ID and version — they evolve
c8ctl element-template search "ai agent"

# 2. Inspect the selected provider's model and authentication fields.
c8ctl element-template get-properties <id>
c8ctl element-template get-properties <id> --detailed data.systemPrompt.prompt

# 3. Replace placeholders with user-supplied values and selected-template fields.
c8ctl element-template apply -i <id> AgentTools process.bpmn \
  --set 'provider.type=<provider>' \
  --set 'provider.<provider>.authentication.<field>={{secrets.<secret-name>}}' \
  --set 'provider.<provider>.model.<field>=<model>' \
  --set data.systemPrompt.prompt='="You are a customer support agent. Use the available tools to look up customers and orders, and escalate to a human only when needed."' \
  --set data.userPrompt.prompt='="Customer " + customerId + " reports: " + issue' \
  --set data.limits.maxModelCalls='=10'

テンプレートは zeebe:taskDefinition、zeebe:adHoc のコレクションバインディング、デフォルトの入力マッピング、およびモデルプロバイダー固有のフィールドを処理します。これらはテンプレートのバージョンによって異なるため、手作業で記述しないでください。

対応プロバイダー:

  • v1 provider.type:anthropic、bedrock、azureOpenAi、google-vertex-ai、openai、openaiCompatible。
  • v2 provider.type:anthropic、bedrock、openai、google-gemini、mistral、custom。Azure/Foundry、Vertex AI、OpenAI-compatible は、これらのバックエンドです。

BPMN の形状

ホストは bpmn:adHocSubProcess です。サービスタスクでも通常のサブプロセスでもありません。ツールはその中に配置します。

bpmn:adHocSubProcess  (template applied here)
└── <root activities, each one a tool>
    bpmn:serviceTask   — e.g., REST connector call
    bpmn:scriptTask    — FEEL computation
    bpmn:userTask      — human-in-the-loop
    bpmn:subProcess    — multi-step or async tool

lint ループでは検出されない重要なルールです。BPMN を読んで確認してください。

  • 要素の型は bpmn:adHocSubProcess でなければなりません。通常の bpmn:subProcess やサービスタスクでは、コネクターをホストできません。
  • ツールのルートノードは、LLM が選択するエントリーアクティビティです。ルートノードには入力シーケンスフローがなく、境界イベントでもありません。入力フローがあると、そのノードは通常のフローステップになり、エージェントには認識されません。
  • アドホックサブプロセスには、少なくとも 1 つのアクティビティを含める必要があります。これは BPMN のセマンティクスであり、空のエージェントは拒否されます。
  • ツールの実行フローのどこかで、変数 toolCallResult を設定する必要があります。単一アクティビティのツールではそのアクティビティ自体が該当し、サブフローツールではサブフロー内の任意のアクティビティを使用できます。

ツールの定義

複数の部分からなるレビューでは、包括的なタスクではなく、独立した各チェックを焦点を絞ったルートツールとしてモデル化します。

LLM がツールを正しく選択するかどうかは、次の 3 つで決まります。

  1. ツール名 — アドホックサブプロセス内の アクティビティ ID(例:LookupCustomer、GetCurrentWeather)。コネクターは、人が見るための name 属性ではなく BPMN の id をツール名として LLM に渡します。内容が伝わる ID を選んでください。

  2. ツールの説明 — アクティビティの <bpmn:documentation> の値です。ドキュメントがない場合、コネクターはアクティビティの name 属性を代わりに使用しますが、必ず documentation を明示的に設定してください。適切な説明では、ツールの機能、使用する状況、使用しない状況、返される内容を示します。

    「ID で顧客を検索します。顧客の名前、ティア、アカウントのステータスを返します。ユーザーが顧客 ID または名前に言及した場合に呼び出してください。匿名の問い合わせでは呼び出さないでください。」

    LLM には説明がそのまま表示されます。ベンダー名、内部 URL、またはそのまま引用されたくない情報は含めないでください。c8ctl element-template apply は <bpmn:documentation> を書き込みません。ツールコネクターテンプレートを適用した後、手動で追記してください。

  3. 入力スキーマ — アクティビティの入力マッピング内にある fromAi() 呼び出しから自動的に導出されます。fromAi() の呼び出しがないと、スキーマは空になり、LLM はパラメーターを渡せません。

ツールは 単一のアクティビティ(サービスタスク、スクリプトタスク、ユーザータスク)にも、さらにアクティビティを含む bpmn:subProcess をルートとする サブフロー にもできます。どちらの場合も、LLM に見えるのはルートノードのみです。説明、入力、スキーマはそこから読み取られます。内部のサブフローステップは LLM からは見えません。通常の BPMN のセマンティクスに従って順番に実行され、サブプロセスの完了時に変数が上位に伝播されます。

サブフローツールの場合、これは文字どおりです。fromAi() 呼び出しは、子孫のアクティビティではなく、bpmn:subProcess ルート自身の zeebe:ioMapping に配置してください。子タスクの fromAi() は空のスキーマを生成するため、LLM は引数なしでツールを呼び出し、フォームフィールドを含むすべての下流の値が null になります。

4 種類(REST、スクリプト、ユーザータスク、サブフロー)の XML の例は、references/tool-modeling.md にあります。

fromAi() — AI 生成パラメーターの宣言

fromAi() は、値に「LLM が実行時にこれを提供する」というタグを付けます。最初の引数には toolCall.<paramName> への参照を指定する必要があります。最後のセグメントが、LLM から見えるパラメーター名になります。この関数は、省略可能な説明、型(デフォルトは "string"。さらに "number"、"boolean"、"array"、"object")、JSON Schema のフラグメント、および {required: false} などを指定するオプションコンテキストを受け取ります。

<zeebe:input
  source='="https://api.example.com/customers/" + fromAi(toolCall.id, "Customer ID", "string")'
  target="url" />

完全なシグネチャと、6 種類すべての呼び出し形式(位置指定、名前付き、列挙型スキーマ、省略可能なパラメーター、複数呼び出しの JSON 本文)については、references/fromai.md を参照してください。

toolCallResult — エージェントへの出力の返却

ツールの処理が完了すると、コネクターはツールのスコープから toolCallResult という名前の変数を読み取り、ツール呼び出しの応答として LLM に転送します。このルールで重要なのは、どのアクティビティが設定するかではなく、スコープです。

  • 単一アクティビティのツール — アクティビティ自体が toolCallResult を設定します(結果式/結果変数/出力マッピング/スクリプトの結果変数を使用)。
  • サブフローツール — サブフロー内の任意のアクティビティが toolCallResult を設定できます。BPMN の変数スコープにより、サブプロセスの完了時に値がそのスコープへ引き継がれます。

アクティビティの種類に応じた設定方法:

  • 結果式を使用するコネクター:value="={toolCallResult: response.body}"。
  • 結果変数を使用するコネクター:結果変数の名前を toolCallResult にします。
  • 出力マッピング:<zeebe:output source="=someValue" target="toolCallResult" />。
  • スクリプトタスク:<zeebe:script expression="..." resultVariable="toolCallResult" />。

値にはプリミティブ型(文字列、数値)または複雑な FEEL コンテキストを指定できます。LLM に送信する前に JSON にシリアライズされます。ツールの処理が完了した時点で toolCallResult が未設定または空の場合、コネクターは「ツールは成功しましたが、結果が返されませんでした」という汎用メッセージを LLM に送り、次のターンの品質が低下します。必ず意味のある値を設定してください。

プロンプト

data.systemPrompt.prompt と data.userPrompt.prompt はどちらも FEEL 文字列で、= で始まります。

<zeebe:input
  source='="You are a customer support agent. Use available tools to look up customers and orders. Escalate to a human only when needed."'
  target="data.systemPrompt.prompt" />
<zeebe:input
  source='="Customer " + customerId + " (priority: " + priority + ") reports: " + issue'
  target="data.userPrompt.prompt" />
  • 静的プロンプト:="You are ..."。プレーンテキストの場合も = は必須です。
  • 変数の補間:="Customer " + customerId + " reports: " + issue。+ はスカラー値を文字列に変換します。
  • フィードバックループのプロンプト:=if (is defined(followUpInput)) then followUpInput else initialUserInput。ユーザーの追加入力を受けてエージェントに戻るループで使用します。詳しくは、以下の「応答インタラクション」を参照してください。

長く構造化されたプロンプトを使う場合は、上流のスクリプトタスクで文字列を組み立て、変数として渡してください。

ツール呼び出しのフィードバックループ

ツールのフィードバックループは内部処理です。エージェントジョブワーカーは LLM を繰り返し呼び出し、LLM が選択したツールを実行して結果を収集し、LLM が最終応答を生成するか data.limits.maxModelCalls に達するまで再度プロンプトを送信します。ループをモデル化する必要はありません。モデル化するのはツールのみです。

エージェントの応答の読み取り

エージェントは、コネクターの結果変数フィールドで指定された単一のコンテキスト変数に出力を書き込みます。デフォルトは agent です。同じプロセスに複数のエージェントがある場合は、それぞれに固有の結果変数名(例:mySecondAgent)を付け、エージェントコンテキストの入力フィールドもそれに合わせて(mySecondAgent.context など)変更し、エージェント間の干渉を避けてください。

結果コンテキストに含まれるフィールドは、応答の設定によって異なります(以下の例ではデフォルトの agent を使用します)。

  • agent.responseText — data.response.format.type=text の場合(デフォルト)。
  • agent.responseJson — format=json の場合、または format=text で data.response.format.parseJson=true の場合。
  • agent.context — data.response.includeAgentContext=true の場合。以下の応答インタラクションパターンで必要です。

プロバイダーと format=json の互換性。 OpenAI は data.response.format.type=json をネイティブでサポートしています(JSON モード。スキーマを指定すると構造化出力を生成します)。Anthropic と AWS Bedrock では、data.response.format.schema を指定した場合にのみサポートされます。その他のプロバイダーおよび v1 テンプレートでは、format=text と data.response.format.parseJson=true を使用し、agent.responseJson を読み取ってください。

スキーマは FEEL コンテキストリテラルです。 format=json の場合、data.response.format.schema は feel: required です。引用符で囲んだ JSON 文字列ではなく、={ type: "object", properties: { ... } } のように記述してください。

JSON の解析に失敗した場合。 動作は 2 つの方法で異なります。format=text で parseJson=true を指定した場合、responseJson は省略されますが、解析できない生のテキストが responseText に格納されます(インシデントは発生しません)。ネイティブの format=json では、エラーコード FAILED_TO_PARSE_RESPONSE_CONTENT のインシデントが発生します。適切なフォールバックが必要な場合は、エラー境界イベントで処理してください。

レスポンスのやり取り(ユーザーによるフィードバックループ)

エージェントが最終回答を生成した後、ユーザー(または審査役を務める別のエージェント)に確認や修正を依頼し、結果を戻してもらうことができます。一般的なパターンは、アドホックサブプロセスから followUpInput を収集するユーザータスクに接続し、その後、同じエージェントのアドホックサブプロセスに戻す方法です。ユーザープロンプトの FEEL は、初回入力とフォローアップ入力で切り替えます。

data.userPrompt.prompt = =if (is defined(followUpInput)) then followUpInput else initialUserInput

エージェントは再入場しても会話コンテキストを保持します。コンテキスト処理フィールド名はテンプレートのバージョンによって変化しているため、最新情報についてはサブプロセスのドキュメントを参照してください。

制限とメモリ

  • data.limits.maxModelCalls — エージェントの実行ごとにLLM呼び出しの回数を制限します。必ず設定してください(一般的な開始値は5~20です)。適切な上限がないと、問題のあるプロンプトによってコストが膨らむ可能性があります。時間による制限はありません。
  • data.memory.contextWindowSize — エージェントがLLMに再送する過去のメッセージ数を制限します(デフォルトは20)。値を小さくするとトークンを節約でき、大きくするとより多くのコンテキストを保持できます。
  • data.memory.storage.type — in-process(デフォルト)、camunda-document(コンテキストが変数サイズの上限を超えたときにCamunda Documentストアに退避)、またはcustomです。ハイフンを含む形式を使用してください。

トラブルシューティング

lintループでは検出できない、わかりにくい失敗パターンです。

  • ツールに入力シーケンスフローがある — ツールではなく、通常のフローステップになります。ツールのROOTノードには、入力フローがあってはなりません。サブフローツール内の内部アクティビティには、入力フローを設定できます(実際に設定します)。これがサブフローの仕組みです。
  • ツール名の混同 — LLMに表示されるツール名は、name属性ではなくBPMNの**id**です。説明的なPascalCaseのIDを使用してください。
  • 文字列だけのプロンプト — システムプロンプトとユーザープロンプトはいずれもFEELです。リテラルも必ず="..."の形式にしてください。
  • 文字列内の数値を扱うFEEL — 数値をURLやメッセージに連結するにはstring(x)が必要です。文字列と変換されていない数値の間で+を使うとエラーになります。型変換についてはcamunda-feel §を参照してください。
  • ハイフンを含むメモリストレージの型 — in-process、camunda-document、customです。camelCaseではありません。

最終ステップ

エージェントプロセスの完了を宣言する前に、BPMN lintループ(camunda-bpmnを参照)を実行してください。

c8ctl bpmn lint process.bpmn

lintでは、サブフローツール内でのfromAi()の誤配置も検出されるようになりました。bpmnlint-plugin-camunda-compatのagent-fromai-contractルールは、ツールのエントリー要素ではなく子孫アクティビティにfromAi()呼び出しが宣言されている場合に警告します(サブフローツールの場合、エントリー要素はbpmn:subProcessルート自身のzeebe:ioMappingです)。まずlintを実行してください。問題が検出されなかったにもかかわらず、サブフローツールのパラメーターがnullのまま返される場合は、上記の「ツールの定義」をもう一度確認してください。

lintではBPMNの構造上の問題は検出できますが、コネクターテンプレートの入力は検証されません。lintで問題がないことを確認したら、BPMNを読み込んで次の点を確認してください。

  • ホスト要素がbpmn:adHocSubProcessであり、未設定のアドホックサブプロセスではなく、AI Agent Sub-processテンプレートが適用されている。
  • すべてのツールのルートノードに入力シーケンスフローがなく、<bpmn:documentation>要素がある(applyではこの要素は書き込まれないため、直接編集して設定してください)。
  • すべてのツールのフローで、toolCallResultがスコープ内に設定されている。
  • 両方のプロンプトが=で始まっている。
  • data.limits.maxModelCallsが設定されている。
  • プロバイダー、モデル、{{secrets.NAME}}の参照について、ユーザーの確認が取れている。シークレットの値をBPMNに記述してはいけません。

リファレンス

詳細なリファレンス資料は、references/ を参照してください。

  • tool-modeling.md — 4 種類のツール形式(REST コネクター、スクリプトタスク、ユーザータスク、サブフロー)の XML の例。非同期コールバックを含むサブフローも掲載しています。
  • fromai.md — fromAi() のシグネチャ全体と、すべての呼び出し形式(位置引数、名前付き引数、列挙型スキーマ、オプションパラメーター、複数回呼び出す JSON ボディ)
  • v1-to-v2-upgrade.md — c8ctl element-template update を使用して v1 の要素を v2 テンプレートに移行する方法。ID のペア、ドライラン/レポートのワークフロー、レシピと手動でのプロバイダーマッピング、アップグレード後の手順を掲載しています。
  • ai-agent-task.md — 以前の Task バリアント(すべてのツール呼び出しを監査/傍受する形式)。限定的な用途にのみ使用してください。

コメント