@botbotgo/agent-harness 0.0.55 → 0.0.56

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.
package/README.md CHANGED
@@ -18,13 +18,7 @@ That means:
18
18
  - runtime lifecycle stays stable even if backend implementations change
19
19
  - backend internals stay behind adapters
20
20
 
21
- The repository also keeps two boundary documents current:
22
-
23
- - `docs/upstream-feature-matrix.md`
24
- - `docs/product-boundary.md`
25
- - `docs/feature-checklist.md`
26
-
27
- What the runtime provides:
21
+ The runtime provides:
28
22
 
29
23
  - `createAgentHarness(workspaceRoot)`, `run(...)`, `resolveApproval(...)`, `subscribe(...)`, inspection methods, and `stop(...)`
30
24
  - YAML-defined workspace assembly for routing, models, tools, stores, backends, MCP, recovery, and maintenance
@@ -32,6 +26,19 @@ What the runtime provides:
32
26
  - local `resources/tools/` and `resources/skills/` discovery
33
27
  - persisted threads, runs, approvals, events, queue state, and recovery metadata
34
28
 
29
+ The repository-owned default config layer is intentionally full-shaped. The shipped YAML keeps explicit defaults for the important runtime and agent knobs so teams can start from concrete config instead of reverse-engineering adapter behavior from source.
30
+
31
+ The default rule is:
32
+
33
+ - if LangChain v1 or DeepAgents already has the feature, map it in YAML and adapt it internally
34
+ - do not add a new public runtime API unless the problem is truly runtime-owned
35
+
36
+ Boundary documents live in:
37
+
38
+ - `docs/upstream-feature-matrix.md`
39
+ - `docs/product-boundary.md`
40
+ - `docs/feature-checklist.md`
41
+
35
42
  ## Quick Start
36
43
 
37
44
  Install:
@@ -96,14 +103,6 @@ try {
96
103
  - MCP bridge support for agent-declared MCP servers
97
104
  - MCP server support for exposing harness tools outward
98
105
 
99
- ## Design Notes
100
-
101
- - `agent-harness` is not a third agent framework
102
- - LangChain v1 and DeepAgents own agent execution semantics
103
- - `agent-harness` owns workspace assembly, runtime lifecycle, approvals, inspection, recovery, and operations
104
- - when upstream already has the feature, prefer passthrough or light YAML adaptation over a new harness abstraction
105
- - when a feature can be expressed in YAML, prefer YAML over expanding the public API
106
-
107
106
  ## How To Use
108
107
 
109
108
  ### Create A Runtime
@@ -114,7 +113,7 @@ import { AgentHarnessRuntime, createAgentHarness } from "@botbotgo/agent-harness
114
113
  const runtime: AgentHarnessRuntime = await createAgentHarness("/absolute/path/to/workspace");
115
114
  ```
116
115
 
117
- `createAgentHarness(...)` loads one workspace, resolves `resources/`, initializes persistence under `runRoot`, and starts runtime maintenance.
116
+ `createAgentHarness(...)` loads the workspace, resolves `resources/`, initializes persistence under `runRoot`, and starts runtime maintenance.
118
117
 
119
118
  ### Run A Request
120
119
 
@@ -138,7 +137,7 @@ const result = await run(runtime, {
138
137
  });
139
138
  ```
140
139
 
141
- `run(runtime, { ... })` creates or continues a persisted thread and returns `threadId`, `runId`, `state`, and a compact text `output`. Richer upstream results remain available through `outputContent`, `contentBlocks`, and `structuredResponse` without expanding the main facade.
140
+ `run(runtime, { ... })` creates or continues a persisted thread and returns `threadId`, `runId`, `state`, and compact text `output`. Richer upstream result shapes stay available through `outputContent`, `contentBlocks`, and `structuredResponse`.
142
141
 
143
142
  Use `invocation` as the runtime-facing request envelope:
144
143
 
@@ -177,7 +176,7 @@ const result = await run(runtime, {
177
176
  });
178
177
  ```
179
178
 
180
- `subscribe(...)` is a read-only observer surface over stored lifecycle events.
179
+ `subscribe(...)` is the read-only observer surface over stored lifecycle events.
181
180
 
182
181
  The runtime event stream includes:
183
182
 
@@ -213,9 +212,11 @@ if (approval) {
213
212
  }
214
213
  ```
215
214
 
216
- These methods return runtime-facing records, not raw persistence or backend checkpoint objects.
215
+ These methods return runtime-facing records, not raw checkpoint or backend objects.
217
216
 
218
- ### Bridge MCP Servers Into Agents
217
+ ### Expose And Consume MCP
218
+
219
+ Bridge MCP servers into agents:
219
220
 
220
221
  ```yaml
221
222
  apiVersion: agent-harness/v1alpha1
@@ -232,9 +233,7 @@ spec:
232
233
  args: ["./mcp-browser-server.mjs"]
233
234
  ```
234
235
 
235
- The runtime discovers MCP tools, filters them through agent configuration, and exposes them like other tools.
236
-
237
- ### Expose Runtime Tools As An MCP Server
236
+ Expose harness tools as an MCP server:
238
237
 
239
238
  ```ts
240
239
  import { createToolMcpServer, serveToolsOverStdio } from "@botbotgo/agent-harness";
@@ -256,7 +255,7 @@ await stop(runtime);
256
255
  Use Kubernetes-style YAML:
257
256
 
258
257
  - collection files use `apiVersion`, plural `kind`, and `spec: []`
259
- - single-object files use `apiVersion`, singular `kind`, `metadata`, and `spec`
258
+ - singleton files use `apiVersion`, singular `kind`, `metadata`, and `spec`
260
259
 
261
260
  Core workspace files:
262
261
 
@@ -274,19 +273,17 @@ Core workspace files:
274
273
  - `resources/tools/`
275
274
  - `resources/skills/`
276
275
 
277
- There are three configuration layers:
276
+ There are three main configuration layers:
278
277
 
279
278
  - runtime policy in `config/workspace.yaml`
280
279
  - reusable object catalogs in `config/*.yaml`
281
280
  - agent assembly in `config/agents/*.yaml`
282
281
 
283
- The repository-owned default config layer is intentionally full-shaped. The shipped YAML keeps explicit default values for the main runtime knobs so teams can start from concrete config instead of reconstructing adapter defaults from code.
284
-
285
282
  ### `config/workspace.yaml`
286
283
 
287
- Use this file for runtime-level policy shared by the whole workspace.
284
+ Use this file for workspace-wide runtime policy.
288
285
 
289
- Primary fields:
286
+ Important fields:
290
287
 
291
288
  - `runRoot`
292
289
  - `concurrency.maxConcurrentRuns`
@@ -299,13 +296,36 @@ Primary fields:
299
296
  - `recovery.resumeResumingRunsOnStartup`
300
297
  - `recovery.maxRecoveryAttempts`
301
298
 
302
- If `runRoot` is omitted, the runtime defaults to `<workspace-root>/run-data`.
299
+ `recovery.resumeResumingRunsOnStartup` keeps checkpoint resume a runtime-owned lifecycle behavior instead of exposing checkpoint orchestration as public API.
300
+
301
+ Example:
302
+
303
+ ```yaml
304
+ apiVersion: agent-harness/v1alpha1
305
+ kind: Runtime
306
+ metadata:
307
+ name: default
308
+ spec:
309
+ runRoot: ./.agent
310
+ concurrency:
311
+ maxConcurrentRuns: 3
312
+ routing:
313
+ defaultAgentId: orchestra
314
+ modelRouting: false
315
+ maintenance:
316
+ checkpoints:
317
+ enabled: true
318
+ recovery:
319
+ enabled: true
320
+ resumeResumingRunsOnStartup: true
321
+ maxRecoveryAttempts: 3
322
+ ```
303
323
 
304
324
  ### `config/agent-context.md`
305
325
 
306
- Use this file for shared bootstrap context loaded into agents at construction time.
326
+ Use this file for shared bootstrap memory loaded at agent construction time.
307
327
 
308
- Put stable project context here. Do not use it as mutable long-term memory.
328
+ Keep stable project context here. Treat it as startup context, not mutable long-term memory.
309
329
 
310
330
  ### `config/models.yaml`
311
331
 
@@ -354,7 +374,7 @@ spec:
354
374
 
355
375
  ### `config/backends.yaml`
356
376
 
357
- Use reusable DeepAgent backend presets so filesystem and long-term memory topology stays in YAML instead of application code:
377
+ Use reusable DeepAgents backend presets so filesystem and `/memories/*` topology stays in YAML:
358
378
 
359
379
  ```yaml
360
380
  apiVersion: agent-harness/v1alpha1
@@ -377,9 +397,7 @@ spec:
377
397
 
378
398
  Use this file for reusable tool objects.
379
399
 
380
- Supported tool families in the built-in runtime include function tools, backend tools, MCP tools, provider-native tools, and bundles.
381
-
382
- Provider-native tools are declared in YAML and resolved directly to upstream provider tool factories.
400
+ Built-in tool families include function tools, backend tools, MCP tools, bundles, and provider-native tools. Provider-native tools are declared in YAML and resolved directly to upstream factories.
383
401
 
384
402
  ### `config/mcp.yaml`
385
403
 
@@ -387,16 +405,14 @@ Use this file for named MCP server presets.
387
405
 
388
406
  ### `config/agents/*.yaml`
389
407
 
390
- Agents are always declared with `kind: Agent` and `spec.execution.backend`.
408
+ Agents always use `kind: Agent` plus `spec.execution.backend`.
391
409
 
392
- Use two nested sections inside each agent:
410
+ Use two nested sections:
393
411
 
394
412
  - `spec.runtime` for harness-owned runtime placement such as `spec.runtime.runRoot`
395
413
  - `spec.execution` for upstream execution semantics and adapter-facing config
396
414
 
397
- This keeps the public product model small while letting LangChain v1 and DeepAgents concepts pass through with minimal translation.
398
-
399
- Example lightweight host:
415
+ Example direct host:
400
416
 
401
417
  ```yaml
402
418
  apiVersion: agent-harness/v1alpha1
@@ -420,11 +436,15 @@ spec:
420
436
  store:
421
437
  ref: store/default
422
438
  interruptOn: {}
439
+ filesystem:
440
+ rootDir: .
441
+ virtualMode: true
442
+ maxFileSizeMb: 10
423
443
  middleware: []
424
444
  systemPrompt: Answer simple requests directly.
425
445
  ```
426
446
 
427
- Example main execution host:
447
+ Example orchestra host:
428
448
 
429
449
  ```yaml
430
450
  apiVersion: agent-harness/v1alpha1
@@ -453,36 +473,29 @@ spec:
453
473
  interruptOn: {}
454
474
  middleware: []
455
475
  generalPurposeAgent: true
456
- taskDescription: Complete delegated sidecar work and return concise results.
476
+ taskDescription: Complete delegated sidecar work and return concise results without bloating the parent context.
457
477
  ```
458
478
 
459
- For backend-specific agent options, prefer the upstream concept directly inside `spec.execution.config`. Upstream feature coverage is tracked in [docs/upstream-feature-matrix.md](docs/upstream-feature-matrix.md).
460
-
461
- ### `resources/`
462
-
463
- Use `resources/` for executable local extensions:
464
-
465
- - `resources/tools/` for tool modules
466
- - `resources/skills/` for SKILL packages
467
-
468
- Tool modules are discovered from `resources/tools/*.js`, `resources/tools/*.mjs`, and `resources/tools/*.cjs`.
479
+ For backend-specific options, prefer the upstream concept directly inside `spec.execution.config`. Upstream feature coverage is tracked in [docs/upstream-feature-matrix.md](docs/upstream-feature-matrix.md).
469
480
 
470
481
  ## Design Notes
471
482
 
483
+ - `agent-harness` is not a third agent framework
472
484
  - public runtime contract stays generic and small
473
485
  - application-level orchestration and lifecycle management stays in the harness
474
486
  - upstream LangChain v1 and DeepAgents concepts should be expressed as directly as possible in YAML
475
- - recovery, approvals, threads, runs, and events are runtime concepts, not backend-specific escape hatches
476
- - backend implementation details should stay internal unless product requirements force exposure
477
- - new LangChain v1 or DeepAgents public config should land in YAML passthrough and compatibility tests before adding new public runtime APIs
487
+ - when a feature can be expressed in YAML, prefer YAML over expanding the public API
488
+ - recovery, approvals, threads, runs, and events are runtime concepts, not backend escape hatches
489
+ - new LangChain v1 or DeepAgents config should land in YAML mapping and tests before adding public runtime APIs
478
490
 
479
- In short: `agent-harness` is a public runtime contract generic enough to survive backend changes, while the deep execution semantics stay upstream.
491
+ In short, the product model stays stable while the execution semantics remain upstream-owned.
480
492
 
481
493
  ## API Summary
482
494
 
483
495
  Primary exports:
484
496
 
485
497
  - `createAgentHarness`
498
+ - `AgentHarnessRuntime`
486
499
  - `run`
487
500
  - `resolveApproval`
488
501
  - `subscribe`
@@ -46,7 +46,25 @@ spec:
46
46
  ref: store/default
47
47
  # Upstream execution feature: no declarative HITL tool routing by default.
48
48
  interruptOn: {}
49
+ # Upstream execution feature: filesystem middleware settings for LangChain v1 agents.
50
+ # This only becomes active when `middleware` includes `{ kind: filesystem }`, or when
51
+ # automatic upstream middleware such as skills or memory need a filesystem backend.
52
+ # Keep the default root inside the workspace so file-aware middleware stays bounded.
53
+ filesystem:
54
+ rootDir: .
55
+ virtualMode: true
56
+ maxFileSizeMb: 10
49
57
  # Upstream execution feature: no extra declarative middleware beyond the runtime's automatic injections.
58
+ # Common upstream middleware kinds that this harness can compile directly from YAML:
59
+ # - `filesystem`
60
+ # - `patchToolCalls`
61
+ # - `summarization`
62
+ # - `dynamicSystemPrompt`
63
+ # - `humanInTheLoop`
64
+ # - `todoList`
65
+ # - `pii`, `piiRedaction`
66
+ #
67
+ # Keep the default empty so the lightweight direct host stays minimal.
50
68
  middleware: []
51
69
  # Upstream execution feature: system prompt for the lightweight direct-response host.
52
70
  # This prompt should keep the agent focused on:
@@ -66,6 +66,16 @@ spec:
66
66
  # Upstream execution feature: no extra declarative HITL rules by default.
67
67
  interruptOn: {}
68
68
  # Upstream execution feature: no extra declarative middleware beyond upstream deepagents defaults by default.
69
+ # Common upstream middleware kinds that this harness can compile directly from YAML:
70
+ # - `patchToolCalls`
71
+ # - `summarization`
72
+ # - `dynamicSystemPrompt`
73
+ # - `humanInTheLoop`
74
+ # - `todoList`
75
+ # - `pii`, `piiRedaction`
76
+ #
77
+ # DeepAgents already includes its own filesystem, planning, subagent, and memory semantics.
78
+ # Keep this list empty unless you are intentionally adding extra upstream middleware on top.
69
79
  middleware: []
70
80
  # Upstream execution feature: keep the built-in general-purpose subagent enabled.
71
81
  generalPurposeAgent: true
@@ -1 +1 @@
1
- export declare const AGENT_HARNESS_VERSION = "0.0.54";
1
+ export declare const AGENT_HARNESS_VERSION = "0.0.55";
@@ -1 +1 @@
1
- export const AGENT_HARNESS_VERSION = "0.0.54";
1
+ export const AGENT_HARNESS_VERSION = "0.0.55";
@@ -525,6 +525,8 @@ export class AgentRuntimeAdapter {
525
525
  async resolveMiddleware(binding, interruptOn) {
526
526
  const declarativeMiddleware = await resolveDeclaredMiddleware(getBindingMiddlewareConfigs(binding), {
527
527
  resolveModel: (model) => this.resolveModel(model),
528
+ resolveBackend: (resolvedBinding) => this.options.backendResolver?.(resolvedBinding ?? binding),
529
+ resolveFilesystemBackend: (resolvedBinding) => this.resolveFilesystemBackend(resolvedBinding ?? binding),
528
530
  resolveCustom: this.options.declaredMiddlewareResolver,
529
531
  binding,
530
532
  });
@@ -575,6 +577,14 @@ export class AgentRuntimeAdapter {
575
577
  contextSchema: subagent.contextSchema,
576
578
  middleware: (await resolveDeclaredMiddleware(subagent.middleware, {
577
579
  resolveModel: (model) => this.resolveModel(model),
580
+ resolveBackend: (resolvedBinding) => {
581
+ const targetBinding = resolvedBinding ?? binding;
582
+ return targetBinding ? this.options.backendResolver?.(targetBinding) : undefined;
583
+ },
584
+ resolveFilesystemBackend: (resolvedBinding) => {
585
+ const targetBinding = resolvedBinding ?? binding;
586
+ return targetBinding ? this.resolveFilesystemBackend(targetBinding) : undefined;
587
+ },
578
588
  resolveCustom: this.options.declaredMiddlewareResolver,
579
589
  binding,
580
590
  })),
@@ -3,12 +3,17 @@ type MiddlewareConfig = Record<string, unknown>;
3
3
  type MiddlewareFactoryContext = {
4
4
  config: MiddlewareConfig;
5
5
  resolveModel: (model: CompiledModel) => Promise<unknown>;
6
+ resolveBackend?: () => unknown;
7
+ resolveFilesystemBackend?: () => unknown;
8
+ binding?: CompiledAgentBinding;
6
9
  };
7
10
  type MiddlewareFactory = (context: MiddlewareFactoryContext) => Promise<unknown | unknown[] | null | undefined>;
8
11
  export declare const DECLARATIVE_MIDDLEWARE_REGISTRY: Record<string, MiddlewareFactory>;
9
12
  export declare const SUPPORTED_DECLARATIVE_MIDDLEWARE_KINDS: readonly string[];
10
13
  export declare function resolveDeclaredMiddleware(middlewareConfigs: unknown[] | undefined, options: {
11
14
  resolveModel: (model: CompiledModel) => Promise<unknown>;
15
+ resolveBackend?: (binding?: CompiledAgentBinding) => unknown;
16
+ resolveFilesystemBackend?: (binding?: CompiledAgentBinding) => unknown;
12
17
  resolveCustom?: (input: {
13
18
  kind: string;
14
19
  config: Record<string, unknown>;
@@ -1,4 +1,5 @@
1
- import { anthropicPromptCachingMiddleware, contextEditingMiddleware, humanInTheLoopMiddleware, llmToolSelectorMiddleware, modelCallLimitMiddleware, modelFallbackMiddleware, modelRetryMiddleware, openAIModerationMiddleware, piiMiddleware, summarizationMiddleware, todoListMiddleware, toolCallLimitMiddleware, toolEmulatorMiddleware, toolRetryMiddleware, } from "langchain";
1
+ import { anthropicPromptCachingMiddleware, contextEditingMiddleware, dynamicSystemPromptMiddleware, humanInTheLoopMiddleware, llmToolSelectorMiddleware, modelCallLimitMiddleware, modelFallbackMiddleware, modelRetryMiddleware, openAIModerationMiddleware, piiMiddleware, piiRedactionMiddleware, summarizationMiddleware, todoListMiddleware, toolCallLimitMiddleware, toolEmulatorMiddleware, toolRetryMiddleware, } from "langchain";
2
+ import { createFilesystemMiddleware, createPatchToolCallsMiddleware, createSummarizationMiddleware as createDeepAgentSummarizationMiddleware, } from "deepagents";
2
3
  function asMiddlewareConfig(value) {
3
4
  return typeof value === "object" && value !== null && !Array.isArray(value) ? { ...value } : null;
4
5
  }
@@ -26,6 +27,18 @@ async function resolveReferencedModelList(values, options) {
26
27
  return Promise.all(values.map((value) => resolveReferencedModel(value, options)));
27
28
  }
28
29
  async function createSummarizationMiddleware({ config, resolveModel }) {
30
+ if (config.provider === "deepagents") {
31
+ const runtimeConfig = { ...config };
32
+ runtimeConfig.model = await resolveReferencedModel(runtimeConfig.model, { resolveModel });
33
+ if (runtimeConfig.model === undefined) {
34
+ throw new Error("deepagents summarization middleware requires model or modelRef");
35
+ }
36
+ if (runtimeConfig.backend === undefined) {
37
+ throw new Error("deepagents summarization middleware requires backend");
38
+ }
39
+ delete runtimeConfig.provider;
40
+ return createDeepAgentSummarizationMiddleware(runtimeConfig);
41
+ }
29
42
  const runtimeConfig = { ...config };
30
43
  runtimeConfig.model = await resolveReferencedModel(runtimeConfig.model, { resolveModel });
31
44
  if (runtimeConfig.model === undefined) {
@@ -33,6 +46,17 @@ async function createSummarizationMiddleware({ config, resolveModel }) {
33
46
  }
34
47
  return summarizationMiddleware(runtimeConfig);
35
48
  }
49
+ async function createBindingAwareSummarizationMiddleware(context) {
50
+ const runtimeConfig = { ...context.config };
51
+ if (context.binding?.agent.executionMode === "deepagent") {
52
+ runtimeConfig.provider = "deepagents";
53
+ runtimeConfig.backend ??= context.resolveBackend?.() ?? context.resolveFilesystemBackend?.();
54
+ }
55
+ return createSummarizationMiddleware({
56
+ ...context,
57
+ config: runtimeConfig,
58
+ });
59
+ }
36
60
  async function createLlmToolSelectorMiddleware({ config, resolveModel }) {
37
61
  const runtimeConfig = { ...config };
38
62
  runtimeConfig.model = await resolveReferencedModel(runtimeConfig.model, { resolveModel });
@@ -54,8 +78,15 @@ async function createPiiDeclarativeMiddleware({ config }) {
54
78
  const { piiType: _piiType, ...piiOptions } = config;
55
79
  return piiMiddleware(piiType, piiOptions);
56
80
  }
81
+ async function createFilesystemDeclarativeMiddleware({ config, resolveFilesystemBackend }) {
82
+ const runtimeConfig = { ...config };
83
+ runtimeConfig.backend ??= resolveFilesystemBackend?.();
84
+ return createFilesystemMiddleware(runtimeConfig);
85
+ }
57
86
  export const DECLARATIVE_MIDDLEWARE_REGISTRY = {
58
- summarization: createSummarizationMiddleware,
87
+ filesystem: createFilesystemDeclarativeMiddleware,
88
+ patchToolCalls: async () => createPatchToolCallsMiddleware(),
89
+ summarization: createBindingAwareSummarizationMiddleware,
59
90
  llmToolSelector: createLlmToolSelectorMiddleware,
60
91
  modelRetry: async ({ config }) => modelRetryMiddleware(config),
61
92
  modelFallback: createModelFallbackDeclarativeMiddleware,
@@ -64,10 +95,12 @@ export const DECLARATIVE_MIDDLEWARE_REGISTRY = {
64
95
  modelCallLimit: async ({ config }) => modelCallLimitMiddleware(config),
65
96
  todoList: async ({ config }) => todoListMiddleware(config),
66
97
  contextEditing: async ({ config }) => contextEditingMiddleware(config),
98
+ dynamicSystemPrompt: async ({ config }) => dynamicSystemPromptMiddleware(config),
67
99
  toolEmulator: async ({ config }) => toolEmulatorMiddleware(config),
68
100
  humanInTheLoop: async ({ config }) => humanInTheLoopMiddleware(config),
69
101
  openAIModeration: async ({ config }) => openAIModerationMiddleware(config),
70
102
  pii: createPiiDeclarativeMiddleware,
103
+ piiRedaction: async ({ config }) => piiRedactionMiddleware(config),
71
104
  anthropicPromptCaching: async ({ config }) => anthropicPromptCachingMiddleware(config),
72
105
  };
73
106
  export const SUPPORTED_DECLARATIVE_MIDDLEWARE_KINDS = Object.freeze(Object.keys(DECLARATIVE_MIDDLEWARE_REGISTRY).sort());
@@ -85,6 +118,9 @@ export async function resolveDeclaredMiddleware(middlewareConfigs, options) {
85
118
  const resolvedBuiltin = await registeredFactory({
86
119
  config: runtimeConfig,
87
120
  resolveModel: options.resolveModel,
121
+ resolveBackend: () => options.resolveBackend?.(options.binding),
122
+ resolveFilesystemBackend: () => options.resolveFilesystemBackend?.(options.binding),
123
+ binding: options.binding,
88
124
  });
89
125
  if (Array.isArray(resolvedBuiltin)) {
90
126
  resolved.push(...resolvedBuiltin);
@@ -41,6 +41,9 @@ function validateMiddlewareConfig(agent) {
41
41
  if (kind === "humanInTheLoop" && typeof typed.interruptOn !== "object") {
42
42
  throw new Error(`Agent ${agent.id} humanInTheLoop middleware requires interruptOn`);
43
43
  }
44
+ if (kind === "filesystem" && agent.executionMode === "deepagent") {
45
+ throw new Error(`Agent ${agent.id} cannot use filesystem middleware with DeepAgents; configure filesystem behavior through the deepagent backend instead`);
46
+ }
44
47
  if (kind === "pii" && typeof typed.piiType !== "string") {
45
48
  throw new Error(`Agent ${agent.id} pii middleware requires piiType`);
46
49
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botbotgo/agent-harness",
3
- "version": "0.0.55",
3
+ "version": "0.0.56",
4
4
  "description": "Workspace runtime for multi-agent applications",
5
5
  "type": "module",
6
6
  "packageManager": "npm@10.9.2",