docs(plugin): reorganize context API reference

This commit is contained in:
RockChinQ
2026-09-11 00:03:42 +08:00
parent 5cbe5eee59
commit df06842ecb
38 changed files with 780 additions and 934 deletions
+3 -3
View File
@@ -700,8 +700,8 @@
{
"group": "Plugin SDK API",
"pages": [
"en/plugin/dev/apis/common",
"en/plugin/dev/apis/agent-run",
"en/plugin/dev/apis/common",
"en/plugin/dev/apis/platform",
"en/plugin/dev/apis/pipeline-events",
"en/plugin/dev/apis/messages",
@@ -1006,8 +1006,8 @@
{
"group": "插件 SDK API",
"pages": [
"zh/plugin/dev/apis/common",
"zh/plugin/dev/apis/agent-run",
"zh/plugin/dev/apis/common",
"zh/plugin/dev/apis/platform",
"zh/plugin/dev/apis/pipeline-events",
"zh/plugin/dev/apis/messages",
@@ -1307,8 +1307,8 @@
{
"group": "プラグイン SDK API",
"pages": [
"ja/plugin/dev/apis/common",
"ja/plugin/dev/apis/agent-run",
"ja/plugin/dev/apis/common",
"ja/plugin/dev/apis/platform",
"ja/plugin/dev/apis/pipeline-events",
"ja/plugin/dev/apis/messages",
+194 -132
View File
@@ -1,179 +1,241 @@
---
title: "Run Context APIs"
title: "Context APIs"
---
Runner provides `ctx.api` bound to the current run ID, context, and resource grants. Custom `run(ctx)` implementations and registered handlers share `RunnerContext`. `self.plugin` still exposes [Common APIs](/en/plugin/dev/apis/common), but does not automatically represent the current run.
A context contains data for one component invocation. Each component receives a different context, so start with the entry point for your component.
## Access
| Component | Handler entry point | Context type |
| --- | --- | --- |
| EventListener | `handler(event_context)` | `EventContext` |
| Command | `subcommand(context)` | `ExecuteContext` |
| Tool | `call(params, session, query_id)` | No separate context object |
| Runner | `run(ctx)` or `handler(ctx)` | `RunnerContext` |
| KnowledgeEngine | `ingest(context)`, `retrieve(context)` | `IngestionContext`, `RetrievalContext` |
| KnowledgeRetriever | `retrieve(context)` | `RetrievalContext` |
| Parser | `parse(context)` | `ParseContext` |
| Page | `handle_api(request)` | `PageRequest` |
This page covers the data and methods available through these contexts. Use `self.plugin` for models, knowledge bases, storage, and other LangBot capabilities; see [LangBot API](/en/plugin/dev/apis/common). For platform operations, see [Platform API](/en/plugin/dev/apis/platform).
`EventContext`, `ExecuteContext`, and `Session` also carry `instance_uuid`, `workspace_uuid`, and `placement_generation`. These fields identify the current instance and workspace for execution; plugins must not treat them as authorization data.
## EventListener
EventListener handles Pipeline events. Its event handler receives an `EventContext`:
```python
# Inside Runner.run(ctx) or a registered handler
api = ctx.api
event = event_context.event
sender_id = event.sender_id
```
In the examples below, `api` refers to the current run API. Use `await` for the methods below, except synchronous `get_allowed_*` methods and streaming context/iterator APIs. Do not retain or reuse it across runs.
### Context data
### Configuration and permissions
| Property | Type | Description |
| --- | --- | --- |
| `event` | `BaseEventModel` | Current event object; its actual type matches the registered event type |
| `event_name` | `str` | Current event class name |
| `query_id` | `int` | Current Pipeline request ID |
| `query_uuid` | `str \| None` | Stable identifier for the current Pipeline request |
| `eid` | `int` | Temporary event number inside Plugin Runtime; do not persist it |
| `is_prevent_default` | `bool` | Whether default handling has been stopped; change it with `prevent_default()` |
| `is_prevent_postorder` | `bool` | Whether later plugins have been stopped; change it with `prevent_postorder()` |
`ctx.config` contains the processor or Runner instance configuration; `self.get_plugin_config()` reads plugin-level configuration. Manifest `spec.permissions` declares requested permissions; actual resources also depend on user configuration and the current event.
See [Pipeline Events](/en/plugin/dev/apis/pipeline-events) for event fields and all supported event types.
```yaml
spec:
capabilities:
tool_calling: true
permissions:
tools: [detail, call]
### Context methods
| Method | Return value | Description |
| --- | --- | --- |
| `await event_context.reply(message_chain, quote_origin=False)` | - | Reply in the conversation for the current request |
| `await event_context.get_bot_uuid()` | `str` | Get the source bot UUID |
| `await event_context.set_query_var(key, value)` | - | Set a variable on the current request |
| `await event_context.get_query_var(key)` | `Any` | Get one request variable |
| `await event_context.get_query_vars()` | `dict[str, Any]` | Get all request variables |
| `await event_context.create_new_conversation()` | `dict[str, Any]` | Clear the current Pipeline conversation so a later request starts a new one |
| `await event_context.list_pipeline_knowledge_bases()` | `list[dict[str, Any]]` | List knowledge bases bound to the current Pipeline Local Agent |
| `await event_context.retrieve_knowledge(kb_id, query_text, top_k=5, filters=None)` | `list[dict[str, Any]]` | Search a knowledge base bound to the current Pipeline |
| `event_context.prevent_default()` | - | Stop the default handling of the current event |
| `event_context.prevent_postorder()` | - | Stop later plugins from handling the current event |
`reply()` accepts a [MessageChain](/en/plugin/dev/apis/messages). Request variables, replies, and Pipeline knowledge-base methods require an associated Pipeline request. The `kb_id` passed to `retrieve_knowledge()` must come from `list_pipeline_knowledge_bases()`.
`prevent_default()` only affects Pipeline events whose default flow can be stopped. See [Pipeline Events](/en/plugin/dev/apis/pipeline-events#prevent-default-behavior).
## Command
A Command subcommand handler receives an `ExecuteContext`:
```python
query = " ".join(context.crt_params)
session = context.session
```
This is the minimum declaration for replies and tool calls. Add other entries to `spec.permissions` as needed:
### Context data
| `spec.permissions` | Operations |
| Property | Type | Description |
| --- | --- | --- |
| `session` | `Session` | Session that contains the current message |
| `command_text` | `str` | Complete command text without the command prefix |
| `full_command_text` | `str` | Complete command text including the prefix |
| `command` | `str` | Root command name |
| `crt_command` | `str` | Subcommand currently being executed |
| `params` | `list[str]` | All arguments after the root command |
| `crt_params` | `list[str]` | Arguments not yet consumed by the current subcommand |
| `privilege` | `int` | Command privilege level of the current user |
| `query_id` | `int` | Current Pipeline request ID |
| `query_uuid` | `str \| None` | Stable identifier for the current Pipeline request |
The SDK calls `context.shift()` before entering the current subcommand. Components do not need to call it directly.
### Context methods
| Method | Return value | Description |
| --- | --- | --- |
| `await context.reply(message_chain, quote_origin=False)` | - | Reply in the conversation for the current request |
| `await context.get_bot_uuid()` | `str` | Get the source bot UUID |
| `await context.set_query_var(key, value)` | - | Set a variable on the current request |
| `await context.get_query_var(key)` | `Any` | Get one request variable |
| `await context.get_query_vars()` | `dict[str, Any]` | Get all request variables |
| `await context.create_new_conversation()` | `dict[str, Any]` | Clear the current Pipeline conversation so a later request starts a new one |
| `await context.list_pipeline_knowledge_bases()` | `list[dict[str, Any]]` | List knowledge bases bound to the current Pipeline Local Agent |
| `await context.retrieve_knowledge(kb_id, query_text, top_k=5, filters=None)` | `list[dict[str, Any]]` | Search a knowledge base bound to the current Pipeline |
These request methods behave the same as their EventListener equivalents. See [Command](/en/plugin/dev/components/command) for registration and return values.
## Tool
Tool has no separate context object. Its `call()` parameters carry the invocation data:
```python
conversation_type = session.launcher_type.value
conversation_id = session.launcher_id
sender_id = session.sender_id
```
| Parameter | Description |
| --- | --- |
| `models` | `invoke`, `stream`, `rerank`, `count_tokens` |
| `tools` | `detail`, `call` |
| `knowledge_bases` | `list`, `retrieve` |
| `history` | `page`, `search` |
| `events` | `get`, `page` |
| `storage` | `plugin`, `workspace` |
| `interactions` | `request` |
| `params` | Arguments generated by the model or caller from the tool JSON Schema |
| `session` | Current session data |
| `query_id` | Current Pipeline request ID; pass it unchanged to LangBot APIs that require request context |
Inspect the resources actually granted:
Common `Session` properties are:
```python
models = api.get_allowed_models() # Each item has model_id and operations
tools = api.get_allowed_tools() # Each item has tool_name and parameters
knowledge_bases = api.get_allowed_knowledge_bases() # Each item has kb_id
```
Check context capabilities through `api.ctx.context.available_apis`. Do not call an API whose flag is `False`; a manifest permission alone does not enable it.
## Replies and logs
| Runner method | Purpose |
| Property | Description |
| --- | --- |
| `await ctx.reply(text)` | Send text to the current event conversation; return the action result. |
| `await ctx.log(text, level="info")` | Record a log at `debug`, `info`, `warning`, or `error` level. |
| `ctx.reply_stream()` | Update one reply through an async context manager. |
| `launcher_type` | Conversation type: `person` or `group` |
| `launcher_id` | Private-chat user or group ID |
| `sender_id` | Current message sender ID |
| `bot_uuid` | Current bot UUID |
| `using_conversation` | Current Pipeline conversation |
| `conversations` | Pipeline conversations stored in this Session |
| `use_prompt_name` | Active prompt name |
| `create_time`, `update_time` | Session creation and update times |
`ctx.reply(text)` is equivalent to `await api.call_tool("event_reply", {"text": text})`. The event must have a reply target and grant `event_reply`. Logs and text returned by an independent Agent are not automatically sent to the platform.
`session` is a data object and has no context methods such as `reply()`. A tool return value goes back to its caller; it is not sent to the chat platform automatically. Use `self.plugin` for LangBot and platform capabilities. If an API requires `session` and `query_id`, pass the values received by the current call.
### Streaming replies
## Runner
Both custom `run(ctx)` implementations and Runner event handlers receive a `RunnerContext`. It remains valid only while the current invocation is running.
```python
async with api.reply_stream() as reply:
await reply.update("Processing…")
await reply.update("Processing complete.")
result = reply.result
text = ctx.input.to_text()
event_type = ctx.event.event_type
```
Runner can use `ctx.reply_stream()` to also record the action start and result.
### Context data
`update(text)` takes the **complete text so far**, not a delta, and returns the action result. Normal exit completes the reply. Message events with platform streaming support enabled update the platform message; other replyable events buffer text and send once on successful exit. Errors or cancellation discard buffered partial text; already displayed content is not guaranteed to be retracted. Debug mode simulates platform delivery.
| Property | Type | Description |
| --- | --- | --- |
| `run_id` | `str` | Current run ID |
| `trigger` | `AgentTrigger` | Trigger type, source, and time |
| `event` | `AgentEventContext` | Standard event envelope with the event ID, type, source, time, and raw data |
| `platform_event` | Platform event type | Platform event parsed into its specific event type |
| `conversation` | `ConversationContext \| None` | Current conversation, thread, bot, and workspace identifiers |
| `actor` | `ActorContext \| None` | Actor that caused the event |
| `subject` | `SubjectContext \| None` | Message, group, or other object affected by the event |
| `input` | `AgentInput` | Current text, structured content, and attachments |
| `delivery` | `DeliveryContext` | Output target and streaming, editing, and reaction capabilities |
| `resources` | `AgentResources` | Models, tools, knowledge bases, skills, and storage authorized for this run |
| `context` | `ContextAccess` | Conversation cursors, inline policy, and available context APIs |
| `state` | `AgentRunState` | Scope-specific state snapshot loaded at the start of the run |
| `runtime` | `AgentRuntimeContext` | LangBot version, trace ID, and deadline |
| `config` | `dict[str, Any]` | Current Agent or plugin-processor instance configuration |
| `adapter` | `AdapterContext \| None` | Additional entry-adapter data |
| `metadata` | `dict[str, Any]` | Other metadata supplied by the Host |
This requires `available_apis.reply_stream` and the `event_reply` permission. Model streaming and platform streaming are separate APIs; the plugin explicitly connects them.
Prefer the stable properties in this table. `event.data` and `adapter.extra` carry additional data that has not been promoted to stable fields.
## Models, tools, and knowledge bases
### Replies and logs
See [Common APIs](/en/plugin/dev/apis/common) for model parameters and usage objects. The run API also provides:
| Method | Return value | Description |
| --- | --- | --- |
| `await ctx.get_bot_uuid()` | `str` | Get the source bot UUID; raises an error when no bot is associated |
| `await ctx.reply(message_chain, quote_origin=False)` | `Any` | Reply to the current event with a string or `MessageChain` |
| `ctx.reply_stream()` | Async context manager | Stream full-text updates to one reply |
| `await ctx.log(text, level="info")` | - | Write to this run's log; levels are `debug`, `info`, `warning`, and `error` |
| Method | Result or purpose |
| --- | --- |
| `invoke_llm(llm_model_uuid, messages, ...)` | `Message` |
| `invoke_llm_with_usage(llm_model_uuid, messages, ...)` | `LLMInvokeResult` |
| `invoke_llm_stream(llm_model_uuid, messages, ...)` | Async iterator of `MessageChunk` |
| `invoke_llm_stream_events(llm_model_uuid, messages, ...)` | Async iterator of `LLMStreamEvent` |
| `count_tokens(llm_model_uuid, messages, funcs=None, extra_args=None, timeout=None)` | Input token count, `int` |
| `invoke_rerank(rerank_model_uuid, query, documents, top_k=None, extra_args=None, timeout=30.0)` | List with `index` and `relevance_score` |
| `get_tool_detail(tool_name)` | Tool description and parameter schema, `dict` |
| `call_tool(tool_name, parameters)` | Tool result, `dict`; no `session` or `query_id` |
| `retrieve_knowledge(kb_id, query_text, top_k=5, filters=None)` | Retrieval result list |
Each `reply_stream().update(text)` call supplies the complete current text. If the platform does not support streaming, LangBot sends one complete message when the stream finishes. Debug mode only simulates delivery.
All four model invocation methods also accept `remove_think=None`; non-streaming methods accept `timeout=None`. Timeouts are bounded by the remaining run time. Resource lists may be empty; do not assume a first model or knowledge base exists.
### Available tools
```python
allowed = {tool.tool_name for tool in api.get_allowed_tools()}
if "event_get_actor" in allowed:
actor = await api.call_tool("event_get_actor", {})
```
| Method | Return value | Description |
| --- | --- | --- |
| `await ctx.get_available_tools()` | `list[dict[str, Any]]` | Get context actions, platform APIs, plugin tools, and MCP tools callable in this invocation |
| `await ctx.call_tool(tool_name, parameters=None)` | `dict[str, Any]` | Call a tool from that list |
LangBot fixes targets for `event_*` tools; `platform_*` tools accept targets according to their schema. Use names and parameters from the granted list; pass `{}` to tools with no parameters.
Each item returned by `get_available_tools()` contains `name`, `description`, `parameters`, `type`, and `operations`. The result is already filtered by the current Agent or plugin-processor configuration and the event's capabilities. `ctx.call_tool()` cannot call a tool absent from this list.
## History and events
### Prompt, history, and events
The current input does not include full history. Pull records within the current run scope as needed; passing another conversation ID does not expand access.
| Method | Return value | Availability field |
| --- | --- | --- |
| `await ctx.get_prompt()` | `list[dict[str, Any]]` | `prompt_get` |
| `await ctx.history_page(conversation_id=None, before_cursor=None, after_cursor=None, limit=50, direction="backward", include_attachments=False)` | `HistoryPage` | `history_page` |
| `await ctx.history_search(query, filters=None, top_k=10)` | `HistorySearchResult` | `history_search` |
| `await ctx.event_get(event_id)` | `AgentEventRecord` | `event_get` |
| `await ctx.event_page(conversation_id=None, event_types=None, before_cursor=None, limit=50)` | `EventPage` | `event_page` |
| `await ctx.steering_pull(mode="all", limit=None)` | `SteeringPullResult` | `steering_pull` |
| Method | Returns |
| --- | --- |
| `get_prompt()` | Effective prompt list; capability flag: `prompt_get` |
| `history_page(conversation_id=None, before_cursor=None, after_cursor=None, limit=50, direction="backward", include_attachments=False)` | `HistoryPage` |
| `history_search(query, filters=None, top_k=10)` | `HistorySearchResult` |
| `event_get(event_id)` | `AgentEventRecord` |
| `event_page(conversation_id=None, event_types=None, before_cursor=None, limit=50)` | `EventPage` |
| `steering_pull(mode="all", limit=None)` | `SteeringPullResult`; consume queued follow-up inputs |
### State
```python
if api.ctx.context.available_apis.history_page:
page = await api.history_page(limit=20)
for item in page.items:
print(item.model_dump())
if page.has_more and page.prev_cursor:
older = await api.history_page(before_cursor=page.prev_cursor, limit=20)
```
| Method | Return value | Description |
| --- | --- | --- |
| `await ctx.state_get(scope, key)` | `dict[str, Any]` | Read a state value |
| `await ctx.state_set(scope, key, value)` | `dict[str, Any]` | Store a JSON-serializable state value |
| `await ctx.state_delete(scope, key)` | `dict[str, Any]` | Delete a state value |
| `await ctx.state_list(scope, prefix=None, limit=100)` | `dict[str, Any]` | List state keys in a scope |
Page results are SDK objects: use `.items`, `.has_more`, `.prev_cursor`, and `.next_cursor`, not dictionary indexing. Use `before_cursor` for older records, and `after_cursor` with `direction="forward"` for newer records. History search may only provide text matching. `steering_pull` accepts `all`, `one`, or `one-at-a-time` for Runners supporting follow-up inputs.
`scope` can be `conversation`, `actor`, `subject`, or `runner`. These methods require `ctx.context.available_apis.state` to be `true`.
## State and storage
### Run records
| Method | Returns |
| --- | --- |
| `state_get(scope, key)` | `{"value": ...}` |
| `state_set(scope, key, value)` | `{"success": ...}` |
| `state_delete(scope, key)` | `{"success": ...}` |
| `state_list(scope, prefix=None, limit=100)` | `{"keys": [...], "has_more": ...}` |
| Method | Return value | Availability field |
| --- | --- | --- |
| `await ctx.run_get(run_id=None)` | `AgentRun` | `run_get` |
| `await ctx.run_list(conversation_id=None, statuses=None, before_cursor=None, limit=50)` | `RunPage` | `run_list` |
| `await ctx.run_events_page(run_id=None, before_cursor=None, after_cursor=None, limit=50, direction="forward")` | `RunEventPage` | `run_events_page` |
| `await ctx.run_cancel(run_id=None, reason=None)` | `AgentRun` | `run_cancel` |
| `await ctx.run_append_result(result)` | `AgentRunEvent` | `run_append_result` |
| `await ctx.run_finalize(run_id=None, status=None, reason=None)` | `AgentRun` | `run_finalize` |
State requires `available_apis.state` and a Host-enabled scope: `conversation`, `actor`, `subject`, or `runner`. Values must be JSON-serializable; use a key prefix such as `external.`. LangBot persists state; these methods return dictionaries.
`run_id=None` refers to the current run. The SDK completes a normal event handler automatically. When a custom `run(ctx)` yields `RunnerResult`, do not register the same result again with `run_append_result()`.
```python
if api.ctx.context.available_apis.state:
await api.state_set("conversation", "external.last_topic", "setup")
value = await api.state_get("conversation", "external.last_topic")
```
### Availability and authorization
Plugin and workspace storage provide `set_plugin_storage`, `get_plugin_storage`, `get_plugin_storage_keys`, `delete_plugin_storage`, and the corresponding `*_workspace_storage*` methods. Parameters match [Common APIs](/en/plugin/dev/apis/common); values are `bytes`. Access requires `api.ctx.resources.storage.plugin_storage` or `workspace_storage` respectively.
Use `ctx.context.available_apis` to check whether prompt, history, event, state, and run-record methods are available. Authorized models, tools, and knowledge bases are in `ctx.resources.models`, `ctx.resources.tools`, and `ctx.resources.knowledge_bases`.
## Run records
During Runner execution, model, tool, knowledge-base, storage, and platform calls through `self.plugin` are automatically associated with the current run and validated against `ctx.resources`. Do not pass `run_id`. After the handler returns, do not use this context or its run-bound calls from background tasks.
The following methods require the matching `available_apis` flag and only access runs within the authorized scope.
`ctx.api` is the lower-level run-scoped proxy. Normal component code should prefer the `ctx` methods listed on this page and use `self.plugin` for LangBot APIs.
| Method | Returns |
| --- | --- |
| `run_get(run_id=None)` | `AgentRun` |
| `run_list(conversation_id=None, statuses=None, before_cursor=None, limit=50)` | `RunPage` |
| `run_events_page(run_id=None, before_cursor=None, after_cursor=None, limit=50, direction="forward")` | `RunEventPage` |
| `run_cancel(run_id=None, reason=None)` | `AgentRun` |
| `run_append_result(result)` | `AgentRunEvent` |
| `run_finalize(run_id=None, status=None, reason=None)` | `AgentRun` |
## Data-only contexts
`run_id=None` selects the current run. Registered handlers finish automatically when they return. Custom `run(ctx)` implementations can yield `RunnerResult`; do not append the same result again through `run_append_result`.
The following components receive task input rather than an EventListener or Runner execution context. Their fields, return values, and complete examples live in the corresponding component guides.
## Structured interactions (Runner)
To request confirmation or form input, yield `RunnerResult.interaction_requested(ctx.run_id, request)`. `request` accepts an `InteractionRequest` object or dictionary. Required fields are `interaction_id`, `title`, and `fallback_text`; optional fields include `kind` (`form`, `confirmation`, `choice`), `fields`, `actions`, and `expires_at`.
This requires `spec.capabilities.interactions: true`, `spec.permissions.interactions: [request]`, and Host authorization. Inspect `ctx.delivery.interactions` for surface support; submissions return as `interaction.submitted` events. This is a Runner result event, not a method on `ctx.api`, and is yielded from a custom run(ctx) implementation.
## Error handling
```python
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", {})
except PermissionDeniedError as exc:
await ctx.log(str(exc), level="warning")
except AgentAPIException as exc:
await ctx.log(f"{exc.error.code}: {exc.error.message}", level="error")
```
This example runs inside a Runner. `PermissionDeniedError` means a resource, operation, or capability is not granted. `AgentAPIException.error` contains `code`, `message`, `retryable`, and `details`. A timed-out send may already have succeeded; do not resend solely because `retryable` is true.
| Component entry point | Main data | Component guide |
| --- | --- | --- |
| `KnowledgeEngine.ingest(context: IngestionContext)` | File, target knowledge base, creation settings, and parse result | [KnowledgeEngine](/en/plugin/dev/components/knowledge-engine#document-ingestion) |
| `KnowledgeEngine.retrieve(context: RetrievalContext)` | Query, target knowledge base, retrieval settings, and filters | [KnowledgeEngine](/en/plugin/dev/components/knowledge-engine#knowledge-retrieval) |
| `KnowledgeRetriever.retrieve(context: RetrievalContext)` | Query and external knowledge-base settings | [KnowledgeRetriever](/en/plugin/dev/components/knowledge-retriever#retrieval-context) |
| `Parser.parse(context: ParseContext)` | File content, filename, MIME type, and metadata | [Parser](/en/plugin/dev/components/parser#parse-method) |
| `Page.handle_api(request: PageRequest)` | Endpoint, HTTP method, body, and headers | [Page](/en/plugin/dev/components/page#pagerequest-fields) |
+2 -113
View File
@@ -1,119 +1,8 @@
---
title: "Plugin Common APIs"
title: "LangBot API"
---
LangBot provides a series of APIs for plugins to operate various LangBot modules and control message contexts.
All components can access these LangBot APIs through `self.plugin`. Runner also provides `ctx.api`, bound to the current invocation and its resource grants; see [Run Context APIs](/en/plugin/dev/apis/agent-run). Operations with an explicit bot and target are covered in [Platform APIs](/en/plugin/dev/apis/platform).
## Request API
Operations for the currently processing user request (message). Only available in `EventListener` and `Command` components. Access methods:
- In event handler methods of `EventListener`: Internal methods of `event_context: context.EventContext` object
- In subcommand handler methods of `Command`: Internal methods of `context: ExecuteContext` object
### Direct Reply Message
Directly reply with a message chain to the session where the current request is located.
For message chain construction methods, please refer to [Message Platform Entities](/en/plugin/dev/apis/messages).
```python
async def reply(
self, message_chain: platform_message.MessageChain, quote_origin: bool = False
):
"""Reply to the message request
Args:
message_chain (platform.types.MessageChain): LangBot message chain
quote_origin (bool): Whether to quote the original message
"""
# Usage example
await event_context.reply(
platform_message.MessageChain([
platform_message.Plain(text="Hello, world!"),
]),
)
```
### Get Bot UUID
Get the UUID of the bot that originated the current request.
```python
async def get_bot_uuid(self) -> str:
"""Get the bot uuid"""
# Usage example
bot_uuid = await event_context.get_bot_uuid()
```
### Set Request Variables
Some information in a single request is stored in request variables. When using external Agent platforms like Dify, [these variables are explicitly passed to Agent platforms](/en/deploy/pipelines/readme.html#request-variables).
```python
async def set_query_var(self, key: str, value: Any):
"""Set a query variable"""
# Usage example
await event_context.set_query_var("key", "value")
```
### Get Request Variables
Get a single request variable.
```python
async def get_query_var(self, key: str) -> Any:
"""Get a query variable"""
# Usage example
query_var = await event_context.get_query_var("key")
```
### Get All Request Variables
```python
async def get_query_vars(self) -> dict[str, Any]:
"""Get all query variables"""
# Usage example
query_vars = await event_context.get_query_vars()
```
### List Pipeline Knowledge Bases
Get the list of knowledge bases configured for the pipeline used by the current request.
```python
async def list_pipeline_knowledge_bases(self) -> list[dict[str, Any]]:
"""List knowledge bases configured for the current pipeline"""
# Usage example
knowledge_bases = await event_context.list_pipeline_knowledge_bases()
# Return example
[
{
"uuid": "kb_uuid",
"name": "Product Docs",
"description": "Internal product documentation",
}
]
```
Only returns knowledge bases bound in the `Local Agent` configuration of the pipeline corresponding to the current request. If the current pipeline has no knowledge bases configured, or does not use `Local Agent`, an empty list is returned.
### Start a new conversation
`await event_context.create_new_conversation()` clears the conversation currently used by the Pipeline session, so subsequent processing starts a new one. It returns an empty dictionary and does not delete platform chat history.
### Retrieve from Pipeline knowledge bases
`await event_context.retrieve_knowledge(kb_id, query_text, top_k=5, filters=None)` returns retrieval results. `kb_id` must come from `list_pipeline_knowledge_bases()`; this request API cannot access knowledge bases outside the Pipeline configuration.
Use `self.plugin` for models, tools, knowledge bases, and storage. For the current event, replies, and conversation state, see [Context APIs](/en/plugin/dev/apis/agent-run).
## LangBot API
+1 -1
View File
@@ -62,4 +62,4 @@ In addition to the above entities, there are also entities like `Friend` and `Gr
## Platform APIs
Use [Platform APIs](/en/plugin/dev/apis/platform) to query users, manage groups, and call platform-specific actions. Runner call authorized platform tools through [Run Context APIs](/en/plugin/dev/apis/agent-run).
Use [Platform APIs](/en/plugin/dev/apis/platform) to query users, manage groups, and call platform-specific actions. Runner uses the same `self.plugin` entrypoint; use `ctx.reply()` for the current conversation.
+5 -44
View File
@@ -248,42 +248,13 @@ class PromptPreProcessing(BaseEventModel):
"""Existing message records for this conversation, can be modified, langbot_plugin.api.entities.builtin.provider.message.Message or langbot_plugin.api.entities.builtin.provider.message.MessageChunk type"""
```
## Event Context APIs
## EventListener context
```python
...
@self.handler(events.PersonMessageReceived)
async def handler(event_context: context.EventContext):
...
```
Event handlers read the current event through `event_context.event`. See [Context APIs](/en/plugin/dev/apis/agent-run#eventlistener) for the complete `EventContext` properties and methods.
Event processing methods will be passed the `EventContext` object, which contains event context information, and the object has both [Request API](/en/plugin/dev/apis/common) and event context specific APIs. The following is a list of event context specific APIs:
### Prevent default behavior
### Get Original Event Attributes
`event_context.event` attribute is the original event object, which can get the attributes of the original event. The type is the type of the event being listened to.
For example, when the event being listened to is `GroupMessageReceived`:
```python
event = event_context.event
print(event.launcher_type) # Launcher object type (group)
print(event.launcher_id) # Group ID
print(event.sender_id) # Sender account ID
print(event.message_chain) # Message chain
```
### Prevent Default Behavior
```python
def prevent_default(self):
"""Prevent default behavior"""
# Usage example
event_context.prevent_default()
```
Calling this method will prevent the default subsequent behavior of this event, and the pipeline will end directly.
Calling `event_context.prevent_default()` stops the default handling of the current event. Only these events support it:
<Info>
Only the following events can prevent default behavior:
@@ -297,14 +268,4 @@ Only the following events can prevent default behavior:
- NormalMessageResponded
</Info>
### Prevent Postorder Execution
```python
def prevent_postorder(self):
"""Prevent postorder execution"""
# Usage example
event_context.prevent_postorder()
```
Calling this method will prevent the subsequent plugins from executing this time.
Call `event_context.prevent_postorder()` to stop later plugins from handling the current event.
+7 -7
View File
@@ -64,15 +64,15 @@ account = await self.plugin.call_platform_api(
Only actions declared by the adapter are allowed; this is not unrestricted pass-through to every platform endpoint. Plugins call the Host through the runtime, rather than accessing `ctx.query.adapter` or `adapter.bot`.
## Calling from an event processor
## Runner
Runner can also call these platform APIs through `self.plugin`, specifying the bot and target explicitly. To use the current event grants and record actions in its run trace, use `ctx.api` or `ctx.reply()`:
During Runner execution, model, tool, knowledge-base, storage, and platform calls through `self.plugin` automatically use the current run and its authorization. Do not pass `run_id`. Concurrent runs remain isolated. Do not continue these run-bound calls after the handler returns.
Use `await ctx.get_bot_uuid()` for the current bot. Platform calls must match the tool grants for this invocation. Event-target grants cannot access another target. Ungranted actions, including platform-specific actions, are rejected. These calls also use Mock delivery in debug mode.
```python
tools = {tool.tool_name for tool in ctx.api.get_allowed_tools()}
if "event_get_actor" in tools:
actor = await ctx.api.call_tool("event_get_actor", {})
tools = await ctx.get_available_tools()
if any(tool["name"] == "event_get_actor" for tool in tools):
actor = await ctx.call_tool("event_get_actor")
await ctx.log(str(actor))
```
See [Run Context APIs](/en/plugin/dev/apis/agent-run) for access, permissions, and replies. Event debugging mocks platform tools; `self.plugin.call_platform_api()` in regular components performs real calls.
+2 -1
View File
@@ -211,4 +211,5 @@ For specific return values, please refer to the definition of `CommandReturn`: [
You have learned the basic information about command registration and command execution. Next, you can:
- Check out [Plugin Common APIs](/en/plugin/dev/apis/common)
- See the complete [`ExecuteContext` API reference](/en/plugin/dev/apis/agent-run#command).
- Check out [Plugin Common APIs](/en/plugin/dev/apis/common).
+2 -1
View File
@@ -103,5 +103,6 @@ Event registration is implemented through the `@self.handler` decorator, with th
You have learned the basic information about event listeners. Next, you can:
- Check the `List of Monitorable Events` and `Event Context APIs` in the documentation [Pipeline Events](/en/plugin/dev/apis/pipeline-events)
- See [Pipeline Events](/en/plugin/dev/apis/pipeline-events) for event types and fields.
- See the complete [`EventContext` API reference](/en/plugin/dev/apis/agent-run#eventlistener).
- Check out [Plugin Common APIs](/en/plugin/dev/apis/common)
+5 -3
View File
@@ -6,6 +6,8 @@ Runner implements Agent execution or typed event handlers for a **Plugin process
For environment setup, see the [plugin development tutorial](/en/plugin/dev/tutor).
See [Context APIs](/en/plugin/dev/apis/agent-run#runner) for the complete `RunnerContext` fields and methods.
## Adding a Runner Component
A plugin can contain several event processors. Run `lbp comp Runner` in the plugin directory. Enter `welcome` as the name and `Welcome new members` as the description.
@@ -147,7 +149,6 @@ async with ctx.reply_stream() as reply:
The reply finishes when the `async with` block exits normally. If streaming is unsupported, disabled, or the event is not a message, the Host sends one complete message at the end. Exceptions discard buffered partial text. Debug runs simulate delivery.
This API uses the same permission as `ctx.reply()`. Runner components can use `self.get_run_api(ctx).reply_stream()`; model output text is still not sent automatically.
## Registering Events
@@ -189,7 +190,8 @@ After installing the plugin, bind the Bot's **Member joined** and **Message rece
## Next Steps
- See the [`RunnerContext` API reference](/en/plugin/dev/apis/agent-run#runner).
- See [LangBot API](/en/plugin/dev/apis/common) for models, tools, knowledge bases, and storage.
- See [Platform API](/en/plugin/dev/apis/platform) for messaging and other platform operations.
- Explore more examples in [RunnerDemo](https://github.com/langbot-app/langbot-plugin-demo/tree/main/RunnerDemo).
- To extend Pipeline steps such as preprocessing or completion of a model call, use [Event Listener](/en/plugin/dev/components/event-listener).
See [Run Context APIs](/en/plugin/dev/apis/agent-run) for replies, models, tools, history, and state.
+1
View File
@@ -173,4 +173,5 @@ Now execute the command `lbp run` in the plugin directory to start debugging. Co
You have learned the basic usage of tools. Next, you can:
- See how Tool receives [`session` and `query_id`](/en/plugin/dev/apis/agent-run#tool).
- Check out [Plugin Common APIs](/en/plugin/dev/apis/common)
+194 -132
View File
@@ -1,179 +1,241 @@
---
title: "実行コンテキスト API"
title: "コンテキスト API"
---
Runner の `ctx.api` は現在の実行 ID、コンテキスト、リソースの許可範囲に結び付いています。独自の `run(ctx)` と登録した処理関数は同じ `RunnerContext` を使用します。`self.plugin` から[共通 API](/ja/plugin/dev/apis/common)も利用できますが、現在の実行を自動的に表すものではありません。
コンテキストには、1 回のコンポーネント呼び出しに関するデータが含まれます。コンポーネントごとに受け取るコンテキストが異なるため、まず対象コンポーネントの入口を確認してください。
## アクセス方法
| コンポーネント | ハンドラーの入口 | コンテキスト型 |
| --- | --- | --- |
| EventListener | `handler(event_context)` | `EventContext` |
| Command | `subcommand(context)` | `ExecuteContext` |
| Tool | `call(params, session, query_id)` | 独立したコンテキストオブジェクトなし |
| Runner | `run(ctx)` または `handler(ctx)` | `RunnerContext` |
| KnowledgeEngine | `ingest(context)`、`retrieve(context)` | `IngestionContext`、`RetrievalContext` |
| KnowledgeRetriever | `retrieve(context)` | `RetrievalContext` |
| Parser | `parse(context)` | `ParseContext` |
| Page | `handle_api(request)` | `PageRequest` |
このページでは、コンテキストのデータとメソッドのみを説明します。モデル、ナレッジベース、ストレージなどの LangBot 機能には `self.plugin` を使用します。詳細は [LangBot API](/ja/plugin/dev/apis/common) を参照してください。プラットフォーム操作は[プラットフォーム API](/ja/plugin/dev/apis/platform)に記載しています。
`EventContext`、`ExecuteContext`、`Session` には `instance_uuid`、`workspace_uuid`、`placement_generation` も含まれます。これらは現在の実行に対応するインスタンスとワークスペースを示すためのもので、プラグイン側の認可情報として使用しないでください。
## EventListener
EventListener はパイプラインイベントを処理します。イベントハンドラーは `EventContext` を受け取ります。
```python
# Inside Runner.run(ctx) or a registered handler
api = ctx.api
event = event_context.event
sender_id = event.sender_id
```
以下の `api` は現在の実行の API です。 同期の `get_allowed_*` とストリーミングのコンテキスト・イテレーター以外は、`await` で呼び出します。別の実行へ持ち越して再利用しないでください。
### コンテキストデータ
### 設定と権限
| プロパティ | 型 | 説明 |
| --- | --- | --- |
| `event` | `BaseEventModel` | 現在のイベントオブジェクト。実際の型は登録したイベント型と一致します |
| `event_name` | `str` | 現在のイベントクラス名 |
| `query_id` | `int` | 現在のパイプラインリクエスト ID |
| `query_uuid` | `str \| None` | 現在のパイプラインリクエストの安定した識別子 |
| `eid` | `int` | Plugin Runtime 内の一時的なイベント番号。永続化しないでください |
| `is_prevent_default` | `bool` | デフォルト処理を停止済みか。変更には `prevent_default()` を使用します |
| `is_prevent_postorder` | `bool` | 後続プラグインを停止済みか。変更には `prevent_postorder()` を使用します |
`ctx.config` はプロセッサーまたは Runner インスタンスの設定、`self.get_plugin_config()` はプラグイン全体の設定です。`spec.permissions` は要求する権限を宣言し、実際に利用できるリソースはユーザー設定と現在のイベントにも依存します。
イベントのフィールドと購読可能なイベントは[パイプラインイベント](/ja/plugin/dev/apis/pipeline-events)を参照してください。
```yaml
spec:
capabilities:
tool_calling: true
permissions:
tools: [detail, call]
### コンテキストメソッド
| メソッド | 戻り値 | 説明 |
| --- | --- | --- |
| `await event_context.reply(message_chain, quote_origin=False)` | - | 現在のリクエストの会話に返信 |
| `await event_context.get_bot_uuid()` | `str` | 送信元 Bot の UUID を取得 |
| `await event_context.set_query_var(key, value)` | - | 現在のリクエストに変数を設定 |
| `await event_context.get_query_var(key)` | `Any` | リクエスト変数を 1 つ取得 |
| `await event_context.get_query_vars()` | `dict[str, Any]` | すべてのリクエスト変数を取得 |
| `await event_context.create_new_conversation()` | `dict[str, Any]` | 現在のパイプライン会話をクリアし、後続リクエストで新しい会話を作成 |
| `await event_context.list_pipeline_knowledge_bases()` | `list[dict[str, Any]]` | 現在のパイプラインの Local Agent に設定されたナレッジベースを取得 |
| `await event_context.retrieve_knowledge(kb_id, query_text, top_k=5, filters=None)` | `list[dict[str, Any]]` | 現在のパイプラインに設定されたナレッジベースを検索 |
| `event_context.prevent_default()` | - | 現在のイベントのデフォルト処理を停止 |
| `event_context.prevent_postorder()` | - | 後続プラグインによる現在のイベント処理を停止 |
`reply()` は [MessageChain](/ja/plugin/dev/apis/messages) を受け取ります。リクエスト変数、返信、パイプラインのナレッジベース API には、関連付けられたパイプラインリクエストが必要です。`retrieve_knowledge()` の `kb_id` は `list_pipeline_knowledge_bases()` の結果から指定します。
`prevent_default()` はデフォルトフローを停止できるイベントにのみ作用します。詳細は[パイプラインイベント](/ja/plugin/dev/apis/pipeline-events#デフォルト動作を阻止)を参照してください。
## Command
Command のサブコマンドハンドラーは `ExecuteContext` を受け取ります。
```python
query = " ".join(context.crt_params)
session = context.session
```
返信とツール呼び出しに必要な最小設定です。他の機能を使う場合は `spec.permissions` に追加します:
### コンテキストデータ
| `spec.permissions` | 操作 |
| プロパティ | 型 | 説明 |
| --- | --- | --- |
| `session` | `Session` | 現在のメッセージが属するセッション |
| `command_text` | `str` | コマンド接頭辞を除いた完全なコマンド文字列 |
| `full_command_text` | `str` | 接頭辞を含む完全なコマンド文字列 |
| `command` | `str` | ルートコマンド名 |
| `crt_command` | `str` | 現在実行中のサブコマンド名 |
| `params` | `list[str]` | ルートコマンド以降のすべての引数 |
| `crt_params` | `list[str]` | 現在のサブコマンドで未処理の引数 |
| `privilege` | `int` | 現在のユーザーのコマンド権限レベル |
| `query_id` | `int` | 現在のパイプラインリクエスト ID |
| `query_uuid` | `str \| None` | 現在のパイプラインリクエストの安定した識別子 |
SDK は現在のサブコマンドに入る前に `context.shift()` を呼び出します。コンポーネントから直接呼び出す必要はありません。
### コンテキストメソッド
| メソッド | 戻り値 | 説明 |
| --- | --- | --- |
| `await context.reply(message_chain, quote_origin=False)` | - | 現在のリクエストの会話に返信 |
| `await context.get_bot_uuid()` | `str` | 送信元 Bot の UUID を取得 |
| `await context.set_query_var(key, value)` | - | 現在のリクエストに変数を設定 |
| `await context.get_query_var(key)` | `Any` | リクエスト変数を 1 つ取得 |
| `await context.get_query_vars()` | `dict[str, Any]` | すべてのリクエスト変数を取得 |
| `await context.create_new_conversation()` | `dict[str, Any]` | 現在のパイプライン会話をクリアし、後続リクエストで新しい会話を作成 |
| `await context.list_pipeline_knowledge_bases()` | `list[dict[str, Any]]` | 現在のパイプラインの Local Agent に設定されたナレッジベースを取得 |
| `await context.retrieve_knowledge(kb_id, query_text, top_k=5, filters=None)` | `list[dict[str, Any]]` | 現在のパイプラインに設定されたナレッジベースを検索 |
これらのリクエストメソッドは EventListener と同じ動作です。登録方法と戻り値は [Command コンポーネント](/ja/plugin/dev/components/command)を参照してください。
## Tool
Tool には独立したコンテキストオブジェクトがありません。`call()` の引数として呼び出し情報を受け取ります。
```python
conversation_type = session.launcher_type.value
conversation_id = session.launcher_id
sender_id = session.sender_id
```
| 引数 | 説明 |
| --- | --- |
| `models` | `invoke`, `stream`, `rerank`, `count_tokens` |
| `tools` | `detail`, `call` |
| `knowledge_bases` | `list`, `retrieve` |
| `history` | `page`, `search` |
| `events` | `get`, `page` |
| `storage` | `plugin`, `workspace` |
| `interactions` | `request` |
| `params` | ツールの JSON Schema に基づいてモデルまたは呼び出し元が生成した引数 |
| `session` | 現在のセッションデータ |
| `query_id` | 現在のパイプラインリクエスト ID。リクエストコンテキストが必要な LangBot API にそのまま渡します |
実際に許可されたリソースを確認します:
`Session` の主なプロパティは次のとおりです。
```python
models = api.get_allowed_models() # Each item has model_id and operations
tools = api.get_allowed_tools() # Each item has tool_name and parameters
knowledge_bases = api.get_allowed_knowledge_bases() # Each item has kb_id
```
コンテキスト API の利用可否は `api.ctx.context.available_apis` で確認できます。`False` の API は呼び出せません。マニフェストへの権限追加だけで有効になるわけではありません。
## 返信とログ
| Runner メソッド | 用途 |
| プロパティ | 説明 |
| --- | --- |
| `await ctx.reply(text)` | 現在のイベントの会話へテキストを送信し、操作結果を返します。 |
| `await ctx.log(text, level="info")` | `debug`、`info`、`warning`、`error` のログを記録します。 |
| `ctx.reply_stream()` | 非同期コンテキストマネージャーで同じ返信を更新します。 |
| `launcher_type` | 会話種別:`person` または `group` |
| `launcher_id` | 個人チャットのユーザー ID またはグループ ID |
| `sender_id` | 現在のメッセージ送信者 ID |
| `bot_uuid` | 現在の Bot UUID |
| `using_conversation` | 現在のパイプライン会話 |
| `conversations` | この Session に保存されたパイプライン会話 |
| `use_prompt_name` | 使用中のプロンプト名 |
| `create_time`、`update_time` | Session の作成時刻と更新時刻 |
`ctx.reply(text)` は `await api.call_tool("event_reply", {"text": text})` と同じです。イベントに返信先があり、`event_reply` が許可されている必要があります。ログや独立した Agent の出力テキストは自動送信されません。
`session` はデータオブジェクトであり、`reply()` などのコンテキストメソッドはありません。ツールの戻り値は呼び出し元へ返され、チャットプラットフォームには自動送信されません。LangBot とプラットフォームの機能には `self.plugin` を使用します。API が `session` と `query_id` を要求する場合は、現在の呼び出しで受け取った値を渡してください。
### ストリーミング返信
## Runner
独自の `run(ctx)` と Runner のイベントハンドラーは、どちらも `RunnerContext` を受け取ります。このコンテキストは現在の実行中だけ有効です。
```python
async with api.reply_stream() as reply:
await reply.update("Processing…")
await reply.update("Processing complete.")
result = reply.result
text = ctx.input.to_text()
event_type = ctx.event.event_type
```
Runner では `ctx.reply_stream()` を使うと、操作の開始と結果も記録されます。
### コンテキストデータ
`update(text)` には差分ではなく**その時点の全文**を渡します。戻り値は操作結果です。正常終了時に返信を完了します。プラットフォームでストリーミング返信が有効なメッセージイベントでは表示を更新し、それ以外の返信可能なイベントでは正常終了時に全文を一度送信します。例外やキャンセルでは未送信のテキストを破棄しますが、表示済みの内容の撤回は保証されません。デバッグ時の送信は Mock です。
| プロパティ | 型 | 説明 |
| --- | --- | --- |
| `run_id` | `str` | 現在の実行 ID |
| `trigger` | `AgentTrigger` | トリガーの種類、発生元、時刻 |
| `event` | `AgentEventContext` | イベント ID、種類、発生元、時刻、元データを含む標準イベントエンベロープ |
| `platform_event` | プラットフォームイベント型 | イベント型に応じて解析されたプラットフォームイベント |
| `conversation` | `ConversationContext \| None` | 現在の会話、スレッド、Bot、ワークスペースの識別子 |
| `actor` | `ActorContext \| None` | イベントを発生させた主体 |
| `subject` | `SubjectContext \| None` | イベントの対象となるメッセージやグループなど |
| `input` | `AgentInput` | 現在のテキスト、構造化コンテンツ、添付ファイル |
| `delivery` | `DeliveryContext` | 出力先とストリーミング、編集、リアクションの対応状況 |
| `resources` | `AgentResources` | 今回の実行で許可されたモデル、ツール、ナレッジベース、スキル、ストレージ |
| `context` | `ContextAccess` | 会話カーソル、インライン方針、利用可能なコンテキスト API |
| `state` | `AgentRunState` | 実行開始時に読み込まれたスコープ別状態のスナップショット |
| `runtime` | `AgentRuntimeContext` | LangBot バージョン、トレース ID、期限 |
| `config` | `dict[str, Any]` | 現在の Agent またはプラグイン処理インスタンスの設定 |
| `adapter` | `AdapterContext \| None` | エントリーアダプターの追加データ |
| `metadata` | `dict[str, Any]` | ホストが提供するその他のメタデータ |
`available_apis.reply_stream` と `event_reply` 権限が必要です。モデル出力のストリーミングとプラットフォームへの送信は別の API です。
上表の安定したプロパティを優先してください。`event.data` と `adapter.extra` には、安定したフィールドに含まれない追加データが入ります。
## モデル、ツール、ナレッジベース
### 返信とログ
モデルの引数と使用量の形式は[共通 API](/ja/plugin/dev/apis/common)を参照してください。実行 API には次のメソッドもあります:
| メソッド | 戻り値 | 説明 |
| --- | --- | --- |
| `await ctx.get_bot_uuid()` | `str` | 送信元 Bot UUID を取得。関連する Bot がなければエラー |
| `await ctx.reply(message_chain, quote_origin=False)` | `Any` | 文字列または `MessageChain` で現在のイベントに返信 |
| `ctx.reply_stream()` | 非同期コンテキストマネージャー | 1 件の返信を完全なテキストで逐次更新 |
| `await ctx.log(text, level="info")` | - | 今回の実行ログへ記録。レベルは `debug`、`info`、`warning`、`error` |
| メソッド | 戻り値・用途 |
| --- | --- |
| `invoke_llm(llm_model_uuid, messages, ...)` | `Message` |
| `invoke_llm_with_usage(llm_model_uuid, messages, ...)` | `LLMInvokeResult` |
| `invoke_llm_stream(llm_model_uuid, messages, ...)` | `MessageChunk` の非同期イテレーター |
| `invoke_llm_stream_events(llm_model_uuid, messages, ...)` | `LLMStreamEvent` の非同期イテレーター |
| `count_tokens(llm_model_uuid, messages, funcs=None, extra_args=None, timeout=None)` | 入力トークン数(`int`) |
| `invoke_rerank(rerank_model_uuid, query, documents, top_k=None, extra_args=None, timeout=30.0)` | `index`、`relevance_score` を含むリスト |
| `get_tool_detail(tool_name)` | ツールの説明と引数 schema(`dict`) |
| `call_tool(tool_name, parameters)` | ツール結果(`dict`)。`session`、`query_id` は不要 |
| `retrieve_knowledge(kb_id, query_text, top_k=5, filters=None)` | 検索結果のリスト |
`reply_stream().update(text)` には、その時点の完全なテキストを渡します。プラットフォームがストリーミングに対応しない場合、終了時に完全なメッセージを 1 件送信します。デバッグモードでは送信をシミュレートします。
4 種類のモデル呼び出しは `remove_think=None`、非ストリーミング呼び出しは `timeout=None` も受け取ります。タイムアウトは実行の残り時間に制限されます。リソース一覧が空の場合もあります。
### 利用可能なツール
```python
allowed = {tool.tool_name for tool in api.get_allowed_tools()}
if "event_get_actor" in allowed:
actor = await api.call_tool("event_get_actor", {})
```
| メソッド | 戻り値 | 説明 |
| --- | --- | --- |
| `await ctx.get_available_tools()` | `list[dict[str, Any]]` | 今回呼び出せるコンテキスト操作、プラットフォーム API、プラグインツール、MCP ツールを取得 |
| `await ctx.call_tool(tool_name, parameters=None)` | `dict[str, Any]` | 上記一覧のツールを呼び出す |
`event_*` ツールの対象は LangBot がイベントから固定し、`platform_*` ツールの対象は schema に従って指定します。許可された一覧の名前と引数を使い、引数なしのツールには `{}` を渡します。
`get_available_tools()` の各項目には `name`、`description`、`parameters`、`type`、`operations` が含まれます。結果は現在の Agent またはプラグイン処理インスタンスの設定とイベント機能で絞り込まれています。一覧にないツールは `ctx.call_tool()` で呼び出せません。
## 履歴とイベント
### プロンプト、履歴、イベント
現在の入力には全履歴が含まれません。必要に応じて現在の実行範囲の記録を取得します。別の会話 ID を渡してアクセス範囲を広げることはできません。
| メソッド | 戻り値 | 利用可否フィールド |
| --- | --- | --- |
| `await ctx.get_prompt()` | `list[dict[str, Any]]` | `prompt_get` |
| `await ctx.history_page(conversation_id=None, before_cursor=None, after_cursor=None, limit=50, direction="backward", include_attachments=False)` | `HistoryPage` | `history_page` |
| `await ctx.history_search(query, filters=None, top_k=10)` | `HistorySearchResult` | `history_search` |
| `await ctx.event_get(event_id)` | `AgentEventRecord` | `event_get` |
| `await ctx.event_page(conversation_id=None, event_types=None, before_cursor=None, limit=50)` | `EventPage` | `event_page` |
| `await ctx.steering_pull(mode="all", limit=None)` | `SteeringPullResult` | `steering_pull` |
| メソッド | 戻り値 |
| --- | --- |
| `get_prompt()` | 適用されたプロンプトのリスト。機能フラグは `prompt_get` |
| `history_page(conversation_id=None, before_cursor=None, after_cursor=None, limit=50, direction="backward", include_attachments=False)` | `HistoryPage` |
| `history_search(query, filters=None, top_k=10)` | `HistorySearchResult` |
| `event_get(event_id)` | `AgentEventRecord` |
| `event_page(conversation_id=None, event_types=None, before_cursor=None, limit=50)` | `EventPage` |
| `steering_pull(mode="all", limit=None)` | `SteeringPullResult`。実行中に追加された入力を取得 |
### 状態
```python
if api.ctx.context.available_apis.history_page:
page = await api.history_page(limit=20)
for item in page.items:
print(item.model_dump())
if page.has_more and page.prev_cursor:
older = await api.history_page(before_cursor=page.prev_cursor, limit=20)
```
| メソッド | 戻り値 | 説明 |
| --- | --- | --- |
| `await ctx.state_get(scope, key)` | `dict[str, Any]` | 状態値を取得 |
| `await ctx.state_set(scope, key, value)` | `dict[str, Any]` | JSON シリアライズ可能な状態値を保存 |
| `await ctx.state_delete(scope, key)` | `dict[str, Any]` | 状態値を削除 |
| `await ctx.state_list(scope, prefix=None, limit=100)` | `dict[str, Any]` | 指定スコープの状態キーを一覧表示 |
ページ結果は SDK オブジェクトです。辞書ではなく `.items`、`.has_more`、`.prev_cursor`、`.next_cursor` を使います。古い記録は `before_cursor`、新しい記録は `after_cursor` と `direction="forward"` で取得します。履歴検索はテキスト一致のみの場合があります。追加入力対応 Runner の `steering_pull` は `all`、`one`、`one-at-a-time` を受け取ります。
`scope` は `conversation`、`actor`、`subject`、`runner` のいずれかです。これらのメソッドには `ctx.context.available_apis.state` が `true` である必要があります。
## 状態とストレージ
### 実行記録
| メソッド | 戻り値 |
| --- | --- |
| `state_get(scope, key)` | `{"value": ...}` |
| `state_set(scope, key, value)` | `{"success": ...}` |
| `state_delete(scope, key)` | `{"success": ...}` |
| `state_list(scope, prefix=None, limit=100)` | `{"keys": [...], "has_more": ...}` |
| メソッド | 戻り値 | 利用可否フィールド |
| --- | --- | --- |
| `await ctx.run_get(run_id=None)` | `AgentRun` | `run_get` |
| `await ctx.run_list(conversation_id=None, statuses=None, before_cursor=None, limit=50)` | `RunPage` | `run_list` |
| `await ctx.run_events_page(run_id=None, before_cursor=None, after_cursor=None, limit=50, direction="forward")` | `RunEventPage` | `run_events_page` |
| `await ctx.run_cancel(run_id=None, reason=None)` | `AgentRun` | `run_cancel` |
| `await ctx.run_append_result(result)` | `AgentRunEvent` | `run_append_result` |
| `await ctx.run_finalize(run_id=None, status=None, reason=None)` | `AgentRun` | `run_finalize` |
状態には `available_apis.state` とホストが許可するスコープ(`conversation`、`actor`、`subject`、`runner`)が必要です。値は JSON 化可能にし、`external.` などのキープレフィックスを推奨します。LangBot が永続化し、API は辞書を返します。
`run_id=None` は現在の実行を指します。通常のイベントハンドラーは SDK が自動的に完了します。独自の `run(ctx)` が `RunnerResult` を yield する場合、同じ結果を `run_append_result()` で重複登録しないでください。
```python
if api.ctx.context.available_apis.state:
await api.state_set("conversation", "external.last_topic", "setup")
value = await api.state_get("conversation", "external.last_topic")
```
### 利用可否と権限
プラグインおよびワークスペースのストレージは `set_plugin_storage`、`get_plugin_storage`、`get_plugin_storage_keys`、`delete_plugin_storage` と対応する `*_workspace_storage*` を使用します。引数は[共通 API](/ja/plugin/dev/apis/common)と同じで、値は `bytes` です。`api.ctx.resources.storage.plugin_storage` または `workspace_storage` の権限が必要です。
プロンプト、履歴、イベント、状態、実行記録の API が利用可能かどうかは `ctx.context.available_apis` で確認します。許可されたモデル、ツール、ナレッジベースはそれぞれ `ctx.resources.models`、`ctx.resources.tools`、`ctx.resources.knowledge_bases` にあります。
## 実行記録
Runner の実行中に `self.plugin` から呼び出すモデル、ツール、ナレッジベース、ストレージ、プラットフォーム API は、自動的に現在の実行へ関連付けられ、`ctx.resources` に基づいて再検証されます。`run_id` を渡す必要はありません。ハンドラー終了後にバックグラウンドタスクからこのコンテキストや実行に紐づく呼び出しを使用しないでください。
以下は同名の `available_apis` フラグが必要で、許可された範囲の実行のみ操作できます。
`ctx.api` は低レベルの実行スコーププロキシです。通常のコンポーネントコードでは、このページに記載した `ctx` メソッドと、LangBot API 用の `self.plugin` を使用してください。
| メソッド | 戻り値 |
| --- | --- |
| `run_get(run_id=None)` | `AgentRun` |
| `run_list(conversation_id=None, statuses=None, before_cursor=None, limit=50)` | `RunPage` |
| `run_events_page(run_id=None, before_cursor=None, after_cursor=None, limit=50, direction="forward")` | `RunEventPage` |
| `run_cancel(run_id=None, reason=None)` | `AgentRun` |
| `run_append_result(result)` | `AgentRunEvent` |
| `run_finalize(run_id=None, status=None, reason=None)` | `AgentRun` |
## データ専用コンテキスト
`run_id=None` は現在の実行を指します。登録した処理関数は戻ると自動終了します。独自の `run(ctx)` は `yield RunnerResult` で結果を報告できます。同じ結果を `run_append_result` で重複登録しないでください。
以下のコンポーネントが受け取るものはタスク入力であり、EventListener や Runner の実行コンテキストメソッドはありません。フィールド、戻り値、完全な例は各コンポーネントガイドに記載しています。
## 構造化インタラクション(Runner)
確認やフォーム入力には `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` のメソッドではありません。独自の run(ctx) から yield します。
## エラー処理
```python
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", {})
except PermissionDeniedError as exc:
await ctx.log(str(exc), level="warning")
except AgentAPIException as exc:
await ctx.log(f"{exc.error.code}: {exc.error.message}", level="error")
```
Runner 内の例です。`PermissionDeniedError` はリソース・操作・機能の権限不足を示します。`AgentAPIException.error` は `code`、`message`、`retryable`、`details` を持ちます。送信のタイムアウト時は成功済みの場合もあるため、`retryable` だけで再送しないでください。
| コンポーネントの入口 | 主なデータ | コンポーネントガイド |
| --- | --- | --- |
| `KnowledgeEngine.ingest(context: IngestionContext)` | ファイル、対象ナレッジベース、作成設定、解析結果 | [KnowledgeEngine](/ja/plugin/dev/components/knowledge-engine#ドキュメント取り込み) |
| `KnowledgeEngine.retrieve(context: RetrievalContext)` | クエリ、対象ナレッジベース、検索設定、フィルター | [KnowledgeEngine](/ja/plugin/dev/components/knowledge-engine#ナレッジ検索) |
| `KnowledgeRetriever.retrieve(context: RetrievalContext)` | クエリと外部ナレッジベース設定 | [KnowledgeRetriever](/ja/plugin/dev/components/knowledge-retriever#検索コンテキスト) |
| `Parser.parse(context: ParseContext)` | ファイル内容、ファイル名、MIME タイプ、メタデータ | [Parser](/ja/plugin/dev/components/parser#解析メソッド) |
| `Page.handle_api(request: PageRequest)` | エンドポイント、HTTP メソッド、本文、ヘッダー | [Page](/ja/plugin/dev/components/page#pagerequest-フィールド) |
+2 -113
View File
@@ -1,119 +1,8 @@
---
title: "プラグイン共通API"
title: "LangBot API"
---
LangBotは、プラグインがさまざまなLangBotモジュールを操作し、メッセージコンテキストを制御するための一連のAPIを提供します。
すべてのコンポーネントは `self.plugin` から本ページの LangBot API を利用できます。Runner の `ctx.api` は現在の実行とリソースの許可範囲に結び付いています。[実行コンテキスト API](/ja/plugin/dev/apis/agent-run)を参照してください。Bot と宛先を指定する操作は[プラットフォーム API](/ja/plugin/dev/apis/platform)に記載しています。
## リクエストAPI
現在処理中のユーザーリクエスト(メッセージ)に対する操作です。`EventListener`と`Command`コンポーネントでのみ使用可能です。アクセス方法:
- `EventListener`のイベントハンドラメソッド内: `event_context: context.EventContext`オブジェクトの内部メソッド
- `Command`のサブコマンドハンドラメソッド内: `context: ExecuteContext`オブジェクトの内部メソッド
### 直接返信メッセージ
現在のリクエストが存在するセッションにメッセージチェーンで直接返信します。
メッセージチェーンの構築方法については、[メッセージプラットフォームエンティティ](/en/plugin/dev/apis/messages)を参照してください。
```python
async def reply(
self, message_chain: platform_message.MessageChain, quote_origin: bool = False
):
"""メッセージリクエストに返信する
Args:
message_chain (platform.types.MessageChain): LangBotメッセージチェーン
quote_origin (bool): 元のメッセージを引用するかどうか
"""
# 使用例
await event_context.reply(
platform_message.MessageChain([
platform_message.Plain(text="Hello, world!"),
]),
)
```
### Bot UUIDの取得
現在のリクエストを発行したBotのUUIDを取得します。
```python
async def get_bot_uuid(self) -> str:
"""Bot UUIDを取得する"""
# 使用例
bot_uuid = await event_context.get_bot_uuid()
```
### リクエスト変数の設定
単一のリクエスト内の一部の情報は、リクエスト変数に保存されます。Difyなどの外部Agent プラットフォームを使用する場合、[これらの変数はAgent プラットフォームに明示的に渡されます](/en/deploy/pipelines/readme.html#request-variables)。
```python
async def set_query_var(self, key: str, value: Any):
"""クエリ変数を設定する"""
# 使用例
await event_context.set_query_var("key", "value")
```
### リクエスト変数の取得
単一のリクエスト変数を取得します。
```python
async def get_query_var(self, key: str) -> Any:
"""クエリ変数を取得する"""
# 使用例
query_var = await event_context.get_query_var("key")
```
### すべてのリクエスト変数の取得
```python
async def get_query_vars(self) -> dict[str, Any]:
"""すべてのクエリ変数を取得する"""
# 使用例
query_vars = await event_context.get_query_vars()
```
### 現在のパイプラインに設定されたナレッジベース一覧の取得
現在のリクエストが使用するパイプラインに設定されたナレッジベースの一覧を取得します。
```python
async def list_pipeline_knowledge_bases(self) -> list[dict[str, Any]]:
"""List knowledge bases configured for the current pipeline"""
# 使用例
knowledge_bases = await event_context.list_pipeline_knowledge_bases()
# 返り値の例
[
{
"uuid": "kb_uuid",
"name": "Product Docs",
"description": "社内製品ドキュメント",
}
]
```
現在のリクエストに対応するパイプラインの `Local Agent` 設定にバインドされたナレッジベースのみを返します。現在のパイプラインにナレッジベースが設定されていない場合、または `Local Agent` を使用していない場合は、空のリストが返されます。
### 新しい会話を開始
`await event_context.create_new_conversation()` は現在のパイプラインセッションが使用している会話を解除し、後続の処理で新しい会話を開始します。空の辞書を返し、プラットフォームのチャット履歴は削除しません。
### パイプラインのナレッジベースを検索
`await event_context.retrieve_knowledge(kb_id, query_text, top_k=5, filters=None)` は検索結果のリストを返します。`kb_id` は `list_pipeline_knowledge_bases()` で取得します。このリクエスト API ではパイプラインに設定されていないナレッジベースにアクセスできません。
モデル、ツール、ナレッジベース、ストレージには `self.plugin` を使用します。現在のイベント、返信、会話の状態については[コンテキスト API](/ja/plugin/dev/apis/agent-run) を参照してください。
## LangBot API
+1 -1
View File
@@ -62,4 +62,4 @@ msg_chain = MessageChain([
## プラットフォーム API
ユーザー取得、グループ管理、固有の操作には[プラットフォーム API](/ja/plugin/dev/apis/platform)を使用してください。Runner は[実行コンテキスト API](/ja/plugin/dev/apis/agent-run)から許可されたツールを呼び出します。
ユーザー取得、グループ管理、固有の操作には[プラットフォーム API](/ja/plugin/dev/apis/platform)を使用してください。Runner も同じ `self.plugin` を使用し、現在の会話には `ctx.reply()` で返信します。
+5 -44
View File
@@ -248,42 +248,13 @@ class PromptPreProcessing(BaseEventModel):
"""この会話の既存メッセージレコード、変更可能、langbot_plugin.api.entities.builtin.provider.message.Messageまたはlangbot_plugin.api.entities.builtin.provider.message.MessageChunk型"""
```
## イベントコンテキストAPI
## EventListener コンテキスト
```python
...
@self.handler(events.PersonMessageReceived)
async def handler(event_context: context.EventContext):
...
```
イベントハンドラーは `event_context.event` から現在のイベントを取得します。`EventContext` の完全なプロパティとメソッドは[コンテキスト API](/ja/plugin/dev/apis/agent-run#eventlistener)を参照してください。
イベント処理メソッドには`EventContext`オブジェクトが渡され、イベントコンテキスト情報が含まれます。このオブジェクトには[リクエストAPI](/ja/plugin/dev/apis/common)とイベントコンテキスト固有のAPIの両方があります。以下は、イベントコンテキスト固有のAPIのリストです:
### デフォルト動作を阻止
### 元のイベント属性の取得
`event_context.event`属性は元のイベントオブジェクトであり、元のイベントの属性を取得できます。型はリッスンされているイベントの型です。
例えば、リッスンされているイベントが`GroupMessageReceived`の場合:
```python
event = event_context.event
print(event.launcher_type) # 起動元オブジェクトタイプ(group)
print(event.launcher_id) # グループID
print(event.sender_id) # 送信者アカウントID
print(event.message_chain) # メッセージチェーン
```
### デフォルト動作を防止
```python
def prevent_default(self):
"""デフォルト動作を防止する"""
# 使用例
event_context.prevent_default()
```
このメソッドを呼び出すと、このイベントのデフォルトの後続動作が防止され、パイプラインは直接終了します。
`event_context.prevent_default()` を呼び出すと、現在のイベントのデフォルト処理が停止します。この操作を利用できるイベントは次のとおりです。
<Info>
以下のイベントのみデフォルト動作を阻止できます:
@@ -297,14 +268,4 @@ event_context.prevent_default()
- NormalMessageResponded
</Info>
### 後続実行を防止
```python
def prevent_postorder(self):
"""後続実行を防止する"""
# 使用例
event_context.prevent_postorder()
```
このメソッドを呼び出すと、後続のプラグインがこの時点で実行されなくなります。
`event_context.prevent_postorder()` を呼び出すと、後続プラグインによる現在のイベント処理を停止できます。
+7 -7
View File
@@ -64,15 +64,15 @@ account = await self.plugin.call_platform_api(
アダプターが宣言した操作のみ呼び出せます。すべてのプラットフォーム API を任意に転送できるわけではありません。プラグインはランタイム経由でホストを呼び出し、`ctx.query.adapter` や `adapter.bot` には直接アクセスしません。
## イベントプロセッサーからの呼び出し
## Runner
Runner も `self.plugin` から Bot と宛先を指定して本ページの API を利用できます。現在のイベントの許可範囲で操作し、実行記録に残すには `ctx.api` または `ctx.reply()` を使用します:
Runner の実行中、`self.plugin` によるモデル、ツール、ナレッジベース、ストレージ、プラットフォーム呼び出しは現在の実行と権限に自動的に関連付けられます。`run_id` の指定は不要です。同時実行は互いに分離されます。ハンドラー終了後に実行に紐づく API を呼び続けないでください。
現在のボットは `await ctx.get_bot_uuid()` で取得します。プラットフォーム呼び出しは今回のツール権限に従い、イベント対象だけが許可されている場合は別の対象を指定できません。プラットフォーム固有の操作を含む未許可の操作は拒否されます。デバッグではこれらの呼び出しも Mock を使用します。
```python
tools = {tool.tool_name for tool in ctx.api.get_allowed_tools()}
if "event_get_actor" in tools:
actor = await ctx.api.call_tool("event_get_actor", {})
tools = await ctx.get_available_tools()
if any(tool["name"] == "event_get_actor" for tool in tools):
actor = await ctx.call_tool("event_get_actor")
await ctx.log(str(actor))
```
アクセス方法、権限、返信の例は[実行コンテキスト API](/ja/plugin/dev/apis/agent-run)を参照してください。イベントデバッグのプラットフォームツールは Mock ですが、通常のコンポーネントの `self.plugin.call_platform_api()` は実際の呼び出しです。
+2 -1
View File
@@ -211,4 +211,5 @@ yield CommandReturn(
コマンド登録とコマンド実行の基本情報を学びました。次は:
- [プラグイン共通API](/en/plugin/dev/apis/common)を確認してください
- 完全な [`ExecuteContext` API リファレンス](/ja/plugin/dev/apis/agent-run#command)を確認します。
- [LangBot API](/ja/plugin/dev/apis/common)を確認します。
+3 -2
View File
@@ -103,5 +103,6 @@ class EventContext(pydantic.BaseModel):
イベントリスナーの基本情報を学びました。次は:
- ドキュメント[パイプラインイベント](/en/plugin/dev/apis/pipeline-events)で`監視可能なイベントのリスト`と`イベントコンテキストAPI`を確認してください
- [プラグイン共通API](/en/plugin/dev/apis/common)を確認してください
- [パイプラインイベント](/ja/plugin/dev/apis/pipeline-events)でイベントの種類とフィールドを確認します。
- 完全な [`EventContext` API リファレンス](/ja/plugin/dev/apis/agent-run#eventlistener)を確認します。
- [LangBot API](/ja/plugin/dev/apis/common)を確認します。
+5 -3
View File
@@ -6,6 +6,8 @@ Runner は Agent の実行ロジック、または「プラグインプロセッ
環境の準備は[プラグイン開発チュートリアル](/ja/plugin/dev/tutor)を参照してください。
`RunnerContext` の完全なフィールドとメソッドは[コンテキスト API](/ja/plugin/dev/apis/agent-run#runner)を参照してください。
## Runner コンポーネントの追加
1 つのプラグインに複数のイベントプロセッサーを追加できます。プラグインのディレクトリで `lbp comp Runner` を実行し、名前に `welcome`、説明に `Welcome new members` を入力します。
@@ -147,7 +149,6 @@ async with ctx.reply_stream() as reply:
`async with` ブロックが正常終了すると返信が完了します。ストリーミングが未対応・無効の場合やメッセージ以外のイベントでは、最後に全文を一度だけ送信します。例外時には、バッファ内の未完成テキストを送信しません。デバッグでは送信をシミュレーションします。
権限は `ctx.reply()` と共通です。Runner も `self.get_run_api(ctx).reply_stream()` を利用できます。モデルの出力テキストが自動送信されることはありません。
## イベントの登録
@@ -189,7 +190,8 @@ async with ctx.reply_stream() as reply:
## 次のステップ
- [`RunnerContext` API リファレンス](/ja/plugin/dev/apis/agent-run#runner)を確認します。
- モデル、ツール、ナレッジベース、ストレージについては [LangBot API](/ja/plugin/dev/apis/common)を確認します。
- メッセージ送信などについては[プラットフォーム API](/ja/plugin/dev/apis/platform)を確認します。
- [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)を参照してください。
+2 -1
View File
@@ -173,4 +173,5 @@ httpx
ツールの基本的な使い方を学びました。次は:
- [プラグイン共通API](/en/plugin/dev/apis/common)を確認してください
- Tool が受け取る [`session` と `query_id`](/ja/plugin/dev/apis/agent-run#tool)を確認します。
- [LangBot API](/ja/plugin/dev/apis/common)を確認します。
+96 -3
View File
@@ -22,6 +22,10 @@ from langbot_plugin.api.entities.builtin.runner.errors import (
)
from langbot_plugin.api.proxies.runner import RunnerAPIProxy
from langbot_plugin.api.proxies.langbot_api import LangBotAPIProxy
from langbot_plugin.api.proxies.event_context import EventContextProxy
from langbot_plugin.api.proxies.execute_context import ExecuteContextProxy
from langbot_plugin.api.entities.builtin.provider.session import Session
from langbot_plugin.api.proxies.invocation import bind_invocation
from langbot_plugin.api.entities.builtin.provider.message import Message
ROOT = Path(__file__).resolve().parents[1]
@@ -59,6 +63,8 @@ class Host:
"prev_cursor": "older",
"next_cursor": None,
},
"reply_message": {},
"set_query_var": {},
"state_set": {"success": True},
"state_get": {"value": "setup"},
}
@@ -118,6 +124,65 @@ def snippets(locale, page):
return re.findall(r"^```python\n(.*?)^```", source, re.M | re.S)
def verify_context_reference():
source = (ROOT / "zh/plugin/dev/apis/agent-run.mdx").read_text()
query_methods = {
"reply",
"get_bot_uuid",
"set_query_var",
"get_query_var",
"get_query_vars",
"create_new_conversation",
"list_pipeline_knowledge_bases",
"retrieve_knowledge",
}
runner_methods = {
name
for name, value in RunnerContext.__dict__.items()
if callable(value) and not name.startswith("_")
}
runner_methods.discard("model_post_init")
for prefix in ("event_context", "context"):
missing = sorted(
name for name in query_methods if f"{prefix}.{name}(" not in source
)
assert not missing, f"{prefix} methods missing from context reference: {missing}"
for name in ("prevent_default", "prevent_postorder"):
assert f"event_context.{name}(" in source
missing = sorted(name for name in runner_methods if f"ctx.{name}(" not in source)
assert not missing, f"RunnerContext methods missing from context reference: {missing}"
assert "`platform_event`" in source
required_fields = {
"instance_uuid",
"workspace_uuid",
"placement_generation",
"query_id",
"query_uuid",
"eid",
"event_name",
"event",
"is_prevent_default",
"is_prevent_postorder",
"session",
"command_text",
"full_command_text",
"command",
"crt_command",
"params",
"crt_params",
"privilege",
*RunnerContext.model_fields,
}
missing = sorted(name for name in required_fields if f"`{name}`" not in source)
assert not missing, f"Context fields missing from context reference: {missing}"
assert "spec.permissions" not in source
assert "spec.capabilities" not in source
async def execute(block, namespace):
# Examples are function bodies; signature reference blocks may include stubs.
function = "async def example():\n" + "\n".join(
@@ -131,6 +196,12 @@ async def execute(block, namespace):
cls = (
LangBotAPIProxy
if owner == "self.plugin"
else EventContextProxy
if owner == "event_context"
else ExecuteContextProxy
if owner == "context"
else RunnerContext
if owner == "ctx"
else RunnerAPIProxy
if owner == "api"
else None
@@ -147,6 +218,7 @@ async def execute(block, namespace):
async def main():
verify_context_reference()
total = 0
for page in ("common", "agent-run", "platform"):
blocks = snippets("zh", page)
@@ -154,9 +226,24 @@ async def main():
assert blocks == snippets(locale, page), f"{page}: {locale} code differs"
for block in blocks:
host = Host()
api = RunnerAPIProxy(context(), host)
ctx = SimpleNamespace(api=api, log=AsyncMock())
ctx = context()
api = RunnerAPIProxy(ctx, host)
ctx._api = api
ctx._results = asyncio.Queue()
session = Session(launcher_type="group", launcher_id="docs-group", sender_id="docs-user")
namespace = {
"event_context": EventContextProxy.model_construct(
query_id=42,
event=SimpleNamespace(sender_id="docs-user"),
plugin_runtime_handler=host,
),
"context": ExecuteContextProxy.model_construct(
query_id=43,
plugin_runtime_handler=host,
crt_params=["Hello!"],
session=session,
),
"session": session,
"Any": Any,
"Message": Message,
"api": api,
@@ -171,7 +258,13 @@ async def main():
"bot_uuid": "bot",
"print": lambda *args: None,
}
await execute(block, namespace)
with bind_invocation(host, api):
await execute(block, namespace)
for name, data in host.calls:
if name in {"reply_message", "set_query_var"}:
expected_query = 42 if "event_context" in block else 43
assert data["query_id"] == expected_query
assert "run_id" not in data
if "reply.update" in block:
ops = [
data["operation"]
@@ -76,9 +76,9 @@ Please always maintain a friendly and professional attitude. If you need to use
![AI Capability Config](/images/articles/external/8f4b3820ed5b-14-langbot-pipeline-ai-capability.png)
选择 **Dify Service API** 作为 Runner:
选择 **Dify Service API** 作为运行器:
![Select Dify Runner](/images/articles/external/efa6fcae9c58-15-langbot-runner-dropdown.png)
![选择 Dify 运行器](/images/articles/external/efa6fcae9c58-15-langbot-runner-dropdown.png)
填写配置:
- **Base URL**: `https://api.dify.ai/v1`
@@ -120,9 +120,9 @@ http://localhost:7860/flow/{flow-id}
![LangBot Pipeline AI Tab](/images/articles/external/3c7d6bc96738-08-langbot-pipeline-ai-tab.png)
配置 **Runner**,选择 **Langflow API**:
配置**运行器**,选择 **Langflow API**:
![LangBot Runner Dropdown](/images/articles/external/ef9bbef78165-09-langbot-runner-dropdown.png)
![LangBot 运行器下拉菜单](/images/articles/external/ef9bbef78165-09-langbot-runner-dropdown.png)
填写 Langflow 配置:
@@ -101,7 +101,7 @@ http://localhost:5678/webhook/{your-webhook-id}
![LangBot pipelines page](/images/articles/external/ef2b2f83bd16-04-langbot-pipelines.png)
切换到 **AI** 标签页,在 Runner 下拉菜单中选择 "n8n Workflow API"。配置:
切换到 **AI** 标签页,在运行器下拉菜单中选择 "n8n Workflow API"。配置:
- **Webhook URL**:粘贴你的 n8n 生产环境 webhook URL
- **Authentication Type**:None(与 n8n webhook 设置保持一致)
+196 -132
View File
@@ -1,179 +1,243 @@
---
title: "运行上下文 API"
title: "上下文 API"
---
Runner 的 `ctx.api` 携带当前运行的 ID、上下文与资源授权;自定义 `run(ctx)` 和事件处理函数使用同一种 `RunnerContext`。`self.plugin` 仍可访问[插件通用 API](/zh/plugin/dev/apis/common),但不会自动代表当前运行。
上下文保存当前一次组件调用的数据。不同组件接收的上下文不同,请先按组件找到对应入口。
## 访问方式
| 组件 | 处理函数入口 | 上下文类型 |
| --- | --- | --- |
| EventListener | `handler(event_context)` | `EventContext` |
| Command | `subcommand(context)` | `ExecuteContext` |
| Tool | `call(params, session, query_id)` | 无独立上下文对象 |
| 运行器 | `run(ctx)` 或 `handler(ctx)` | `RunnerContext` |
| KnowledgeEngine | `ingest(context)`、`retrieve(context)` | `IngestionContext`、`RetrievalContext` |
| KnowledgeRetriever | `retrieve(context)` | `RetrievalContext` |
| Parser | `parse(context)` | `ParseContext` |
| Page | `handle_api(request)` | `PageRequest` |
本页只介绍上下文中的数据和方法。模型、知识库、存储等 LangBot 能力统一通过 `self.plugin` 调用,见 [LangBot API](/zh/plugin/dev/apis/common);平台操作见[平台 API](/zh/plugin/dev/apis/platform)。
`EventContext`、`ExecuteContext` 和 `Session` 还会携带 `instance_uuid`、`workspace_uuid` 和 `placement_generation`。这些字段用于标识当前执行所在的实例和工作区,不应作为插件自行鉴权的依据。
## EventListener
EventListener 处理流水线事件。事件处理函数接收 `EventContext`:
```python
# Inside Runner.run(ctx) or a registered handler
api = ctx.api
event = event_context.event
sender_id = event.sender_id
```
以下示例中的 `api` 均指当前运行的 API。 除 `get_allowed_*` 同步方法和流式上下文/迭代接口外,下文方法均使用 `await` 调用。不要跨运行保存或复用这个对象。
### 上下文数据
### 配置与授权
| 属性 | 类型 | 说明 |
| --- | --- | --- |
| `event` | `BaseEventModel` | 当前事件对象,实际类型与注册的事件类型一致 |
| `event_name` | `str` | 当前事件类名 |
| `query_id` | `int` | 当前流水线请求 ID |
| `query_uuid` | `str \| None` | 当前流水线请求的稳定标识 |
| `eid` | `int` | Plugin Runtime 内的临时事件编号,不应持久化 |
| `is_prevent_default` | `bool` | 是否已阻止默认处理;通过 `prevent_default()` 修改 |
| `is_prevent_postorder` | `bool` | 是否已阻止后续插件;通过 `prevent_postorder()` 修改 |
`ctx.config` 是处理器或 Runner 实例的配置;`self.get_plugin_config()` 读取插件级配置。清单中的 `spec.permissions` 只声明需要的权限,实际可用资源还取决于用户配置和当前事件。
事件对象的字段和所有可监听事件见[流水线事件](/zh/plugin/dev/apis/pipeline-events)。
```yaml
spec:
capabilities:
tool_calling: true
permissions:
tools: [detail, call]
### 上下文方法
| 方法 | 返回值 | 说明 |
| --- | --- | --- |
| `await event_context.reply(message_chain, quote_origin=False)` | - | 回复当前请求所在会话 |
| `await event_context.get_bot_uuid()` | `str` | 获取当前请求来源机器人 UUID |
| `await event_context.set_query_var(key, value)` | - | 设置当前请求变量 |
| `await event_context.get_query_var(key)` | `Any` | 获取一个请求变量 |
| `await event_context.get_query_vars()` | `dict[str, Any]` | 获取全部请求变量 |
| `await event_context.create_new_conversation()` | `dict[str, Any]` | 清除流水线当前使用的对话,后续请求会创建新对话 |
| `await event_context.list_pipeline_knowledge_bases()` | `list[dict[str, Any]]` | 列出当前流水线 Local Agent 绑定的知识库 |
| `await event_context.retrieve_knowledge(kb_id, query_text, top_k=5, filters=None)` | `list[dict[str, Any]]` | 检索当前流水线已绑定的知识库 |
| `event_context.prevent_default()` | - | 阻止当前事件的默认处理 |
| `event_context.prevent_postorder()` | - | 阻止后续插件继续处理当前事件 |
`reply()` 使用 [MessageChain](/zh/plugin/dev/apis/messages)。请求变量、回复和流水线知识库方法依赖当前请求;没有关联请求的事件不能调用这些方法。`retrieve_knowledge()` 的 `kb_id` 必须来自 `list_pipeline_knowledge_bases()`。
`prevent_default()` 只对支持中止默认流程的流水线事件生效,具体事件见[流水线事件](/zh/plugin/dev/apis/pipeline-events#阻止默认行为)。
## Command
Command 的子命令处理函数接收 `ExecuteContext`:
```python
query = " ".join(context.crt_params)
session = context.session
```
这是回复消息和调用工具所需的最小配置。需要其他能力时,在 `spec.permissions` 中按需添加:
### 上下文数据
| `spec.permissions` | 可选操作 |
| 属性 | 类型 | 说明 |
| --- | --- | --- |
| `session` | `Session` | 当前消息所属会话 |
| `command_text` | `str` | 去掉命令前缀后的完整文本 |
| `full_command_text` | `str` | 包含命令前缀的完整文本 |
| `command` | `str` | 根命令名称 |
| `crt_command` | `str` | 当前正在执行的子命令名称 |
| `params` | `list[str]` | 根命令后的全部参数 |
| `crt_params` | `list[str]` | 当前子命令尚未消费的参数 |
| `privilege` | `int` | 当前用户的命令权限级别 |
| `query_id` | `int` | 当前流水线请求 ID |
| `query_uuid` | `str \| None` | 当前流水线请求的稳定标识 |
`context.shift()` 由 SDK 在进入当前子命令前调用,组件不需要手动调用。
### 上下文方法
| 方法 | 返回值 | 说明 |
| --- | --- | --- |
| `await context.reply(message_chain, quote_origin=False)` | - | 回复当前请求所在会话 |
| `await context.get_bot_uuid()` | `str` | 获取当前请求来源机器人 UUID |
| `await context.set_query_var(key, value)` | - | 设置当前请求变量 |
| `await context.get_query_var(key)` | `Any` | 获取一个请求变量 |
| `await context.get_query_vars()` | `dict[str, Any]` | 获取全部请求变量 |
| `await context.create_new_conversation()` | `dict[str, Any]` | 清除流水线当前使用的对话,后续请求会创建新对话 |
| `await context.list_pipeline_knowledge_bases()` | `list[dict[str, Any]]` | 列出当前流水线 Local Agent 绑定的知识库 |
| `await context.retrieve_knowledge(kb_id, query_text, top_k=5, filters=None)` | `list[dict[str, Any]]` | 检索当前流水线已绑定的知识库 |
这些请求方法的行为与 EventListener 相同。命令的注册和返回值见 [Command 组件](/zh/plugin/dev/components/command)。
## Tool
Tool 没有独立的上下文对象。调用信息直接传入 `call()`:
```python
conversation_type = session.launcher_type.value
conversation_id = session.launcher_id
sender_id = session.sender_id
```
| 参数 | 说明 |
| --- | --- |
| `models` | `invoke`, `stream`, `rerank`, `count_tokens` |
| `tools` | `detail`, `call` |
| `knowledge_bases` | `list`, `retrieve` |
| `history` | `page`, `search` |
| `events` | `get`, `page` |
| `storage` | `plugin`, `workspace` |
| `interactions` | `request` |
| `params` | 模型或调用方根据工具 JSON Schema 生成的参数 |
| `session` | 当前会话数据 |
| `query_id` | 当前流水线请求 ID;调用需要请求上下文的 LangBot API 时原样传入 |
查询实际授权的资源:
`Session` 的常用字段如下:
```python
models = api.get_allowed_models() # Each item has model_id and operations
tools = api.get_allowed_tools() # Each item has tool_name and parameters
knowledge_bases = api.get_allowed_knowledge_bases() # Each item has kb_id
```
上下文能力可通过 `api.ctx.context.available_apis` 检查。某项为 `False` 时不要调用对应接口;只在清单中声明权限不会自动启用它。
## 回复与日志
| Runner 方法 | 用途 |
| 属性 | 说明 |
| --- | --- |
| `await ctx.reply(text)` | 向当前事件的会话发送文本,返回动作结果。 |
| `await ctx.log(text, level="info")` | 记录日志;级别为 `debug`、`info`、`warning`、`error`。 |
| `ctx.reply_stream()` | 以异步上下文管理器更新同一条回复。 |
| `launcher_type` | 会话类型:`person` 或 `group` |
| `launcher_id` | 私聊用户或群组 ID |
| `sender_id` | 当前消息发送者 ID |
| `bot_uuid` | 当前机器人 UUID |
| `using_conversation` | 当前流水线会话 |
| `conversations` | 该 Session 保存的流水线会话列表 |
| `use_prompt_name` | 当前使用的提示词名称 |
| `create_time`、`update_time` | Session 的创建时间和更新时间 |
`ctx.reply(text)` 等价于 `await api.call_tool("event_reply", {"text": text})`。需要当前事件具有回复目标,并且 `event_reply` 已被授权。日志和独立 Agent 返回的文本不会自动发送到平台。
`session` 只保存数据,不提供 `reply()` 等上下文方法。工具的返回值交给调用方,不会自动发送到聊天平台。需要调用 LangBot 或平台能力时使用 `self.plugin`;相关接口要求 `session` 和 `query_id` 时,传入本次调用收到的值。
### 流式回复
<span id="runner"></span>
## 运行器
SDK `Runner` 类型的自定义 `run(ctx)` 和事件处理函数都接收 `RunnerContext`。该上下文只在本次运行期间有效。
```python
async with api.reply_stream() as reply:
await reply.update("Processing…")
await reply.update("Processing complete.")
result = reply.result
text = ctx.input.to_text()
event_type = ctx.event.event_type
```
Runner 也可使用 `ctx.reply_stream()`,它会同时记录动作的开始与结果。
### 上下文数据
`update(text)` 接收**当前完整文本**,不是新增片段;返回本次动作结果。正常退出时完成回复。支持流式且开启流式回复的消息事件会更新平台消息;其他可回复事件会缓存文本,在成功结束时发送一次。异常或取消时丢弃缓存中的未完成文本,已显示的内容不保证能撤回。调试模式仅模拟平台发送。
| 属性 | 类型 | 说明 |
| --- | --- | --- |
| `run_id` | `str` | 本次运行 ID |
| `trigger` | `AgentTrigger` | 触发类型、来源和时间 |
| `event` | `AgentEventContext` | 标准事件信封,包含事件 ID、类型、来源、时间和原始数据 |
| `platform_event` | 平台事件类型 | 按事件类型解析后的平台事件对象 |
| `conversation` | `ConversationContext \| None` | 当前会话、线程、机器人和工作区标识 |
| `actor` | `ActorContext \| None` | 事件发起者 |
| `subject` | `SubjectContext \| None` | 事件所作用的消息、群组等对象 |
| `input` | `AgentInput` | 当前输入的文本、结构化内容和附件 |
| `delivery` | `DeliveryContext` | 当前输出目标及流式、编辑、回应等能力 |
| `resources` | `AgentResources` | 本次运行已授权的模型、工具、知识库、技能和存储 |
| `context` | `ContextAccess` | 会话游标、内联范围和可用上下文 API |
| `state` | `AgentRunState` | 本次运行开始时读取到的各作用域状态快照 |
| `runtime` | `AgentRuntimeContext` | LangBot 版本、追踪 ID 和截止时间 |
| `config` | `dict[str, Any]` | 当前 Agent 或插件处理器实例配置 |
| `adapter` | `AdapterContext \| None` | 入口适配器附加数据 |
| `metadata` | `dict[str, Any]` | 宿主提供的其他元数据 |
此接口需要 `available_apis.reply_stream` 和 `event_reply` 权限。模型的流式输出与平台的流式发送是两个接口,需要插件主动连接。
优先使用上表中的稳定字段。`event.data` 和 `adapter.extra` 用于承载尚未进入稳定字段的附加信息。
## 模型、工具与知识库
### 回复与日志
模型调用的参数和用量结构见[通用 API](/zh/plugin/dev/apis/common)。运行 API 还提供以下方法:
| 方法 | 返回值 | 说明 |
| --- | --- | --- |
| `await ctx.get_bot_uuid()` | `str` | 获取来源机器人 UUID;无关联机器人时抛出异常 |
| `await ctx.reply(message_chain, quote_origin=False)` | `Any` | 回复当前事件,支持字符串或 `MessageChain` |
| `ctx.reply_stream()` | 异步上下文管理器 | 流式更新同一条回复 |
| `await ctx.log(text, level="info")` | - | 写入本次运行日志;级别支持 `debug`、`info`、`warning`、`error` |
| 方法 | 返回或用途 |
| --- | --- |
| `invoke_llm(llm_model_uuid, messages, ...)` | `Message` |
| `invoke_llm_with_usage(llm_model_uuid, messages, ...)` | `LLMInvokeResult` |
| `invoke_llm_stream(llm_model_uuid, messages, ...)` | 异步迭代 `MessageChunk` |
| `invoke_llm_stream_events(llm_model_uuid, messages, ...)` | 异步迭代 `LLMStreamEvent` |
| `count_tokens(llm_model_uuid, messages, funcs=None, extra_args=None, timeout=None)` | 模型输入 token 数,`int` |
| `invoke_rerank(rerank_model_uuid, query, documents, top_k=None, extra_args=None, timeout=30.0)` | 带 `index`、`relevance_score` 的列表 |
| `get_tool_detail(tool_name)` | 工具说明与参数 schema,`dict` |
| `call_tool(tool_name, parameters)` | 工具结果,`dict`;无需 `session`、`query_id` |
| `retrieve_knowledge(kb_id, query_text, top_k=5, filters=None)` | 检索结果列表 |
`reply_stream()` 的 `update(text)` 接收当前完整文本。平台不支持流式时,LangBot 会在结束时发送一条完整消息;调试模式只模拟发送。
四个模型调用方法还支持 `remove_think=None`;非流式调用支持 `timeout=None`。调用超时受本次运行的剩余时间约束。资源列表可能为空,不能直接假定存在第一个模型或知识库。
### 可用工具
```python
allowed = {tool.tool_name for tool in api.get_allowed_tools()}
if "event_get_actor" in allowed:
actor = await api.call_tool("event_get_actor", {})
```
| 方法 | 返回值 | 说明 |
| --- | --- | --- |
| `await ctx.get_available_tools()` | `list[dict[str, Any]]` | 获取本次实际允许调用的上下文动作、平台 API、插件工具和 MCP 工具 |
| `await ctx.call_tool(tool_name, parameters=None)` | `dict[str, Any]` | 调用上述列表中的工具 |
`event_*` 工具由 LangBot 固定事件中的目标,`platform_*` 工具允许按 schema 指定目标。使用实际授权列表中的名称与参数;无参数工具传 `{}`。
`get_available_tools()` 的每一项包含 `name`、`description`、`parameters`、`type` 和 `operations`。返回结果已经按当前 Agent 或插件处理器的配置和事件能力过滤;不在列表中的工具不能通过 `ctx.call_tool()` 调用。
## 历史与事件
### 提示词、历史与事件
当前输入不包含完整历史。按需读取当前运行范围内的记录;不能通过传入其他会话 ID 扩大访问范围。
| 方法 | 返回值 | 可用性字段 |
| --- | --- | --- |
| `await ctx.get_prompt()` | `list[dict[str, Any]]` | `prompt_get` |
| `await ctx.history_page(conversation_id=None, before_cursor=None, after_cursor=None, limit=50, direction="backward", include_attachments=False)` | `HistoryPage` | `history_page` |
| `await ctx.history_search(query, filters=None, top_k=10)` | `HistorySearchResult` | `history_search` |
| `await ctx.event_get(event_id)` | `AgentEventRecord` | `event_get` |
| `await ctx.event_page(conversation_id=None, event_types=None, before_cursor=None, limit=50)` | `EventPage` | `event_page` |
| `await ctx.steering_pull(mode="all", limit=None)` | `SteeringPullResult` | `steering_pull` |
| 方法 | 返回值 |
| --- | --- |
| `get_prompt()` | 生效的提示词列表;能力标识为 `prompt_get` |
| `history_page(conversation_id=None, before_cursor=None, after_cursor=None, limit=50, direction="backward", include_attachments=False)` | `HistoryPage` |
| `history_search(query, filters=None, top_k=10)` | `HistorySearchResult` |
| `event_get(event_id)` | `AgentEventRecord` |
| `event_page(conversation_id=None, event_types=None, before_cursor=None, limit=50)` | `EventPage` |
| `steering_pull(mode="all", limit=None)` | `SteeringPullResult`;读取运行中排队的追加输入 |
### 状态
```python
if api.ctx.context.available_apis.history_page:
page = await api.history_page(limit=20)
for item in page.items:
print(item.model_dump())
if page.has_more and page.prev_cursor:
older = await api.history_page(before_cursor=page.prev_cursor, limit=20)
```
| 方法 | 返回值 | 说明 |
| --- | --- | --- |
| `await ctx.state_get(scope, key)` | `dict[str, Any]` | 读取状态值 |
| `await ctx.state_set(scope, key, value)` | `dict[str, Any]` | 写入可 JSON 序列化的状态值 |
| `await ctx.state_delete(scope, key)` | `dict[str, Any]` | 删除状态值 |
| `await ctx.state_list(scope, prefix=None, limit=100)` | `dict[str, Any]` | 列出指定作用域的状态键 |
分页结果是 SDK 对象,使用 `.items`、`.has_more`、`.prev_cursor`、`.next_cursor`,不是字典下标。读取旧记录使用 `before_cursor`;读取新记录使用 `after_cursor` 和 `direction="forward"`。历史搜索可能只提供文本匹配。`steering_pull` 的 `mode` 可为 `all`、`one` 或 `one-at-a-time`,用于支持追加输入的 Runner。
`scope` 支持 `conversation`、`actor`、`subject` 和 `runner`。这些方法要求 `ctx.context.available_apis.state` 为 `true`。
## 状态与存储
### 运行记录
| 方法 | 返回值 |
| --- | --- |
| `state_get(scope, key)` | `{"value": ...}` |
| `state_set(scope, key, value)` | `{"success": ...}` |
| `state_delete(scope, key)` | `{"success": ...}` |
| `state_list(scope, prefix=None, limit=100)` | `{"keys": [...], "has_more": ...}` |
| 方法 | 返回值 | 可用性字段 |
| --- | --- | --- |
| `await ctx.run_get(run_id=None)` | `AgentRun` | `run_get` |
| `await ctx.run_list(conversation_id=None, statuses=None, before_cursor=None, limit=50)` | `RunPage` | `run_list` |
| `await ctx.run_events_page(run_id=None, before_cursor=None, after_cursor=None, limit=50, direction="forward")` | `RunEventPage` | `run_events_page` |
| `await ctx.run_cancel(run_id=None, reason=None)` | `AgentRun` | `run_cancel` |
| `await ctx.run_append_result(result)` | `AgentRunEvent` | `run_append_result` |
| `await ctx.run_finalize(run_id=None, status=None, reason=None)` | `AgentRun` | `run_finalize` |
状态需要 `available_apis.state` 和宿主允许的作用域:`conversation`(当前会话)、`actor`(当前用户)、`subject`(当前群组或对象)、`runner`(Runner 实例)。值必须可 JSON 序列化,建议使用 `external.` 等键前缀。状态由 LangBot 持久化,接口返回字典。
`run_id=None` 表示当前运行。普通事件处理函数结束后,SDK 会自动完成本次运行;自定义 `run(ctx)` 通过 `yield RunnerResult` 返回结果时,也不需要再调用 `run_append_result()` 重复登记。
```python
if api.ctx.context.available_apis.state:
await api.state_set("conversation", "external.last_topic", "setup")
value = await api.state_get("conversation", "external.last_topic")
```
### 可用性与授权
插件和工作空间存储使用 `set_plugin_storage`、`get_plugin_storage`、`get_plugin_storage_keys`、`delete_plugin_storage`,以及对应的 `*_workspace_storage*` 方法。参数与[通用 API](/zh/plugin/dev/apis/common)一致,值为 `bytes`,分别受 `api.ctx.resources.storage.plugin_storage` 和 `workspace_storage` 授权限制。
通过 `ctx.context.available_apis` 判断提示词、历史、事件、状态和运行记录接口是否可用。模型、工具和知识库的授权范围分别位于 `ctx.resources.models`、`ctx.resources.tools` 和 `ctx.resources.knowledge_bases`。
## 运行记录
运行器执行期间,通过 `self.plugin` 发起的模型、工具、知识库、存储和平台调用会自动关联当前运行,并按 `ctx.resources` 再次校验,无需传入 `run_id`。处理函数结束后,不要继续在后台任务中使用本次上下文或这些运行关联调用。
以下接口按同名 `available_apis` 标识检查能力,只能操作当前授权范围内的运行。
`ctx.api` 是底层的运行级代理。普通组件代码应优先使用本页列出的 `ctx` 方法,并通过 `self.plugin` 调用 LangBot API。
| 方法 | 返回值 |
| --- | --- |
| `run_get(run_id=None)` | `AgentRun` |
| `run_list(conversation_id=None, statuses=None, before_cursor=None, limit=50)` | `RunPage` |
| `run_events_page(run_id=None, before_cursor=None, after_cursor=None, limit=50, direction="forward")` | `RunEventPage` |
| `run_cancel(run_id=None, reason=None)` | `AgentRun` |
| `run_append_result(result)` | `AgentRunEvent` |
| `run_finalize(run_id=None, status=None, reason=None)` | `AgentRun` |
## 数据型上下文
`run_id=None` 表示当前运行。事件处理函数返回后自动结束;自定义 `run(ctx)` 可通过 `yield RunnerResult` 上报结果,不要再用 `run_append_result` 重复登记。
以下组件收到的是本次任务的输入数据,不提供 EventListener 或运行器的上下文方法。字段、返回值和完整示例放在对应组件教程中。
## 结构化交互(Runner)
需要用户确认或填写表单时,通过 `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` 方法,Runner 的普通处理函数不直接提供此接口。
## 错误处理
```python
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", {})
except PermissionDeniedError as exc:
await ctx.log(str(exc), level="warning")
except AgentAPIException as exc:
await ctx.log(f"{exc.error.code}: {exc.error.message}", level="error")
```
这是 Runner 中的示例。`PermissionDeniedError` 表示资源、操作或能力未授权;`AgentAPIException.error` 包含 `code`、`message`、`retryable`、`details`。发送消息等动作超时后,结果可能不确定,不应仅依据 `retryable` 自动重发。
| 组件入口 | 主要数据 | 组件教程 |
| --- | --- | --- |
| `KnowledgeEngine.ingest(context: IngestionContext)` | 文件、目标知识库、创建配置和解析结果 | [KnowledgeEngine](/zh/plugin/dev/components/knowledge-engine#文档摄取) |
| `KnowledgeEngine.retrieve(context: RetrievalContext)` | 查询、目标知识库、检索配置和过滤条件 | [KnowledgeEngine](/zh/plugin/dev/components/knowledge-engine#知识检索) |
| `KnowledgeRetriever.retrieve(context: RetrievalContext)` | 查询和外部知识库配置 | [KnowledgeRetriever](/zh/plugin/dev/components/knowledge-retriever#检索上下文) |
| `Parser.parse(context: ParseContext)` | 文件内容、文件名、MIME 类型和元数据 | [Parser](/zh/plugin/dev/components/parser#解析方法) |
| `Page.handle_api(request: PageRequest)` | 接口路径、HTTP 方法、请求体和请求头 | [Page](/zh/plugin/dev/components/page#pagerequest-字段) |
+4 -115
View File
@@ -1,126 +1,15 @@
---
title: "插件通用 API"
title: "LangBot API"
---
LangBot 为插件提供了一系列 API ,用于操作 LangBot 各个模块、控制消息上下文等。
所有组件都可通过 `self.plugin` 使用本页的 LangBot API。Runner 的 `ctx.api` 则携带当前运行的上下文和资源授权,见[运行上下文 API](/zh/plugin/dev/apis/agent-run)。指定机器人和目标的平台操作见[平台 API](/zh/plugin/dev/apis/platform)。
## 请求 API
操作当前正在处理的用户请求(消息)。仅在`EventListener`和`Command`组件中可用。访问方式如下:
- `EventListener` 的各个事件处理器方法中:`event_context: context.EventContext`对象内部方法
- `Command` 的各个子命令处理器方法中:`context: ExecuteContext`对象内部方法
### 直接回复消息
直接回复一个消息链到当前请求所在会话。
消息链构造方式请参考[消息平台实体](/zh/plugin/dev/apis/messages)。
```python
async def reply(
self, message_chain: platform_message.MessageChain, quote_origin: bool = False
):
"""Reply to the message request
Args:
message_chain (platform.types.MessageChain): LangBot message chain
quote_origin (bool): Whether to quote the original message
"""
# 调用示例
await event_context.reply(
platform_message.MessageChain([
platform_message.Plain(text="Hello, world!"),
]),
)
```
### 获取机器人 UUID
获取当前请求来源机器人 UUID。
```python
async def get_bot_uuid(self) -> str:
"""Get the bot uuid"""
# 调用示例
bot_uuid = await event_context.get_bot_uuid()
```
### 设置请求变量
单次请求中某些信息会被存储到请求变量中,在使用 Dify 等外部 Agent 平台时,[这些变量会显式传入 Agent 平台](/zh/deploy/pipelines/readme.html#%E8%AF%B7%E6%B1%82%E5%8F%98%E9%87%8F)。
```python
async def set_query_var(self, key: str, value: Any):
"""Set a query variable"""
# 调用示例
await event_context.set_query_var("key", "value")
```
### 获取请求变量
获取单个请求变量。
```python
async def get_query_var(self, key: str) -> Any:
"""Get a query variable"""
# 调用示例
query_var = await event_context.get_query_var("key")
```
### 获取所有请求变量
```python
async def get_query_vars(self) -> dict[str, Any]:
"""Get all query variables"""
# 调用示例
query_vars = await event_context.get_query_vars()
```
### 获取当前流水线配置的知识库列表
获取当前请求所使用流水线中配置的知识库列表。
```python
async def list_pipeline_knowledge_bases(self) -> list[dict[str, Any]]:
"""List knowledge bases configured for the current pipeline"""
# 调用示例
knowledge_bases = await event_context.list_pipeline_knowledge_bases()
# 返回示例
[
{
"uuid": "kb_uuid",
"name": "Product Docs",
"description": "内部产品文档",
}
]
```
仅返回当前请求对应流水线在 `Local Agent` 配置中绑定的知识库。若当前流水线未配置知识库,或未使用 `Local Agent`,则返回空列表。
### 开始新对话
`await event_context.create_new_conversation()` 清除当前流水线会话正在使用的对话,后续处理会重新建立对话。返回空字典,不会清除平台聊天记录。
### 检索当前流水线的知识库
`await event_context.retrieve_knowledge(kb_id, query_text, top_k=5, filters=None)` 返回检索结果列表。`kb_id` 必须来自 `list_pipeline_knowledge_bases()`;不能用这个请求接口访问流水线未配置的知识库。
模型、工具、知识库和存储等能力通过 `self.plugin` 访问。当前事件、回复和会话状态的访问方式见[上下文 API](/zh/plugin/dev/apis/agent-run)。
## LangBot API
这些 API 可在提供 `self.plugin` 的普通组件中调用。访问方式如下:
这些 API 可在所有组件中通过 `self.plugin` 调用。访问方式如下:
- 插件根目录`main.py`中:`self` 对象内部方法,这些 API 均由插件类父类 `BasePlugin` 提供。
- 普通组件类中:`self.plugin` 对象内部方法。
- 组件类中:`self.plugin` 对象内部方法。
### 获取插件配置信息
+1 -1
View File
@@ -62,4 +62,4 @@ msg_chain = MessageChain([
## 平台 API
查询用户、管理群组和调用平台专有接口,请使用[平台 API](/zh/plugin/dev/apis/platform)。Runner 通过[运行上下文 API](/zh/plugin/dev/apis/agent-run)调用已授权的平台工具。
查询用户、管理群组和调用平台专有接口,请使用[平台 API](/zh/plugin/dev/apis/platform)。运行器使用相同的 `self.plugin` 入口,当前会话回复使用 `ctx.reply()`。
+4 -43
View File
@@ -259,42 +259,13 @@ class PromptPreProcessing(BaseEventModel):
"""此对话现有消息记录,可修改,langbot_plugin.api.entities.builtin.provider.message.Message 或 langbot_plugin.api.entities.builtin.provider.message.MessageChunk 类型"""
```
## 事件上下文 API
## EventListener 上下文
```python
...
@self.handler(events.PersonMessageReceived)
async def handler(event_context: context.EventContext):
...
```
事件处理方法将被传入`EventContext`对象,该对象包含事件的上下文信息,该对象同时具有[请求 API](/zh/plugin/dev/apis/common)和事件上下文特定 API,以下为事件上下文特定 API 列表:
### 获取原事件属性
`event_context.event` 属性为原事件对象,可获取原事件的属性。其类型即为监听的事件类型。
例如:当监听的事件是`GroupMessageReceived`时:
```python
event = event_context.event
print(event.launcher_type) # 发起对象类型(group)
print(event.launcher_id) # 群号
print(event.sender_id) # 发送者账号 ID
print(event.message_chain) # 消息链
```
事件处理函数通过 `event_context.event` 读取当前事件。`EventContext` 的完整属性和方法见[上下文 API](/zh/plugin/dev/apis/agent-run#eventlistener)。
### 阻止默认行为
```python
def prevent_default(self):
"""阻止默认行为"""
# 调用示例
event_context.prevent_default()
```
调用该方法后,该事件后续默认行为将被阻止,流水线将直接结束。
调用 `event_context.prevent_default()` 后,当前事件的默认处理将停止。仅以下事件支持此操作:
<Info>
仅以下事件可阻止默认行为:
@@ -308,14 +279,4 @@ event_context.prevent_default()
- NormalMessageResponded
</Info>
### 阻止后序插件执行
```python
def prevent_postorder(self):
"""阻止后序插件执行"""
# 调用示例
event_context.prevent_postorder()
```
调用该方法后,注册了该事件的后序插件此次将不被执行。
调用 `event_context.prevent_postorder()` 可阻止后续插件继续处理当前事件。
+7 -7
View File
@@ -64,15 +64,15 @@ account = await self.plugin.call_platform_api(
只能调用适配器已声明的动作,并非任意平台接口都能透传。插件通过运行时调用宿主,不直接访问 `ctx.query.adapter` 或 `adapter.bot`。
## 在事件处理器中调用
## 运行器
Runner 也可以通过 `self.plugin` 调用本页的平台 API,显式指定机器人和目标。若要按当前事件的授权查询或回复,并在运行记录中展示动作,请使用 `ctx.api` 或 `ctx.reply()`:
运行器执行期间,`self.plugin` 的模型、工具、知识库、存储和平台调用自动关联当前运行并执行授权检查,无需传入 `run_id`。同一插件的并发运行互相隔离。不要在处理函数返回后继续调用这些运行关联的 API。
通过 `await ctx.get_bot_uuid()` 获取当前机器人。平台调用必须匹配本次工具授权:仅授权当前事件目标时,不能改传其他目标;未授权的动作(包括平台专有动作)会被拒绝。调试中的这些调用同样使用 Mock。
```python
tools = {tool.tool_name for tool in ctx.api.get_allowed_tools()}
if "event_get_actor" in tools:
actor = await ctx.api.call_tool("event_get_actor", {})
tools = await ctx.get_available_tools()
if any(tool["name"] == "event_get_actor" for tool in tools):
actor = await ctx.call_tool("event_get_actor")
await ctx.log(str(actor))
```
访问方式、权限与回复示例见[运行上下文 API](/zh/plugin/dev/apis/agent-run)。事件调试中的平台工具使用 Mock;普通组件的 `self.plugin.call_platform_api()` 是实际调用。
+3 -3
View File
@@ -4,8 +4,8 @@ title: "添加组件"
插件由一种或多种组件构成,为 LangBot 提供不同的功能。目前支持的组件类型有:
- 事件处理器(Runner):处理机器人收到的消息、成员入群等事件。详见[开发教程](/zh/plugin/dev/components/runner)。
- Agent 运行器(Runner):为 Agent 提供模型调用、外部 Agent 服务连接等运行方式。
- 插件处理器(运行器):处理机器人收到的消息、成员入群等事件。详见[开发教程](/zh/plugin/dev/components/runner)。
- Agent 使用的运行器:为 Agent 提供模型调用、外部 Agent 服务连接等运行方式。
- 事件监听器(EventListener):监听流水线执行期间的事件,对上下文或流水线进行修改。
- 命令(Command):由用户通过`!`(或其他已设置的前缀)开头的命令消息触发。
- 工具(Tool):供 LangBot 内置的 Local Agent 在执行期间由 LLM 调用。
@@ -73,7 +73,7 @@ components:
各个组件的详细使用方式请参考:
- [Runner](./runner)
- [运行器](./runner)
- [EventListener](./event-listener)
- [Command](./command)
- [Tool](./tool)
+2 -1
View File
@@ -211,4 +211,5 @@ yield CommandReturn(
您已经了解了命令注册和命令执行的基本信息,接下来可以:
- 查看[插件通用 API](/zh/plugin/dev/apis/common)
- 查看完整的 [`ExecuteContext` 上下文 API](/zh/plugin/dev/apis/agent-run#command)
- 查看 [LangBot API](/zh/plugin/dev/apis/common)
+3 -2
View File
@@ -103,5 +103,6 @@ class EventContext(pydantic.BaseModel):
您已经了解了事件监听器的基本信息,接下来可以:
- 在文档[流水线事件](/zh/plugin/dev/apis/pipeline-events)中查看`可监听的事件列表`和`事件上下文 API`
- 查看[插件通用 API](/zh/plugin/dev/apis/common)
- 在[流水线事件](/zh/plugin/dev/apis/pipeline-events)中查看可监听的事件及字段
- 查看完整的 [`EventContext` 上下文 API](/zh/plugin/dev/apis/agent-run#eventlistener)
- 查看 [LangBot API](/zh/plugin/dev/apis/common)
+9 -7
View File
@@ -1,12 +1,14 @@
---
title: "组件:Runner"
title: "组件:运行器"
---
Runner 组件用于实现 Agent 的运行逻辑,也可以按事件注册处理函数,供「插件处理器」使用。两种写法共用 `RunnerContext`,插件安装后由用户选择组件并配置。
运行器组件通过 SDK 的 `Runner` 类型实现 Agent 的运行逻辑,也可以按事件注册处理函数,供「插件处理器」使用。两种写法共用 `RunnerContext`,插件安装后由用户选择组件并配置。
环境准备见[插件开发教程](/zh/plugin/dev/tutor)。
## 添加 Runner 组件
`RunnerContext` 的完整字段和方法见[上下文 API](/zh/plugin/dev/apis/agent-run#runner)。
## 添加运行器组件
单个插件中可以添加多个事件处理器。请在插件目录执行命令 `lbp comp Runner`,名称填写 `welcome`,描述填写 `Welcome new members`。
@@ -33,7 +35,7 @@ class Echo(Runner):
)
```
## 清单文件:Runner
## 清单文件:运行器
将 `welcome.yaml` 修改为:
@@ -147,7 +149,6 @@ async with ctx.reply_stream() as reply:
正常退出 `async with` 时完成回复。平台不支持流式、未开启流式回复或当前不是消息事件时,会在结束后发送一条完整消息;发生异常时不发送缓存中的未完成文本。调试模式仅模拟发送。
此接口沿用 `ctx.reply()` 的权限。Runner 可通过 `self.get_run_api(ctx).reply_stream()` 使用同一接口,模型返回文本仍不会自动发送。
## 事件注册
@@ -189,7 +190,8 @@ async with ctx.reply_stream() as reply:
## 接下来做什么
- 查看 [`RunnerContext` 上下文 API](/zh/plugin/dev/apis/agent-run#runner)。
- 查看模型、工具、知识库和存储相关的 [LangBot API](/zh/plugin/dev/apis/common)。
- 查看消息发送等[平台 API](/zh/plugin/dev/apis/platform)。
- 查看 [RunnerDemo](https://github.com/langbot-app/langbot-plugin-demo/tree/main/RunnerDemo) 中的更多示例。
- 如果要扩展流水线的预处理、模型调用完成等步骤,请使用[事件监听器](/zh/plugin/dev/components/event-listener)。
回复、模型、工具、历史与状态接口见[运行上下文 API](/zh/plugin/dev/apis/agent-run)。
+2 -1
View File
@@ -174,4 +174,5 @@ httpx
您已经了解了工具的基本用法,接下来可以:
- 查看[插件通用 API](/zh/plugin/dev/apis/common)
- 查看 Tool 的 [`session` 和 `query_id` 说明](/zh/plugin/dev/apis/agent-run#tool)
- 查看 [LangBot API](/zh/plugin/dev/apis/common)
+1 -1
View File
@@ -23,7 +23,7 @@ LangBot 支持调用来自 MCP 服务器的工具。添加 MCP 后,启用了
</Note>
<Note>
MCP 工具需要流水线使用**内置 Agent**,并选择**已开启工具使用能力**的模型——见[模型](../models/readme)。Dify、n8n、Langflow、Coze 等外部 Runner 使用各自平台的工具机制。
MCP 工具需要流水线使用**内置 Agent**,并选择**已开启工具使用能力**的模型——见[模型](../models/readme)。Dify、n8n、Langflow、Coze 等外部运行器使用各自平台的工具机制。
</Note>
## 安装 MCP 服务器
+1 -1
View File
@@ -5,7 +5,7 @@ description: "在 LangBot 中使用 TBox,为 AI 机器人对话管线提供支
[TBox(百宝箱)](https://tbox.cn/)是蚂蚁集团推出的面向 AI 开发者的一站式智能体应用开发平台。在平台上,无论您是否拥有编程基础,都可以通过自然语言,基于各种大模型搭建属于您自己的智能体应用,并将其发布到支付宝小程序、web 服务、浏览器插件等生态渠道。
LangBot 支持接入 TBox 上编排好的智能体,用作流水线 Runner。
LangBot 支持接入 TBox 上编排好的智能体,用作流水线运行器。
在 TBox 上搭建好智能体后,请到[`开放平台`](https://www.tbox.cn/open/authorized-management)创建 API Key:
+1 -1
View File
@@ -21,7 +21,7 @@ Box Runtime 给内置 Agent 一个统一的执行环境:跑命令、读写文
`exec` 在所选 Box 后端中运行;其余五个直接读写映射到 `/workspace` 的工作区目录。选择 Host 时,命令也直接运行在 Box Runtime 主机上。
<Note>
这些工具面向内置 Agent。使用 Dify、n8n、Langflow、Coze 等外部 Runner 时,请使用对应平台自己的工具机制。
这些工具面向内置 Agent。使用 Dify、n8n、Langflow、Coze 等外部运行器时,请使用对应平台自己的工具机制。
</Note>
## 沙箱作用域
+1 -1
View File
@@ -48,5 +48,5 @@ Box API、Agent 工具、会话作用域、生命周期、Skills 和 stdio MCP
| 外部 Host Box 连接被拒绝 | LangBot 与 Box Runtime 两侧设置相同的 `LANGBOT_BOX_CONTROL_TOKEN` |
<Note>
沙箱内置工具和 Skills 当前面向内置 Agent。外部 Runner(Dify、n8n、Langflow、Coze 等)应使用各自平台的工具和执行机制。
沙箱内置工具和 Skills 当前面向内置 Agent。外部运行器(Dify、n8n、Langflow、Coze 等)应使用各自平台的工具和执行机制。
</Note>
+1 -1
View File
@@ -97,5 +97,5 @@ LangBot 当前读取以下三个字段:
| `register_skill` 报错 | 路径必须在 `/workspace` 下,目录或两层内子目录需含 `SKILL.md` |
<Note>
Skills 当前面向内置 Agent,依赖函数调用和沙箱后端。外部 Runner(Dify、n8n、Langflow、Coze 等)请使用各自平台的等价机制。
Skills 当前面向内置 Agent,依赖函数调用和沙箱后端。外部运行器(Dify、n8n、Langflow、Coze 等)请使用各自平台的等价机制。
</Note>