openclaw.json now sends `Authorization: Bearer ${AGAP_MCP_TOKEN}` to the agap
MCP server, which requires it as of kb#180. The token is injected from
openai/.env via docker-compose.yml and only substituted here, never inlined.
It maps to agent id `adolf`, which is also what the kb#147 vault gate reads.
Fixes tools.media.audio, which had been added but never restart-validated:
the per-entry `apiKey: "not-needed"` is rejected by the schema
("tools.media.audio.models.0: Invalid input"), and an invalid config makes the
gateway refuse to start outright -- adolf crash-looped on the first restart
after the block landed. The old comment claimed the schema requires a
non-empty apiKey; it is the opposite, apiKey is not a valid per-entry key at
all. Isolated with `openclaw config validate` against the running image
(2026.6.11): {provider, model} and {provider, model, baseUrl} validate, and
adding apiKey alone reproduces the failure. baseUrl is kept -- that is the
per-entry override pointing the openai-shaped provider at the local
faster-whisper server. Provider auth follows the normal model auth order per
docs/nodes/audio.md, and faster-whisper-server has no auth to satisfy anyway.
Two lessons encoded in the comments: `enabled: false` does NOT exempt an entry
from schema validation, and a config edit is not done until a restart boots
healthy -- this sat invalid but latent because the running gateway still held
an older loaded config. The block stays enabled: false; turning STT on is
still a kb#175/#191 decision (GTX 1070 co-residency).
Also adds the proactive-prioritization and todoist-capture design notes and
the vw-mcp prototype.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
394 lines
22 KiB
JSON
394 lines
22 KiB
JSON
{
|
|
// Adolf P6 — OpenClaw gateway config for the "adolf" container.
|
|
// Lives in the adolf-state VOLUME (mounted at /home/node/.openclaw), not
|
|
// in the openai/ git repo. Secrets referenced below (${VAR}) are resolved
|
|
// from this container's process env, itself sourced from openai/.env
|
|
// (gitignored) via docker-compose.yml — never inlined here.
|
|
|
|
gateway: {
|
|
mode: "local",
|
|
auth: {
|
|
// Compose already binds "lan" (0.0.0.0) and publishes 18789/18790 to
|
|
// the host, so this is a non-loopback bind and auth is mandatory.
|
|
// Shared-secret token auth also gives the openclaw-tools bridge
|
|
// (which calls POST /tools/invoke with the same token) full
|
|
// trusted-operator scope, which is what lets gateway.tools.allow
|
|
// below actually unlock cron/nodes for it.
|
|
mode: "token",
|
|
token: "${OPENCLAW_GATEWAY_TOKEN}",
|
|
},
|
|
tools: {
|
|
// cron and nodes are owner-only and hard-denied on the HTTP
|
|
// /tools/invoke surface by default. The openclaw-tools MCP bridge
|
|
// (P5) calls that surface for cron_create/cron_list/nodes_invoke, so
|
|
// without this allow-list those tools 404 even with a valid token.
|
|
// "browser" added (kb#64 follow-up) so Adolf can drive the OpenClaw
|
|
// browser via the openclaw-tools bridge for authenticated web access
|
|
// (e.g. the family wiki login form).
|
|
allow: ["cron", "nodes", "browser"],
|
|
},
|
|
},
|
|
|
|
// Audio understanding (kb#175, STT source 2: "local STT on Agap").
|
|
// OpenClaw's bundled media-understanding pipeline (docs/nodes/media-
|
|
// understanding.md) auto-transcribes inbound audio attachments before the
|
|
// agent turn runs -- no plugin code needed, this is pure config. A voice
|
|
// note sent to Adolf over the existing Matrix DM (source 1, see below)
|
|
// gets transcribed by the `openai`-shaped entry below, which is redirected
|
|
// via baseUrl/apiKey to the LOCAL faster-whisper server (openai/docker-
|
|
// compose.yml's `faster-whisper` service, same compose project as this
|
|
// container, reachable by service name) instead of hosted OpenAI --
|
|
// confirmed supported via src/media-understanding/runner.entries.ts's
|
|
// per-entry baseUrl override (docs/gateway/config-tools.md "Tools and
|
|
// custom providers"). apiKey is a dummy: faster-whisper-server has no
|
|
// auth, but OpenClaw's schema requires a non-empty value.
|
|
//
|
|
// ⚠️ NOT ACTIVATED YET (2026-07-26): the `faster-whisper` container does
|
|
// not exist (never started -- `docker ps -a` shows no such container).
|
|
// Starting it opens a 4th tenant on the single 8GB GTX 1070 already at
|
|
// ~6.2GB with bge-m3 + gemma3:4b + tei-reranker (~1.8GB headroom) and
|
|
// could evict tei-reranker, silently breaking Hindsight recall (see
|
|
// DESIGN-a2a-agents.md §3b and kb#191, which is the unimplemented
|
|
// residency-guard/VRAM-alert task -- still in Backlog). This config
|
|
// block is deliberately inert until #191 lands or alvis explicitly
|
|
// accepts the co-residency risk; `enabled: false` below.
|
|
// SCHEMA FIX 2026-07-30 (kb#180 restart). This block previously carried a
|
|
// per-entry `apiKey: "not-needed"`, which the schema REJECTS:
|
|
// tools.media.audio.models.0: Invalid input
|
|
// and an invalid config makes the gateway refuse to start outright -- adolf
|
|
// crash-looped on the first restart after the block was added. Two lessons
|
|
// encoded here: `enabled: false` does NOT exempt an entry from schema
|
|
// validation, and a config edit is not "done" until a real restart boots
|
|
// healthy (this block sat invalid but latent because the running gateway
|
|
// still held an older loaded config).
|
|
//
|
|
// The old comment claimed the schema "requires a non-empty apiKey" -- it is
|
|
// the opposite: `apiKey` is not a valid per-entry key at all. Verified with
|
|
// `openclaw config validate` against this image (2026.6.11): entries with
|
|
// {provider, model} and {provider, model, baseUrl} validate; adding
|
|
// `apiKey` is the sole cause of the failure. Per docs/nodes/audio.md,
|
|
// provider auth follows the normal model auth order (auth profiles, env
|
|
// vars, models.providers.*.apiKey) -- and faster-whisper-server has no auth
|
|
// to satisfy anyway, so no key belongs here. `baseUrl` is kept: that is the
|
|
// per-entry override that redirects the `openai`-shaped provider to the
|
|
// LOCAL faster-whisper server.
|
|
tools: {
|
|
media: {
|
|
audio: {
|
|
// Still deliberately inert: the `faster-whisper` container does not
|
|
// exist, and starting it opens a 4th tenant on the 8GB GTX 1070 (see
|
|
// the kb#191 residency-guard note above). This block is now merely
|
|
// SCHEMA-VALID rather than boot-breaking; flipping this to true is a
|
|
// separate decision that still belongs to kb#175/#191.
|
|
enabled: false,
|
|
echoTranscript: true, // let the sender see what Adolf heard before it acts
|
|
echoFormat: '📝 "{transcript}"',
|
|
models: [
|
|
{
|
|
provider: "openai",
|
|
model: "deepdml/faster-whisper-large-v3-turbo-ct2", // must match WHISPER__MODEL in openai/docker-compose.yml
|
|
baseUrl: "http://faster-whisper:8000/v1",
|
|
},
|
|
],
|
|
},
|
|
},
|
|
},
|
|
|
|
// Browser tool — bundled plugin, off by default. Enables a dedicated,
|
|
// agent-only headless Chromium profile ("openclaw") driven through the
|
|
// gateway's loopback control service. Chromium is already in the image
|
|
// (playwright chromium-1228). Needs both this browser.enabled=true and the
|
|
// "browser" entry in gateway.tools.allow above.
|
|
browser: {
|
|
enabled: true,
|
|
// Chromium's setuid sandbox can't initialize inside this container (no
|
|
// unprivileged user namespaces), so run with --no-sandbox. Safe here: the
|
|
// browser profile is agent-only and isolated, and the container already
|
|
// drops NET_RAW/NET_ADMIN. Without this, `browser start` fails with
|
|
// "No usable sandbox".
|
|
noSandbox: true,
|
|
// The local *.alogins.net services resolve to the host gateway (private
|
|
// 172.17.0.1 via extra_hosts), so the browser's SSRF guard blocks them by
|
|
// default ("navigation blocked by policy"). Opt in for this trusted,
|
|
// self-owned network — same decision as channels.matrix.network above.
|
|
ssrfPolicy: {
|
|
dangerouslyAllowPrivateNetwork: true,
|
|
},
|
|
},
|
|
|
|
// Model provider: adolf-llm (P2/P4), the Kimi-CLI OpenAI-compatible
|
|
// wrapper on :8010. Its HTTP server (openai/adolf-llm/server.js) performs
|
|
// NO api-key/Authorization validation at all -- ADOLF_KEY's value is
|
|
// functionally irrelevant to adolf-llm itself. It's still wired through
|
|
// env (not hardcoded) because OpenClaw's custom-provider schema requires
|
|
// a non-empty apiKey field and ${VAR} substitution fails closed on an
|
|
// empty/missing var.
|
|
models: {
|
|
mode: "merge",
|
|
providers: {
|
|
"adolf-llm": {
|
|
baseUrl: "http://adolf-llm:8010/v1",
|
|
apiKey: "${ADOLF_KEY}",
|
|
api: "openai-completions",
|
|
// Margin above the server.js SSE heartbeat cadence (empty-content
|
|
// keepalive delta every ~25s once idle) so the idle watchdog never
|
|
// fires on long thinking/tool/MCP phases even if a heartbeat tick
|
|
// is delayed (kb #71). Raised to 10min: long agentic turns (Cognee
|
|
// tool-loops / recalls up to 150s each) were producing no *content*
|
|
// progress for >300s, tripping "no response from model" and surfacing
|
|
// an error before the agent finished. The wrapper now also kills the
|
|
// kimi child on disconnect, so an over-timeout turn no longer orphans.
|
|
timeoutSeconds: 600,
|
|
models: [
|
|
{ id: "adolf", name: "Adolf", input: ["text", "image"] },
|
|
],
|
|
},
|
|
},
|
|
},
|
|
|
|
agents: {
|
|
defaults: {
|
|
model: "adolf-llm/adolf",
|
|
},
|
|
},
|
|
|
|
ui: {
|
|
assistant: { name: "Adolf" },
|
|
},
|
|
|
|
// Matrix channel (P6). Deliberately no accessToken/userId/password here:
|
|
// MATRIX_HOMESERVER / MATRIX_USER_ID / MATRIX_PASSWORD / MATRIX_DEVICE_NAME
|
|
// are config-key-backed env vars OpenClaw reads automatically when the
|
|
// matching config key is unset, so real creds never touch this file or
|
|
// git. Password auth (not the raw access token) mints Adolf its own fresh
|
|
// Matrix device instead of reusing the existing matrixbot (Python/nio)
|
|
// device -- see the P6 report for why that separation matters.
|
|
//
|
|
// Conservative defaults on purpose: dm "pairing" (owner must approve
|
|
// unknown senders) and groupPolicy "disabled" (no room handling yet).
|
|
// Revisit once the legacy matrixbot adapter is retired.
|
|
channels: {
|
|
matrix: {
|
|
enabled: true,
|
|
encryption: true,
|
|
dm: { policy: "allowlist", allowFrom: ["@admin:mtx.alogins.net", "@elizaveta:mtx.alogins.net"] },
|
|
groupPolicy: "disabled",
|
|
autoJoin: "always",
|
|
// mtx.alogins.net is deliberately mapped to the host-gateway (private)
|
|
// IP via extra_hosts in docker-compose.yml to dodge a hairpin-NAT dead
|
|
// end on the public route -- not an actual SSRF exposure, so opt out
|
|
// of the private-network block for this trusted, self-owned homeserver.
|
|
network: { dangerouslyAllowPrivateNetwork: true },
|
|
},
|
|
},
|
|
|
|
// MCP registry (P6) -- same servers as openai/shared-mcp.json,
|
|
// expressed in OpenClaw's own mcp.servers schema. `type: "http"` is
|
|
// OpenClaw's documented CLI-native alias for transport: "streamable-http".
|
|
mcp: {
|
|
servers: {
|
|
// kb#144 (A2A-12): toolFilter.include is OpenClaw's OWN per-server
|
|
// tool-scoping mechanism (mcp.servers.*.toolFilter, zod-validated;
|
|
// applied in agent-bundle-mcp-materialize.js when THIS container's own
|
|
// tool bundle is built). CORRECTION (kb#144 second pass, 2026-07-22):
|
|
// this does NOT reach the model on Adolf's kimi backbone -- Kimi CLI
|
|
// (inside the separate adolf-llm container) reads its own
|
|
// project-root .mcp.json, seeded from openai/shared-mcp.json, and
|
|
// applies ITS OWN enabledTools/disabledTools (McpServerCommonFields,
|
|
// computeEnabledNames). Live wire.jsonl verification (restart + one
|
|
// real turn) proved OpenClaw's toolFilter alone left Kimi's actual
|
|
// tool counts unchanged. This block is still correct for OpenClaw's
|
|
// own MCP client surface -- see openai/shared-mcp.json for the layer
|
|
// that actually scopes what the model sees.
|
|
//
|
|
// Scoped to Adolf's CORE memory ops: recall/retain/reflect (the
|
|
// hooks below do IMPLICIT recall/retain automatically; these MCP
|
|
// tools cover explicit "remember this" / "what do you recall about
|
|
// X" turns) plus single-memory read/update and directive CRUD
|
|
// (standing instructions). Cuts 20 rarely-used/admin tools: the
|
|
// mental-model CRUD (7), document CRUD (3), operation-tracking (3),
|
|
// tags (1), bank admin (4), sync_retain, invalidate_memory -- none
|
|
// of which Adolf's Matrix persona drives turn-to-turn; reach the
|
|
// hindsight MCP directly (unscoped) for that admin work instead of
|
|
// paying for it on every Adolf turn. 29 tools -> 9.
|
|
//
|
|
// kb#169: this raw MCP surface previously pointed at /mcp/adolf/ --
|
|
// the single unpartitioned bank with content from every human's
|
|
// conversations. #153 scopes the hindsight-memory PLUGIN's
|
|
// recall/retain hooks by interlocutor, but this MCP tool surface is a
|
|
// second, independent path to memory that #153 does not touch: a
|
|
// model call to e.g. `recall` here bypassed interlocutor scoping
|
|
// entirely. Repointed to /mcp/adolf-shared/ (option 2 of #169) --
|
|
// the household-shared bank (0 facts as of 2026-07-26, pre-existing
|
|
// per agent-registry.yaml's memory.banks target list). This surface
|
|
// can now only ever read/write the shared bank, never a private one,
|
|
// regardless of which human is talking to Adolf -- safe by
|
|
// construction, no dependency on #153 landing first. Option 1 (drop
|
|
// entirely) was not chosen because, until #153's scoped plugin tools
|
|
// land, this is still Adolf's only path for explicit "remember
|
|
// this"/"what do you recall" turns; option 3 (dynamic per-interlocutor
|
|
// bank selection) is not supported -- this config's url is a single
|
|
// static bank_id per MCP server entry, not a per-request parameter.
|
|
hindsight: {
|
|
type: "http",
|
|
url: "http://hindsight:8888/mcp/adolf-shared/",
|
|
toolFilter: {
|
|
include: ["recall", "retain", "reflect", "list_memories", "get_memory", "update_memory", "list_directives", "create_directive", "delete_directive"],
|
|
},
|
|
},
|
|
// Already minimal (5 tools -- message_send/cron_create/cron_list/
|
|
// nodes_invoke/browser_invoke, all core to Adolf's matrix-chat +
|
|
// cron-scheduling + browser capabilities) -- deliberately NO
|
|
// toolFilter here, not an oversight.
|
|
"openclaw-tools": {
|
|
type: "http",
|
|
url: "http://openclaw-tools:8020/mcp",
|
|
},
|
|
// kanboard-mcp-adolf (kb task #58) -- standalone kanboard-mcp image
|
|
// (source /home/alvis/kanboard/mcp), second instance on :3104,
|
|
// authenticated as the Kanboard "adolf" user via its own personal API
|
|
// access token (KANBOARD_AUTH_USER=adolf in that instance's
|
|
// .env.adolf) -- a genuinely distinct credential from the "claude"
|
|
// instance on :3103 (app-wide jsonrpc token). Not part of the openai
|
|
// compose network, so reached via host.docker.internal (already
|
|
// extra_hosts-mapped for this container) rather than a service name.
|
|
// kb#144: scoped to task-triage/proactive-monitoring core --
|
|
// list/read/search/create/update/move/status/assign/comment/
|
|
// activity. Cuts subtask CRUD, task-link CRUD, tag CRUD, and
|
|
// destructive remove_task/remove_comment (9 tools) -- deep
|
|
// task-graph management is claude-coder's job (the actual task
|
|
// worker), not Adolf's lighter triage/reporting role. 23 -> 14.
|
|
kanboard: {
|
|
type: "http",
|
|
url: "http://host.docker.internal:3104/mcp",
|
|
toolFilter: {
|
|
include: ["kanboard_list_projects", "kanboard_get_project", "kanboard_list_tasks", "kanboard_my_tasks", "kanboard_get_task", "kanboard_search_tasks", "kanboard_list_users", "kanboard_project_activity", "kanboard_create_task", "kanboard_update_task", "kanboard_move_task", "kanboard_change_task_status", "kanboard_assign_task", "kanboard_add_comment"],
|
|
},
|
|
},
|
|
// marketplace-mcp (kb task #61) -- the SAME shared marketplace-mcp
|
|
// instance Claude Code and OpenWebUI use (single service, port 3101,
|
|
// network_mode: host on the Agap host), not a second copy. It can
|
|
// place real orders on live marketplace accounts, so it's gated by a
|
|
// shared bearer token (MARKETPLACE_MCP_TOKEN in Vaultwarden / this
|
|
// container's env, injected via openai/.env -> docker-compose.yml).
|
|
// Reached via host.docker.internal, same reasoning as kanboard above.
|
|
// kb#144: scoped to READ-ONLY discovery (find_best/search/product/
|
|
// recommendations/reviews/compare/status). Cuts the checkout
|
|
// surface -- add_to_cart, get_cart, login, open_vnc, save_session,
|
|
// submit_sms (6 tools) -- real-money/session-auth actions Adolf
|
|
// shouldn't take unattended from background Matrix chat. This
|
|
// whole server is also the FIRST candidate to move OUT to Torgash
|
|
// (kb#130's marketplace-analyst persona, not yet built) per
|
|
// design §2/§8; scoping now both cuts tokens and removes purchase
|
|
// risk in the meantime rather than waiting on Torgash to exist.
|
|
// 13 -> 7.
|
|
marketplace: {
|
|
type: "http",
|
|
url: "http://host.docker.internal:3101/mcp",
|
|
headers: {
|
|
Authorization: "Bearer ${MARKETPLACE_MCP_TOKEN}",
|
|
},
|
|
toolFilter: {
|
|
include: ["marketplace_find_best", "marketplace_search", "marketplace_get_product", "marketplace_get_recommendations", "marketplace_get_reviews", "marketplace_compare_prices", "marketplace_status"],
|
|
},
|
|
},
|
|
// agap-mcp (kb#64) -- the SAME shared agap-mcp instance Claude Code uses
|
|
// (network_mode: host, :3100, bearer-authenticated since kb#180). Grants Adolf
|
|
// the same access as Claude: vault (vw_* for credential fetching) plus
|
|
// gitea/ha/zabbix/radicale. Reached via host.docker.internal like
|
|
// kanboard/marketplace above.
|
|
// kb#144: scoped to Adolf's proactive-auditor/personal-assistant
|
|
// core -- vault read/write (trusted, credential help), HA
|
|
// (smart-home monitoring), Zabbix (the literal "proactive
|
|
// auditor" job), calendar read/write (minus admin
|
|
// create/delete_calendar), Todoist. Cuts all 6 gitea_* tools
|
|
// (repo/wiki/issue management is claude-coder's infra-ops domain,
|
|
// not Adolf's Matrix persona) plus radicale_create_calendar/
|
|
// delete_calendar (rare calendar-admin ops) -- 8 tools. 32 -> 24.
|
|
// kb#95: added wiki_search/wiki_read/wiki_edit (family MediaWiki,
|
|
// family.alogins.net / РодоВики -- source of truth for relatives,
|
|
// dates, events) -- squarely Adolf's persona domain. 35 -> 27.
|
|
agap: {
|
|
type: "http",
|
|
url: "http://host.docker.internal:3100/mcp",
|
|
// kb#180: agap-mcp's listener is authenticated now (DESIGN §4 --
|
|
// :3100 is host-networked and the LAN carries VPN peers, so an
|
|
// open JSON-RPC listener handed ha_call_service/wiki_edit/todoist
|
|
// writes to anyone). Same pattern as marketplace above:
|
|
// AGAP_MCP_TOKEN lives in Vaultwarden, is injected into this
|
|
// container via openai/.env -> docker-compose.yml, and is only
|
|
// substituted here -- never inlined. The token maps to agent id
|
|
// `adolf` in AGAP_MCP_AGENT_TOKENS, which is also what the kb#147
|
|
// vault gate reads to allow vw_* (adolf = trust_class trusted).
|
|
headers: {
|
|
Authorization: "Bearer ${AGAP_MCP_TOKEN}",
|
|
},
|
|
toolFilter: {
|
|
// kb#170: added todoist_capture_idea (classify + create in one
|
|
// call — see agap-mcp/src/capture.js) so Adolf's proactive-
|
|
// secretary persona can capture+tag an idea in one tool call
|
|
// instead of list_projects+create_task+manual tagging.
|
|
include: ["vw_get_password", "vw_get_item", "vw_list_items", "vw_create_login", "vw_update_password", "ha_get_state", "ha_list_entities", "ha_call_service", "ha_get_history", "zabbix_get_problems", "zabbix_get_hosts", "zabbix_get_items", "zabbix_get_triggers", "radicale_list_calendars", "radicale_list_events", "radicale_get_event", "radicale_put_event", "radicale_delete_event", "radicale_move_event", "todoist_list_tasks", "todoist_list_projects", "todoist_create_task", "todoist_update_task", "todoist_complete_task", "todoist_capture_idea", "wiki_search", "wiki_read", "wiki_edit"],
|
|
},
|
|
},
|
|
},
|
|
},
|
|
|
|
// Memory plugins (P8). Activation entry is required for the gateway to
|
|
// load a plugin at startup (discovery alone is not enough).
|
|
plugins: {
|
|
entries: {
|
|
// Hindsight memory plugin (kb #75, H3) — installed external plugin
|
|
// under .openclaw/extensions/hindsight-memory, bind-mounted read-only
|
|
// from openai/hindsight-openclaw-plugin (see that project's
|
|
// docker-compose.yml adolf.volumes). Structural successor to
|
|
// cognee-memory above: LLM-free recall inject (before_prompt_build) +
|
|
// async retain (agent_end) against the hindsight service, bank
|
|
// "adolf" (same bank the mcp.servers.hindsight tool surface above
|
|
// uses, so hook-based and tool-based memory stay one consistent
|
|
// store). No cognify/sweep config here — Hindsight's retain does
|
|
// extraction/consolidation server-side, so that whole class of
|
|
// config (sweepIntervalMs etc. above) doesn't apply.
|
|
"hindsight-memory": {
|
|
enabled: true,
|
|
// Same opt-in requirement as cognee-memory above: before_prompt_build
|
|
// => allowPromptInjection; agent_end => allowConversationAccess.
|
|
hooks: { allowConversationAccess: true, allowPromptInjection: true },
|
|
},
|
|
// Kimi quota readout (kb #62) — installed external plugin, bind-mounted
|
|
// read-only from openai/quota-command-openclaw-plugin (see that
|
|
// project's docker-compose.yml adolf.volumes) onto
|
|
// .openclaw/extensions/quota-command. Registers a `/quota` native
|
|
// command; no hooks, so no allowConversationAccess/allowPromptInjection
|
|
// opt-in needed.
|
|
"quota-command": {
|
|
enabled: true,
|
|
},
|
|
// Kimi quota footer (kb #85) — installed external plugin, bind-mounted
|
|
// read-only from openai/kimi-quota-footer-plugin (see that project's
|
|
// docker-compose.yml adolf.volumes) onto
|
|
// .openclaw/extensions/kimi-quota-footer. Appends a compact Kimi
|
|
// usage line to every outgoing reply via the reply_payload_sending
|
|
// hook (not a raw conversation hook, so no allowConversationAccess/
|
|
// allowPromptInjection opt-in needed), reusing the same LLM-free
|
|
// adolf-llm:8010/usage route as quota-command above. Verified this
|
|
// hook fires on Adolf's actual send path (sendDurableMessageBatch ->
|
|
// deliverOutboundPayloadsInternal) as long as channels.matrix.streaming
|
|
// stays unset/"off" as it is today — see the plugin's index.js header
|
|
// comment for the streaming caveat if that ever changes.
|
|
"kimi-quota-footer": {
|
|
enabled: true,
|
|
},
|
|
// Todoist idea capture (kb#170 component 1) — installed external
|
|
// plugin, bind-mounted read-only from openai/todoist-capture-plugin
|
|
// (see that project's docker-compose.yml adolf.volumes) onto
|
|
// .openclaw/extensions/todoist-capture. Registers a `/idea` native
|
|
// command; no hooks (no allowConversationAccess/allowPromptInjection
|
|
// needed) — it POSTs straight to agap-mcp's /capture-idea route.
|
|
"todoist-capture": {
|
|
enabled: true,
|
|
},
|
|
},
|
|
},
|
|
}
|