@botbotgo/agent-harness 0.0.50 → 0.0.52
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 +90 -45
- package/dist/config/agents/direct.yaml +36 -34
- package/dist/config/agents/orchestra.yaml +69 -75
- package/dist/config/backends.yaml +16 -0
- package/dist/contracts/types.d.ts +1 -0
- package/dist/package-version.d.ts +1 -1
- package/dist/package-version.js +1 -1
- package/dist/runtime/agent-runtime-adapter.js +14 -3
- package/dist/workspace/agent-binding-compiler.js +19 -3
- package/dist/workspace/object-loader.js +93 -55
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -6,21 +6,22 @@
|
|
|
6
6
|
|
|
7
7
|
It is not a new agent framework. It is the runtime layer around LangChain v1 and DeepAgents that turns one workspace into one operable application runtime.
|
|
8
8
|
|
|
9
|
-
The
|
|
9
|
+
The boundary is strict:
|
|
10
10
|
|
|
11
11
|
- LangChain v1 and DeepAgents own agent execution semantics
|
|
12
|
-
- `agent-harness` owns application
|
|
12
|
+
- `agent-harness` owns application-level orchestration and lifecycle management
|
|
13
13
|
|
|
14
14
|
That means:
|
|
15
15
|
|
|
16
16
|
- public API stays small
|
|
17
|
-
- complex
|
|
18
|
-
-
|
|
17
|
+
- complex setup and operating policy live in YAML
|
|
18
|
+
- application-level orchestration and lifecycle management stays in the harness
|
|
19
|
+
- runtime lifecycle stays stable even if backend implementations change
|
|
19
20
|
|
|
20
21
|
What the runtime provides:
|
|
21
22
|
|
|
22
23
|
- `createAgentHarness(...)`, `run(...)`, `subscribe(...)`, inspection methods, and `stop(...)`
|
|
23
|
-
- YAML-defined workspace assembly for routing, models, tools, stores, MCP, recovery, and maintenance
|
|
24
|
+
- YAML-defined workspace assembly for routing, models, tools, stores, backends, MCP, recovery, and maintenance
|
|
24
25
|
- backend-adapted execution with current LangChain v1 and DeepAgents adapters
|
|
25
26
|
- local `resources/tools/` and `resources/skills/` discovery
|
|
26
27
|
- persisted threads, runs, approvals, events, queue state, and recovery metadata
|
|
@@ -44,6 +45,7 @@ your-workspace/
|
|
|
44
45
|
embedding-models.yaml
|
|
45
46
|
vector-stores.yaml
|
|
46
47
|
stores.yaml
|
|
48
|
+
backends.yaml
|
|
47
49
|
tools.yaml
|
|
48
50
|
mcp.yaml
|
|
49
51
|
agents/
|
|
@@ -201,11 +203,11 @@ metadata:
|
|
|
201
203
|
spec:
|
|
202
204
|
execution:
|
|
203
205
|
backend: deepagent
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
206
|
+
modelRef: model/default
|
|
207
|
+
mcpServers:
|
|
208
|
+
- name: browser
|
|
209
|
+
command: node
|
|
210
|
+
args: ["./mcp-browser-server.mjs"]
|
|
209
211
|
```
|
|
210
212
|
|
|
211
213
|
The runtime discovers MCP tools, filters them through agent configuration, and exposes them like other tools.
|
|
@@ -242,6 +244,7 @@ Core workspace files:
|
|
|
242
244
|
- `config/embedding-models.yaml`
|
|
243
245
|
- `config/vector-stores.yaml`
|
|
244
246
|
- `config/stores.yaml`
|
|
247
|
+
- `config/backends.yaml`
|
|
245
248
|
- `config/tools.yaml`
|
|
246
249
|
- `config/mcp.yaml`
|
|
247
250
|
- `config/agents/direct.yaml`
|
|
@@ -323,6 +326,38 @@ spec:
|
|
|
323
326
|
checkpointerKind: MemorySaver
|
|
324
327
|
```
|
|
325
328
|
|
|
329
|
+
Built-in store kinds today:
|
|
330
|
+
|
|
331
|
+
- `FileStore`
|
|
332
|
+
- `InMemoryStore`
|
|
333
|
+
|
|
334
|
+
Built-in checkpointer kinds today:
|
|
335
|
+
|
|
336
|
+
- `MemorySaver`
|
|
337
|
+
- `FileCheckpointer`
|
|
338
|
+
- `SqliteSaver`
|
|
339
|
+
|
|
340
|
+
If you need other store or checkpointer implementations, inject them through runtime resolvers instead of treating them as built-in harness features.
|
|
341
|
+
|
|
342
|
+
### `config/backends.yaml`
|
|
343
|
+
|
|
344
|
+
Use reusable DeepAgent backend presets so filesystem and long-term memory topology stays in YAML instead of application code:
|
|
345
|
+
|
|
346
|
+
```yaml
|
|
347
|
+
apiVersion: agent-harness/v1alpha1
|
|
348
|
+
kind: Backends
|
|
349
|
+
spec:
|
|
350
|
+
- kind: Backend
|
|
351
|
+
name: default
|
|
352
|
+
backendKind: CompositeBackend
|
|
353
|
+
state:
|
|
354
|
+
kind: VfsSandbox
|
|
355
|
+
timeout: 600
|
|
356
|
+
routes:
|
|
357
|
+
/memories/:
|
|
358
|
+
kind: StoreBackend
|
|
359
|
+
```
|
|
360
|
+
|
|
326
361
|
### `config/tools.yaml`
|
|
327
362
|
|
|
328
363
|
Use this file for reusable tool objects.
|
|
@@ -347,6 +382,13 @@ Use this file for named MCP server presets.
|
|
|
347
382
|
|
|
348
383
|
Agents are always declared with `kind: Agent` and `spec.execution.backend`.
|
|
349
384
|
|
|
385
|
+
Use two nested sections inside each agent:
|
|
386
|
+
|
|
387
|
+
- `spec.runtime` for harness-owned runtime placement such as `spec.runtime.runRoot`
|
|
388
|
+
- `spec.execution` for upstream execution semantics and adapter-facing config
|
|
389
|
+
|
|
390
|
+
This keeps the public product model small while letting LangChain v1 and DeepAgents concepts pass through with minimal translation.
|
|
391
|
+
|
|
350
392
|
Example lightweight host:
|
|
351
393
|
|
|
352
394
|
```yaml
|
|
@@ -357,10 +399,11 @@ metadata:
|
|
|
357
399
|
spec:
|
|
358
400
|
execution:
|
|
359
401
|
backend: langchain-v1
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
402
|
+
modelRef: model/default
|
|
403
|
+
config:
|
|
404
|
+
checkpointer:
|
|
405
|
+
ref: checkpointer/default
|
|
406
|
+
systemPrompt: Answer simple requests directly.
|
|
364
407
|
```
|
|
365
408
|
|
|
366
409
|
Example main execution host:
|
|
@@ -373,21 +416,16 @@ metadata:
|
|
|
373
416
|
spec:
|
|
374
417
|
execution:
|
|
375
418
|
backend: deepagent
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
kind: VfsSandbox
|
|
387
|
-
timeout: 600
|
|
388
|
-
routes:
|
|
389
|
-
/memories/:
|
|
390
|
-
kind: StoreBackend
|
|
419
|
+
modelRef: model/default
|
|
420
|
+
memory:
|
|
421
|
+
- path: config/agent-context.md
|
|
422
|
+
config:
|
|
423
|
+
store:
|
|
424
|
+
ref: store/default
|
|
425
|
+
checkpointer:
|
|
426
|
+
ref: checkpointer/default
|
|
427
|
+
backend:
|
|
428
|
+
ref: backend/default
|
|
391
429
|
```
|
|
392
430
|
|
|
393
431
|
Client-configurable agent fields include:
|
|
@@ -395,21 +433,29 @@ Client-configurable agent fields include:
|
|
|
395
433
|
- `metadata.name`
|
|
396
434
|
- `metadata.description`
|
|
397
435
|
- `spec.execution.backend`
|
|
398
|
-
- `spec.
|
|
399
|
-
- `spec.
|
|
400
|
-
- `spec.tools`
|
|
401
|
-
- `spec.skills`
|
|
402
|
-
- `spec.memory`
|
|
403
|
-
- `spec.
|
|
404
|
-
- `spec.
|
|
405
|
-
- `spec.
|
|
406
|
-
- `spec.
|
|
407
|
-
- `spec.
|
|
408
|
-
- `spec.
|
|
409
|
-
- `spec.
|
|
410
|
-
- `spec.
|
|
411
|
-
|
|
412
|
-
|
|
436
|
+
- `spec.runtime.runRoot`
|
|
437
|
+
- `spec.execution.modelRef`
|
|
438
|
+
- `spec.execution.tools`
|
|
439
|
+
- `spec.execution.skills`
|
|
440
|
+
- `spec.execution.memory`
|
|
441
|
+
- `spec.execution.subagents`
|
|
442
|
+
- `spec.execution.mcpServers`
|
|
443
|
+
- `spec.execution.config.systemPrompt`
|
|
444
|
+
- `spec.execution.config.checkpointer`
|
|
445
|
+
- `spec.execution.config.store`
|
|
446
|
+
- `spec.execution.config.backend`
|
|
447
|
+
- `spec.execution.config.middleware`
|
|
448
|
+
- `spec.execution.config.responseFormat`
|
|
449
|
+
- `spec.execution.config.contextSchema`
|
|
450
|
+
- `spec.execution.config.stateSchema`
|
|
451
|
+
- `spec.execution.config.interruptOn`
|
|
452
|
+
- `spec.execution.config.filesystem`
|
|
453
|
+
- `spec.execution.config.taskDescription`
|
|
454
|
+
- `spec.execution.config.generalPurposeAgent`
|
|
455
|
+
- `spec.execution.config.includeAgentName`
|
|
456
|
+
- `spec.execution.config.version`
|
|
457
|
+
|
|
458
|
+
For backend-specific agent options, prefer passing the upstream concept directly inside `spec.execution.config`. The loader keeps a small stable product shape, but it also preserves adapter-facing passthrough fields so new LangChain v1 or DeepAgents parameters can flow into adapters without expanding the public API surface.
|
|
413
459
|
|
|
414
460
|
### `resources/`
|
|
415
461
|
|
|
@@ -431,7 +477,6 @@ SKILL packages are discovered from `resources/skills/` and attached to agents th
|
|
|
431
477
|
- upstream LangChain v1 and DeepAgents concepts should be expressed as directly as possible in YAML
|
|
432
478
|
- recovery, approvals, threads, runs, and events are runtime concepts, not backend-specific escape hatches
|
|
433
479
|
- backend implementation details should stay internal unless product requirements force exposure
|
|
434
|
-
- application-level orchestration and lifecycle management stays in the harness
|
|
435
480
|
|
|
436
481
|
In short: `agent-harness` is a public runtime contract generic enough to survive backend changes, while the deep execution semantics stay upstream.
|
|
437
482
|
|
|
@@ -9,41 +9,43 @@ metadata:
|
|
|
9
9
|
# agent-harness feature: human-readable summary for inventory and UI.
|
|
10
10
|
description: Manual low-latency host for direct answers and lightweight inventory lookup. Do not use it as the default executor for tool-heavy or specialist-shaped tasks.
|
|
11
11
|
spec:
|
|
12
|
-
|
|
13
|
-
# Current backend adapter for this host profile.
|
|
14
|
-
backend: langchain-v1
|
|
12
|
+
runtime: {}
|
|
15
13
|
# =====================
|
|
16
14
|
# Runtime Agent Features
|
|
17
15
|
# =====================
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
16
|
+
execution:
|
|
17
|
+
# Current backend adapter for this host profile.
|
|
18
|
+
backend: langchain-v1
|
|
19
|
+
# Upstream execution feature: model ref for the underlying LLM used by the direct-response agent.
|
|
20
|
+
# This should point at a cheap, fast, general-purpose chat model, because `direct` is intended
|
|
21
|
+
# to be the low-latency path for simple requests.
|
|
22
|
+
modelRef: model/default
|
|
23
|
+
config:
|
|
24
|
+
# Runtime execution feature: checkpointer config passed into the selected backend adapter.
|
|
25
|
+
# Even the lightweight direct path can benefit from resumable state during interactive use.
|
|
26
|
+
# Available `kind` options in this harness: `FileCheckpointer`, `MemorySaver`, `SqliteSaver`.
|
|
27
|
+
# `path` is only used by `FileCheckpointer` and `SqliteSaver`; omit it for `MemorySaver`.
|
|
28
|
+
checkpointer:
|
|
29
|
+
ref: checkpointer/default
|
|
30
|
+
# Upstream execution feature: system prompt for the lightweight direct-response host.
|
|
31
|
+
# This prompt should keep the agent focused on:
|
|
32
|
+
# - answering simple requests in one turn
|
|
33
|
+
# - staying lightweight instead of planning or orchestrating
|
|
34
|
+
# - avoiding specialist-style decomposition unless the caller explicitly switches agents
|
|
35
|
+
#
|
|
36
|
+
# The direct host is intentionally narrower than the orchestra host:
|
|
37
|
+
# - `direct` is optimized for latency and straightforward completion
|
|
38
|
+
# - `orchestra` is optimized for multi-step work, tools, delegation, and specialist use
|
|
39
|
+
#
|
|
40
|
+
# Keep this prompt biased toward concise, self-contained answers. If richer routing policy is
|
|
41
|
+
# needed for choosing between host agents, configure that separately via `Runtime.spec.routing`
|
|
42
|
+
# rather than overloading the direct host prompt with classifier behavior.
|
|
43
|
+
systemPrompt: |-
|
|
44
|
+
You are the direct agent.
|
|
43
45
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
This is a manual low-latency host.
|
|
47
|
+
Answer simple requests directly.
|
|
48
|
+
Keep the path lightweight.
|
|
49
|
+
Do not delegate.
|
|
50
|
+
Do not perform broad multi-step execution.
|
|
51
|
+
Do not behave like the default execution host.
|
|
@@ -9,86 +9,80 @@ metadata:
|
|
|
9
9
|
# agent-harness feature: human-readable summary for inventory and UI.
|
|
10
10
|
description: Default execution host. Answer directly when possible, use local tools and skills first, and delegate only when a specialist is a better fit. Not a reflex delegation-only planner.
|
|
11
11
|
spec:
|
|
12
|
-
|
|
13
|
-
# Current backend adapter for this host profile.
|
|
14
|
-
backend: deepagent
|
|
12
|
+
runtime: {}
|
|
15
13
|
# =====================
|
|
16
14
|
# Runtime Agent Features
|
|
17
15
|
# =====================
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
#
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
# This becomes the top-level instruction block for the selected execution backend and should hold the
|
|
63
|
-
# agent's durable role, priorities, and behavioral guardrails rather than bulky project facts.
|
|
64
|
-
systemPrompt: |-
|
|
65
|
-
You are the orchestra agent.
|
|
16
|
+
execution:
|
|
17
|
+
# Current backend adapter for this host profile.
|
|
18
|
+
backend: deepagent
|
|
19
|
+
# Upstream execution feature: model ref for the underlying LLM used by this execution host.
|
|
20
|
+
modelRef: model/default
|
|
21
|
+
memory:
|
|
22
|
+
# Upstream execution feature: bootstrap memory sources supplied to the selected backend at construction time.
|
|
23
|
+
# These paths resolve relative to the workspace root unless they are already absolute.
|
|
24
|
+
# Treat this as agent-owned startup context, not as a dynamic long-term memory sink:
|
|
25
|
+
# - keep `systemPrompt` for stable role, boundaries, and hard behavioral rules
|
|
26
|
+
# - use `memory:` for stable project knowledge, operating conventions, and shared or agent-specific context files
|
|
27
|
+
# - use `/memories/*` via the backend/store below for durable knowledge learned from prior runs
|
|
28
|
+
# - use the harness checkpointer for resumable graph state for an in-flight run
|
|
29
|
+
# Updating these files changes future agent constructions, but they are still bootstrap inputs rather than
|
|
30
|
+
# self-updating runtime memory.
|
|
31
|
+
- path: config/agent-context.md
|
|
32
|
+
config:
|
|
33
|
+
# Runtime execution feature: checkpointer config passed into the selected backend adapter.
|
|
34
|
+
# This persists resumable graph state for this agent.
|
|
35
|
+
# Available `kind` options in this harness: `FileCheckpointer`, `MemorySaver`, `SqliteSaver`.
|
|
36
|
+
# `path` is only used by `FileCheckpointer` and `SqliteSaver`; omit it for `MemorySaver`.
|
|
37
|
+
checkpointer:
|
|
38
|
+
# ref: checkpointer/sqlite
|
|
39
|
+
ref: checkpointer/default
|
|
40
|
+
# Upstream execution feature: store config passed into the selected backend adapter.
|
|
41
|
+
# In the default deepagent adapter this is the LangGraph store used by `StoreBackend` routes.
|
|
42
|
+
# Built-in kinds in this harness today: `FileStore`, `InMemoryStore`.
|
|
43
|
+
# Other store kinds should flow through a custom runtime resolver instead of being claimed as built in.
|
|
44
|
+
store:
|
|
45
|
+
ref: store/default
|
|
46
|
+
# Upstream execution feature: backend config passed into the selected backend adapter.
|
|
47
|
+
# Prefer a reusable backend preset via `ref` so backend topology stays declarative and reusable in YAML.
|
|
48
|
+
# The default preset keeps DeepAgent execution semantics upstream-owned:
|
|
49
|
+
# - workspace execution uses a lightweight VFS sandbox
|
|
50
|
+
# - long-term memory under `/memories/*` uses `StoreBackend`
|
|
51
|
+
# - `CompositeBackend` composes those backend instances together
|
|
52
|
+
# The harness injects the resolved store/checkpointer instances, but the backend topology itself stays upstream-shaped.
|
|
53
|
+
backend:
|
|
54
|
+
ref: backend/default
|
|
55
|
+
# Upstream execution feature: system prompt for the orchestration host.
|
|
56
|
+
# This becomes the top-level instruction block for the selected execution backend and should hold the
|
|
57
|
+
# agent's durable role, priorities, and behavioral guardrails rather than bulky project facts.
|
|
58
|
+
systemPrompt: |-
|
|
59
|
+
You are the orchestra agent.
|
|
66
60
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
61
|
+
You are the default execution host.
|
|
62
|
+
Try to finish the request yourself before delegating.
|
|
63
|
+
Use your own tools first when they are sufficient.
|
|
64
|
+
Use your own skills first when they are sufficient.
|
|
65
|
+
Delegate only when a specialist is a clearly better fit or when your own tools and skills are not enough.
|
|
66
|
+
If neither you nor any suitable specialist can do the work, say so plainly.
|
|
73
67
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
68
|
+
Do not delegate by reflex.
|
|
69
|
+
Do not delegate just because a task has multiple steps.
|
|
70
|
+
Do not delegate when a direct answer or a short local tool pass is enough.
|
|
71
|
+
Keep the critical path local when immediate progress depends on it; otherwise delegate bounded sidecar work to
|
|
72
|
+
the most appropriate specialist.
|
|
79
73
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
74
|
+
Use your own tools for lightweight discovery, inventory, and context gathering.
|
|
75
|
+
Prefer the structured checkout, indexing, retrieval, and inventory tools that are already attached to you over
|
|
76
|
+
ad hoc shell work when those tools are sufficient.
|
|
77
|
+
Use the attached specialist descriptions as the source of truth for what each specialist is for.
|
|
78
|
+
Do not delegate to a specialist whose description does not clearly match the task.
|
|
79
|
+
Integrate specialist results into one coherent answer and do not claim checks or evidence you did not obtain.
|
|
86
80
|
|
|
87
|
-
|
|
88
|
-
|
|
81
|
+
When the user asks about available tools, skills, or agents, use the attached inventory tools instead of
|
|
82
|
+
inferring from memory.
|
|
89
83
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
84
|
+
Write to `/memories/*` only when the information is durable, reusable across future runs or threads, and likely
|
|
85
|
+
to matter again: user preferences, project conventions, confirmed decisions, reusable summaries, and stable
|
|
86
|
+
ownership facts are good candidates.
|
|
87
|
+
Do not store transient reasoning, temporary plans, scratch work, one-off search results, or intermediate
|
|
88
|
+
outputs that can be cheaply recomputed.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# agent-harness feature: schema version for reusable backend presets.
|
|
2
|
+
apiVersion: agent-harness/v1alpha1
|
|
3
|
+
# agent-harness feature: object type for named DeepAgent backend presets.
|
|
4
|
+
kind: Backends
|
|
5
|
+
spec:
|
|
6
|
+
# upstream deepagents feature: default hybrid backend for workspace execution plus durable /memories storage.
|
|
7
|
+
- kind: Backend
|
|
8
|
+
name: default
|
|
9
|
+
description: Default DeepAgent backend preset with a virtual workspace sandbox and durable /memories storage.
|
|
10
|
+
backendKind: CompositeBackend
|
|
11
|
+
state:
|
|
12
|
+
kind: VfsSandbox
|
|
13
|
+
timeout: 600
|
|
14
|
+
routes:
|
|
15
|
+
/memories/:
|
|
16
|
+
kind: StoreBackend
|
|
@@ -95,6 +95,7 @@ export type LangChainAgentParams = {
|
|
|
95
95
|
stateSchema?: unknown;
|
|
96
96
|
responseFormat?: unknown;
|
|
97
97
|
contextSchema?: unknown;
|
|
98
|
+
filesystem?: Record<string, unknown>;
|
|
98
99
|
middleware?: Array<Record<string, unknown>>;
|
|
99
100
|
passthrough?: Record<string, unknown>;
|
|
100
101
|
subagents?: CompiledSubAgent[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const AGENT_HARNESS_VERSION = "0.0.
|
|
1
|
+
export declare const AGENT_HARNESS_VERSION = "0.0.51";
|
package/dist/package-version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const AGENT_HARNESS_VERSION = "0.0.
|
|
1
|
+
export const AGENT_HARNESS_VERSION = "0.0.51";
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import path from "node:path";
|
|
1
2
|
import { Command, MemorySaver } from "@langchain/langgraph";
|
|
2
3
|
import { tool as createLangChainTool } from "@langchain/core/tools";
|
|
3
4
|
import { createDeepAgent, createMemoryMiddleware, createSkillsMiddleware, createSubAgentMiddleware, FilesystemBackend, } from "deepagents";
|
|
@@ -475,10 +476,20 @@ export class AgentRuntimeAdapter {
|
|
|
475
476
|
return this.compileInterruptOn(getBindingPrimaryTools(binding), getBindingInterruptCompatibilityRules(binding));
|
|
476
477
|
}
|
|
477
478
|
resolveFilesystemBackend(binding) {
|
|
479
|
+
const filesystemConfig = getBindingLangChainParams(binding)?.filesystem;
|
|
480
|
+
const configuredRootDir = typeof filesystemConfig?.rootDir === "string" && filesystemConfig.rootDir.trim().length > 0
|
|
481
|
+
? filesystemConfig.rootDir
|
|
482
|
+
: undefined;
|
|
483
|
+
const workspaceRoot = binding.harnessRuntime.workspaceRoot;
|
|
484
|
+
const rootDir = configuredRootDir
|
|
485
|
+
? (path.isAbsolute(configuredRootDir) ? configuredRootDir : path.resolve(workspaceRoot ?? process.cwd(), configuredRootDir))
|
|
486
|
+
: workspaceRoot ?? process.cwd();
|
|
478
487
|
return new FilesystemBackend({
|
|
479
|
-
rootDir
|
|
480
|
-
virtualMode:
|
|
481
|
-
maxFileSizeMb:
|
|
488
|
+
rootDir,
|
|
489
|
+
virtualMode: filesystemConfig?.virtualMode === true,
|
|
490
|
+
maxFileSizeMb: typeof filesystemConfig?.maxFileSizeMb === "number" && Number.isFinite(filesystemConfig.maxFileSizeMb)
|
|
491
|
+
? filesystemConfig.maxFileSizeMb
|
|
492
|
+
: 10,
|
|
482
493
|
});
|
|
483
494
|
}
|
|
484
495
|
async resolveLangChainAutomaticMiddleware(binding) {
|
|
@@ -127,14 +127,22 @@ function resolveInterruptOn(agent) {
|
|
|
127
127
|
return (agent.deepAgentConfig?.interruptOn ??
|
|
128
128
|
agent.langchainAgentConfig?.interruptOn);
|
|
129
129
|
}
|
|
130
|
-
function resolveBackendConfig(agent) {
|
|
130
|
+
function resolveBackendConfig(agent, refs) {
|
|
131
131
|
if (agent.executionMode !== "deepagent") {
|
|
132
132
|
return undefined;
|
|
133
133
|
}
|
|
134
134
|
const backendConfig = typeof agent.deepAgentConfig?.backend === "object" && agent.deepAgentConfig.backend
|
|
135
135
|
? agent.deepAgentConfig.backend
|
|
136
136
|
: undefined;
|
|
137
|
-
|
|
137
|
+
if (!backendConfig) {
|
|
138
|
+
return undefined;
|
|
139
|
+
}
|
|
140
|
+
if (isRefConfig(backendConfig)) {
|
|
141
|
+
return {
|
|
142
|
+
config: materializeWorkspaceObjectConfig(refs, backendConfig.ref, ["backend"], `Agent ${agent.id} backend`),
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
return { config: backendConfig };
|
|
138
146
|
}
|
|
139
147
|
function isRefConfig(value) {
|
|
140
148
|
if (typeof value?.ref !== "string" || value.ref.trim().length === 0) {
|
|
@@ -161,6 +169,11 @@ function materializeWorkspaceObjectConfig(refs, ref, allowedKinds, ownerLabel) {
|
|
|
161
169
|
const { checkpointerKind: _checkpointerKind, ...rest } = config;
|
|
162
170
|
return checkpointerKind ? { kind: checkpointerKind, ...rest } : config;
|
|
163
171
|
}
|
|
172
|
+
if (object.kind === "backend") {
|
|
173
|
+
const backendKind = typeof config.backendKind === "string" ? config.backendKind : undefined;
|
|
174
|
+
const { backendKind: _backendKind, ...rest } = config;
|
|
175
|
+
return backendKind ? { kind: backendKind, ...rest } : config;
|
|
176
|
+
}
|
|
164
177
|
return config;
|
|
165
178
|
}
|
|
166
179
|
function resolveStoreConfig(agent, refs) {
|
|
@@ -208,7 +221,7 @@ export function compileBinding(workspaceRoot, agent, agents, referencedSubagentI
|
|
|
208
221
|
const compiledAgentSkills = compileAgentSkills(workspaceRoot, agent);
|
|
209
222
|
const compiledAgentMemory = compileAgentMemories(workspaceRoot, agent.memorySources);
|
|
210
223
|
const compiledAgentModel = requireModel(models, agent.modelRef || (internalSubagent ? "model/default" : ""), agent.id);
|
|
211
|
-
const backend = resolveBackendConfig(agent);
|
|
224
|
+
const backend = resolveBackendConfig(agent, refs);
|
|
212
225
|
const store = resolveStoreConfig(agent, refs);
|
|
213
226
|
const checkpointer = resolveCheckpointerConfig(agent, refs);
|
|
214
227
|
const runRoot = typeof agent.runRoot === "string" && agent.runRoot.trim().length > 0
|
|
@@ -245,6 +258,9 @@ export function compileBinding(workspaceRoot, agent, agents, referencedSubagentI
|
|
|
245
258
|
stateSchema: agent.langchainAgentConfig?.stateSchema,
|
|
246
259
|
responseFormat: agent.langchainAgentConfig?.responseFormat,
|
|
247
260
|
contextSchema: agent.langchainAgentConfig?.contextSchema,
|
|
261
|
+
filesystem: typeof agent.langchainAgentConfig?.filesystem === "object" && agent.langchainAgentConfig.filesystem
|
|
262
|
+
? { ...agent.langchainAgentConfig.filesystem }
|
|
263
|
+
: undefined,
|
|
248
264
|
middleware: compileMiddlewareConfigs(agent.langchainAgentConfig?.middleware, models, agent.id),
|
|
249
265
|
passthrough: typeof agent.langchainAgentConfig?.passthrough === "object" && agent.langchainAgentConfig.passthrough
|
|
250
266
|
? { ...agent.langchainAgentConfig.passthrough }
|
|
@@ -61,6 +61,11 @@ function toArray(value) {
|
|
|
61
61
|
function asObject(value) {
|
|
62
62
|
return typeof value === "object" && value ? value : undefined;
|
|
63
63
|
}
|
|
64
|
+
function asMutableObject(value) {
|
|
65
|
+
return typeof value === "object" && value !== null && !Array.isArray(value)
|
|
66
|
+
? { ...value }
|
|
67
|
+
: undefined;
|
|
68
|
+
}
|
|
64
69
|
function normalizeCatalogSpec(document, options = {}) {
|
|
65
70
|
const typed = asObject(document);
|
|
66
71
|
const spec = typed?.spec;
|
|
@@ -211,9 +216,14 @@ function readCapabilities(value) {
|
|
|
211
216
|
return Object.keys(capabilities).length > 0 ? capabilities : undefined;
|
|
212
217
|
}
|
|
213
218
|
function readExecutionConfig(value) {
|
|
214
|
-
return
|
|
215
|
-
|
|
216
|
-
|
|
219
|
+
return asMutableObject(value);
|
|
220
|
+
}
|
|
221
|
+
function readExecutionAgentConfig(item) {
|
|
222
|
+
const execution = readExecutionConfig(item.execution);
|
|
223
|
+
return asMutableObject(execution?.config) ?? {};
|
|
224
|
+
}
|
|
225
|
+
function readRuntimeConfig(item) {
|
|
226
|
+
return asMutableObject(item.runtime);
|
|
217
227
|
}
|
|
218
228
|
function cloneConfigValue(value) {
|
|
219
229
|
if (Array.isArray(value)) {
|
|
@@ -245,21 +255,42 @@ function resolveExecutionBackend(item, current) {
|
|
|
245
255
|
}
|
|
246
256
|
return undefined;
|
|
247
257
|
}
|
|
248
|
-
function
|
|
249
|
-
const
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
258
|
+
function readExecutionSingleRef(item, key) {
|
|
259
|
+
const execution = readExecutionConfig(item.execution);
|
|
260
|
+
return readSingleRef(execution?.[key]);
|
|
261
|
+
}
|
|
262
|
+
function readExecutionRefArray(item, key) {
|
|
263
|
+
const execution = readExecutionConfig(item.execution);
|
|
264
|
+
return readRefArray(execution?.[key]);
|
|
265
|
+
}
|
|
266
|
+
function readExecutionPathArray(item, key) {
|
|
267
|
+
const execution = readExecutionConfig(item.execution);
|
|
268
|
+
return readPathArray(execution?.[key]);
|
|
269
|
+
}
|
|
270
|
+
function readExecutionObjectArray(item, key) {
|
|
271
|
+
const execution = readExecutionConfig(item.execution);
|
|
272
|
+
return readObjectArray(execution?.[key]);
|
|
273
|
+
}
|
|
274
|
+
function readSharedAgentConfig(config) {
|
|
275
|
+
const middleware = readMiddlewareArray(config.middleware);
|
|
276
|
+
return {
|
|
277
|
+
...(typeof config.systemPrompt === "string" ? { systemPrompt: config.systemPrompt } : {}),
|
|
278
|
+
...((typeof config.checkpointer === "object" && config.checkpointer) || typeof config.checkpointer === "boolean"
|
|
279
|
+
? { checkpointer: config.checkpointer }
|
|
280
|
+
: {}),
|
|
281
|
+
...(typeof config.interruptOn === "object" && config.interruptOn ? { interruptOn: config.interruptOn } : {}),
|
|
282
|
+
...(config.stateSchema !== undefined ? { stateSchema: config.stateSchema } : {}),
|
|
283
|
+
...(config.responseFormat !== undefined ? { responseFormat: config.responseFormat } : {}),
|
|
284
|
+
...(config.contextSchema !== undefined ? { contextSchema: config.contextSchema } : {}),
|
|
285
|
+
...(config.includeAgentName === "inline" ? { includeAgentName: "inline" } : {}),
|
|
286
|
+
...(config.version === "v1" || config.version === "v2" ? { version: config.version } : {}),
|
|
287
|
+
...(typeof config.filesystem === "object" && config.filesystem ? { filesystem: config.filesystem } : {}),
|
|
288
|
+
...(middleware ? { middleware } : {}),
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
function readLangchainAgentConfig(item) {
|
|
292
|
+
const config = readExecutionAgentConfig(item);
|
|
293
|
+
const passthrough = readPassthroughConfig(config, [
|
|
263
294
|
"systemPrompt",
|
|
264
295
|
"checkpointer",
|
|
265
296
|
"interruptOn",
|
|
@@ -273,43 +304,48 @@ function readSharedAgentConfig(item) {
|
|
|
273
304
|
"store",
|
|
274
305
|
"taskDescription",
|
|
275
306
|
"generalPurposeAgent",
|
|
307
|
+
"filesystem",
|
|
276
308
|
]);
|
|
277
309
|
return {
|
|
278
|
-
...(
|
|
279
|
-
...(
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
...(typeof item.interruptOn === "object" && item.interruptOn ? { interruptOn: item.interruptOn } : {}),
|
|
283
|
-
...(item.stateSchema !== undefined ? { stateSchema: item.stateSchema } : {}),
|
|
284
|
-
...(item.responseFormat !== undefined ? { responseFormat: item.responseFormat } : {}),
|
|
285
|
-
...(item.contextSchema !== undefined ? { contextSchema: item.contextSchema } : {}),
|
|
286
|
-
...(item.includeAgentName === "inline" ? { includeAgentName: "inline" } : {}),
|
|
287
|
-
...(item.version === "v1" || item.version === "v2" ? { version: item.version } : {}),
|
|
288
|
-
...(middleware ? { middleware } : {}),
|
|
310
|
+
...readSharedAgentConfig(config),
|
|
311
|
+
...(typeof config.store === "object" && config.store ? { store: config.store } : {}),
|
|
312
|
+
...(typeof config.taskDescription === "string" && config.taskDescription.trim() ? { taskDescription: config.taskDescription } : {}),
|
|
313
|
+
...(typeof config.generalPurposeAgent === "boolean" ? { generalPurposeAgent: config.generalPurposeAgent } : {}),
|
|
289
314
|
...(passthrough ? { passthrough } : {}),
|
|
290
315
|
};
|
|
291
316
|
}
|
|
292
|
-
function readLangchainAgentConfig(item) {
|
|
293
|
-
return {
|
|
294
|
-
...readSharedAgentConfig(item),
|
|
295
|
-
...(typeof item.store === "object" && item.store ? { store: item.store } : {}),
|
|
296
|
-
...(typeof item.taskDescription === "string" && item.taskDescription.trim() ? { taskDescription: item.taskDescription } : {}),
|
|
297
|
-
...(typeof item.generalPurposeAgent === "boolean" ? { generalPurposeAgent: item.generalPurposeAgent } : {}),
|
|
298
|
-
};
|
|
299
|
-
}
|
|
300
317
|
function readDeepAgentConfig(item) {
|
|
318
|
+
const config = readExecutionAgentConfig(item);
|
|
319
|
+
const passthrough = readPassthroughConfig(config, [
|
|
320
|
+
"systemPrompt",
|
|
321
|
+
"checkpointer",
|
|
322
|
+
"interruptOn",
|
|
323
|
+
"stateSchema",
|
|
324
|
+
"responseFormat",
|
|
325
|
+
"contextSchema",
|
|
326
|
+
"includeAgentName",
|
|
327
|
+
"version",
|
|
328
|
+
"middleware",
|
|
329
|
+
"backend",
|
|
330
|
+
"store",
|
|
331
|
+
"taskDescription",
|
|
332
|
+
"generalPurposeAgent",
|
|
333
|
+
"filesystem",
|
|
334
|
+
]);
|
|
301
335
|
return {
|
|
302
|
-
...readSharedAgentConfig(
|
|
303
|
-
...(typeof
|
|
304
|
-
...(typeof
|
|
305
|
-
...(typeof
|
|
306
|
-
...(typeof
|
|
336
|
+
...readSharedAgentConfig(config),
|
|
337
|
+
...(typeof config.backend === "object" && config.backend ? { backend: config.backend } : {}),
|
|
338
|
+
...(typeof config.store === "object" && config.store ? { store: config.store } : {}),
|
|
339
|
+
...(typeof config.taskDescription === "string" && config.taskDescription.trim() ? { taskDescription: config.taskDescription } : {}),
|
|
340
|
+
...(typeof config.generalPurposeAgent === "boolean" ? { generalPurposeAgent: config.generalPurposeAgent } : {}),
|
|
341
|
+
...(passthrough ? { passthrough } : {}),
|
|
307
342
|
};
|
|
308
343
|
}
|
|
309
344
|
export function parseAgentItem(item, sourcePath) {
|
|
310
|
-
const subagentRefs =
|
|
311
|
-
const subagentPathRefs =
|
|
345
|
+
const subagentRefs = readExecutionRefArray(item, "subagents");
|
|
346
|
+
const subagentPathRefs = readExecutionPathArray(item, "subagents");
|
|
312
347
|
const executionMode = String(resolveExecutionBackend(item) ?? "deepagent");
|
|
348
|
+
const runtime = readRuntimeConfig(item);
|
|
313
349
|
return {
|
|
314
350
|
id: String(item.id),
|
|
315
351
|
executionMode: executionMode,
|
|
@@ -317,12 +353,12 @@ export function parseAgentItem(item, sourcePath) {
|
|
|
317
353
|
? { delegation: true, memory: true }
|
|
318
354
|
: { delegation: true, memory: true }),
|
|
319
355
|
description: String(item.description ?? ""),
|
|
320
|
-
modelRef:
|
|
321
|
-
runRoot: typeof
|
|
322
|
-
toolRefs:
|
|
323
|
-
mcpServers:
|
|
324
|
-
skillPathRefs:
|
|
325
|
-
memorySources:
|
|
356
|
+
modelRef: readExecutionSingleRef(item, "modelRef") ?? "",
|
|
357
|
+
runRoot: typeof runtime?.runRoot === "string" ? runtime.runRoot : undefined,
|
|
358
|
+
toolRefs: readExecutionRefArray(item, "tools"),
|
|
359
|
+
mcpServers: readExecutionObjectArray(item, "mcpServers"),
|
|
360
|
+
skillPathRefs: readExecutionPathArray(item, "skills"),
|
|
361
|
+
memorySources: readExecutionPathArray(item, "memory"),
|
|
326
362
|
subagentRefs,
|
|
327
363
|
subagentPathRefs,
|
|
328
364
|
langchainAgentConfig: readLangchainAgentConfig(item),
|
|
@@ -341,11 +377,13 @@ async function objectItemsFromDocument(document, sourcePath) {
|
|
|
341
377
|
? normalizeCatalogSpec(document, { defaultKind: "Model" })
|
|
342
378
|
: catalogKind === "Stores"
|
|
343
379
|
? normalizeCatalogSpec(document)
|
|
344
|
-
: catalogKind === "
|
|
345
|
-
? normalizeCatalogSpec(document, { defaultKind: "
|
|
346
|
-
: catalogKind === "
|
|
347
|
-
? normalizeCatalogSpec(document)
|
|
348
|
-
:
|
|
380
|
+
: catalogKind === "Backends"
|
|
381
|
+
? normalizeCatalogSpec(document, { defaultKind: "Backend" })
|
|
382
|
+
: catalogKind === "Tools"
|
|
383
|
+
? normalizeCatalogSpec(document, { defaultKind: "Tool" })
|
|
384
|
+
: catalogKind === "McpServers"
|
|
385
|
+
? normalizeCatalogSpec(document)
|
|
386
|
+
: [];
|
|
349
387
|
if (catalogItems.length > 0) {
|
|
350
388
|
return catalogItems;
|
|
351
389
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@botbotgo/agent-harness",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.52",
|
|
4
4
|
"description": "Workspace runtime for multi-agent applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"packageManager": "npm@10.9.2",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"scripts": {
|
|
51
51
|
"build": "rm -rf dist tsconfig.tsbuildinfo && tsc -p tsconfig.json && cp -R config dist/",
|
|
52
52
|
"check": "tsc -p tsconfig.json --noEmit",
|
|
53
|
-
"test": "vitest run test/public-api.test.ts test/resource-optional-provider.test.ts test/resource-isolation.test.ts test/stock-research-app-load-harness.test.ts test/stock-research-app-run.test.ts test/release-workflow.test.ts test/release-version.test.ts test/gitignore.test.ts test/package-lock.test.ts test/readme.test.ts test/runtime-adapter-regressions.test.ts test/runtime-capabilities.test.ts test/runtime-recovery.test.ts test/tool-extension-gaps.test.ts test/checkpoint-maintenance.test.ts test/llamaindex-dependency-compat.test.ts test/skill-standard.test.ts test/routing-config.test.ts test/workspace-compat-regressions.test.ts test/upstream-compat-regressions.test.ts test/yaml-format.test.ts",
|
|
53
|
+
"test": "vitest run test/public-api.test.ts test/resource-optional-provider.test.ts test/resource-isolation.test.ts test/stock-research-app-load-harness.test.ts test/stock-research-app-run.test.ts test/stock-research-app-config.test.ts test/release-workflow.test.ts test/release-version.test.ts test/gitignore.test.ts test/package-lock.test.ts test/readme.test.ts test/runtime-adapter-regressions.test.ts test/runtime-capabilities.test.ts test/runtime-recovery.test.ts test/tool-extension-gaps.test.ts test/checkpoint-maintenance.test.ts test/llamaindex-dependency-compat.test.ts test/skill-standard.test.ts test/routing-config.test.ts test/workspace-compat-regressions.test.ts test/upstream-compat-regressions.test.ts test/yaml-format.test.ts",
|
|
54
54
|
"test:real-providers": "vitest run test/real-provider-harness.test.ts",
|
|
55
55
|
"release:prepare": "npm version patch --no-git-tag-version && node ./scripts/sync-example-version.mjs",
|
|
56
56
|
"release:pack": "npm pack --dry-run",
|