docs(plugin): document unified Runner development and APIs

This commit is contained in:
RockChinQ
2026-09-10 18:04:42 +08:00
parent cb26081730
commit 5cbe5eee59
30 changed files with 233 additions and 246 deletions
+11 -14
View File
@@ -2,16 +2,13 @@
title: "実行コンテキスト API"
---
AgentRunner と EventProcessor は、現在の実行に許可されたモデル、ツール、ナレッジベース、コンテキストへアクセスする API を使用します。両コンポーネントでは `self.plugin` を使用できません。
Runner の `ctx.api` は現在の実行 ID、コンテキスト、リソースの許可範囲に結び付いています。独自の `run(ctx)` と登録した処理関数は同じ `RunnerContext` を使用します。`self.plugin` から[共通 API](/ja/plugin/dev/apis/common)も利用できますが、現在の実行を自動的に表すものではありません。
## アクセス方法
```python
# Inside an EventProcessor handler
# Inside Runner.run(ctx) or a registered handler
api = ctx.api
# Inside AgentRunner.run(ctx)
api = self.get_run_api(ctx)
```
以下の `api` は現在の実行の API です。 同期の `get_allowed_*` とストリーミングのコンテキスト・イテレーター以外は、`await` で呼び出します。別の実行へ持ち越して再利用しないでください。
@@ -52,7 +49,7 @@ knowledge_bases = api.get_allowed_knowledge_bases() # Each item has kb_id
## 返信とログ
| EventProcessor メソッド | 用途 |
| Runner メソッド | 用途 |
| --- | --- |
| `await ctx.reply(text)` | 現在のイベントの会話へテキストを送信し、操作結果を返します。 |
| `await ctx.log(text, level="info")` | `debug`、`info`、`warning`、`error` のログを記録します。 |
@@ -69,7 +66,7 @@ async with api.reply_stream() as reply:
result = reply.result
```
EventProcessor では `ctx.reply_stream()` を使うと、操作の開始と結果も記録されます。
Runner では `ctx.reply_stream()` を使うと、操作の開始と結果も記録されます。
`update(text)` には差分ではなく**その時点の全文**を渡します。戻り値は操作結果です。正常終了時に返信を完了します。プラットフォームでストリーミング返信が有効なメッセージイベントでは表示を更新し、それ以外の返信可能なイベントでは正常終了時に全文を一度送信します。例外やキャンセルでは未送信のテキストを破棄しますが、表示済みの内容の撤回は保証されません。デバッグ時の送信は Mock です。
@@ -157,19 +154,19 @@ if api.ctx.context.available_apis.state:
| `run_append_result(result)` | `AgentRunEvent` |
| `run_finalize(run_id=None, status=None, reason=None)` | `AgentRun` |
`run_id=None` は現在の実行を指します。EventProcessor はハンドラーの完了時に自動終了するため、通常は記録の手動追加・終了は不要です。AgentRunner は `yield AgentRunResult` で結果を報告します。同じ結果を `run_append_result` で重複登録しないでください。
`run_id=None` は現在の実行を指します。登録した処理関数は戻ると自動終了します。独自の `run(ctx)` は `yield RunnerResult` で結果を報告できます。同じ結果を `run_append_result` で重複登録しないでください。
## 構造化インタラクション(AgentRunner)
## 構造化インタラクション(Runner)
確認やフォーム入力には `yield AgentRunResult.interaction_requested(ctx.run_id, request)` を使用します。`request` は `InteractionRequest` または辞書で、必須フィールドは `interaction_id`、`title`、`fallback_text` です。`kind`(`form`、`confirmation`、`choice`)、`fields`、`actions`、`expires_at` は任意です。
確認やフォーム入力には `yield RunnerResult.interaction_requested(ctx.run_id, request)` を使用します。`request` は `InteractionRequest` または辞書で、必須フィールドは `interaction_id`、`title`、`fallback_text` です。`kind`(`form`、`confirmation`、`choice`)、`fields`、`actions`、`expires_at` は任意です。
`spec.capabilities.interactions: true` と `spec.permissions.interactions: [request]` の宣言、およびホストの許可が必要です。画面の対応状況は `ctx.delivery.interactions` で確認し、送信結果は `interaction.submitted` イベントとして返ります。これは Runner の結果イベントであり、`ctx.api` のメソッドではありません。通常の EventProcessor ハンドラーには直接公開されていません。
`spec.capabilities.interactions: true` と `spec.permissions.interactions: [request]` の宣言、およびホストの許可が必要です。画面の対応状況は `ctx.delivery.interactions` で確認し、送信結果は `interaction.submitted` イベントとして返ります。これは Runner の結果イベントであり、`ctx.api` のメソッドではありません。独自の run(ctx) から yield します。
## エラー処理
```python
from langbot_plugin.api.proxies.agent_run import PermissionDeniedError
from langbot_plugin.api.entities.builtin.agent_runner.errors import AgentAPIException
from langbot_plugin.api.proxies.runner import PermissionDeniedError
from langbot_plugin.api.entities.builtin.runner.errors import AgentAPIException
try:
result = await api.call_tool("event_get_actor", {})
@@ -179,4 +176,4 @@ except AgentAPIException as exc:
await ctx.log(f"{exc.error.code}: {exc.error.message}", level="error")
```
EventProcessor 内の例です。`PermissionDeniedError` はリソース・操作・機能の権限不足を示します。`AgentAPIException.error` は `code`、`message`、`retryable`、`details` を持ちます。送信のタイムアウト時は成功済みの場合もあるため、`retryable` だけで再送しないでください。
Runner 内の例です。`PermissionDeniedError` はリソース・操作・機能の権限不足を示します。`AgentAPIException.error` は `code`、`message`、`retryable`、`details` を持ちます。送信のタイムアウト時は成功済みの場合もあるため、`retryable` だけで再送しないでください。
+1 -1
View File
@@ -4,7 +4,7 @@ title: "プラグイン共通API"
LangBotは、プラグインがさまざまなLangBotモジュールを操作し、メッセージコンテキストを制御するための一連のAPIを提供します。
`Command`、`EventListener`、`Tool` などの通常のコンポーネントは `self.plugin` を使用します。`AgentRunner` と `EventProcessor` は `self.plugin` ではなく[実行コンテキスト API](/ja/plugin/dev/apis/agent-run)を使用してください。プラットフォームの操作は[プラットフォーム API](/ja/plugin/dev/apis/platform)を参照してください。
すべてのコンポーネントは `self.plugin` から本ページの LangBot API を利用できます。Runner の `ctx.api` は現在の実行とリソースの許可範囲に結び付いています。[実行コンテキスト API](/ja/plugin/dev/apis/agent-run)を参照してください。Bot と宛先を指定する操作は[プラットフォーム API](/ja/plugin/dev/apis/platform)に記載しています。
## リクエストAPI
+1 -1
View File
@@ -62,4 +62,4 @@ msg_chain = MessageChain([
## プラットフォーム API
ユーザー取得、グループ管理、固有の操作には[プラットフォーム API](/ja/plugin/dev/apis/platform)を使用してください。EventProcessor と AgentRunner は[実行コンテキスト API](/ja/plugin/dev/apis/agent-run)から許可されたツールを呼び出します。
ユーザー取得、グループ管理、固有の操作には[プラットフォーム API](/ja/plugin/dev/apis/platform)を使用してください。Runner は[実行コンテキスト API](/ja/plugin/dev/apis/agent-run)から許可されたツールを呼び出します。
+1 -1
View File
@@ -66,7 +66,7 @@ account = await self.plugin.call_platform_api(
## イベントプロセッサーからの呼び出し
EventProcessor と AgentRunner は実行に許可されたツールを使用し、汎用の `call_platform_api` は公開しません。現在のイベントで発起者の取得が許可されている場合の例です:
Runner も `self.plugin` から Bot と宛先を指定して本ページの API を利用できます。現在のイベントの許可範囲で操作し、実行記録に残すには `ctx.api` または `ctx.reply()` を使用します:
```python
tools = {tool.tool_name for tool in ctx.api.get_allowed_tools()}
+3 -3
View File
@@ -4,8 +4,8 @@ title: "コンポーネントの追加"
プラグインは、LangBotにさまざまな機能を提供する1つ以上のコンポーネントで構成されています。現在サポートされているコンポーネントタイプには次のものがあります:
- プラグインプロセッサー(EventProcessor):インスタンスを作成してイベントに紐付け、プラグインのコードで処理します。[チュートリアル](/ja/plugin/dev/components/event-processor)を参照してください。
- Agent ランナー(AgentRunner):Agent の設定で選択する実行コンポーネントです。独立したプラグインプロセッサーとは異なります。
- プラグインプロセッサー(Runner):インスタンスを作成してイベントに紐付け、プラグインのコードで処理します。[チュートリアル](/ja/plugin/dev/components/runner)を参照してください。
- Agent ランナー(Runner):Agent の設定で選択する実行コンポーネントです。独立したプラグインプロセッサーとは異なります。
- イベントリスナー(EventListener): パイプライン実行中のイベントをリッスンし、コンテキストやパイプラインを変更します。
- コマンド(Command): `!`(または他の設定されたプレフィックス)で始まるユーザーコマンドメッセージによってトリガーされます。
- ツール(Tool): LangBotの組み込みLocal Agentの実行中にLLMによって呼び出されます。
@@ -72,7 +72,7 @@ components:
各コンポーネントの詳細な使用方法については、次を参照してください:
- [EventProcessor](./event-processor)
- [Runner](./runner)
- [EventListener](./event-listener)
- [Command](./command)
- [Tool](./tool)
+1 -1
View File
@@ -3,7 +3,7 @@ title: "コンポーネント: イベントリスナー"
---
<Info>
このコンポーネントはパイプラインの処理を拡張します。メッセージ受信やメンバー参加などの Bot イベントを処理する場合は、[イベントプロセッサー](/ja/plugin/dev/components/event-processor)を参照してください。
このコンポーネントはパイプラインの処理を拡張します。メッセージ受信やメンバー参加などの Bot イベントを処理する場合は、[イベントプロセッサー](/ja/plugin/dev/components/runner)を参照してください。
</Info>
LangBotのパイプラインは実行時にイベントを生成し、プラグインがフックして処理できるようにします。各プラグインは1つのイベントリスナー(components/event_listener/default.yaml)のみを持つことができますが、その中で任意の数のイベントを登録できます。
@@ -1,28 +1,45 @@
---
title: "コンポーネント: イベントプロセッサー"
title: "コンポーネント: Runner"
---
イベントプロセッサー(EventProcessor)は、メッセージ受信やメンバー参加などの Bot イベントを処理するコンポーネントです。インストール後、ユーザーは LangBot で「プラグインプロセッサー」を作成してコンポーネントを選び、Bot のイベントを紐付けます。
Runner は Agent の実行ロジック、または「プラグインプロセッサー」用のイベント処理関数を実装するコンポーネントです。どちらも `RunnerContext` を受け取り、インストール後にユーザーがコンポーネントを選択・設定します。
環境の準備は[プラグイン開発チュートリアル](/ja/plugin/dev/tutor)を参照してください。
## イベントプロセッサーコンポーネントの追加
## Runner コンポーネントの追加
1 つのプラグインに複数のイベントプロセッサーを追加できます。プラグインのディレクトリで `lbp comp EventProcessor` を実行し、名前に `welcome`、説明に `Welcome new members` を入力します。
1 つのプラグインに複数のイベントプロセッサーを追加できます。プラグインのディレクトリで `lbp comp Runner` を実行し、名前に `welcome`、説明に `Welcome new members` を入力します。
```bash
lbp comp EventProcessor
lbp comp Runner
```
生成される `components/event_processor/welcome.yaml` はコンポーネントを定義するファイルで、`welcome.py` に処理を記述します。
生成される `components/runner/welcome.yaml` はコンポーネントを定義するファイルで、`welcome.py` に処理を記述します。
## マニフェストファイル: イベントプロセッサー
## 実行ロジックの実装
モデルの接続や独自の実行ループには `spec.usages: [agent]` を宣言し、`run(ctx)` から結果を返します:
```python
from langbot_plugin.api.definition.components.runner import Runner, RunnerContext, RunnerResult
from langbot_plugin.api.entities.builtin.provider.message import Message
class Echo(Runner):
async def run(self, ctx: RunnerContext):
yield RunnerResult.run_completed(
ctx.run_id,
message=Message(role="assistant", content=ctx.input.to_text()),
)
```
## マニフェストファイル: Runner
`welcome.yaml` を次の内容に変更します。
```yaml
apiVersion: langbot/v1
kind: EventProcessor
kind: Runner
metadata:
name: welcome
label:
@@ -34,6 +51,7 @@ metadata:
zh_Hans: 欢迎新成员,并响应 /hello 消息。
ja_JP: 新しいメンバーを歓迎し、/hello に返信します。
spec:
usages: [event]
events:
- group.member_joined
- message.received
@@ -65,14 +83,17 @@ execution:
`spec.events` は対応するイベント、`spec.config` は詳細画面でユーザーが変更できる設定です。この例ではメンバー参加とメッセージ受信に対応し、歓迎メッセージと返信の有効・無効を設定できます。返信には、上記の `tool_calling` と `permissions.tools` の指定が必要です。
`spec.usages` は選択先を指定します。`agent` は Agent とパイプライン、`event` はプラグインプロセッサーです。`[agent, event]` の併記も可能です。`event` には `spec.events` が必要です。以下はイベント処理関数の例です。独自の `run(ctx)` から `await super().run(ctx)` で呼び出すこともできます。
## プラグインの実装
`Welcome` クラスの `initialize` メソッド内で処理関数を登録します。`welcome.py` を次の内容に変更してください。
```python
from langbot_plugin.api.definition.components.event_processor import (
EventProcessor,
EventProcessorContext,
from langbot_plugin.api.definition.components.runner import (
Runner,
RunnerContext,
)
from langbot_plugin.api.entities.builtin.platform.events import (
MemberJoinedEvent,
@@ -81,13 +102,13 @@ from langbot_plugin.api.entities.builtin.platform.events import (
from langbot_plugin.api.entities.builtin.platform.message import Plain
class Welcome(EventProcessor):
class Welcome(Runner):
async def initialize(self):
await super().initialize()
@self.handler(MemberJoinedEvent)
async def on_join(ctx: EventProcessorContext):
name = ctx.event.member.nickname or str(ctx.event.member.id)
async def on_join(ctx: RunnerContext):
name = ctx.platform_event.member.nickname or str(ctx.platform_event.member.id)
await ctx.log(f"Member joined: {name}")
if not ctx.config.get("reply_enabled", True):
await ctx.log("Replies are disabled for this processor")
@@ -97,9 +118,9 @@ class Welcome(EventProcessor):
await ctx.log("Welcome action completed")
@self.handler(MessageReceivedEvent)
async def on_message(ctx: EventProcessorContext):
async def on_message(ctx: RunnerContext):
text = "".join(
item.text for item in ctx.event.message_chain if isinstance(item, Plain)
item.text for item in ctx.platform_event.message_chain if isinstance(item, Plain)
).strip()
if text != "/hello":
await ctx.log("Message ignored: expected /hello")
@@ -112,7 +133,7 @@ class Welcome(EventProcessor):
`on_join` は参加したメンバーに挨拶し、`on_message` は `/hello` に返信します。「返信する」を無効にすると、ログだけを記録します。
`ctx.event` は現在のイベント、`ctx.config` はこのプロセッサーの設定です。返信には `ctx.reply()`、ログの記録には `ctx.log()` を使います。関数の実行が終わると、イベントの処理も終了します。
`ctx.platform_event` は現在のイベント、`ctx.config` はこのプロセッサーの設定です。返信には `ctx.reply()`、ログの記録には `ctx.log()` を使います。関数の実行が終わると、イベントの処理も終了します。
## ストリーミング返信
@@ -126,7 +147,7 @@ async with ctx.reply_stream() as reply:
`async with` ブロックが正常終了すると返信が完了します。ストリーミングが未対応・無効の場合やメッセージ以外のイベントでは、最後に全文を一度だけ送信します。例外時には、バッファ内の未完成テキストを送信しません。デバッグでは送信をシミュレーションします。
権限は `ctx.reply()` と共通です。AgentRunner も `self.get_run_api(ctx).reply_stream()` を利用できます。モデルの出力テキストが自動送信されることはありません。
権限は `ctx.reply()` と共通です。Runner も `self.get_run_api(ctx).reply_stream()` を利用できます。モデルの出力テキストが自動送信されることはありません。
## イベントの登録
@@ -168,7 +189,7 @@ async with ctx.reply_stream() as reply:
## 次のステップ
- [EventProcessorDemo](https://github.com/langbot-app/langbot-plugin-demo/tree/main/EventProcessorDemo)で他の実装例を確認できます。
- [RunnerDemo](https://github.com/langbot-app/langbot-plugin-demo/tree/main/RunnerDemo)で他の実装例を確認できます。
- パイプラインの前処理やモデル呼び出し完了時などに機能を追加する場合は、[イベントリスナー](/ja/plugin/dev/components/event-listener)を使用してください。
返信、モデル、ツール、履歴、状態は[実行コンテキスト API](/ja/plugin/dev/apis/agent-run)を参照してください。
+1 -1
View File
@@ -3,7 +3,7 @@ title: "プラグイン開発チュートリアル"
---
<Info>
メッセージ受信やメンバー参加などを処理するプラグインを作る場合は、基本環境を準備した後、[イベントプロセッサーのチュートリアル](/ja/plugin/dev/components/event-processor)に進んでください。
メッセージ受信やメンバー参加などを処理するプラグインを作る場合は、基本環境を準備した後、[イベントプロセッサーのチュートリアル](/ja/plugin/dev/components/runner)に進んでください。
</Info>
## アーキテクチャの基礎