@botbotgo/agent-harness 0.0.93 → 0.0.94

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.
@@ -2,7 +2,9 @@ type LangGraphPresetNode = {
2
2
  id: string;
3
3
  kind: string;
4
4
  prompt?: string;
5
- specialist?: string;
5
+ role?: string;
6
+ agent?: string;
7
+ tool?: string;
6
8
  };
7
9
  type LangGraphPresetEdge = {
8
10
  from: string;
@@ -16,7 +18,7 @@ export type LangGraphPresetWorkflow = {
16
18
  };
17
19
  export type LangGraphPresetName = "react" | "prompt-chaining" | "routing" | "parallelization" | "plan-execute" | "review-loop" | "evaluator-optimizer" | "approval-gate" | "handoff" | "orchestrator-workers";
18
20
  type LangGraphPresetOptions = {
19
- specialist?: string;
21
+ agent?: string;
20
22
  };
21
23
  export declare const SUPPORTED_LANGGRAPH_PRESETS: LangGraphPresetName[];
22
24
  export declare function resolveLangGraphPresetWorkflow(presetName: string | undefined, options?: LangGraphPresetOptions): LangGraphPresetWorkflow | undefined;
@@ -14,11 +14,11 @@ export const SUPPORTED_LANGGRAPH_PRESETS = [
14
14
  "handoff",
15
15
  "orchestrator-workers",
16
16
  ];
17
- function requireSpecialist(preset, options) {
18
- if (typeof options.specialist === "string" && options.specialist.trim()) {
19
- return options.specialist.trim();
17
+ function requireAgent(preset, options) {
18
+ if (typeof options.agent === "string" && options.agent.trim()) {
19
+ return options.agent.trim();
20
20
  }
21
- throw new Error(`LangGraph preset ${preset} requires config.specialist`);
21
+ throw new Error(`LangGraph preset ${preset} requires config.agent`);
22
22
  }
23
23
  export function resolveLangGraphPresetWorkflow(presetName, options = {}) {
24
24
  switch (presetName) {
@@ -29,7 +29,7 @@ export function resolveLangGraphPresetWorkflow(presetName, options = {}) {
29
29
  return {
30
30
  entryNode: "executor",
31
31
  nodes: [
32
- { id: "executor", kind: "executor" },
32
+ { id: "executor", kind: "agent" },
33
33
  ],
34
34
  edges: [],
35
35
  };
@@ -38,9 +38,9 @@ export function resolveLangGraphPresetWorkflow(presetName, options = {}) {
38
38
  return {
39
39
  entryNode: "planner",
40
40
  nodes: [
41
- { id: "planner", kind: "planner", prompt: DEFAULT_PLANNER_PROMPT },
42
- { id: "executor", kind: "executor" },
43
- { id: "finalizer", kind: "finalizer", prompt: DEFAULT_FINALIZER_PROMPT },
41
+ { id: "planner", kind: "llm", role: "planner", prompt: DEFAULT_PLANNER_PROMPT },
42
+ { id: "executor", kind: "agent" },
43
+ { id: "finalizer", kind: "llm", role: "finalizer", prompt: DEFAULT_FINALIZER_PROMPT },
44
44
  ],
45
45
  edges: [
46
46
  { from: "planner", to: "executor" },
@@ -48,33 +48,33 @@ export function resolveLangGraphPresetWorkflow(presetName, options = {}) {
48
48
  ],
49
49
  };
50
50
  case "routing": {
51
- const specialist = requireSpecialist("routing", options);
51
+ const agent = requireAgent("routing", options);
52
52
  return {
53
53
  entryNode: "planner",
54
54
  nodes: [
55
- { id: "planner", kind: "planner", prompt: DEFAULT_PLANNER_PROMPT },
56
- { id: "specialist", kind: "specialist", specialist },
57
- { id: "finalizer", kind: "finalizer", prompt: DEFAULT_FINALIZER_PROMPT },
55
+ { id: "planner", kind: "llm", role: "planner", prompt: DEFAULT_PLANNER_PROMPT },
56
+ { id: "worker", kind: "agent", agent },
57
+ { id: "finalizer", kind: "llm", role: "finalizer", prompt: DEFAULT_FINALIZER_PROMPT },
58
58
  ],
59
59
  edges: [
60
- { from: "planner", to: "specialist" },
61
- { from: "specialist", to: "finalizer", when: "has_result" },
60
+ { from: "planner", to: "worker" },
61
+ { from: "worker", to: "finalizer", when: "has_result" },
62
62
  ],
63
63
  };
64
64
  }
65
65
  case "parallelization": {
66
- const specialist = requireSpecialist("parallelization", options);
66
+ const agent = requireAgent("parallelization", options);
67
67
  return {
68
68
  entryNode: "planner",
69
69
  nodes: [
70
- { id: "planner", kind: "planner", prompt: DEFAULT_PLANNER_PROMPT },
71
- { id: "specialist", kind: "specialist", specialist },
72
- { id: "reviewer", kind: "reviewer", prompt: DEFAULT_REVIEWER_PROMPT },
73
- { id: "finalizer", kind: "finalizer", prompt: DEFAULT_FINALIZER_PROMPT },
70
+ { id: "planner", kind: "llm", role: "planner", prompt: DEFAULT_PLANNER_PROMPT },
71
+ { id: "worker", kind: "agent", agent },
72
+ { id: "reviewer", kind: "llm", role: "reviewer", prompt: DEFAULT_REVIEWER_PROMPT },
73
+ { id: "finalizer", kind: "llm", role: "finalizer", prompt: DEFAULT_FINALIZER_PROMPT },
74
74
  ],
75
75
  edges: [
76
- { from: "planner", to: "specialist" },
77
- { from: "specialist", to: "reviewer", when: "has_result" },
76
+ { from: "planner", to: "worker" },
77
+ { from: "worker", to: "reviewer", when: "has_result" },
78
78
  { from: "reviewer", to: "finalizer", when: "review_ok" },
79
79
  ],
80
80
  };
@@ -83,11 +83,11 @@ export function resolveLangGraphPresetWorkflow(presetName, options = {}) {
83
83
  return {
84
84
  entryNode: "planner",
85
85
  nodes: [
86
- { id: "planner", kind: "planner", prompt: DEFAULT_PLANNER_PROMPT },
87
- { id: "executor", kind: "executor" },
88
- { id: "reviewer", kind: "reviewer", prompt: DEFAULT_REVIEWER_PROMPT },
89
- { id: "replanner", kind: "replanner", prompt: DEFAULT_REPLANNER_PROMPT },
90
- { id: "finalizer", kind: "finalizer", prompt: DEFAULT_FINALIZER_PROMPT },
86
+ { id: "planner", kind: "llm", role: "planner", prompt: DEFAULT_PLANNER_PROMPT },
87
+ { id: "executor", kind: "agent" },
88
+ { id: "reviewer", kind: "llm", role: "reviewer", prompt: DEFAULT_REVIEWER_PROMPT },
89
+ { id: "replanner", kind: "llm", role: "replanner", prompt: DEFAULT_REPLANNER_PROMPT },
90
+ { id: "finalizer", kind: "llm", role: "finalizer", prompt: DEFAULT_FINALIZER_PROMPT },
91
91
  ],
92
92
  edges: [
93
93
  { from: "planner", to: "executor" },
@@ -101,10 +101,10 @@ export function resolveLangGraphPresetWorkflow(presetName, options = {}) {
101
101
  return {
102
102
  entryNode: "executor",
103
103
  nodes: [
104
- { id: "executor", kind: "executor" },
105
- { id: "reviewer", kind: "reviewer", prompt: DEFAULT_REVIEWER_PROMPT },
106
- { id: "replanner", kind: "replanner", prompt: DEFAULT_REPLANNER_PROMPT },
107
- { id: "finalizer", kind: "finalizer", prompt: DEFAULT_FINALIZER_PROMPT },
104
+ { id: "executor", kind: "agent" },
105
+ { id: "reviewer", kind: "llm", role: "reviewer", prompt: DEFAULT_REVIEWER_PROMPT },
106
+ { id: "replanner", kind: "llm", role: "replanner", prompt: DEFAULT_REPLANNER_PROMPT },
107
+ { id: "finalizer", kind: "llm", role: "finalizer", prompt: DEFAULT_FINALIZER_PROMPT },
108
108
  ],
109
109
  edges: [
110
110
  { from: "executor", to: "reviewer", when: "has_result" },
@@ -117,10 +117,10 @@ export function resolveLangGraphPresetWorkflow(presetName, options = {}) {
117
117
  return {
118
118
  entryNode: "planner",
119
119
  nodes: [
120
- { id: "planner", kind: "planner", prompt: DEFAULT_PLANNER_PROMPT },
120
+ { id: "planner", kind: "llm", role: "planner", prompt: DEFAULT_PLANNER_PROMPT },
121
121
  { id: "approval", kind: "approval" },
122
- { id: "executor", kind: "executor" },
123
- { id: "finalizer", kind: "finalizer", prompt: DEFAULT_FINALIZER_PROMPT },
122
+ { id: "executor", kind: "agent" },
123
+ { id: "finalizer", kind: "llm", role: "finalizer", prompt: DEFAULT_FINALIZER_PROMPT },
124
124
  ],
125
125
  edges: [
126
126
  { from: "planner", to: "approval" },
@@ -130,31 +130,31 @@ export function resolveLangGraphPresetWorkflow(presetName, options = {}) {
130
130
  ],
131
131
  };
132
132
  case "handoff": {
133
- const specialist = requireSpecialist("handoff", options);
133
+ const agent = requireAgent("handoff", options);
134
134
  return {
135
- entryNode: "specialist",
135
+ entryNode: "worker",
136
136
  nodes: [
137
- { id: "specialist", kind: "specialist", specialist },
138
- { id: "finalizer", kind: "finalizer", prompt: DEFAULT_FINALIZER_PROMPT },
137
+ { id: "worker", kind: "agent", agent },
138
+ { id: "finalizer", kind: "llm", role: "finalizer", prompt: DEFAULT_FINALIZER_PROMPT },
139
139
  ],
140
140
  edges: [
141
- { from: "specialist", to: "finalizer", when: "has_result" },
141
+ { from: "worker", to: "finalizer", when: "has_result" },
142
142
  ],
143
143
  };
144
144
  }
145
145
  case "orchestrator-workers": {
146
- const specialist = requireSpecialist("orchestrator-workers", options);
146
+ const agent = requireAgent("orchestrator-workers", options);
147
147
  return {
148
148
  entryNode: "planner",
149
149
  nodes: [
150
- { id: "planner", kind: "planner", prompt: DEFAULT_PLANNER_PROMPT },
151
- { id: "specialist", kind: "specialist", specialist },
152
- { id: "reviewer", kind: "reviewer", prompt: DEFAULT_REVIEWER_PROMPT },
153
- { id: "finalizer", kind: "finalizer", prompt: DEFAULT_FINALIZER_PROMPT },
150
+ { id: "planner", kind: "llm", role: "planner", prompt: DEFAULT_PLANNER_PROMPT },
151
+ { id: "worker", kind: "agent", agent },
152
+ { id: "reviewer", kind: "llm", role: "reviewer", prompt: DEFAULT_REVIEWER_PROMPT },
153
+ { id: "finalizer", kind: "llm", role: "finalizer", prompt: DEFAULT_FINALIZER_PROMPT },
154
154
  ],
155
155
  edges: [
156
- { from: "planner", to: "specialist" },
157
- { from: "specialist", to: "reviewer", when: "has_result" },
156
+ { from: "planner", to: "worker" },
157
+ { from: "worker", to: "reviewer", when: "has_result" },
158
158
  { from: "reviewer", to: "finalizer", when: "review_ok" },
159
159
  ],
160
160
  };
@@ -0,0 +1,6 @@
1
+ import type { LangGraphPresetWorkflow } from "./langgraph-presets.js";
2
+ export type LangGraphProfileName = "coding-runtime" | "personal-assistant" | "research-runtime" | "approval-review-runtime" | "claw-style-assistant" | "chat-operator" | "copilot-sidecar" | "task-delegation-hub";
3
+ type LangGraphProfileOptions = Record<string, unknown>;
4
+ export declare const SUPPORTED_LANGGRAPH_PROFILES: LangGraphProfileName[];
5
+ export declare function resolveLangGraphProfileWorkflow(profileName: string | undefined, options?: LangGraphProfileOptions): LangGraphPresetWorkflow | undefined;
6
+ export {};
@@ -0,0 +1,206 @@
1
+ const DEFAULT_PLANNER_PROMPT = "You are the workflow planner. Produce a concise execution plan for the user request before execution starts.";
2
+ const DEFAULT_REVIEWER_PROMPT = "Review the current result, call out missing verification or obvious gaps, and state whether the work looks sufficient.";
3
+ const DEFAULT_FINALIZER_PROMPT = "Rewrite the current result into a concise user-facing final answer. Preserve facts and caveats.";
4
+ const DEFAULT_REPLANNER_PROMPT = "Refine the plan based on the reviewer feedback and current result. Return only the updated plan.";
5
+ export const SUPPORTED_LANGGRAPH_PROFILES = [
6
+ "coding-runtime",
7
+ "personal-assistant",
8
+ "research-runtime",
9
+ "approval-review-runtime",
10
+ "claw-style-assistant",
11
+ "chat-operator",
12
+ "copilot-sidecar",
13
+ "task-delegation-hub",
14
+ ];
15
+ function readStringOption(options, key) {
16
+ const value = options[key];
17
+ return typeof value === "string" && value.trim() ? value.trim() : undefined;
18
+ }
19
+ function requireAgentOption(profile, options, key) {
20
+ const value = readStringOption(options, key);
21
+ if (value) {
22
+ return value;
23
+ }
24
+ throw new Error(`LangGraph profile ${profile} requires with.${key}`);
25
+ }
26
+ function buildCodingRuntimeWorkflow(options) {
27
+ const coderAgent = requireAgentOption("coding-runtime", options, "coderAgent");
28
+ const verifierAgent = readStringOption(options, "verifierAgent");
29
+ const needsVerification = Boolean(verifierAgent) || options.runIntegrationVerification === true;
30
+ return {
31
+ entryNode: "planner",
32
+ nodes: [
33
+ { id: "planner", kind: "llm", role: "planner", prompt: DEFAULT_PLANNER_PROMPT },
34
+ { id: "coder", kind: "agent", agent: coderAgent },
35
+ { id: "reviewer", kind: "llm", role: "reviewer", prompt: DEFAULT_REVIEWER_PROMPT },
36
+ { id: "replanner", kind: "llm", role: "replanner", prompt: DEFAULT_REPLANNER_PROMPT },
37
+ ...(needsVerification
38
+ ? [{ id: "approval", kind: "approval" }, { id: "verifier", kind: "agent", agent: verifierAgent ?? coderAgent }]
39
+ : []),
40
+ { id: "finalizer", kind: "llm", role: "finalizer", prompt: DEFAULT_FINALIZER_PROMPT },
41
+ ],
42
+ edges: [
43
+ { from: "planner", to: "coder" },
44
+ { from: "coder", to: "reviewer", when: "has_result" },
45
+ { from: "reviewer", to: needsVerification ? "approval" : "finalizer", when: "review_ok" },
46
+ { from: "reviewer", to: "replanner", when: "review_incomplete" },
47
+ { from: "replanner", to: "coder", when: "has_plan" },
48
+ ...(needsVerification
49
+ ? [
50
+ { from: "approval", to: "verifier", when: "approval_approved" },
51
+ { from: "approval", to: "verifier", when: "approval_edited" },
52
+ { from: "verifier", to: "finalizer", when: "has_result" },
53
+ ]
54
+ : []),
55
+ ],
56
+ };
57
+ }
58
+ function buildAssistantWorkflow(options) {
59
+ const worker = readStringOption(options, "defaultWorkerAgent") ??
60
+ readStringOption(options, "defaultResearchAgent") ??
61
+ readStringOption(options, "defaultWritingAgent") ??
62
+ readStringOption(options, "defaultSchedulingAgent");
63
+ return {
64
+ entryNode: "intake",
65
+ nodes: [
66
+ { id: "intake", kind: "llm", role: "planner", prompt: DEFAULT_PLANNER_PROMPT },
67
+ ...(worker ? [{ id: "worker", kind: "agent", agent: worker }] : [{ id: "lookup", kind: "tool", tool: "repo_inventory" }]),
68
+ { id: "reviewer", kind: "llm", role: "reviewer", prompt: DEFAULT_REVIEWER_PROMPT },
69
+ { id: "approval", kind: "approval" },
70
+ { id: "finalizer", kind: "llm", role: "finalizer", prompt: DEFAULT_FINALIZER_PROMPT },
71
+ ],
72
+ edges: [
73
+ { from: "intake", to: worker ? "worker" : "lookup" },
74
+ { from: worker ? "worker" : "lookup", to: "reviewer", when: "has_result" },
75
+ { from: "reviewer", to: "approval", when: "review_incomplete" },
76
+ { from: "reviewer", to: "finalizer", when: "review_ok" },
77
+ { from: "approval", to: "finalizer", when: "approval_approved" },
78
+ { from: "approval", to: "finalizer", when: "approval_edited" },
79
+ ],
80
+ };
81
+ }
82
+ function buildResearchWorkflow(options) {
83
+ const gathererAgent = requireAgentOption("research-runtime", options, "gathererAgent");
84
+ const analystAgent = requireAgentOption("research-runtime", options, "analystAgent");
85
+ const synthesizerAgent = readStringOption(options, "synthesizerAgent");
86
+ return {
87
+ entryNode: "planner",
88
+ nodes: [
89
+ { id: "planner", kind: "llm", role: "planner", prompt: DEFAULT_PLANNER_PROMPT },
90
+ { id: "gatherer", kind: "agent", agent: gathererAgent },
91
+ { id: "coverage-review", kind: "llm", role: "reviewer", prompt: DEFAULT_REVIEWER_PROMPT },
92
+ { id: "analyst", kind: "agent", agent: analystAgent },
93
+ ...(synthesizerAgent ? [{ id: "synthesizer", kind: "agent", agent: synthesizerAgent }] : []),
94
+ { id: "finalizer", kind: "llm", role: "finalizer", prompt: DEFAULT_FINALIZER_PROMPT },
95
+ ],
96
+ edges: [
97
+ { from: "planner", to: "gatherer" },
98
+ { from: "gatherer", to: "coverage-review", when: "has_result" },
99
+ { from: "coverage-review", to: "analyst", when: "review_ok" },
100
+ { from: "coverage-review", to: "gatherer", when: "review_incomplete" },
101
+ { from: "analyst", to: synthesizerAgent ? "synthesizer" : "finalizer", when: "has_result" },
102
+ ...(synthesizerAgent ? [{ from: "synthesizer", to: "finalizer", when: "has_result" }] : []),
103
+ ],
104
+ };
105
+ }
106
+ function buildApprovalReviewWorkflow(options) {
107
+ const preparerAgent = requireAgentOption("approval-review-runtime", options, "preparerAgent");
108
+ const reviewerAgent = readStringOption(options, "reviewerAgent");
109
+ return {
110
+ entryNode: "scope",
111
+ nodes: [
112
+ { id: "scope", kind: "llm", role: "planner", prompt: DEFAULT_PLANNER_PROMPT },
113
+ { id: "preparer", kind: "agent", agent: preparerAgent },
114
+ ...(reviewerAgent ? [{ id: "reviewer-agent", kind: "agent", agent: reviewerAgent }] : [{ id: "risk-review", kind: "llm", role: "reviewer", prompt: DEFAULT_REVIEWER_PROMPT }]),
115
+ { id: "approval", kind: "approval" },
116
+ { id: "finalizer", kind: "llm", role: "finalizer", prompt: DEFAULT_FINALIZER_PROMPT },
117
+ ],
118
+ edges: [
119
+ { from: "scope", to: "preparer" },
120
+ { from: "preparer", to: reviewerAgent ? "reviewer-agent" : "risk-review", when: "has_result" },
121
+ { from: reviewerAgent ? "reviewer-agent" : "risk-review", to: "approval", when: "has_result" },
122
+ { from: "approval", to: "finalizer", when: "approval_approved" },
123
+ { from: "approval", to: "finalizer", when: "approval_edited" },
124
+ ],
125
+ };
126
+ }
127
+ function buildChatOperatorWorkflow(options) {
128
+ const routedAgent = readStringOption(options, "assistantAgent") ??
129
+ readStringOption(options, "researchAgent") ??
130
+ readStringOption(options, "codingAgent") ??
131
+ readStringOption(options, "approvalAgent");
132
+ if (!routedAgent) {
133
+ throw new Error("LangGraph profile chat-operator requires at least one target agent in with.assistantAgent, with.researchAgent, with.codingAgent, or with.approvalAgent");
134
+ }
135
+ return {
136
+ entryNode: "router",
137
+ nodes: [
138
+ { id: "router", kind: "llm", role: "planner", prompt: DEFAULT_PLANNER_PROMPT },
139
+ { id: "worker", kind: "agent", agent: routedAgent },
140
+ { id: "finalizer", kind: "llm", role: "finalizer", prompt: DEFAULT_FINALIZER_PROMPT },
141
+ ],
142
+ edges: [
143
+ { from: "router", to: "worker" },
144
+ { from: "worker", to: "finalizer", when: "has_result" },
145
+ ],
146
+ };
147
+ }
148
+ function buildCopilotSidecarWorkflow(options) {
149
+ const coderAgent = requireAgentOption("copilot-sidecar", options, "coderAgent");
150
+ return {
151
+ entryNode: "intake",
152
+ nodes: [
153
+ { id: "intake", kind: "llm", role: "planner", prompt: DEFAULT_PLANNER_PROMPT },
154
+ { id: "coder", kind: "agent", agent: coderAgent },
155
+ { id: "finalizer", kind: "llm", role: "finalizer", prompt: DEFAULT_FINALIZER_PROMPT },
156
+ ],
157
+ edges: [
158
+ { from: "intake", to: "coder" },
159
+ { from: "coder", to: "finalizer", when: "has_result" },
160
+ ],
161
+ };
162
+ }
163
+ function buildDelegationHubWorkflow(options) {
164
+ const workerAgent = readStringOption(options, "defaultWorkerFallback");
165
+ if (!workerAgent) {
166
+ throw new Error("LangGraph profile task-delegation-hub requires with.defaultWorkerFallback");
167
+ }
168
+ return {
169
+ entryNode: "router",
170
+ nodes: [
171
+ { id: "router", kind: "llm", role: "planner", prompt: DEFAULT_PLANNER_PROMPT },
172
+ { id: "worker", kind: "agent", agent: workerAgent },
173
+ { id: "reviewer", kind: "llm", role: "reviewer", prompt: DEFAULT_REVIEWER_PROMPT },
174
+ { id: "finalizer", kind: "llm", role: "finalizer", prompt: DEFAULT_FINALIZER_PROMPT },
175
+ ],
176
+ edges: [
177
+ { from: "router", to: "worker" },
178
+ { from: "worker", to: "reviewer", when: "has_result" },
179
+ { from: "reviewer", to: "finalizer", when: "review_ok" },
180
+ ],
181
+ };
182
+ }
183
+ export function resolveLangGraphProfileWorkflow(profileName, options = {}) {
184
+ switch (profileName) {
185
+ case undefined:
186
+ case "":
187
+ return undefined;
188
+ case "coding-runtime":
189
+ return buildCodingRuntimeWorkflow(options);
190
+ case "personal-assistant":
191
+ case "claw-style-assistant":
192
+ return buildAssistantWorkflow(options);
193
+ case "research-runtime":
194
+ return buildResearchWorkflow(options);
195
+ case "approval-review-runtime":
196
+ return buildApprovalReviewWorkflow(options);
197
+ case "chat-operator":
198
+ return buildChatOperatorWorkflow(options);
199
+ case "copilot-sidecar":
200
+ return buildCopilotSidecarWorkflow(options);
201
+ case "task-delegation-hub":
202
+ return buildDelegationHubWorkflow(options);
203
+ default:
204
+ throw new Error(`Unsupported LangGraph profile ${String(profileName)}. Supported profiles: ${SUPPORTED_LANGGRAPH_PROFILES.join(", ")}`);
205
+ }
206
+ }
@@ -245,6 +245,22 @@ function resolveLangGraphWorkflowConfig(agent, refs) {
245
245
  if (agent.executionMode !== "langgraph") {
246
246
  return undefined;
247
247
  }
248
+ const profile = typeof agent.langchainAgentConfig?.profile === "string" && agent.langchainAgentConfig.profile.trim()
249
+ ? agent.langchainAgentConfig.profile.trim()
250
+ : typeof agent.langchainAgentConfig?.passthrough === "object" &&
251
+ agent.langchainAgentConfig.passthrough &&
252
+ typeof agent.langchainAgentConfig.passthrough.profile === "string" &&
253
+ agent.langchainAgentConfig.passthrough.profile.trim()
254
+ ? agent.langchainAgentConfig.passthrough.profile.trim()
255
+ : undefined;
256
+ const profileWith = typeof agent.langchainAgentConfig?.with === "object" && agent.langchainAgentConfig.with
257
+ ? { ...agent.langchainAgentConfig.with }
258
+ : typeof agent.langchainAgentConfig?.passthrough === "object" &&
259
+ agent.langchainAgentConfig.passthrough &&
260
+ typeof agent.langchainAgentConfig.passthrough.with === "object" &&
261
+ agent.langchainAgentConfig.passthrough.with
262
+ ? { ...agent.langchainAgentConfig.passthrough.with }
263
+ : undefined;
248
264
  const preset = typeof agent.langchainAgentConfig?.preset === "string" && agent.langchainAgentConfig.preset.trim()
249
265
  ? agent.langchainAgentConfig.preset.trim()
250
266
  : typeof agent.langchainAgentConfig?.passthrough === "object" &&
@@ -269,15 +285,22 @@ function resolveLangGraphWorkflowConfig(agent, refs) {
269
285
  ? agent.langchainAgentConfig.passthrough.langgraph
270
286
  : undefined;
271
287
  if (!workflowConfig) {
272
- return preset ? { preset } : undefined;
288
+ return profile || preset ? { ...(profile ? { profile } : {}), ...(profileWith ? { with: profileWith } : {}), ...(preset ? { preset } : {}) } : undefined;
273
289
  }
274
290
  if (isRefConfig(workflowConfig)) {
275
291
  return {
276
292
  config: materializeWorkspaceObjectConfig(refs, workflowConfig.ref, ["langgraph-workflow"], `Agent ${agent.id} workflow`),
293
+ ...(profile ? { profile } : {}),
294
+ ...(profileWith ? { with: profileWith } : {}),
277
295
  ...(preset ? { preset } : {}),
278
296
  };
279
297
  }
280
- return { config: workflowConfig, ...(preset ? { preset } : {}) };
298
+ return {
299
+ config: workflowConfig,
300
+ ...(profile ? { profile } : {}),
301
+ ...(profileWith ? { with: profileWith } : {}),
302
+ ...(preset ? { preset } : {}),
303
+ };
281
304
  }
282
305
  function resolveRuntimeModelRefs(agent, refs) {
283
306
  const merged = {
@@ -341,8 +364,12 @@ export function compileBinding(workspaceRoot, agent, agents, referencedSubagentI
341
364
  },
342
365
  };
343
366
  if (agent.executionMode !== "deepagent") {
344
- const langGraphPassthrough = agent.executionMode === "langgraph" && langGraphWorkflow?.config
345
- ? { workflow: langGraphWorkflow.config }
367
+ const langGraphPassthrough = agent.executionMode === "langgraph"
368
+ ? {
369
+ ...(langGraphWorkflow?.profile ? { profile: langGraphWorkflow.profile } : {}),
370
+ ...(langGraphWorkflow?.with ? { with: langGraphWorkflow.with } : {}),
371
+ ...(langGraphWorkflow?.config ? { workflow: langGraphWorkflow.config } : {}),
372
+ }
346
373
  : undefined;
347
374
  const langchainAgentParams = {
348
375
  model: compiledAgentModel,
@@ -383,6 +410,8 @@ export function compileBinding(workspaceRoot, agent, agents, referencedSubagentI
383
410
  adapter: {
384
411
  kind: agent.executionMode === "langgraph" ? "langgraph" : "langchain-v1",
385
412
  config: {
413
+ ...(agent.executionMode === "langgraph" && langGraphWorkflow?.profile ? { profile: langGraphWorkflow.profile } : {}),
414
+ ...(agent.executionMode === "langgraph" && langGraphWorkflow?.with ? { with: langGraphWorkflow.with } : {}),
386
415
  ...(agent.executionMode === "langgraph" && langGraphWorkflow?.preset ? { preset: langGraphWorkflow.preset } : {}),
387
416
  ...(agent.executionMode === "langgraph" && langGraphWorkflow?.config ? { workflow: langGraphWorkflow.config } : {}),
388
417
  params: langchainAgentParams,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botbotgo/agent-harness",
3
- "version": "0.0.93",
3
+ "version": "0.0.94",
4
4
  "description": "Workspace runtime for multi-agent applications",
5
5
  "type": "module",
6
6
  "packageManager": "npm@10.9.2",