@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 +70 -57
- package/dist/config/agents/direct.yaml +18 -0
- package/dist/config/agents/orchestra.yaml +10 -0
- package/dist/package-version.d.ts +1 -1
- package/dist/package-version.js +1 -1
- package/dist/runtime/agent-runtime-adapter.js +10 -0
- package/dist/runtime/declared-middleware.d.ts +5 -0
- package/dist/runtime/declared-middleware.js +38 -2
- package/dist/workspace/validate.js +3 -0
- package/package.json +1 -1
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
215
|
+
These methods return runtime-facing records, not raw checkpoint or backend objects.
|
|
217
216
|
|
|
218
|
-
###
|
|
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
|
-
|
|
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
|
-
-
|
|
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
|
|
284
|
+
Use this file for workspace-wide runtime policy.
|
|
288
285
|
|
|
289
|
-
|
|
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
|
-
|
|
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
|
|
326
|
+
Use this file for shared bootstrap memory loaded at agent construction time.
|
|
307
327
|
|
|
308
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
408
|
+
Agents always use `kind: Agent` plus `spec.execution.backend`.
|
|
391
409
|
|
|
392
|
-
Use two nested sections
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
-
|
|
476
|
-
-
|
|
477
|
-
- new LangChain v1 or DeepAgents
|
|
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
|
|
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.
|
|
1
|
+
export declare const AGENT_HARNESS_VERSION = "0.0.55";
|
package/dist/package-version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const AGENT_HARNESS_VERSION = "0.0.
|
|
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
|
-
|
|
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
|
}
|