cd /news/ai-agents/put-claude-code-and-codex-inside-wec… · home › topics › ai-agents › article
[ARTICLE · art-151925] src=dev.to ↗ pub= topic=ai-agents verified=true sentiment=↑ positive

Put Claude Code and Codex Inside WeChat, Lark and DingTalk with LangBot Runner Plugins

The LangBot project released version 4.11, which removes the nine built-in runners from src/langbot/pkg/provider/runners/ and turns runners into installable plugin components, letting teams run Claude Code and Codex agents from WeChat Work, Lark and DingTalk group chats. The release adds a RunnerRegistry that discovers plugin runners over LIST_RUNNERS and generates ids as plugin:author/plugin_name/runner_name, plus a twelve-package adapter layer under src/langbot/pkg/platform/adapters/, with official ClaudeCodeAgent and CodexAgent plugin ids. Runner plugins execute in a separate plugin-runtime container, making deployment a two-container setup.

by read5 min views2 publishedOct 17, 2026

A team already lives in Claude Code and Codex — repos, shell, MCP servers on their own machines. Colleagues should reach that same power from WeChat Work, Lark and DingTalk group chats, without a terminal.

On 4.10 that was awkward — not inbound: 4.10.11 already ships openclaw_weixin, lark, dingtalk under src/langbot/pkg/platform/sources/. The processing side was the wall: nine built-in runners under src/langbot/pkg/provider/runners/ (localagent.py, difysvapi.py, … weknoraapi.py), so adding Claude Code meant patching LangBot or wrapping the CLI in an HTTP service outside the bot.

4.11 flips that: a Runner is a plugin, and the platform is only the event source. Support depends on the adapter and platform — check the support matrix first.

New in 4.11: the built-in runners are gone. src/langbot/pkg/provider/runners/ holds ten files at v4.10.11 and does not exist at v4.11.0; src/langbot/pkg/provider/ keeps only modelmgr/, session/, tools/ (git ls-tree, both revisions).

A Runner is a plugin component. The runtime reports installed plugins' runners over LIST_RUNNERS; the host discovers and caches them in RunnerRegistry (src/langbot/pkg/agent/runner/registry.py:20,24,152), generating ids as plugin:author/plugin_name/runner_name (src/langbot/pkg/agent/runner/id.py:24-27) and rejecting anything without that prefix ( id.py:52-57; PROTOCOL_V1.md §13).

The manifest is the contract: id, name, label, description, capabilities, permissions, config_schema, metadata (§4.2); capabilities is a typed boolean model for UI and resource projection, not a permission grant, and permissions is the access ceiling, intersected with the binding policy.

Official ids: plugin:langbot-team/ClaudeCodeAgent/default, plugin:langbot-team/CodexAgent/default (docs/agent-runner-pluginization/OFFICIAL_RUNNER_PLUGINS.md:33-34).

New in 4.11: the adapter layer. src/langbot/pkg/platform/adapters/ is absent at v4.10.11; 4.11 splits it into twelve packages with manifest.yaml, adapter.py, event_converter.py, and the Lark manifest declares kind: MessagePlatformAdapter (src/langbot/pkg/platform/adapters/lark/manifest.yaml:1-4,13). The inbound file inventory is unchanged: between v4.10.11 and v4.11.0, all 22 files under src/langbot/pkg/platform/sources/ are modifications — no additions, no deletions — so no new platform arrived here.

Where config lands: ai.runner.id stores the runner id and ai.runner_config[<runner_id>] its settings (src/langbot/templates/metadata/pipeline/ai.yaml:6-18), so switching runners keeps earlier settings.

Runner plugins execute in a separate plugin-runtime container, so this is a two-container setup (local demo values — replace them):

docker network create lang7-411
docker run -d --name lang7-411-core --network lang7-411 -e BOX__ENABLED=false \
  -p 15400:5300 -v "$PWD/deploy/411/data:/app/data" rockchin/langbot:v4.11.0
docker run -d --name lang7-411-runtime --network lang7-411 --network-alias langbot_plugin_runtime \
  -v "$PWD/deploy/411/data/plugins:/app/data/plugins" \
  rockchin/langbot:v4.11.0 uv run --no-sync -m langbot_plugin.cli.__init__ rt

The admin account starts as admin@langbot.local; the password is a local demo value — replace it.

Step 1 — install from the marketplace. UI: Extensions → Extension Marketplace (web/src/i18n/locales/zh-Hans.ts:337-341); CLI: POST /api/v1/plugins/install/marketplace with {plugin_author, plugin_name}, returning {task_id} for task plugin-install-marketplace; the record carries install_source=marketplace (src/langbot/pkg/api/http/controller/groups/plugins.py:923-960). Here we installed langbot-team/LocalAgent; the Claude Code and Codex plugins use the same door (repo langbot-plugins, Runner/claude-code-agent, Runner/codex-agent).

Step 2 — confirm where it landed. The artifact is not in the mounted plugins/ directory but inside the runtime container at /app/data/plugin-runtime/artifacts/sha256/<digest>/code/ (manifest.yaml, main.py, pkg/, components/, CERTIFICATION.md), while the host-mounted plugins/ stays empty (observed 2026-10-16); <digest> is the recorded artifact_digest. Three checks: the API ( GET /api/v1/plugins returns a {plugins: [...]} array containing it, plugins.py:387-397); the database (a plugin_settings row holding artifact_digest, runtime_revision, install_source, enabled, src/langbot/pkg/entity/persistence/plugin.py:12-35,46-51); and the logs — Mounting plugin langbot-team/LocalAgent... → Initializing Runner component: default → Component default initialized, instance type: DefaultRunner (observed 2026-10-16). The point: the runtime instantiates a component instance and the Runner capability hangs off it.

Step 3 — pick the Runner in the pipeline. In the pipeline editor open AI capabilities (web/src/i18n/locales/zh-Hans.ts:1941) and find the stage card labelled "运行方式" ( src/langbot/templates/metadata/pipeline/ai.yaml:7-9) with its required "运行器" dropdown (:14-18). The value is the full runner id, e.g. plugin:langbot-team/LocalAgent/default; for Claude Code, plugin:langbot-team/ClaudeCodeAgent/default. Here the LocalAgent block at ai.runner_config[<runner_id>] read timeout: 300, max-tool-iterations: 100 (observed 2026-10-16).

Step 4 — connect the chat platform as an event source. Connect a WeChat Work, Lark or DingTalk adapter; events arrive, event bindings route them into a pipeline, and the selected Runner does the work — one bot, several pipelines, each free to use a different Runner.

Claude Code and Codex settings come from their READMEs: command defaults to claude / codex, timeout to 300 / 1800 seconds, plus workspace, ssh-target, mcp-servers-json (Runner/claude-code-agent, Runner/codex-agent).

API: GET /api/v1/plugins contains langbot-team/LocalAgent with enabled true. Database: digest and revision persisted — values observed here:

SELECT plugin_author, plugin_name, artifact_digest, runtime_revision, install_source, enabled
FROM plugin_settings;
-- langbot-team|LocalAgent|2d2ce17055d70dd7736e6902595be3262992fd1598a00bd9d79d19fef1c16329|1|marketplace|1

Runtime container: the same ls shows the files listed above while the host-mounted plugins/ stays empty; an empty result means the wrong layer. Pipeline: ai.runner.id must start with plugin: (web/src/app/home/pipelines/pipeline-config-safety.ts:7-25) and ai.runner_config must hold an object keyed by that id. Then send a real message and confirm the reply comes from the installed Runner.

src/langbot/pkg/platform/sources/ file set matches 4.10.11 — all 22 files are modifications, none added or removed — and what 4.11 adds is the platform/adapters/ event-adapter layer; the adapter plus the event binding decides whether a platform works, not the Runner. The support matrix in {space_url}/api/v1/marketplace/plugins/download/{author}/{name}/{version} (src/langbot/pkg/plugin/connector.py:1795-1797); installs from GitHub or a local archive record github / local. plugin_settings.artifact_digest — here the two LocalAgent 0.2.1 digests ClaudeCodeAgent defaults dangerously-skip-permissions to true (false restores Claude Code's own checks; LangBot has no interactive approval flow today) and CodexAgent to approval-policy=never / sandbox-mode=danger-full-access. Trusted workspaces only. ask_user_question into interaction.requested for the adapter to render as a card; the CLI stops while the user answers, and the answer starts a new run resuming the same session.PROTOCOL_V1.md §13).install_info._certification read verification: "invalid" with certificate_id: null, while the marketplace reported certificate_status: "issued" — do not assume local verification passed because a plugin is listed (see article 4). In 4.11 a Runner is not shipped with LangBot but installed from the marketplace, configured in the app, selected per pipeline. The platform delivers the event; the Runner decides how it is processed — a local CLI agent (Claude Code, Codex, ACP) or a service runner such as Dify, Coze, n8n, Langflow or DeerFlow.

Primary reference: the pinned migration doc pipeline-migration-config-map.zh-CN.md, which also lists the minimum Runner plugin versions the migrator requires; the v4.11.0 release page has the notes. Plugins are also listed in Runner/ in langbot-plugins.

Next: if your instance was upgraded from 4.10, that old config landing in the new shape is article 3 — the migration touches ai.runner.runner, ai.runner.id and ai.runner_config together. For a hosted environment, Cloud is worth a separate look (https://space.langbot.app).

── more in #ai-agents 4 stories · sorted by recency
── more on @langbot 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/put-claude-code-and-…] indexed:0 read:5min 2026-10-17 · —