openbot 0.5.4 → 0.5.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/CLAUDE.md +5 -4
  2. package/deploy/README.md +2 -4
  3. package/dist/app/cli.js +3 -1
  4. package/dist/app/cloud-mode.js +5 -16
  5. package/dist/app/ensure-default-stack.js +54 -0
  6. package/dist/app/openbot-plugin.js +4 -0
  7. package/dist/app/server.js +2 -3
  8. package/dist/harness/index.js +3 -0
  9. package/dist/plugins/openbot/index.js +6 -5
  10. package/dist/plugins/openbot/model.js +2 -41
  11. package/dist/plugins/openbot/runtime.js +9 -4
  12. package/dist/plugins/storage/index.js +3 -325
  13. package/dist/plugins/storage/service.js +18 -21
  14. package/dist/services/plugins/host.js +21 -0
  15. package/dist/services/plugins/model-registry.js +34 -9
  16. package/dist/services/plugins/registry.js +26 -42
  17. package/dist/services/plugins/service.js +5 -1
  18. package/dist/services/todo/types.js +1 -0
  19. package/docs/plugins.md +14 -12
  20. package/docs/templates/AGENT.example.md +8 -14
  21. package/package.json +2 -2
  22. package/src/app/cli.ts +3 -1
  23. package/src/app/cloud-mode.ts +7 -22
  24. package/src/app/ensure-default-stack.ts +63 -0
  25. package/src/app/openbot-plugin.ts +5 -0
  26. package/src/app/server.ts +2 -5
  27. package/src/app/types.ts +4 -8
  28. package/src/harness/index.ts +4 -0
  29. package/src/plugins/storage/index.ts +3 -368
  30. package/src/plugins/storage/service.ts +17 -22
  31. package/src/services/plugins/host.ts +36 -0
  32. package/src/services/plugins/model-registry.ts +41 -9
  33. package/src/services/plugins/registry.ts +28 -43
  34. package/src/services/plugins/service.ts +13 -12
  35. package/src/services/plugins/types.ts +36 -2
  36. package/src/services/todo/types.ts +12 -0
  37. package/src/plugins/approval/index.ts +0 -147
  38. package/src/plugins/bash/index.ts +0 -545
  39. package/src/plugins/delegation/index.ts +0 -153
  40. package/src/plugins/memory/index.ts +0 -182
  41. package/src/plugins/openbot/context.ts +0 -137
  42. package/src/plugins/openbot/history.ts +0 -158
  43. package/src/plugins/openbot/index.ts +0 -95
  44. package/src/plugins/openbot/model.ts +0 -76
  45. package/src/plugins/openbot/runtime.ts +0 -504
  46. package/src/plugins/openbot/system-prompt.ts +0 -57
  47. package/src/plugins/preview/index.ts +0 -323
  48. package/src/plugins/todo/index.ts +0 -166
  49. package/src/plugins/todo/service.ts +0 -123
  50. package/src/plugins/ui/index.ts +0 -130
package/CLAUDE.md CHANGED
@@ -20,6 +20,7 @@ OpenBot is a local-first, event-driven harness for running AI agents, built on t
20
20
  ### Request flow
21
21
 
22
22
  `src/app/server.ts` is the only HTTP surface, with three routes:
23
+
23
24
  - `GET /api/events` — opens an SSE stream for a `channelId`(+`threadId`), or the special `__global__` channel for active-run snapshots across all channels.
24
25
  - `POST /api/publish` — publishes an event; the common case is `agent:invoke`, which resolves a target agent and calls `runAgent` (fire-and-forget, streamed back over SSE + persisted). Also special-cased inline for file upload/write and `action:agent_run_stop`.
25
26
  - `GET /api/state` — same dispatch as `/api/publish` but synchronous (collects emitted events into a JSON response instead of streaming) and defaults to the hidden `state` agent; used for deterministic, non-LLM reads (storage plugin actions).
@@ -28,13 +29,13 @@ OpenBot is a local-first, event-driven harness for running AI agents, built on t
28
29
 
29
30
  ### Plugins (`src/plugins/*`, registered in `src/services/plugins/registry.ts`)
30
31
 
31
- Built-ins: `openbot` (batteries-included runtime: bash, memory, todo, storage, delegation, approval all bundled in), `bash`, `storage`, `approval` (gates protected tool calls behind UI confirmation), `memory` (`remember`/`recall`/`forget`, append-only JSONL, scoped `global`/`agent`/`channel`), `todo` (`todo_write`/`todo_read`, thread-scoped checklist in `todos.json`), `delegation` (calling other agents), `ui`, `plugin-manager` (marketplace + npm plugin install), `preview`. Community plugins are npm packages installed on demand into `~/.openbot/plugins/<name>/dist/index.js` and loaded dynamically via `resolvePlugin`; they export a `Plugin`-shaped object as `plugin` or `default` (see `parsePluginModule`).
32
+ Core built-ins: `storage` (infra handlers for `/api/state`), `plugin-manager` (marketplace + npm plugin install). The default agent runtime is **`@meetopenbot/openbot`**, a community npm package installed to `~/.openbot/plugins/@meetopenbot/openbot/` on first boot (`ensureDefaultStack`). Disk-installed plugins take precedence over built-ins in `resolvePlugin`.
32
33
 
33
- A `Plugin`'s `factory(context)` returns a `MelonyPlugin`; `PluginContext` carries `agentId`, `agentDetails`, per-agent `config` (from `AGENT.md` frontmatter), the shared `storage` service, the merged `tools` map, `publicBaseUrl`, and the run's `abortSignal`.
34
+ A `Plugin`'s `factory(context)` returns a `MelonyPlugin`; `PluginContext` carries `agentId`, `agentDetails`, per-agent `config` (from `AGENT.md` frontmatter), the shared `storage` service, the merged `tools` map, `publicBaseUrl`, the run's `abortSignal`, and `host` (platform hooks: `runAgent`, cloud auth, model registry, config).
34
35
 
35
36
  ### Agents
36
37
 
37
- Agents are markdown files with YAML frontmatter (`~/.openbot/agents/<agentId>/AGENT.md`) listing `plugins: [{id, config}]`; the body is the system prompt. `claude-code` and `gemini-cli` runtime plugins own their entire tool loop (attaching tool plugins like `bash` to them is a no-op) — only the `openbot` runtime plugin consumes the merged `tools` map. Two built-in agent ids are hardcoded in `src/app/agent-ids.ts` and can be overridden by an on-disk `AGENT.md` overlay merged on top of code defaults: `system` (`ORCHESTRATOR_AGENT_ID`, the default orchestrator, listed) and `state` (`STATE_AGENT_ID`, hidden, backs `/api/state` and deterministic storage/marketplace actions).
38
+ Agents are markdown files with YAML frontmatter (`~/.openbot/agents/<agentId>/AGENT.md`) listing `plugins: [{id, config}]`; the body is the system prompt. The default **`system`** orchestrator references `@meetopenbot/openbot` (materialized on first boot). Built-in agent ids in `src/app/agent-ids.ts`: `system` (orchestrator, listed) and `state` (hidden, backs `/api/state`). `system` may be customized via `agents/system/AGENT.md`; deleting that file reverts to bootstrap defaults on next start.
38
39
 
39
40
  ### Storage (`src/plugins/storage/service.ts`, `src/services/plugins/domain.ts`)
40
41
 
@@ -42,7 +43,7 @@ Agents are markdown files with YAML frontmatter (`~/.openbot/agents/<agentId>/AG
42
43
 
43
44
  ### Cloud mode (`src/app/cloud-mode.ts`)
44
45
 
45
- Set via `OPENBOT_CLOUD_MODE=1` for platform-managed (Fly.io) deployments: the `system` agent is forced onto a coordinator model (`openbot/coordinator-1`) and LLM/integration calls proxy through `OPENBOT_INTEGRATIONS_BASE_URL` with an HMAC `OPENBOT_INTEGRATIONS_TOKEN`. `OPENBOT_GATEWAY_TOKEN`, when set, gates every route except `/api/health` behind an `x-openbot-gateway-token` header check (see `server.ts`) — this is how the control plane's proxy authenticates to a per-tenant instance. See `deploy/README.md` for the full env var contract and control-plane integration sequence.
46
+ Set via `OPENBOT_CLOUD_MODE=1` for platform-managed (Fly.io) deployments. The `system` agent openbot plugin defaults to **credits** mode and can be switched to **BYOK** in agent config. `OPENBOT_GATEWAY_TOKEN`, when set, gates every route except `/api/health` behind an `x-openbot-gateway-token` header check (see `server.ts`) — this is how the control plane's proxy authenticates to a per-tenant instance. See `deploy/README.md` for the full env var contract and control-plane integration sequence.
46
47
 
47
48
  ## Conventions
48
49
 
package/deploy/README.md CHANGED
@@ -39,9 +39,7 @@ Copy `deploy/fly.toml`, set `app` to your tenant id, and ensure the volume name
39
39
  | `OPENBOT_CHANNELS_WORKSPACE_DIR` | Yes (cloud) | Channel workspace parent, e.g. `/data/workspace` |
40
40
  | `OPENBOT_PUBLIC_URL` | Yes (cloud) | Public HTTPS URL for file links |
41
41
  | `OPENBOT_GATEWAY_TOKEN` | Yes (cloud) | Per-workspace HMAC token; gateway sends `x-openbot-gateway-token` on proxied requests |
42
- | `OPENBOT_CLOUD_MODE` | Yes (cloud) | Set to `1` for platform-managed OpenBot (system agent uses integrations proxy) |
43
- | `OPENBOT_INTEGRATIONS_BASE_URL` | Yes (cloud) | Integrations gateway base URL, e.g. `https://integrations.openbot.one/abc123` |
44
- | `OPENBOT_INTEGRATIONS_TOKEN` | Yes (cloud) | Per-workspace HMAC token for `x-openbot-integrations-token` on LLM proxy requests |
42
+ | `OPENBOT_CLOUD_MODE` | Yes (cloud) | Set to `1` for platform-managed OpenBot (system agent defaults to credits mode) |
45
43
  | `PORT` | Auto | Set by Fly (`8080`) |
46
44
 
47
45
  ## Health check
@@ -54,7 +52,7 @@ Your control plane should:
54
52
 
55
53
  1. `fly apps create openbot-{tenantId}`
56
54
  2. `fly volumes create openbot_data --region {region} --size {gb}`
57
- 3. `fly secrets set OPENBOT_PUBLIC_URL=... OPENBOT_CLOUD_MODE=1 OPENBOT_INTEGRATIONS_BASE_URL=... OPENBOT_INTEGRATIONS_TOKEN=...`
55
+ 3. `fly secrets set OPENBOT_PUBLIC_URL=... OPENBOT_CLOUD_MODE=1`
58
56
  4. `fly deploy` with a pinned image tag
59
57
  5. Poll `/api/health` until `status === 'ok'`
60
58
 
package/dist/app/cli.js CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { Command } from 'commander';
3
3
  import { bootstrap } from './bootstrap.js';
4
+ import { ensureDefaultStack } from './ensure-default-stack.js';
4
5
  import { startServer } from './server.js';
5
6
  const program = new Command();
6
7
  const REQUIRED_NODE_VERSION = '20.12.0';
@@ -17,13 +18,14 @@ function checkNodeVersion() {
17
18
  }
18
19
  }
19
20
  checkNodeVersion();
20
- program.name('openbot').description('OpenBot CLI').version('0.5.4');
21
+ program.name('openbot').description('OpenBot CLI').version('0.5.6');
21
22
  program
22
23
  .command('start')
23
24
  .description('Start the OpenBot harness')
24
25
  .option('-p, --port <number>', 'Port to listen on')
25
26
  .action(async (options) => {
26
27
  await bootstrap();
28
+ await ensureDefaultStack();
27
29
  await startServer(options);
28
30
  });
29
31
  program.parse();
@@ -1,24 +1,13 @@
1
1
  import { ORCHESTRATOR_AGENT_ID } from './agent-ids.js';
2
- /** Platform-managed OpenBot (Fly + integrations proxy). Self-hosted when unset. */
2
+ /** Platform-managed OpenBot (Fly). Self-hosted when unset. */
3
3
  export const isCloudMode = () => process.env.OPENBOT_CLOUD_MODE === '1';
4
- /** Platform-managed coordinator model for cloud workspaces. */
5
- export const COORDINATOR_MODEL = 'openbot/coordinator-1';
6
- /** Default cloud system agent model. */
7
- export const CLOUD_SYSTEM_MODEL = COORDINATOR_MODEL;
8
- export function getCloudIntegrationsConfig() {
9
- if (!isCloudMode())
10
- return null;
11
- const baseUrl = process.env.OPENBOT_INTEGRATIONS_BASE_URL?.trim();
12
- const token = process.env.OPENBOT_INTEGRATIONS_TOKEN?.trim();
13
- if (!baseUrl || !token)
14
- return null;
15
- return { baseUrl: baseUrl.replace(/\/$/, ''), token };
16
- }
4
+ /** Default cloud openbot plugin auth mode. */
5
+ export const DEFAULT_CLOUD_OPENBOT_AUTH_MODE = 'credits';
17
6
  export function isCloudSystemAgent(agentId) {
18
7
  return isCloudMode() && agentId === ORCHESTRATOR_AGENT_ID;
19
8
  }
20
- export function resolveCloudSystemModel(configModel) {
21
- return configModel?.trim() || COORDINATOR_MODEL;
9
+ export function parseOpenbotAuthMode(value) {
10
+ return value === 'byok' ? 'byok' : 'credits';
22
11
  }
23
12
  export function assertCloudSystemAgentPluginsMutable(agentId, plugins) {
24
13
  void agentId;
@@ -0,0 +1,54 @@
1
+ import fs from 'node:fs/promises';
2
+ import { existsSync } from 'node:fs';
3
+ import path from 'node:path';
4
+ import matter from 'gray-matter';
5
+ import { ORCHESTRATOR_AGENT_ID } from './agent-ids.js';
6
+ import { DEFAULT_SYSTEM_AGENT_MODEL, OPENBOT_PLUGIN_ID } from './openbot-plugin.js';
7
+ import { DEFAULT_CLOUD_OPENBOT_AUTH_MODE, isCloudMode } from './cloud-mode.js';
8
+ import { DEFAULT_AGENTS_DIR, getBaseDir } from './config.js';
9
+ import { pluginService } from '../services/plugins/service.js';
10
+ function systemAgentMdPath() {
11
+ return path.join(getBaseDir(), DEFAULT_AGENTS_DIR, ORCHESTRATOR_AGENT_ID, 'AGENT.md');
12
+ }
13
+ function defaultSystemPluginConfig() {
14
+ const config = {
15
+ model: DEFAULT_SYSTEM_AGENT_MODEL,
16
+ };
17
+ if (isCloudMode()) {
18
+ config.authMode = DEFAULT_CLOUD_OPENBOT_AUTH_MODE;
19
+ }
20
+ return config;
21
+ }
22
+ async function ensureOpenbotPluginInstalled() {
23
+ if (await pluginService.isInstalled(OPENBOT_PLUGIN_ID)) {
24
+ return;
25
+ }
26
+ console.log(`[bootstrap] Installing ${OPENBOT_PLUGIN_ID} from npm`);
27
+ await pluginService.install({ packageName: OPENBOT_PLUGIN_ID });
28
+ }
29
+ async function ensureSystemAgentMaterialized() {
30
+ const agentMdPath = systemAgentMdPath();
31
+ if (existsSync(agentMdPath)) {
32
+ return;
33
+ }
34
+ const agentDir = path.dirname(agentMdPath);
35
+ await fs.mkdir(agentDir, { recursive: true });
36
+ const frontmatter = {
37
+ name: 'OpenBot',
38
+ description: 'First-party orchestration agent for OpenBot.',
39
+ plugins: [
40
+ {
41
+ id: OPENBOT_PLUGIN_ID,
42
+ config: defaultSystemPluginConfig(),
43
+ },
44
+ ],
45
+ };
46
+ const content = matter.stringify('', frontmatter);
47
+ await fs.writeFile(agentMdPath, content, 'utf-8');
48
+ console.log(`[bootstrap] Materialized system agent at ${agentMdPath}`);
49
+ }
50
+ /** Install the default agent plugin from npm and materialize the system agent on first boot. */
51
+ export async function ensureDefaultStack() {
52
+ await ensureOpenbotPluginInstalled();
53
+ await ensureSystemAgentMaterialized();
54
+ }
@@ -0,0 +1,4 @@
1
+ /** npm package id for the monolithic OpenBot agent runtime plugin. */
2
+ export const OPENBOT_PLUGIN_ID = '@meetopenbot/openbot';
3
+ /** Default model for the materialized system agent. */
4
+ export const DEFAULT_SYSTEM_AGENT_MODEL = 'openai/gpt-5.4-mini';
@@ -9,7 +9,7 @@ const require = createRequire(import.meta.url);
9
9
  const pkg = require('../../package.json');
10
10
  import { generateId } from 'melony';
11
11
  import { getBaseDir, loadConfig } from '../app/config.js';
12
- import { isCloudMode, getCloudIntegrationsConfig } from './cloud-mode.js';
12
+ import { isCloudMode } from './cloud-mode.js';
13
13
  import { processService } from '../services/process.js';
14
14
  import { runAgent, STATE_AGENT_ID, ORCHESTRATOR_AGENT_ID } from '../harness/index.js';
15
15
  import { initPlugins } from '../services/plugins/registry.js';
@@ -31,8 +31,7 @@ export async function startServer(options = {}) {
31
31
  const config = loadConfig();
32
32
  processService.syncWorkspaceVariablesToProcessEnv();
33
33
  if (isCloudMode()) {
34
- const integrations = getCloudIntegrationsConfig();
35
- console.log(`[server] Cloud mode enabled${integrations ? '' : ' (integrations proxy env not set)'}`);
34
+ console.log('[server] Cloud mode enabled');
36
35
  }
37
36
  const openBotDir = getBaseDir();
38
37
  const PORT = Number(options.port ?? config.port ?? process.env.PORT ?? 4132);
@@ -6,6 +6,7 @@ import { resolvePlugin } from '../services/plugins/registry.js';
6
6
  import { abortRegistry, abortKey } from '../services/abort.js';
7
7
  import { loadConfig } from '../app/config.js';
8
8
  import { getPublicBaseUrl } from '../plugins/storage/files.js';
9
+ import { createPluginHost } from '../services/plugins/host.js';
9
10
  export { STATE_AGENT_ID, ORCHESTRATOR_AGENT_ID };
10
11
  async function emitEvent(chunk, state, { persistEvents, channelId, threadId, onEvent, parentAgentId, parentToolCallId, }) {
11
12
  ensureEventId(chunk);
@@ -67,6 +68,7 @@ export async function runAgent(options) {
67
68
  }
68
69
  }
69
70
  const builder = melony().initialState(state);
71
+ const pluginHost = createPluginHost(runAgent);
70
72
  for (const ref of pluginRefs) {
71
73
  const plugin = await resolvePlugin(ref.id);
72
74
  if (!plugin)
@@ -79,6 +81,7 @@ export async function runAgent(options) {
79
81
  tools,
80
82
  publicBaseUrl,
81
83
  abortSignal,
84
+ host: pluginHost,
82
85
  }));
83
86
  }
84
87
  const runtime = builder.build();
@@ -1,4 +1,4 @@
1
- import { isCloudSystemAgent, resolveCloudSystemModel } from '../../app/cloud-mode.js';
1
+ import { isCloudSystemAgent, parseOpenbotAuthMode } from '../../app/cloud-mode.js';
2
2
  import { openbotRuntime } from './runtime.js';
3
3
  import { bashPlugin } from '../bash/index.js';
4
4
  import { memoryPlugin } from '../memory/index.js';
@@ -72,11 +72,12 @@ export const openbotPlugin = {
72
72
  ],
73
73
  };
74
74
  approvalPlugin.factory({ ...context, config: approvalConfig })(builder);
75
- const model = isCloudSystemAgent(agentId)
76
- ? resolveCloudSystemModel(config?.model)
77
- : config?.model;
75
+ const authMode = isCloudSystemAgent(agentId)
76
+ ? parseOpenbotAuthMode(config?.authMode)
77
+ : 'byok';
78
78
  return openbotRuntime({
79
- model,
79
+ model: config?.model,
80
+ authMode,
80
81
  agentId,
81
82
  storage,
82
83
  toolDefinitions: tools,
@@ -1,52 +1,13 @@
1
- import { createOpenAI, openai as defaultOpenai } from '@ai-sdk/openai';
1
+ import { openai as defaultOpenai } from '@ai-sdk/openai';
2
2
  import { anthropic } from '@ai-sdk/anthropic';
3
3
  import { google } from '@ai-sdk/google';
4
- import { getCloudIntegrationsConfig, isCloudSystemAgent, } from '../../app/cloud-mode.js';
5
- let cloudOpenAIProvider;
6
- /** Strip credentials — the integrations gateway injects the provider master key. */
7
- const integrationsFetch = async (input, init) => {
8
- const headers = new Headers(init?.headers);
9
- headers.delete('Authorization');
10
- headers.delete('x-api-key');
11
- return globalThis.fetch(input, { ...init, headers });
12
- };
13
- function getCloudOpenAIProvider() {
14
- if (cloudOpenAIProvider !== undefined)
15
- return cloudOpenAIProvider;
16
- const config = getCloudIntegrationsConfig();
17
- if (!config) {
18
- cloudOpenAIProvider = null;
19
- return null;
20
- }
21
- cloudOpenAIProvider = createOpenAI({
22
- baseURL: `${config.baseUrl}/openai/v1`,
23
- apiKey: 'unused',
24
- headers: {
25
- 'x-openbot-integrations-token': config.token,
26
- },
27
- fetch: integrationsFetch,
28
- });
29
- return cloudOpenAIProvider;
30
- }
31
- function resolveOpenbotModel(modelId, agentId) {
32
- if (!agentId || !isCloudSystemAgent(agentId)) {
33
- throw new Error(`OpenBot models are only available for the cloud system agent. Use openai/..., anthropic/..., etc.`);
34
- }
35
- const cloudOpenai = getCloudOpenAIProvider();
36
- if (!cloudOpenai) {
37
- throw new Error('OpenBot cloud model requires OPENBOT_INTEGRATIONS_BASE_URL and OPENBOT_INTEGRATIONS_TOKEN.');
38
- }
39
- return cloudOpenai.chat(modelId);
40
- }
41
- export function resolveModel(modelString, agentId) {
4
+ export function resolveModel(modelString, _agentId) {
42
5
  const [provider, ...rest] = modelString.split('/');
43
6
  const modelId = rest.join('/');
44
7
  if (!modelId) {
45
8
  throw new Error(`Invalid model string: "${modelString}". Expected "provider/model-id".`);
46
9
  }
47
10
  switch (provider) {
48
- case 'openbot':
49
- return resolveOpenbotModel(modelId, agentId);
50
11
  case 'openai':
51
12
  return defaultOpenai(modelId);
52
13
  case 'anthropic':
@@ -69,9 +69,10 @@ function createToolBatchTracker(state, storage, channelId, threadId) {
69
69
  * - When a full batch of results is in, `runLLM` runs again with updated history.
70
70
  */
71
71
  export const openbotRuntime = (options) => (builder) => {
72
- const { model: modelString = 'openai/gpt-4o-mini', agentId, storage, toolDefinitions = {}, abortSignal, } = options;
72
+ const { model: modelString = 'openai/gpt-4o-mini', authMode = 'byok', agentId, storage, toolDefinitions = {}, abortSignal, } = options;
73
73
  let currentModelString = modelString;
74
74
  let model = resolveModel(currentModelString, agentId);
75
+ const isCreditsCloudAgent = (id) => isCloudSystemAgent(id ?? '') && authMode === 'credits';
75
76
  const runLLM = async function* (context, threadId, trigger) {
76
77
  if (!storage)
77
78
  return;
@@ -167,7 +168,7 @@ export const openbotRuntime = (options) => (builder) => {
167
168
  errorMessage.includes('401') ||
168
169
  errorMessage.includes('Unauthorized') ||
169
170
  errorMessage.includes('authentication');
170
- if (isApiKeyError && !isCloudSystemAgent(context.state.agentId)) {
171
+ if (isApiKeyError && !isCreditsCloudAgent(context.state.agentId)) {
171
172
  const registry = await resolveModelRegistry();
172
173
  const providerActions = listApiKeyProvidersFromRegistry(registry).map((provider) => ({
173
174
  id: provider.id,
@@ -234,7 +235,7 @@ export const openbotRuntime = (options) => (builder) => {
234
235
  builder.on('client:ui:widget:response', async function* (event, context) {
235
236
  const { metadata, values, actionId } = event.data;
236
237
  const threadId = event.meta?.threadId || context.state.threadId;
237
- if (isCloudSystemAgent(context.state.agentId))
238
+ if (isCreditsCloudAgent(context.state.agentId))
238
239
  return;
239
240
  if (metadata?.type === 'api_provider_selection') {
240
241
  const provider = actionId;
@@ -350,7 +351,11 @@ export const openbotRuntime = (options) => (builder) => {
350
351
  if (ref.id === 'openbot') {
351
352
  return {
352
353
  ...ref,
353
- config: { ...ref.config, model: currentModelString },
354
+ config: {
355
+ ...ref.config,
356
+ model: currentModelString,
357
+ ...(isCloudSystemAgent(context.state.agentId) ? { authMode: 'byok' } : {}),
358
+ },
354
359
  };
355
360
  }
356
361
  return ref;