@axiom-lattice/core 3.0.4 → 3.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -9035,7 +9035,7 @@ var createReactAgentSchema = (schema6) => {
9035
9035
  };
9036
9036
 
9037
9037
  // src/agent_lattice/builders/ReActAgentGraphBuilder.ts
9038
- var import_langchain45 = require("langchain");
9038
+ var import_langchain47 = require("langchain");
9039
9039
 
9040
9040
  // src/middlewares/codeEvalMiddleware.ts
9041
9041
  var import_langchain37 = require("langchain");
@@ -11249,8 +11249,11 @@ Please select a valid tool from the list above.`
11249
11249
  * The only place to access request.tools (all available tools).
11250
11250
  * Identifies unknown tools and stores error info in metadata.
11251
11251
  *
11252
- * Key: Preserve all tool_calls in original AIMessage, including unknown ones.
11253
- * This allows the model to see what it selected in the next round.
11252
+ * Key: Strip valid tool_calls and only keep unknown ones in the returned
11253
+ * AIMessage. Valid calls must NOT be preserved: afterModel jumps to "model"
11254
+ * and skips ToolNode, so a preserved valid call would have no ToolMessage
11255
+ * and the next model call would be rejected with a 400 dangling tool_calls
11256
+ * error. Stripped valid calls are re-issued by the model in the next round.
11254
11257
  */
11255
11258
  wrapModelCall: async (request, handler) => {
11256
11259
  const availableTools = request.tools || [];
@@ -11280,10 +11283,11 @@ Please select a valid tool from the list above.`
11280
11283
  toolCallId: toolCall.id,
11281
11284
  errorMessage: errorMessageTemplate(toolCall.name, availableToolNames)
11282
11285
  }));
11286
+ const unknownToolIds = new Set(unknownToolCalls.map((toolCall) => toolCall.id));
11287
+ const remainingToolCalls = aiResponse.tool_calls.filter((toolCall) => unknownToolIds.has(toolCall.id));
11283
11288
  const modifiedResponse = new import_messages2.AIMessage({
11284
11289
  content: aiResponse.content,
11285
- tool_calls: aiResponse.tool_calls,
11286
- // Key: preserve all tool_calls, don't delete unknown
11290
+ tool_calls: remainingToolCalls,
11287
11291
  response_metadata: {
11288
11292
  ...aiResponse.response_metadata,
11289
11293
  _unknownToolErrors: unknownToolErrors
@@ -11336,6 +11340,64 @@ Please select a valid tool from the list above.`
11336
11340
  });
11337
11341
  }
11338
11342
 
11343
+ // src/deep_agent_new/middleware/patch_tool_calls.ts
11344
+ var import_langchain45 = require("langchain");
11345
+ function createPatchToolCallsMiddleware() {
11346
+ return (0, import_langchain45.createMiddleware)({
11347
+ name: "patchToolCallsMiddleware",
11348
+ beforeAgent: async (state) => {
11349
+ const messages = state.messages;
11350
+ if (!messages || messages.length === 0) {
11351
+ return;
11352
+ }
11353
+ const replacements = [];
11354
+ for (let i = 0; i < messages.length; i++) {
11355
+ const msg = messages[i];
11356
+ if (import_langchain45.AIMessage.isInstance(msg) && msg.tool_calls != null) {
11357
+ const respondedIds = /* @__PURE__ */ new Set();
11358
+ for (const toolCall of msg.tool_calls) {
11359
+ if (!toolCall.id) continue;
11360
+ const correspondingToolMsg = messages.slice(i).find(
11361
+ (m) => import_langchain45.ToolMessage.isInstance(m) && m.tool_call_id === toolCall.id
11362
+ );
11363
+ if (correspondingToolMsg) {
11364
+ respondedIds.add(toolCall.id);
11365
+ }
11366
+ }
11367
+ const remainingToolCalls = msg.tool_calls.filter(
11368
+ (toolCall) => toolCall.id && respondedIds.has(toolCall.id)
11369
+ );
11370
+ if (remainingToolCalls.length === msg.tool_calls.length) {
11371
+ continue;
11372
+ }
11373
+ const additionalKwargs = { ...msg.additional_kwargs };
11374
+ delete additionalKwargs.tool_calls;
11375
+ if (!msg.id) continue;
11376
+ replacements.push(
11377
+ new import_langchain45.AIMessage({
11378
+ id: msg.id,
11379
+ content: msg.content,
11380
+ name: msg.name,
11381
+ tool_calls: remainingToolCalls,
11382
+ additional_kwargs: additionalKwargs,
11383
+ response_metadata: msg.response_metadata
11384
+ })
11385
+ );
11386
+ }
11387
+ }
11388
+ if (replacements.length === 0) {
11389
+ return;
11390
+ }
11391
+ return {
11392
+ messages: replacements
11393
+ };
11394
+ }
11395
+ });
11396
+ }
11397
+
11398
+ // src/agent_lattice/builders/commonMiddleware.ts
11399
+ var import_langchain46 = require("langchain");
11400
+
11339
11401
  // src/plugin/metaSerializer.ts
11340
11402
  function tryExtractTools(plugin) {
11341
11403
  if (!plugin.middleware) return [];
@@ -12572,6 +12634,30 @@ actually achieve, not just what to build:
12572
12634
 
12573
12635
  Record the goal model in the parent task's description ([[task-tracking]]).
12574
12636
 
12637
+ **HARD RULE \u2014 never guess the target.** If the goal, expected output,
12638
+ consumer, or usable state is unclear at ANY point before writing test
12639
+ cases, you MUST ask the user via ask_user_to_clarify \u2014 never proceed
12640
+ with an assumed expectation. A test case written against a guessed
12641
+ expectation validates the wrong thing. When in doubt, ask.
12642
+
12643
+ ## Knowledge in Skills (apply to EVERY sub-skill workflow)
12644
+
12645
+ **Domain knowledge lives in SKILL.md files, not in prompts.** The
12646
+ deliverable's knowledge (rules, formats, decision logic, procedures) is
12647
+ authored as skills; the executable (agent prompt, workflow step) stays
12648
+ THIN \u2014 role/process only, loading knowledge via "Load [[skill-name]]
12649
+ and follow it". Never write domain knowledge directly into a system
12650
+ prompt or a workflow step's prompt.
12651
+
12652
+ Why: knowledge in prompts cannot be reused, individually verified, or
12653
+ evolved. Knowledge in skills is shared (subSkills), regression-tested
12654
+ ([[eval-verify]]), and improved without touching the executable.
12655
+
12656
+ Applies to every construction path: [[learn-capability]] (skills are
12657
+ the primary output), [[agent-build]] (agent prompt thin, loads skill),
12658
+ [[design-workflow]] (steps reference [[skill-name]] or ref to
12659
+ skill-loading agents). All three follow this single principle.
12660
+
12575
12661
  ## Goal-Driven Validation (apply to EVERY sub-skill workflow)
12576
12662
 
12577
12663
  The agent evaluates goal achievement ITSELF via multi-dimensional test
@@ -12591,6 +12677,29 @@ green = goal achieved (per [[completion-gate]] and [[eval-verify]]).
12591
12677
  The goal model is the acceptance standard \u2014 contentAssertion must
12592
12678
  encode the usable state, not just technical correctness.
12593
12679
 
12680
+ ## Undefined Tasks (outside the skill map)
12681
+
12682
+ If the request does not match any sub-skill workflow: do NOT guess, do
12683
+ NOT refuse, do NOT force-fit an existing flow. Follow the
12684
+ EXPLORE \u2192 PROPOSE \u2192 CONFIRM protocol:
12685
+
12686
+ 1. **Explore** \u2014 inventory before proposing anything:
12687
+ \`list_agents\` / \`load_skills\` (existing assets), \`list_tools\` /
12688
+ \`list_middleware_types\` (capabilities), \`list_connections\`
12689
+ (data sources), eval projects (verification), docs at hand.
12690
+ Goal: know what is reusable and what is missing.
12691
+ 2. **Propose** \u2014 present 2-3 concrete options, each with: what it
12692
+ does, cost, risk, and what it needs (new tools / new skills /
12693
+ approvals).
12694
+ 3. **Confirm** \u2014 the user picks an option or adjusts it. Never
12695
+ execute without a chosen option.
12696
+ 4. **New capability needed?** (new tool type, new skill, new
12697
+ connection) \u2014 include creating it ([[create-skill]] / connection
12698
+ setup) IN the proposed option; never silently proceed without it.
12699
+ 5. **Boundary honesty** \u2014 state clearly what the architect cannot do
12700
+ (e.g. deploy to production, monitor runtime, change frontend),
12701
+ and give the alternative \u2014 never overpromise or silently refuse.
12702
+
12594
12703
  ## Skill Map
12595
12704
  - [[learn-capability]] \u2014 Learn from any source material (user
12596
12705
  description, documents, API specs, conversations, spreadsheets) and
@@ -12657,16 +12766,29 @@ Do NOT use reviewer as:
12657
12766
  verification. If findings show config errors, fix and re-check.`,
12658
12767
  "task-tracking": `---
12659
12768
  name: task-tracking
12660
- description: Manage persistent tasks for agent creation workflows. Use
12661
- manage_task to create parent/subtasks, track progress, and resume
12662
- interrupted runs. Applies to ALL agent building processes.
12769
+ description: Manage persistent tasks with manage_task. Universal rule:
12770
+ once the goal is clear and you know what to do, create the task FIRST
12771
+ then execute. Track parent/subtasks, update status to reflect reality,
12772
+ resume interrupted work. Applies to ANY multi-step agent work \u2014 not
12773
+ just agent building.
12663
12774
  metadata:
12664
12775
  domain: agent-building
12665
12776
  verified: unverified
12666
12777
  ---
12667
12778
  # Task Tracking \u2014 manage_task for Agent Workflows
12668
12779
 
12669
- Every agent creation workflow is a multi-step process \u2014 track it.
12780
+ **Task management is the ongoing record of a goal and its acceptance
12781
+ criteria** \u2014 it answers at any moment: what are we achieving, and what
12782
+ does "done" look like. Create a task when the goal is clear; keep its
12783
+ Objective and Acceptance Criteria current as work proceeds; change
12784
+ status only when the criteria are actually met.
12785
+
12786
+ **Universal principle**: whenever the goal is understood and the work
12787
+ is about to start, create a task BEFORE executing. If you can write an
12788
+ Objective and Acceptance Criteria, it deserves a task. This is not
12789
+ optional and not limited to agent-building \u2014 it applies to any
12790
+ multi-step work (learning, building, modifying skills, fixing, anything
12791
+ with a clear goal).
12670
12792
 
12671
12793
  ## When to create (and when NOT)
12672
12794
 
@@ -12683,13 +12805,32 @@ Do NOT create tasks for:
12683
12805
 
12684
12806
  ## Setup
12685
12807
 
12808
+ **A task is a living record of the GOAL + ACCEPTANCE CRITERIA** \u2014 not a
12809
+ todo label. Every task's description must carry:
12810
+
12811
+ - **Goal Model** \u2014 the full goal model ([[agent-architecture|Goal
12812
+ Model]]): real goal, consumer (who uses the result), usable state
12813
+ (what "done and usable" means concretely)
12814
+ - **Objective** \u2014 one measurable sentence: what result to achieve
12815
+ - **Acceptance Criteria** \u2014 checkboxes that define "done": when ALL
12816
+ are checked, the task is verifiably complete
12817
+
12818
+ The task is created when the goal is confirmed, and its description is
12819
+ CONTINUALLY UPDATED as the work progresses (spec evolves, criteria are
12820
+ met, new criteria emerge). Status changes only when the criteria are
12821
+ truly met \u2014 never as a workaround.
12822
+
12686
12823
  - **Create the parent task when the scope is confirmed** \u2014 before
12687
12824
  starting the first real work phase (probe/design/build):
12688
- \`manage_task create(title: <goal>, description: <summary>, ownerType: "agent")\`
12825
+ \`manage_task create(title: <goal>, description: <Objective + Acceptance Criteria>, ownerType: "agent")\`
12689
12826
  Record the returned parent task id.
12690
12827
  - **Create a subtask per phase** as you start each phase (probe /
12691
12828
  design / build / eval / retro):
12692
- \`manage_task create(title: <phase>, parentId: <parent>, ownerType: "agent")\`
12829
+ \`manage_task create(title: <phase>, description: <Objective + Acceptance Criteria>, parentId: <parent>, ownerType: "agent")\`
12830
+ - **Update the description as work proceeds**: append progress, mark
12831
+ criteria \`[x]\`, revise criteria when the goal model/spec changes.
12832
+ The task tracks the target and its acceptance \u2014 read it to know what
12833
+ "done" means, keep it current so it always reflects reality.
12693
12834
 
12694
12835
  ## Status discipline \u2014 MANDATORY
12695
12836
 
@@ -12820,8 +12961,13 @@ When unsure, use \`show_widget\` for visual comparison.
12820
12961
  - **Follow [[agent-architecture|Goal Model]]** \u2014 establish the goal
12821
12962
  model (real goal / consumer / usable state) and design the agent to
12822
12963
  achieve it; verification is goal-driven ([[agent-architecture|Goal-Driven Validation]]).
12823
- - **NEVER build before confirming.** Design \u2192 ask \u2192 wait for "yes" \u2192
12824
- only then build. No exceptions.
12964
+ - **Follow [[agent-architecture|Knowledge in Skills]]** \u2014 the prompt is
12965
+ thin (role/behavior); domain knowledge lives in SKILL.md which the
12966
+ agent loads ("Load [[skill-name]] and follow it"). Never write
12967
+ domain knowledge directly into a system prompt.
12968
+ - **NEVER build before confirming.** Design \u2192 confirm via
12969
+ \`ask_user_to_clarify\` \u2192 wait for approval \u2192 only then build.
12970
+ No exceptions.
12825
12971
  - **Track with tasks once scope is clear.** After requirements are
12826
12972
  clarified, create the parent task ([[task-tracking]]) before starting
12827
12973
  design. Don't create tasks during clarification.
@@ -12834,18 +12980,23 @@ When unsure, use \`show_widget\` for visual comparison.
12834
12980
 
12835
12981
  ## REACT design steps
12836
12982
 
12837
- 1. Understand the goal (who uses it? inputs? outputs?)
12983
+ 1. **Establish the goal model FIRST** \u2014 real goal / user expectation /
12984
+ consumer / usable state ([[agent-architecture|Goal Model]]); record
12985
+ it in the parent task. Design, build, and verification all derive
12986
+ from it. Only then:
12838
12987
  2. Choose middleware \u2014 call \`list_tools\` and \`list_middleware_types\`
12839
12988
  first. MUST include \`ask_user_to_clarify\` if the agent needs
12840
12989
  confirmation or clarifying questions.
12841
12990
  3. Write the system prompt: role \u2192 workflow \u2192 constraints
12842
12991
  4. Present the design with \`show_widget\`
12843
- 5. Ask for explicit approval \u2014 do NOT build until confirmed
12992
+ 5. Confirm via \`ask_user_to_clarify\` \u2014 do NOT build until approved
12844
12993
  6. Build with \`create_agent\`
12845
12994
 
12846
12995
  ## DEEP_AGENT design steps
12847
12996
 
12848
- 1. Domain analysis \u2014 explain why DEEP_AGENT is the right choice
12997
+ 1. **Establish the goal model FIRST** \u2014 real goal / consumer / usable
12998
+ state, recorded in the parent task ([[agent-architecture|Goal
12999
+ Model]]); then explain why DEEP_AGENT is the right choice
12849
13000
  2. Capability mapping with \`show_widget\`
12850
13001
  3. System prompt emphasizes dynamic todo workflow (analyze \u2192 break
12851
13002
  into todos \u2192 work one at a time \u2192 refine). Middleware: code_eval,
@@ -12997,6 +13148,9 @@ description: Run agent evaluations, interpret results, fix failures, and
12997
13148
  metadata:
12998
13149
  domain: agent-building
12999
13150
  verified: unverified
13151
+ subSkills:
13152
+ - eval-design-tests
13153
+ - eval-run-and-govern
13000
13154
  ---
13001
13155
  # Eval Verify \u2014 Run Evaluations and Upgrade Trust
13002
13156
 
@@ -13013,6 +13167,13 @@ verified: unverified
13013
13167
  parent (eval-{parent-id}) \u2014 see Layered verification below.
13014
13168
  2. \`manage_eval create_case(suiteId, ...)\` per sample or scenario
13015
13169
  Required: inputMessage, steps=[{agent_id}], outputType, contentAssertion
13170
+ **contentAssertion MUST come from the confirmed expected output spec**
13171
+ (learn-capability Phase 2.6) \u2014 never invent expectations at
13172
+ case-writing time. If a needed expectation is not in the spec, extend
13173
+ the spec with user confirmation first.
13174
+ **HARD RULE**: if the target/expected output is unclear at this
13175
+ point, STOP and ask the user (ask_user_to_clarify) \u2014 do not write a
13176
+ case with a guessed expectation.
13016
13177
 
13017
13178
  ## Suites per skill, by source
13018
13179
 
@@ -13022,22 +13183,70 @@ verified: unverified
13022
13183
  (hold-out, never run during fix loop)
13023
13184
  - 0.2 \u2460 \u2192 {skill}-api-verified \u2014 queryability assertion, single step
13024
13185
 
13025
- ## Layered verification (orchestrator + subAgents)
13026
-
13027
- When the design has a parent deep_agent with subAgents (learn-capability
13028
- Phase 2), verification is layered:
13029
- - **Each sub-agent**: its OWN eval project (eval-{sub-agent-id}) \u2014 the
13030
- sub capability is verified independently, with its own fix loop.
13031
- - **The parent agent**: an integration eval project (eval-{parent-id}).
13032
- Integration cases: full end-to-end task input \u2192 parent invokes
13033
- sub-agents \u2192 final aggregated output \u2192 contentAssertion on the final
13034
- result. This verifies ORCHESTRATION (does the parent call the right
13035
- sub-agents in the right order and aggregate correctly).
13036
- - **Parent trust upgrade** requires BOTH: all sub-agent evals pass AND
13037
- the parent's integration eval passes. The parent's metadata
13038
- (verified/source) records this dependency.
13039
- - Independent agents (no parent) keep single-level eval \u2014 no integration
13040
- layer needed.
13186
+ ## Layered verification (orchestrator + components)
13187
+
13188
+ When the design delegates to other agents, verification is layered.
13189
+ "Orchestrator" = a parent deep_agent with subAgents (learn-capability
13190
+ Phase 2) OR a workflow with \`ref\` steps ([[design-workflow]]).
13191
+ "Components" = the subAgents / ref'd agents it calls. Order is MANDATORY:
13192
+ **component evals first, integration second** \u2014 never run the
13193
+ integration eval before every component eval passes.
13194
+
13195
+ - **Each component**: its OWN eval project (eval-{sub-agent-id} /
13196
+ eval-{ref-agent-id}) \u2014 the sub capability is verified independently,
13197
+ with its own fix loop.
13198
+ - **The orchestrator**: an integration eval project (eval-{parent-id} /
13199
+ eval-{workflow-id}). Integration cases: full end-to-end task input \u2192
13200
+ orchestrator invokes components \u2192 final aggregated output \u2192
13201
+ contentAssertion on the final result. This verifies ORCHESTRATION
13202
+ (does the orchestrator call the right components in the right order
13203
+ and aggregate correctly).
13204
+ - **Workflow integration cases** also include branch paths and \`ask\`
13205
+ handling (see Workflow testing below) \u2014 but only AFTER the ref'd
13206
+ agents are independently verified.
13207
+ - **Orchestrator trust upgrade** requires BOTH: all component evals pass
13208
+ AND the orchestrator's integration eval passes. The orchestrator's
13209
+ metadata (verified/source) records this dependency.
13210
+ - Independent agents (no parent, no ref) keep single-level eval \u2014 no
13211
+ integration layer needed.
13212
+
13213
+ ## Workflow testing (WORKFLOW-type agents)
13214
+
13215
+ Workflows compile to the same agent registry and run through the same
13216
+ eval path \u2014 same project naming (eval-{agent-id}), same case structure
13217
+ (inputMessage + steps + contentAssertion). Design differs because the
13218
+ pipeline is DETERMINISTIC:
13219
+
13220
+ - **One case per branch path** \u2014 each if/map/parallel route gets a case
13221
+ whose inputMessage drives it down that path; contentAssertion = the
13222
+ exact output that path must produce (from the expected output spec,
13223
+ Phase 1.5 in [[design-workflow]]).
13224
+ - **Goal-driven dimensions** \u2014 cases cover all four dimensions
13225
+ ([[agent-architecture|Goal-Driven Validation]]), not just happy paths:
13226
+ - Functional correctness \u2014 each branch path produces the right result
13227
+ - Edge robustness \u2014 empty input, if-condition not met, map source
13228
+ empty, malformed data: the pipeline must fail gracefully or take
13229
+ the designed fallback, not crash
13230
+ - Business usability \u2014 output reaches the usable state (usable-state
13231
+ cases come from the confirmed spec, never invented)
13232
+ - Consumer fit \u2014 exact fields/format for system consumers, readable
13233
+ for human consumers
13234
+ - **Data contract cases** \u2014 intermediate \`{{refs}}\` handoffs and
13235
+ \`map\` source shapes are contracts; a contract broken mid-pipeline
13236
+ only surfaces at the end. One case per non-trivial handoff asserting
13237
+ the intermediate output shape (source data + step output).
13238
+ - **\`ask\` steps** \u2014 case interruptPolicy controls them
13239
+ (mode: stop | auto-approve | auto-reject | canned-response):
13240
+ - \`stop\` \u2192 the run pauses at the ask; assert the partial output
13241
+ BEFORE the interaction point
13242
+ - auto-approve / auto-reject / canned-response \u2192 supply the response
13243
+ and continue; assert the flow AFTER the interaction point
13244
+ - \`value\` holds the response text (defaults "\u540C\u610F"/"\u62D2\u7EDD" for
13245
+ approve/reject)
13246
+ - **Exact assertions** \u2014 deterministic pipeline means expected outputs
13247
+ are precise; judge still scores semantics on top.
13248
+ - **Trust upgrade is the same gate** \u2014 [[completion-gate]] applies to
13249
+ workflows: no eval \u2192 stays configured, never verified.
13041
13250
 
13042
13251
  ## Run
13043
13252
 
@@ -13103,11 +13312,39 @@ verified: unverified
13103
13312
  # Design Workflow \u2014 WORKFLOW Agent Design
13104
13313
 
13105
13314
  Use the WORKFLOW type when the process is fully known \u2014 a deterministic
13106
- state machine with pre-defined paths.
13315
+ state machine with pre-defined paths. If the process is NOT fully known
13316
+ (open-ended, needs dynamic decomposition) \u2192 use [[learn-capability]] /
13317
+ [[agent-build]] (REACT / DEEP_AGENT) instead.
13107
13318
  Follow [[agent-architecture|User Interaction Rules]] and
13108
13319
  [[agent-architecture|Goal Model]] \u2014 establish the goal model (real
13109
13320
  goal / consumer / usable state) before designing, and design steps
13110
13321
  that achieve it. Acceptance = workflow outcome meets the usable state.
13322
+ Follow [[agent-architecture|Knowledge in Skills]]: workflow steps
13323
+ orchestrate; domain knowledge lives in SKILL.md. Never write domain
13324
+ knowledge directly into a step's prompt \u2014 load it via [[skill-name]]
13325
+ or delegate to an agent that loads the skill.
13326
+
13327
+ ## CRITICAL RULES
13328
+ - **NEVER build before confirming.** Design \u2192 present the flow as a
13329
+ widget \u2192 discuss step-by-step with the user \u2192 confirm via
13330
+ \`ask_user_to_clarify\` (blocking approval) \u2192 only then call
13331
+ \`create_workflow\`. No exceptions.
13332
+ - **Always visualize the design** \u2014 present with \`show_widget\` as a
13333
+ Flowchart (every step, branch, \`ask\` interaction point) \u2014 never a
13334
+ bare text list (see Visual communication below).
13335
+ - **One decision at a time.** Each message asks exactly one question.
13336
+ - **Track with tasks once scope is clear.** Create the parent task
13337
+ ([[task-tracking]]) before designing; record the expected output spec
13338
+ (Phase 1.5) in it.
13339
+
13340
+ ## Visual communication
13341
+
13342
+ Use \`show_widget\` for all structure explanations \u2014 never ASCII art.
13343
+ | Scenario | What |
13344
+ |----------|------|
13345
+ | Workflow flow | Flowchart (steps, branches, ask points) |
13346
+ | Step-level comparison | Comparison cards |
13347
+ | Data flow / {{refs}} | Flowchart |
13111
13348
 
13112
13349
  ## Phase 0: Load Skills
13113
13350
 
@@ -13117,20 +13354,122 @@ that achieve it. Acceptance = workflow outcome meets the usable state.
13117
13354
 
13118
13355
  ## Phase 1: Design
13119
13356
 
13120
- 1. Analyze the process. Map every step, branch, data dependency.
13121
- 2. Design using the YAML linear DSL (steps, parallel, map, if, ask).
13122
- 3. Present the design as a widget.
13123
- 4. Confirm with user before building.
13124
-
13125
- ## Phase 2: Build
13357
+ 1. **Establish the goal model FIRST** \u2014 real goal / user expectation /
13358
+ consumer / usable state ([[agent-architecture|Goal Model]]); record
13359
+ it in the parent task. It drives the expected output spec (Phase
13360
+ 1.5) and verification (Phase 4). Then analyze the process: map
13361
+ every step, branch, data dependency.
13362
+ 2. **Choose implementation mode per step \u2014 ASK the user** (present as
13363
+ comparison cards). Each step's logic is either inline or \`ref\`:
13364
+ - **inline prompt** \u2014 logic lives in the step's prompt. Fast, no
13365
+ extra agents. Cost: not reusable, no own tools, verified ONLY via
13366
+ the integration eval. OK for trivial one-off glue steps.
13367
+ - **ref sub-agent** \u2014 the step delegates to a registered agent with
13368
+ its own tools/model/skills (built via [[agent-build]], prompt =
13369
+ "Load [[skill-name]] and follow it"). Reusable, independently
13370
+ verified (Phase 2.6). Use when the step needs tools, non-trivial
13371
+ or reusable logic, or independent verification.
13372
+ Present the per-step choice with trade-offs and let the user
13373
+ decide \u2014 NEVER silently pick inline or ref. When in doubt, ask.
13374
+ 3. **Identify knowledge per step** \u2014 for each step, determine the domain
13375
+ knowledge it needs:
13376
+ - Existing skill covers it \u2192 reference [[skill-name]] in the step
13377
+ - No skill yet, but the knowledge is reusable or non-trivial \u2192
13378
+ plan to create it (Phase 1.5)
13379
+ - Trivial one-off logic \u2192 may stay inline in the prompt (accept the
13380
+ trade-off: it is not reusable or individually verifiable)
13381
+ 4. Design using the YAML linear DSL (steps, parallel, map, if, ask).
13382
+ 5. **Present the design as a Flowchart widget** (\`show_widget\`) \u2014 every
13383
+ step, branch, and \`ask\` interaction point. Walk through it with the
13384
+ user step-by-step (each step's responsibility, branch logic, ask
13385
+ points). CONFIRM via \`ask_user_to_clarify\` \u2014 never build without
13386
+ explicit user approval.
13387
+
13388
+ ## Phase 1.5: Expected Output Specification (mandatory \u2014 goal-driven)
13389
+
13390
+ Define the workflow's EXPECTED OUTPUT SPEC from the goal model BEFORE
13391
+ writing skills or building: what the final outcome looks like, per
13392
+ consumer (0.1.5). This is the acceptance standard \u2014 [[eval-verify]]
13393
+ contentAssertion derives from it. HARD RULE: if the target/expected
13394
+ output is unclear, ask the user \u2014 never guess.
13395
+ Present the spec, confirm with the user, record in the parent task.
13396
+
13397
+ ## Phase 2: Create Skills (for missing knowledge)
13398
+
13399
+ For each planned skill (Phase 1.2): write SKILL.md (frontmatter +
13400
+ body encoding the domain rules). Present each for user approval.
13401
+ When 3+ skills share a domain \u2192 create a MOC ([[domain-moc]]).
13402
+ If a ref step needs an agent \u2192 build it via [[agent-build]] (agent
13403
+ prompt = "Load [[skill-name]] and follow it" \u2014 thin, knowledge in
13404
+ skill). Order: sub-agents/skills first, then the workflow that
13405
+ references them.
13406
+
13407
+ ## Phase 2.6: Verify components FIRST (mandatory)
13408
+
13409
+ Every agent referenced by a \`ref\` step is a component with its OWN
13410
+ independent eval (eval-{ref-agent-id}) \u2014 run it and pass it BEFORE
13411
+ building the integration eval. The workflow cannot be considered tested
13412
+ until: \u2460 each ref'd agent's eval passes independently, \u2461 then the
13413
+ workflow's integration eval (branch paths + ask handling) passes. See
13414
+ [[eval-verify|Layered verification]].
13415
+
13416
+ ## Phase 3: Build
13417
+
13418
+ 1. **Configure middleware & tools for the workflow itself** \u2014 inline
13419
+ steps run on the workflow's own model/tools: call
13420
+ \`list_middleware_types\` first; add what the workflow needs \u2014 skill
13421
+ (if steps load [[skill-name]]), widget, ask_user_to_clarify, etc.
13422
+ Tool filtering via \`allowedTools\`. \`ref\` steps use the ref'd
13423
+ agent's own tools/model \u2014 nothing to configure here. Choose
13424
+ \`modelKey\` only when a specific model is required (default
13425
+ otherwise).
13426
+ 2. Call \`create_workflow\` with \`skillLoaded: true\` \u2014 steps reference
13427
+ [[skill-name]] or \`ref\` to skill-loading agents.
13428
+ 3. Then \`validate_workflow(id)\`.
13429
+
13430
+ ## Phase 4: Test (mandatory \u2014 no eval, no trust tier)
13431
+
13432
+ The authoritative verification is [[eval-verify]] \u2014 cases derive from
13433
+ the expected output spec (Phase 1.5). A workflow without a passing eval
13434
+ stays at "configured" forever \u2014 trust can never upgrade
13435
+ ([[completion-gate]], no skip option).
13436
+
13437
+ **Testing is managed through the eval project (eval-{workflow-id})
13438
+ and its cases \u2014 the same governance as agents.** Temporary or quick
13439
+ checks (ad-hoc runs, previewing behavior) may use [[review-agent]] as
13440
+ an interactive pre-check \u2014 but that is NOT the workflow's test suite:
13441
+ it never upgrades trust and never replaces the eval project. Only the
13442
+ eval project's cases passing determine "tested".
13443
+
13444
+ **Test order \u2014 components first, then integration:**
13445
+ 1. Each \`ref\`'d agent: its OWN eval (eval-{ref-agent-id}) must pass
13446
+ independently (Phase 2.6) \u2014 fix it in isolation, not through the
13447
+ workflow.
13448
+ 2. Then the workflow's integration eval (eval-{workflow-id}): one case
13449
+ per branch path (if/map/parallel); \`ask\` steps via case
13450
+ interruptPolicy (auto-approve/canned-response to test the flow AFTER
13451
+ the pause, stop to test up to the pause); assertions are exact \u2014
13452
+ the pipeline is deterministic.
13453
+
13454
+ Workflow trust upgrade requires BOTH layers passing.
13455
+ [[review-agent]] is an optional cheap pre-check only.
13456
+
13457
+ ## Editing workflows
13458
+
13459
+ Get the current YAML \u2192 present the diff \u2192 confirm with the user \u2192
13460
+ \`update_workflow(id, ...)\`. Never re-create.
13461
+ After ANY change: verified resets to unverified and the eval is re-run
13462
+ ([[eval-verify]]) \u2014 the change is not done until the eval passes again.
13463
+ Deleting: warn if any step \`ref\`s it \u2192 confirm \u2192 \`delete_agent\`.
13126
13464
 
13127
- Call \`create_workflow\` with \`skillLoaded: true\`, then
13128
- \`validate_workflow(id)\`.
13129
-
13130
- ## Phase 3: Test
13465
+ ## Metadata
13131
13466
 
13132
- Ask user if they want to test \u2014 the authoritative verification is
13133
- [[eval-verify]]. [[review-agent]] is an optional cheap pre-check only.
13467
+ Always set metadata on workflow creation. At minimum:
13468
+ - verified: "unverified" (upgraded after eval passes)
13469
+ - version: "1.0" (bump on each update)
13470
+ - source: the material name or "user-description"
13471
+ When trust upgrades, update BOTH the skill's verified frontmatter and
13472
+ the workflow's metadata.verified \u2014 they must stay in sync.
13134
13473
 
13135
13474
  ## No edges, state fields, or end step
13136
13475
  The engine auto-generates them. Steps execute top-to-bottom in written
@@ -13356,10 +13695,20 @@ async function resolveConnections(type, connections, tenantId2) {
13356
13695
  throw err;
13357
13696
  }
13358
13697
  }
13359
- async function createCommonMiddlewares(middlewareConfigs, filesystemBackend, fsIsExised, tenantId2) {
13698
+ async function createCommonMiddlewares(middlewareConfigs, filesystemBackend, fsIsExised, tenantId2, model) {
13360
13699
  const middlewares = [];
13361
13700
  middlewares.push(createUnknownToolHandlerMiddleware());
13362
13701
  middlewares.push(createModelSelectorMiddleware());
13702
+ middlewares.push(createPatchToolCallsMiddleware());
13703
+ if (model) {
13704
+ middlewares.push(
13705
+ (0, import_langchain46.summarizationMiddleware)({
13706
+ model,
13707
+ trigger: { tokens: 17e4 },
13708
+ keep: { messages: 6 }
13709
+ })
13710
+ );
13711
+ }
13363
13712
  const filesystemConfig = middlewareConfigs.find((m) => m.type === "filesystem");
13364
13713
  const clawConfig = middlewareConfigs.find((m) => m.type === "claw");
13365
13714
  const needsFilesystemBackend = filesystemConfig?.enabled || clawConfig?.enabled;
@@ -13691,8 +14040,8 @@ var ReActAgentGraphBuilder = class {
13691
14040
  const stateSchema2 = createReactAgentSchema(params.stateSchema);
13692
14041
  const middlewareConfigs = params.middleware || [];
13693
14042
  const filesystemBackend = createFilesystemBackendFactory(middlewareConfigs);
13694
- const middlewares = await createCommonMiddlewares(middlewareConfigs, filesystemBackend, void 0, params.tenantId);
13695
- return (0, import_langchain45.createAgent)({
14043
+ const middlewares = await createCommonMiddlewares(middlewareConfigs, filesystemBackend, void 0, params.tenantId, params.model);
14044
+ return (0, import_langchain47.createAgent)({
13696
14045
  model: params.model,
13697
14046
  tools,
13698
14047
  systemPrompt: params.prompt,
@@ -13706,11 +14055,11 @@ var ReActAgentGraphBuilder = class {
13706
14055
  };
13707
14056
 
13708
14057
  // src/deep_agent_new/agent.ts
13709
- var import_langchain53 = require("langchain");
14058
+ var import_langchain54 = require("langchain");
13710
14059
 
13711
14060
  // src/deep_agent_new/middleware/subagents.ts
13712
14061
  var import_v32 = require("zod/v3");
13713
- var import_langchain48 = require("langchain");
14062
+ var import_langchain50 = require("langchain");
13714
14063
  var import_langgraph8 = require("@langchain/langgraph");
13715
14064
  var import_messages3 = require("@langchain/core/messages");
13716
14065
 
@@ -14125,7 +14474,7 @@ var QueueMode = /* @__PURE__ */ ((QueueMode2) => {
14125
14474
 
14126
14475
  // src/services/Agent.ts
14127
14476
  var import_langgraph6 = require("@langchain/langgraph");
14128
- var import_langchain46 = require("langchain");
14477
+ var import_langchain48 = require("langchain");
14129
14478
 
14130
14479
  // src/chunk_buffer_lattice/ChunkBuffer.ts
14131
14480
  var ChunkBuffer = class {
@@ -14622,7 +14971,7 @@ var Agent = class {
14622
14971
  });
14623
14972
  const humanContent = p.content;
14624
14973
  const input = {
14625
- messages: [new import_langchain46.HumanMessage({ id: humanContent.id, content: humanContent.message })]
14974
+ messages: [new import_langchain48.HumanMessage({ id: humanContent.id, content: humanContent.message })]
14626
14975
  };
14627
14976
  if (files) {
14628
14977
  input.files = files;
@@ -14696,7 +15045,7 @@ var Agent = class {
14696
15045
  remainingPendings.forEach((p) => {
14697
15046
  this.queueStore?.markProcessing(p.id);
14698
15047
  const humanContent = p.content;
14699
- userMessages.push(new import_langchain46.HumanMessage({ id: humanContent.id, content: humanContent.message }));
15048
+ userMessages.push(new import_langchain48.HumanMessage({ id: humanContent.id, content: humanContent.message }));
14700
15049
  this.publish("message:started", {
14701
15050
  type: "message:started",
14702
15051
  messageId: humanContent.id,
@@ -14776,7 +15125,7 @@ var Agent = class {
14776
15125
  if (signal?.aborted) break;
14777
15126
  await this.queueStore?.markProcessing(p.id);
14778
15127
  const humanContent = p.content;
14779
- const message = new import_langchain46.HumanMessage({ id: humanContent.id, content: humanContent.message });
15128
+ const message = new import_langchain48.HumanMessage({ id: humanContent.id, content: humanContent.message });
14780
15129
  const startTime = Date.now();
14781
15130
  this.publish("message:started", {
14782
15131
  type: "message:started",
@@ -14947,7 +15296,7 @@ var Agent = class {
14947
15296
  const messageId = (0, import_uuid4.v4)();
14948
15297
  const input = {
14949
15298
  ...queueMessage.input,
14950
- messages: [new import_langchain46.HumanMessage({ id: messageId, content: queueMessage.input.message })]
15299
+ messages: [new import_langchain48.HumanMessage({ id: messageId, content: queueMessage.input.message })]
14951
15300
  };
14952
15301
  const inputMessage = { ...queueMessage, input };
14953
15302
  return this.agentExecutor(inputMessage, signal);
@@ -14966,7 +15315,7 @@ var Agent = class {
14966
15315
  const messageId = (0, import_uuid4.v4)();
14967
15316
  const input = {
14968
15317
  ...queueMessage.input,
14969
- messages: [new import_langchain46.HumanMessage({ id: messageId, content: queueMessage.input.message })]
15318
+ messages: [new import_langchain48.HumanMessage({ id: messageId, content: queueMessage.input.message })]
14970
15319
  };
14971
15320
  const inputMessage = { ...queueMessage, input };
14972
15321
  const { runnable_agent, runConfig } = await this.getLatticeClientAndRuntimeConfig(inputMessage.custom_run_config);
@@ -15329,7 +15678,7 @@ var Agent = class {
15329
15678
  async getCurrentMessages() {
15330
15679
  const state = await this.getCurrentState();
15331
15680
  const messages = state.values.messages || [];
15332
- const filteredMessages = (0, import_langchain46.filterMessages)(messages, {
15681
+ const filteredMessages = (0, import_langchain48.filterMessages)(messages, {
15333
15682
  includeTypes: ["ai", "human", "tool"]
15334
15683
  //["human", "ai", "tool"],
15335
15684
  });
@@ -15648,7 +15997,7 @@ var AgentInstanceManager = class _AgentInstanceManager {
15648
15997
  var agentInstanceManager = AgentInstanceManager.getInstance();
15649
15998
 
15650
15999
  // src/middlewares/taskMiddleware.ts
15651
- var import_langchain47 = require("langchain");
16000
+ var import_langchain49 = require("langchain");
15652
16001
  var import_zod43 = require("zod");
15653
16002
  var import_langgraph7 = require("@langchain/langgraph");
15654
16003
  function getRunConfig(config) {
@@ -15956,26 +16305,37 @@ function createTaskMiddleware() {
15956
16305
  });
15957
16306
  }
15958
16307
  };
15959
- return (0, import_langchain47.createMiddleware)({
16308
+ return (0, import_langchain49.createMiddleware)({
15960
16309
  name: "TaskMiddleware",
15961
16310
  contextSchema,
15962
16311
  wrapModelCall: async (request, handler) => {
15963
16312
  const taskPrompt = `## Task Management
15964
16313
 
15965
- You can use the \`manage_task\` tool to create persistent tasks for user-visible work tracking.
16314
+ You have the \`manage_task\` tool to track work. Task management is the
16315
+ ongoing record of a GOAL and its ACCEPTANCE CRITERIA.
15966
16316
 
15967
- ### When to create a task
16317
+ ### When to create a task (universal rule)
16318
+ - The goal is clear and you are about to start real work \u2192 create the
16319
+ parent task FIRST (with Objective + Acceptance Criteria in the
16320
+ description), then execute. This is a core duty, not optional.
15968
16321
  - The user explicitly asks you to track, manage, or follow up on work
15969
16322
  - The work spans multiple sessions or might need resumption later
15970
16323
  - The user needs to review or approve output before it is considered done
15971
16324
  - There are multiple independent work items the user wants visibility into
15972
16325
 
15973
16326
  ### When NOT to create a task
16327
+ - Goal not yet clear (still clarifying) \u2014 clarify first, then create
15974
16328
  - One-shot lookups or simple Q&A ("what is X?", "search for Y")
15975
16329
  - Internal exploration steps you take to understand the problem (use \`write_todos\` for your execution plan instead)
15976
16330
  - Trivial single-step actions that complete in the same turn
15977
16331
  - Conversational or informational requests with no deliverable
15978
16332
 
16333
+ ### Keep the task current
16334
+ A task is the living record of the goal + its acceptance criteria.
16335
+ Update the description as work proceeds: check off criteria as met,
16336
+ revise criteria when scope changes, append progress. Status changes
16337
+ only when the criteria are truly met.
16338
+
15979
16339
  ### Ownership defaults
15980
16340
  - No params: ownerType defaults to "user" with current user's ID
15981
16341
  - ownerType="agent": auto-fills ownerId from current agent (subtask for yourself)
@@ -15986,7 +16346,7 @@ You can use the \`manage_task\` tool to create persistent tasks for user-visible
15986
16346
  });
15987
16347
  },
15988
16348
  tools: [
15989
- (0, import_langchain47.tool)(
16349
+ (0, import_langchain49.tool)(
15990
16350
  handleManageTask,
15991
16351
  {
15992
16352
  name: "manage_task",
@@ -16029,6 +16389,29 @@ var taskPlugin = {
16029
16389
  skills: {
16030
16390
  "task-definition": `## Using manage_task
16031
16391
 
16392
+ ### When to create a task (universal rule)
16393
+
16394
+ Create a task BEFORE executing whenever the goal is clear and you know
16395
+ what to do \u2014 not just for long or complex work:
16396
+
16397
+ - Goal is understood and you are about to start real work \u2192 create the
16398
+ parent task FIRST, then execute. The task tracks the work.
16399
+ - Goal is NOT yet clear (still clarifying, gathering requirements) \u2192
16400
+ do NOT create a task yet. Clarify first, create the task once scope
16401
+ is defined.
16402
+ - One-shot lookups, trivial single-step actions, or internal reasoning
16403
+ \u2192 no task needed.
16404
+
16405
+ Rule of thumb: if you can write an Objective and Acceptance Criteria
16406
+ for it, create the task before doing it. Work without a task = work
16407
+ without a contract.
16408
+
16409
+ **A task is the living record of the goal + its acceptance criteria.**
16410
+ Keep the description current as work proceeds: update the Objective
16411
+ when the target evolves, check off criteria as they are met, revise
16412
+ criteria when scope changes. Reading the task always tells you what
16413
+ "done" means; an outdated task is a broken contract.
16414
+
16032
16415
  ### Task description format
16033
16416
 
16034
16417
  When creating a task with manage_task, write the description in this Markdown structure:
@@ -16230,7 +16613,7 @@ function returnCommandWithStateUpdate(result, toolCallId) {
16230
16613
  update: {
16231
16614
  ...stateUpdate,
16232
16615
  messages: [
16233
- new import_langchain48.ToolMessage({
16616
+ new import_langchain50.ToolMessage({
16234
16617
  content: lastMessage?.content || "Task Failed to complete",
16235
16618
  tool_call_id: toolCallId,
16236
16619
  name: "task"
@@ -16259,10 +16642,10 @@ function getSubagents(options) {
16259
16642
  const generalPurposeMiddleware = [...defaultSubagentMiddleware, ...taskMiddleware];
16260
16643
  if (defaultInterruptOn) {
16261
16644
  generalPurposeMiddleware.push(
16262
- (0, import_langchain48.humanInTheLoopMiddleware)({ interruptOn: defaultInterruptOn })
16645
+ (0, import_langchain50.humanInTheLoopMiddleware)({ interruptOn: defaultInterruptOn })
16263
16646
  );
16264
16647
  }
16265
- const generalPurposeSubagent = (0, import_langchain48.createAgent)({
16648
+ const generalPurposeSubagent = (0, import_langchain50.createAgent)({
16266
16649
  model: defaultModel,
16267
16650
  systemPrompt: DEFAULT_SUBAGENT_PROMPT,
16268
16651
  tools: defaultTools,
@@ -16285,8 +16668,8 @@ function getSubagents(options) {
16285
16668
  const middleware = agentParams.middleware ? [...defaultSubagentMiddleware, ...taskMiddleware, ...agentParams.middleware] : [...defaultSubagentMiddleware, ...taskMiddleware];
16286
16669
  const interruptOn = agentParams.interruptOn || defaultInterruptOn;
16287
16670
  if (interruptOn)
16288
- middleware.push((0, import_langchain48.humanInTheLoopMiddleware)({ interruptOn }));
16289
- agents[agentParams.key] = (0, import_langchain48.createAgent)({
16671
+ middleware.push((0, import_langchain50.humanInTheLoopMiddleware)({ interruptOn }));
16672
+ agents[agentParams.key] = (0, import_langchain50.createAgent)({
16290
16673
  model: agentParams.model ?? defaultModel,
16291
16674
  systemPrompt: agentParams.systemPrompt,
16292
16675
  tools: agentParams.tools ?? defaultTools,
@@ -16336,7 +16719,7 @@ function createTaskTool(options) {
16336
16719
  generalPurposeAgent
16337
16720
  });
16338
16721
  const finalTaskDescription = taskDescription ? taskDescription : getTaskToolDescription(subagentDescriptions);
16339
- return (0, import_langchain48.tool)(
16722
+ return (0, import_langchain50.tool)(
16340
16723
  async (input, config) => {
16341
16724
  const { description, subagent_type, async } = input;
16342
16725
  let assistant_id = subagent_type;
@@ -16423,7 +16806,7 @@ You are executing a persistent task (ID: ${input.taskId}). Use manage_task.updat
16423
16806
  return new import_langgraph8.Command({
16424
16807
  update: {
16425
16808
  messages: [
16426
- new import_langchain48.ToolMessage({
16809
+ new import_langchain50.ToolMessage({
16427
16810
  content: `Async task started: ${subagent_thread_id}
16428
16811
  ${description}
16429
16812
  The result will be delivered as a notification when complete. Do not poll.`,
@@ -16457,7 +16840,7 @@ The result will be delivered as a notification when complete. Do not poll.`,
16457
16840
  return new import_langgraph8.Command({
16458
16841
  update: {
16459
16842
  messages: [
16460
- new import_langchain48.ToolMessage({
16843
+ new import_langchain50.ToolMessage({
16461
16844
  content: error instanceof Error ? error.message : "Task Failed to complete",
16462
16845
  tool_call_id: config.toolCall.id,
16463
16846
  name: "task"
@@ -16500,7 +16883,7 @@ function getMainAgentFromConfig(config) {
16500
16883
  });
16501
16884
  }
16502
16885
  function createCheckAsyncTaskTool() {
16503
- return (0, import_langchain48.tool)(
16886
+ return (0, import_langchain50.tool)(
16504
16887
  async (input, config) => {
16505
16888
  const { task_id } = input;
16506
16889
  const mainAgent = getMainAgentFromConfig(config);
@@ -16567,7 +16950,7 @@ Description: ${cached.description}`;
16567
16950
  );
16568
16951
  }
16569
16952
  function createListAsyncTasksTool() {
16570
- return (0, import_langchain48.tool)(
16953
+ return (0, import_langchain50.tool)(
16571
16954
  async (_input, config) => {
16572
16955
  const mainAgent = getMainAgentFromConfig(config);
16573
16956
  if (!mainAgent) {
@@ -16618,7 +17001,7 @@ function createListAsyncTasksTool() {
16618
17001
  );
16619
17002
  }
16620
17003
  function createCancelAsyncTaskTool() {
16621
- return (0, import_langchain48.tool)(
17004
+ return (0, import_langchain50.tool)(
16622
17005
  async (input, config) => {
16623
17006
  const { task_id } = input;
16624
17007
  const mainAgent = getMainAgentFromConfig(config);
@@ -16694,7 +17077,7 @@ function createSubAgentMiddleware(options) {
16694
17077
  );
16695
17078
  }
16696
17079
  const effectiveSystemPrompt = allowAsync ? systemPrompt + getAsyncPromptText() : systemPrompt;
16697
- return (0, import_langchain48.createMiddleware)({
17080
+ return (0, import_langchain50.createMiddleware)({
16698
17081
  name: "subAgentMiddleware",
16699
17082
  tools: allTools,
16700
17083
  wrapModelCall: async (request, handler) => {
@@ -16713,51 +17096,8 @@ ${effectiveSystemPrompt}` : effectiveSystemPrompt;
16713
17096
  });
16714
17097
  }
16715
17098
 
16716
- // src/deep_agent_new/middleware/patch_tool_calls.ts
16717
- var import_langchain49 = require("langchain");
16718
- function createPatchToolCallsMiddleware() {
16719
- return (0, import_langchain49.createMiddleware)({
16720
- name: "patchToolCallsMiddleware",
16721
- beforeAgent: async (state) => {
16722
- const messages = state.messages;
16723
- if (!messages || messages.length === 0) {
16724
- return;
16725
- }
16726
- const patchedMessages = [];
16727
- for (let i = 0; i < messages.length; i++) {
16728
- const msg = messages[i];
16729
- patchedMessages.push(msg);
16730
- if (import_langchain49.AIMessage.isInstance(msg) && msg.tool_calls != null) {
16731
- for (const toolCall of msg.tool_calls) {
16732
- const correspondingToolMsg = messages.slice(i).find(
16733
- (m) => import_langchain49.ToolMessage.isInstance(m) && m.tool_call_id === toolCall.id
16734
- );
16735
- if (!correspondingToolMsg) {
16736
- const toolMsg = `Tool call ${toolCall.name} with id ${toolCall.id} was cancelled - another message came in before it could be completed.`;
16737
- patchedMessages.push(
16738
- new import_langchain49.ToolMessage({
16739
- content: toolMsg,
16740
- name: toolCall.name,
16741
- tool_call_id: toolCall.id
16742
- })
16743
- );
16744
- }
16745
- }
16746
- }
16747
- }
16748
- if (patchedMessages.length === messages.length) {
16749
- return;
16750
- }
16751
- return {
16752
- messages: patchedMessages.slice(messages.length)
16753
- // only the new ToolMessage patches
16754
- };
16755
- }
16756
- });
16757
- }
16758
-
16759
17099
  // src/deep_agent_new/middleware/date.ts
16760
- var import_langchain50 = require("langchain");
17100
+ var import_langchain51 = require("langchain");
16761
17101
  var import_zod44 = require("zod");
16762
17102
  function formatCurrentDate(timezone = "UTC") {
16763
17103
  const now = /* @__PURE__ */ new Date();
@@ -16786,10 +17126,10 @@ function generateDateContext(timezone = "UTC") {
16786
17126
  function createDateMiddleware(options = {}) {
16787
17127
  const timezone = options.timezone || "UTC";
16788
17128
  const dateContext = generateDateContext(timezone);
16789
- return (0, import_langchain50.createMiddleware)({
17129
+ return (0, import_langchain51.createMiddleware)({
16790
17130
  name: "DateMiddleware",
16791
17131
  tools: [
16792
- (0, import_langchain50.tool)(
17132
+ (0, import_langchain51.tool)(
16793
17133
  async () => {
16794
17134
  const now = /* @__PURE__ */ new Date();
16795
17135
  let validTimezone = timezone;
@@ -16885,7 +17225,7 @@ var datePlugin = {
16885
17225
  };
16886
17226
 
16887
17227
  // src/deep_agent_new/middleware/scheduler.ts
16888
- var import_langchain51 = require("langchain");
17228
+ var import_langchain52 = require("langchain");
16889
17229
  var import_zod45 = require("zod");
16890
17230
  var import_uuid5 = require("uuid");
16891
17231
  var import_protocols8 = require("@axiom-lattice/protocols");
@@ -17954,10 +18294,10 @@ function registerAgentAddMessageHandler() {
17954
18294
  function createSchedulerMiddleware(options = {}) {
17955
18295
  const defaultMaxRetries = options.defaultMaxRetries ?? 0;
17956
18296
  registerAgentAddMessageHandler();
17957
- return (0, import_langchain51.createMiddleware)({
18297
+ return (0, import_langchain52.createMiddleware)({
17958
18298
  name: "SchedulerMiddleware",
17959
18299
  tools: [
17960
- (0, import_langchain51.tool)(
18300
+ (0, import_langchain52.tool)(
17961
18301
  async (input, config) => {
17962
18302
  const runConfig = getRunConfig2(config);
17963
18303
  const scheduleLattice = getScheduleLattice(SCHEDULE_LATTICE_KEY);
@@ -17992,7 +18332,7 @@ function createSchedulerMiddleware(options = {}) {
17992
18332
  })
17993
18333
  }
17994
18334
  ),
17995
- (0, import_langchain51.tool)(
18335
+ (0, import_langchain52.tool)(
17996
18336
  async (input, config) => {
17997
18337
  const runConfig = getRunConfig2(config);
17998
18338
  const scheduleLattice = getScheduleLattice(SCHEDULE_LATTICE_KEY);
@@ -18027,7 +18367,7 @@ function createSchedulerMiddleware(options = {}) {
18027
18367
  })
18028
18368
  }
18029
18369
  ),
18030
- (0, import_langchain51.tool)(
18370
+ (0, import_langchain52.tool)(
18031
18371
  async (input, config) => {
18032
18372
  const runConfig = getRunConfig2(config);
18033
18373
  const scheduleLattice = getScheduleLattice(SCHEDULE_LATTICE_KEY);
@@ -18071,7 +18411,7 @@ function createSchedulerMiddleware(options = {}) {
18071
18411
  })
18072
18412
  }
18073
18413
  ),
18074
- (0, import_langchain51.tool)(
18414
+ (0, import_langchain52.tool)(
18075
18415
  async (input) => {
18076
18416
  const scheduleLattice = getScheduleLattice(SCHEDULE_LATTICE_KEY);
18077
18417
  const success = await scheduleLattice.client.cancel(input.taskId);
@@ -18085,7 +18425,7 @@ function createSchedulerMiddleware(options = {}) {
18085
18425
  })
18086
18426
  }
18087
18427
  ),
18088
- (0, import_langchain51.tool)(
18428
+ (0, import_langchain52.tool)(
18089
18429
  async (input, config) => {
18090
18430
  const runConfig = getRunConfig2(config);
18091
18431
  const scheduleLattice = getScheduleLattice(SCHEDULE_LATTICE_KEY);
@@ -19355,7 +19695,7 @@ var MemoryBackend = class {
19355
19695
  // src/deep_agent_new/middleware/todos.ts
19356
19696
  var import_langgraph9 = require("@langchain/langgraph");
19357
19697
  var import_zod46 = require("zod");
19358
- var import_langchain52 = require("langchain");
19698
+ var import_langchain53 = require("langchain");
19359
19699
  var WRITE_TODOS_DESCRIPTION = `Use this tool to create and manage a structured task list for your current work session. This helps you track progress, organize complex tasks, and demonstrate thoroughness to the user.
19360
19700
  It also helps the user understand the progress of the task and overall progress of their requests.
19361
19701
  Only use this tool if you think it will be helpful in staying organized. If the user's request is trivial and takes less than 3 steps, it is better to NOT use this tool and just do the taks directly.
@@ -19589,13 +19929,13 @@ var TodoSchema = import_zod46.z.object({
19589
19929
  });
19590
19930
  var stateSchema = import_zod46.z.object({ todos: import_zod46.z.array(TodoSchema).default([]) });
19591
19931
  function todoListMiddleware(options) {
19592
- const writeTodos = (0, import_langchain52.tool)(
19932
+ const writeTodos = (0, import_langchain53.tool)(
19593
19933
  ({ todos }, config) => {
19594
19934
  return new import_langgraph9.Command({
19595
19935
  update: {
19596
19936
  todos,
19597
19937
  messages: [
19598
- new import_langchain52.ToolMessage({
19938
+ new import_langchain53.ToolMessage({
19599
19939
  content: genUIMarkdown("todo_list", todos),
19600
19940
  tool_call_id: config.toolCall?.id
19601
19941
  })
@@ -19611,7 +19951,7 @@ function todoListMiddleware(options) {
19611
19951
  })
19612
19952
  }
19613
19953
  );
19614
- return (0, import_langchain52.createMiddleware)({
19954
+ return (0, import_langchain53.createMiddleware)({
19615
19955
  name: "todoListMiddleware",
19616
19956
  stateSchema,
19617
19957
  tools: [writeTodos],
@@ -19662,42 +20002,26 @@ ${BASE_PROMPT}` : BASE_PROMPT;
19662
20002
  createFilesystemMiddleware({
19663
20003
  backend: filesystemBackend
19664
20004
  }),
19665
- // Subagent middleware: Automatic conversation summarization when token limits are approached
19666
- (0, import_langchain53.summarizationMiddleware)({
19667
- model,
19668
- trigger: { tokens: 17e4 },
19669
- keep: { messages: 6 }
19670
- }),
19671
20005
  // Subagent middleware: Anthropic prompt caching for improved performance
19672
- (0, import_langchain53.anthropicPromptCachingMiddleware)({
20006
+ (0, import_langchain54.anthropicPromptCachingMiddleware)({
19673
20007
  unsupportedModelBehavior: "ignore"
19674
20008
  }),
19675
- // Subagent middleware: Patches tool calls for compatibility
19676
- createPatchToolCallsMiddleware(),
19677
20009
  ...customMiddleware
19678
20010
  ],
19679
20011
  defaultInterruptOn: interruptOn,
19680
20012
  subagents,
19681
20013
  generalPurposeAgent: true
19682
20014
  }),
19683
- // Automatically summarizes conversation history when token limits are approached
19684
- (0, import_langchain53.summarizationMiddleware)({
19685
- model,
19686
- trigger: { tokens: 17e4 },
19687
- keep: { messages: 6 }
19688
- }),
19689
20015
  // Enables Anthropic prompt caching for improved performance and reduced costs
19690
- (0, import_langchain53.anthropicPromptCachingMiddleware)({
20016
+ (0, import_langchain54.anthropicPromptCachingMiddleware)({
19691
20017
  unsupportedModelBehavior: "ignore"
19692
- }),
19693
- // Patches tool calls to ensure compatibility across different model providers
19694
- createPatchToolCallsMiddleware()
20018
+ })
19695
20019
  ];
19696
20020
  if (interruptOn) {
19697
- middleware.push((0, import_langchain53.humanInTheLoopMiddleware)({ interruptOn }));
20021
+ middleware.push((0, import_langchain54.humanInTheLoopMiddleware)({ interruptOn }));
19698
20022
  }
19699
20023
  middleware.push(...customMiddleware);
19700
- return (0, import_langchain53.createAgent)({
20024
+ return (0, import_langchain54.createAgent)({
19701
20025
  model,
19702
20026
  systemPrompt: finalSystemPrompt,
19703
20027
  tools,
@@ -19747,7 +20071,7 @@ var DeepAgentGraphBuilder = class {
19747
20071
  }));
19748
20072
  const middlewareConfigs = params.middleware || [];
19749
20073
  const filesystemBackend = createFilesystemBackendFactory(middlewareConfigs);
19750
- const middlewares = await createCommonMiddlewares(middlewareConfigs, filesystemBackend, true, params.tenantId);
20074
+ const middlewares = await createCommonMiddlewares(middlewareConfigs, filesystemBackend, true, params.tenantId, params.model);
19751
20075
  const deepAgent = createDeepAgent({
19752
20076
  tools,
19753
20077
  model: params.model,
@@ -19769,7 +20093,7 @@ init_MemoryLatticeManager();
19769
20093
 
19770
20094
  // src/agent_team/agent_team.ts
19771
20095
  var import_v35 = require("zod/v3");
19772
- var import_langchain56 = require("langchain");
20096
+ var import_langchain57 = require("langchain");
19773
20097
 
19774
20098
  // src/agent_team/types.ts
19775
20099
  var TaskStatus = /* @__PURE__ */ ((TaskStatus3) => {
@@ -20205,13 +20529,13 @@ var InMemoryMailboxStore = class {
20205
20529
 
20206
20530
  // src/agent_team/middleware/team.ts
20207
20531
  var import_v34 = require("zod/v3");
20208
- var import_langchain55 = require("langchain");
20532
+ var import_langchain56 = require("langchain");
20209
20533
  var import_langgraph11 = require("@langchain/langgraph");
20210
20534
  var import_uuid6 = require("uuid");
20211
20535
 
20212
20536
  // src/agent_team/middleware/teammate_tools.ts
20213
20537
  var import_v33 = require("zod/v3");
20214
- var import_langchain54 = require("langchain");
20538
+ var import_langchain55 = require("langchain");
20215
20539
  var import_langgraph10 = require("@langchain/langgraph");
20216
20540
 
20217
20541
  // src/agent_team/middleware/formatMessages.ts
@@ -20236,7 +20560,7 @@ ${meta}${body}`;
20236
20560
  // src/agent_team/middleware/teammate_tools.ts
20237
20561
  function createTeammateTools(options) {
20238
20562
  const { teamId, agentId, taskListStore, mailboxStore } = options;
20239
- const claimTaskTool = (0, import_langchain54.tool)(
20563
+ const claimTaskTool = (0, import_langchain55.tool)(
20240
20564
  async (input) => {
20241
20565
  const task = await taskListStore.claimTaskById(
20242
20566
  teamId,
@@ -20266,7 +20590,7 @@ function createTeammateTools(options) {
20266
20590
  })
20267
20591
  }
20268
20592
  );
20269
- const completeTaskTool = (0, import_langchain54.tool)(
20593
+ const completeTaskTool = (0, import_langchain55.tool)(
20270
20594
  async (input) => {
20271
20595
  const task = await taskListStore.completeTask(
20272
20596
  teamId,
@@ -20293,7 +20617,7 @@ function createTeammateTools(options) {
20293
20617
  })
20294
20618
  }
20295
20619
  );
20296
- const failTaskTool = (0, import_langchain54.tool)(
20620
+ const failTaskTool = (0, import_langchain55.tool)(
20297
20621
  async (input) => {
20298
20622
  const task = await taskListStore.failTask(
20299
20623
  teamId,
@@ -20320,7 +20644,7 @@ function createTeammateTools(options) {
20320
20644
  })
20321
20645
  }
20322
20646
  );
20323
- const sendMessageTool = (0, import_langchain54.tool)(
20647
+ const sendMessageTool = (0, import_langchain55.tool)(
20324
20648
  async (input) => {
20325
20649
  await mailboxStore.sendMessage(
20326
20650
  teamId,
@@ -20358,7 +20682,7 @@ function createTeammateTools(options) {
20358
20682
  read: msg.read
20359
20683
  }));
20360
20684
  };
20361
- const readMessagesTool = (0, import_langchain54.tool)(
20685
+ const readMessagesTool = (0, import_langchain55.tool)(
20362
20686
  async (input, config) => {
20363
20687
  const formatAndMarkAsRead = async (msgs2) => {
20364
20688
  for (const msg of msgs2) {
@@ -20370,7 +20694,7 @@ function createTeammateTools(options) {
20370
20694
  if (msgs.length > 0) {
20371
20695
  const formatted2 = await formatAndMarkAsRead(msgs);
20372
20696
  const relevantMsgs2 = await getRelevantMessagesForState();
20373
- const toolMessage2 = new import_langchain54.ToolMessage({
20697
+ const toolMessage2 = new import_langchain55.ToolMessage({
20374
20698
  content: formatted2,
20375
20699
  tool_call_id: config.toolCall?.id,
20376
20700
  name: "read_messages"
@@ -20395,7 +20719,7 @@ function createTeammateTools(options) {
20395
20719
  });
20396
20720
  const relevantMsgs = await getRelevantMessagesForState();
20397
20721
  if (msgs.length === 0) {
20398
- const toolMessage2 = new import_langchain54.ToolMessage({
20722
+ const toolMessage2 = new import_langchain55.ToolMessage({
20399
20723
  content: "No unread messages.",
20400
20724
  tool_call_id: config.toolCall?.id,
20401
20725
  name: "read_messages"
@@ -20405,7 +20729,7 @@ function createTeammateTools(options) {
20405
20729
  });
20406
20730
  }
20407
20731
  const formatted = await formatAndMarkAsRead(msgs);
20408
- const toolMessage = new import_langchain54.ToolMessage({
20732
+ const toolMessage = new import_langchain55.ToolMessage({
20409
20733
  content: formatted,
20410
20734
  tool_call_id: config.toolCall?.id,
20411
20735
  name: "read_messages"
@@ -20420,7 +20744,7 @@ function createTeammateTools(options) {
20420
20744
  schema: import_v33.z.object({})
20421
20745
  }
20422
20746
  );
20423
- const checkTasksTool = (0, import_langchain54.tool)(
20747
+ const checkTasksTool = (0, import_langchain55.tool)(
20424
20748
  async () => {
20425
20749
  const tasks = await taskListStore.getAllTasks(teamId);
20426
20750
  return formatTaskSummary(tasks);
@@ -20431,7 +20755,7 @@ function createTeammateTools(options) {
20431
20755
  schema: import_v33.z.object({})
20432
20756
  }
20433
20757
  );
20434
- const broadcastMessageTool = (0, import_langchain54.tool)(
20758
+ const broadcastMessageTool = (0, import_langchain55.tool)(
20435
20759
  async (input) => {
20436
20760
  const allAgents = await mailboxStore.getRegisteredAgents(teamId);
20437
20761
  const recipients = allAgents.filter((a) => a !== agentId);
@@ -20617,7 +20941,7 @@ You have access to these tools:
20617
20941
  - \`read_messages\`: Read messages from team_lead or teammates
20618
20942
  - \`check_tasks\`: Get current status of all tasks in the team`;
20619
20943
  const assistantId = getTeammateAssistantId(ctx.teamId, spec.name);
20620
- agent = (0, import_langchain55.createAgent)({
20944
+ agent = (0, import_langchain56.createAgent)({
20621
20945
  model: spec.model ?? ctx.defaultModel,
20622
20946
  systemPrompt: teammatePrompt,
20623
20947
  tools: allTools,
@@ -20686,12 +21010,12 @@ async function spawnTeammate(options) {
20686
21010
  function createTeamMiddleware(options) {
20687
21011
  const { teamConfig, taskListStore, mailboxStore, tenantId: tenantId2 } = options;
20688
21012
  const defaultModel = teamConfig.model ?? "claude-sonnet-4-5-20250929";
20689
- const createTeamTool = (0, import_langchain55.tool)(
21013
+ const createTeamTool = (0, import_langchain56.tool)(
20690
21014
  async (input, config) => {
20691
21015
  const state = (0, import_langgraph11.getCurrentTaskInput)();
20692
21016
  if (state?.team?.teamId) {
20693
21017
  const existingId = state.team.teamId;
20694
- const msg = new import_langchain55.ToolMessage({
21018
+ const msg = new import_langchain56.ToolMessage({
20695
21019
  content: `A team is already active (id: ${existingId}). Use this team_id for \`check_tasks\`, \`read_messages\`, \`add_tasks\`, \`send_message\`, \`assign_task\`, \`set_task_status\`, and \`set_task_dependencies\`. Do not call \`create_team\` again unless you need a fresh team for a new objective.`,
20696
21020
  tool_call_id: config.toolCall?.id,
20697
21021
  name: "create_team"
@@ -20780,7 +21104,7 @@ Teammates are now working in the background. Keep calling \`check_tasks\` and \`
20780
21104
  \`\`\`json
20781
21105
  ${teamJson}
20782
21106
  \`\`\``;
20783
- const toolMessage = new import_langchain55.ToolMessage({
21107
+ const toolMessage = new import_langchain56.ToolMessage({
20784
21108
  content: summary,
20785
21109
  tool_call_id: config.toolCall?.id,
20786
21110
  name: "create_team"
@@ -20865,7 +21189,7 @@ After calling create_team, you MUST:
20865
21189
  if (state?.team?.teamId) return state.team.teamId;
20866
21190
  throw new Error("No team_id provided and no team in state. Call create_team first.");
20867
21191
  };
20868
- const addTasksTool = (0, import_langchain55.tool)(
21192
+ const addTasksTool = (0, import_langchain56.tool)(
20869
21193
  async (input, config) => {
20870
21194
  const teamId = resolveTeamId();
20871
21195
  const created = await taskListStore.addTasks(
@@ -20879,7 +21203,7 @@ After calling create_team, you MUST:
20879
21203
  }))
20880
21204
  );
20881
21205
  const summary = created.map((t) => `- ${t.id}: "${t.title}"`).join("\n");
20882
- return new import_langchain55.ToolMessage({
21206
+ return new import_langchain56.ToolMessage({
20883
21207
  content: `Added ${created.length} task(s) to team ${teamId}:
20884
21208
  ${summary}
20885
21209
  Sleeping teammates will wake up and claim these.`,
@@ -20930,20 +21254,20 @@ IMPORTANT: Assigning to a specific teammate
20930
21254
  })
20931
21255
  }
20932
21256
  );
20933
- const assignTaskTool = (0, import_langchain55.tool)(
21257
+ const assignTaskTool = (0, import_langchain56.tool)(
20934
21258
  async (input, config) => {
20935
21259
  const teamId = resolveTeamId();
20936
21260
  const task = await taskListStore.updateTask(teamId, input.task_id, {
20937
21261
  assignee: input.assignee
20938
21262
  });
20939
21263
  if (!task) {
20940
- return new import_langchain55.ToolMessage({
21264
+ return new import_langchain56.ToolMessage({
20941
21265
  content: `Task ${input.task_id} not found in team ${teamId}.`,
20942
21266
  tool_call_id: config.toolCall?.id,
20943
21267
  name: "assign_task"
20944
21268
  });
20945
21269
  }
20946
- return new import_langchain55.ToolMessage({
21270
+ return new import_langchain56.ToolMessage({
20947
21271
  content: `Task "${task.title}" (${task.id}) assigned to ${input.assignee}.`,
20948
21272
  tool_call_id: config.toolCall?.id,
20949
21273
  name: "assign_task"
@@ -20958,20 +21282,20 @@ IMPORTANT: Assigning to a specific teammate
20958
21282
  })
20959
21283
  }
20960
21284
  );
20961
- const setTaskStatusTool = (0, import_langchain55.tool)(
21285
+ const setTaskStatusTool = (0, import_langchain56.tool)(
20962
21286
  async (input, config) => {
20963
21287
  const teamId = resolveTeamId();
20964
21288
  const task = await taskListStore.updateTask(teamId, input.task_id, {
20965
21289
  status: input.status
20966
21290
  });
20967
21291
  if (!task) {
20968
- return new import_langchain55.ToolMessage({
21292
+ return new import_langchain56.ToolMessage({
20969
21293
  content: `Task ${input.task_id} not found in team ${teamId}.`,
20970
21294
  tool_call_id: config.toolCall?.id,
20971
21295
  name: "set_task_status"
20972
21296
  });
20973
21297
  }
20974
- return new import_langchain55.ToolMessage({
21298
+ return new import_langchain56.ToolMessage({
20975
21299
  content: `Task "${task.title}" (${task.id}) status set to ${input.status}.`,
20976
21300
  tool_call_id: config.toolCall?.id,
20977
21301
  name: "set_task_status"
@@ -20986,20 +21310,20 @@ IMPORTANT: Assigning to a specific teammate
20986
21310
  })
20987
21311
  }
20988
21312
  );
20989
- const setTaskDependenciesTool = (0, import_langchain55.tool)(
21313
+ const setTaskDependenciesTool = (0, import_langchain56.tool)(
20990
21314
  async (input, config) => {
20991
21315
  const teamId = resolveTeamId();
20992
21316
  const task = await taskListStore.updateTask(teamId, input.task_id, {
20993
21317
  dependencies: input.dependencies
20994
21318
  });
20995
21319
  if (!task) {
20996
- return new import_langchain55.ToolMessage({
21320
+ return new import_langchain56.ToolMessage({
20997
21321
  content: `Task ${input.task_id} not found in team ${teamId}.`,
20998
21322
  tool_call_id: config.toolCall?.id,
20999
21323
  name: "set_task_dependencies"
21000
21324
  });
21001
21325
  }
21002
- return new import_langchain55.ToolMessage({
21326
+ return new import_langchain56.ToolMessage({
21003
21327
  content: `Task "${task.title}" (${task.id}) dependencies set to [${input.dependencies.join(", ")}].`,
21004
21328
  tool_call_id: config.toolCall?.id,
21005
21329
  name: "set_task_dependencies"
@@ -21014,7 +21338,7 @@ IMPORTANT: Assigning to a specific teammate
21014
21338
  })
21015
21339
  }
21016
21340
  );
21017
- const checkTasksTool = (0, import_langchain55.tool)(
21341
+ const checkTasksTool = (0, import_langchain56.tool)(
21018
21342
  async (input, config) => {
21019
21343
  const teamId = resolveTeamId();
21020
21344
  const tasks = await taskListStore.getAllTasks(teamId);
@@ -21023,7 +21347,7 @@ IMPORTANT: Assigning to a specific teammate
21023
21347
  update: {
21024
21348
  tasks: tasksSnapshot,
21025
21349
  messages: [
21026
- new import_langchain55.ToolMessage({
21350
+ new import_langchain56.ToolMessage({
21027
21351
  content: formatTaskSummary(tasks),
21028
21352
  tool_call_id: config.toolCall?.id,
21029
21353
  name: "check_tasks"
@@ -21059,7 +21383,7 @@ Task Status Values:
21059
21383
  })
21060
21384
  }
21061
21385
  );
21062
- const sendMessageTool = (0, import_langchain55.tool)(
21386
+ const sendMessageTool = (0, import_langchain56.tool)(
21063
21387
  async (input, config) => {
21064
21388
  const teamId = resolveTeamId();
21065
21389
  await mailboxStore.sendMessage(
@@ -21069,7 +21393,7 @@ Task Status Values:
21069
21393
  input.content,
21070
21394
  "direct_message" /* DIRECT_MESSAGE */
21071
21395
  );
21072
- return new import_langchain55.ToolMessage({
21396
+ return new import_langchain56.ToolMessage({
21073
21397
  content: `Message sent to ${input.to}.`,
21074
21398
  tool_call_id: config.toolCall?.id,
21075
21399
  name: "send_message"
@@ -21084,7 +21408,7 @@ Task Status Values:
21084
21408
  })
21085
21409
  }
21086
21410
  );
21087
- const readMessagesTool = (0, import_langchain55.tool)(
21411
+ const readMessagesTool = (0, import_langchain56.tool)(
21088
21412
  async (input, config) => {
21089
21413
  const teamId = resolveTeamId();
21090
21414
  const formatAndMarkAsRead = async (msgs2) => {
@@ -21112,7 +21436,7 @@ Task Status Values:
21112
21436
  if (msgs.length > 0) {
21113
21437
  const formatted2 = await formatAndMarkAsRead(msgs);
21114
21438
  const allTeamMessages2 = await getAllTeamMessagesForState();
21115
- const toolMessage2 = new import_langchain55.ToolMessage({
21439
+ const toolMessage2 = new import_langchain56.ToolMessage({
21116
21440
  content: formatted2,
21117
21441
  tool_call_id: config.toolCall?.id,
21118
21442
  name: "read_messages"
@@ -21144,7 +21468,7 @@ Task Status Values:
21144
21468
  );
21145
21469
  const allTeamMessages = await getAllTeamMessagesForState();
21146
21470
  if (msgs.length === 0) {
21147
- const toolMessage2 = new import_langchain55.ToolMessage({
21471
+ const toolMessage2 = new import_langchain56.ToolMessage({
21148
21472
  content: "No unread messages from teammates.",
21149
21473
  tool_call_id: config.toolCall?.id,
21150
21474
  name: "read_messages"
@@ -21154,7 +21478,7 @@ Task Status Values:
21154
21478
  });
21155
21479
  }
21156
21480
  const formatted = await formatAndMarkAsRead(msgs);
21157
- const toolMessage = new import_langchain55.ToolMessage({
21481
+ const toolMessage = new import_langchain56.ToolMessage({
21158
21482
  content: formatted,
21159
21483
  tool_call_id: config.toolCall?.id,
21160
21484
  name: "read_messages"
@@ -21171,7 +21495,7 @@ Task Status Values:
21171
21495
  })
21172
21496
  }
21173
21497
  );
21174
- const disbandTeamTool = (0, import_langchain55.tool)(
21498
+ const disbandTeamTool = (0, import_langchain56.tool)(
21175
21499
  async (input, config) => {
21176
21500
  const teamId = resolveTeamId();
21177
21501
  await mailboxStore.broadcastMessage(
@@ -21181,7 +21505,7 @@ Task Status Values:
21181
21505
  "shutdown_request" /* SHUTDOWN_REQUEST */
21182
21506
  );
21183
21507
  await new Promise((r) => setTimeout(r, 2e3));
21184
- return new import_langchain55.ToolMessage({
21508
+ return new import_langchain56.ToolMessage({
21185
21509
  content: `Team ${teamId} has been disbanded. All teammates notified and resources cleaned up.`,
21186
21510
  tool_call_id: config.toolCall?.id,
21187
21511
  name: "disband_team"
@@ -21192,7 +21516,7 @@ Task Status Values:
21192
21516
  description: "Disband a team when all work is done. Before calling: (1) Call check_tasks to verify no tasks are still pending/in_progress; (2) if any are, discuss with the team via read_messages and broadcast_message/send_message whether to continue or stop/cancel them; (3) only after alignment (all tasks completed/failed or explicitly stopped), then call this tool. This will: 1) Send a shutdown message to all teammates, 2) Wait briefly for them to clean up, 3) Clear all tasks and messages. Omit team_id to use the active team from state."
21193
21517
  }
21194
21518
  );
21195
- const broadcastMessageTool = (0, import_langchain55.tool)(
21519
+ const broadcastMessageTool = (0, import_langchain56.tool)(
21196
21520
  async (input, config) => {
21197
21521
  const teamId = resolveTeamId();
21198
21522
  await mailboxStore.broadcastMessage(
@@ -21201,7 +21525,7 @@ Task Status Values:
21201
21525
  input.content,
21202
21526
  "broadcast" /* BROADCAST */
21203
21527
  );
21204
- return new import_langchain55.ToolMessage({
21528
+ return new import_langchain56.ToolMessage({
21205
21529
  content: `Broadcast message sent to all teammates.`,
21206
21530
  tool_call_id: config.toolCall?.id,
21207
21531
  name: "broadcast_message"
@@ -21215,7 +21539,7 @@ Task Status Values:
21215
21539
  })
21216
21540
  }
21217
21541
  );
21218
- return (0, import_langchain55.createMiddleware)({
21542
+ return (0, import_langchain56.createMiddleware)({
21219
21543
  name: "teamMiddleware",
21220
21544
  tools: [
21221
21545
  createTeamTool,
@@ -21324,7 +21648,7 @@ function createAgentTeam(config) {
21324
21648
  ];
21325
21649
  const systemPrompt = config.systemPrompt + "\n\n" + TEAM_LEAD_BASE_PROMPT;
21326
21650
  const stateSchema2 = createReactAgentSchema(TEAM_STATE_SCHEMA);
21327
- return (0, import_langchain56.createAgent)({
21651
+ return (0, import_langchain57.createAgent)({
21328
21652
  model: config.model ?? "claude-sonnet-4-5-20250929",
21329
21653
  systemPrompt,
21330
21654
  tools: [],
@@ -21367,7 +21691,7 @@ var TeamAgentGraphBuilder = class {
21367
21691
  });
21368
21692
  const middlewareConfigs = params.middleware || [];
21369
21693
  let filesystemBackend = createFilesystemBackendFactory(middlewareConfigs);
21370
- const middlewares = await createCommonMiddlewares(middlewareConfigs);
21694
+ const middlewares = await createCommonMiddlewares(middlewareConfigs, void 0, void 0, void 0, params.model);
21371
21695
  if (!filesystemBackend) {
21372
21696
  filesystemBackend = async (config2) => {
21373
21697
  return new StateBackend(config2);
@@ -21736,7 +22060,7 @@ function extractLastHumanMessage(messages) {
21736
22060
  }
21737
22061
 
21738
22062
  // src/agent_lattice/builders/WorkflowAgentGraphBuilder.ts
21739
- var import_langchain57 = require("langchain");
22063
+ var import_langchain58 = require("langchain");
21740
22064
  init_MemoryLatticeManager();
21741
22065
  var import_protocols10 = require("@axiom-lattice/protocols");
21742
22066
  init_compile();
@@ -21787,7 +22111,7 @@ var WorkflowAgentGraphBuilder = class {
21787
22111
  const checkpointer = getCheckpointSaver("default");
21788
22112
  const tools = params.tools.map((t) => t.executor).filter(Boolean);
21789
22113
  const middlewareConfigs = params.middleware || [];
21790
- const middlewares = await createCommonMiddlewares(middlewareConfigs, void 0, false, params.tenantId);
22114
+ const middlewares = await createCommonMiddlewares(middlewareConfigs, void 0, false, params.tenantId, params.model);
21791
22115
  const askMiddlewares = await createCommonMiddlewares([
21792
22116
  {
21793
22117
  id: "ask_user_to_clarify",
@@ -21797,11 +22121,11 @@ var WorkflowAgentGraphBuilder = class {
21797
22121
  enabled: true,
21798
22122
  config: {}
21799
22123
  }
21800
- ], void 0, false);
22124
+ ], void 0, false, void 0, params.model);
21801
22125
  const noWrapMiddlewares = stripWrapModelCallHook(middlewares);
21802
22126
  const noWrapAskMiddlewares = stripWrapModelCallHook(askMiddlewares);
21803
22127
  console.log(`[WF BUILDER] building default agent | toolCount=${tools.length} | middlewareCount=${middlewares.length}`);
21804
- const defaultAgent = (0, import_langchain57.createAgent)({
22128
+ const defaultAgent = (0, import_langchain58.createAgent)({
21805
22129
  model: params.model,
21806
22130
  tools,
21807
22131
  systemPrompt: buildStepSystemPrompt(false, params.prompt),
@@ -21821,7 +22145,7 @@ var WorkflowAgentGraphBuilder = class {
21821
22145
  console.log(`[WF BUILDER] resolveAgent: cacheKey=${key4.slice(0, 80)}... | cached=${agentCache.has(key4)}`);
21822
22146
  if (!agentCache.has(key4)) {
21823
22147
  console.log(`[WF BUILDER] creating ${isAsk ? "ask" : "agent"} with responseFormat`);
21824
- const agent = (0, import_langchain57.createAgent)({
22148
+ const agent = (0, import_langchain58.createAgent)({
21825
22149
  model: params.model,
21826
22150
  tools,
21827
22151
  systemPrompt: buildStepSystemPrompt(isAsk, params.prompt),
@@ -21837,7 +22161,7 @@ var WorkflowAgentGraphBuilder = class {
21837
22161
  const key4 = "ask:default";
21838
22162
  if (!agentCache.has(key4)) {
21839
22163
  console.log(`[WF BUILDER] creating ask default agent`);
21840
- const agent = (0, import_langchain57.createAgent)({
22164
+ const agent = (0, import_langchain58.createAgent)({
21841
22165
  model: params.model,
21842
22166
  tools,
21843
22167
  systemPrompt: buildStepSystemPrompt(true, params.prompt),
@@ -23476,6 +23800,40 @@ Call the \`skill\` tool with skill_name: "agent-architecture" to load the
23476
23800
  authoritative workflow. Never announce that you will follow a skill \u2014
23477
23801
  load it and follow its content. If the load fails, retry once, then report it.
23478
23802
 
23803
+ TASK MANAGEMENT IS A CORE DUTY, not a per-skill option. Whenever the
23804
+ goal is clear and you know what to do, create a task FIRST (manage_task)
23805
+ before executing \u2014 for any multi-step work: learning, building,
23806
+ modifying, fixing, anything with an Objective and Acceptance Criteria.
23807
+ - **Check for duplicates BEFORE creating** \u2014 always manage_task
23808
+ action: "list" first (filter ownerType: "agent"). If a task with the
23809
+ same objective already exists (e.g. from an interrupted session),
23810
+ RESUME it instead of creating a new one.
23811
+ - **Decompose into subtasks** \u2014 after the parent task, create a
23812
+ subtask per work item / phase (e.g. design, build, eval), each with
23813
+ its own Objective + Acceptance Criteria.
23814
+ - **Update on completion** \u2014 every finished subtask and the parent:
23815
+ manage_task update(status: "completed", result: "what was done").
23816
+ Use interrupted/failed with summary/failureReason when blocked or
23817
+ unable. Status must always reflect reality \u2014 never leave a finished
23818
+ task dangling in an in-progress state.
23819
+ See [[task-tracking]].
23820
+ The sub-skills below only ADD their own task details on top of this
23821
+ universal duty.
23822
+
23823
+ BUILD GATES \u2014 hard behavioral requirements, no exceptions, no skipping:
23824
+ - Creating a WORKFLOW ([[design-workflow]]): \u2460 show the design as a
23825
+ Flowchart widget (every step, branch, ask point) \u2461 walk through it
23826
+ step-by-step with the user \u2462 ask inline-vs-ref per step \u2463 CONFIRM via
23827
+ ask_user_to_clarify \u2014 only then call create_workflow.
23828
+ - Creating an AGENT ([[agent-build]]): \u2460 present the design with
23829
+ show_widget \u2461 confirm via ask_user_to_clarify \u2014 only then call
23830
+ create_agent.
23831
+ - Both: if the goal model (real goal / consumer / usable state) is
23832
+ unclear, ask BEFORE designing \u2014 never guess.
23833
+ The skills document WHY and HOW; these gates are the unskippable
23834
+ minimum. If you cannot satisfy a gate (e.g. user says skip), record it
23835
+ and proceed only on the user's explicit instruction.
23836
+
23479
23837
  Your sub-skills (accessible via the MOC or direct loading):
23480
23838
  - [[learn-capability]] \u2014 Learn from any source material \u2192 skills + agents
23481
23839
  - [[agent-build]] \u2014 Design and build single agents (REACT/DEEP_AGENT)
@@ -23640,7 +23998,15 @@ var agentArchitectConfig = {
23640
23998
  id: "task",
23641
23999
  type: "task",
23642
24000
  name: "Task",
23643
- description: "Track learning processes and fix loops with approval gates",
24001
+ description: "Core architect duty: once the goal is clear, create tasks to track every multi-step piece of work (learning, building, modifying, fixing). Subtasks per work item; status reflects reality.",
24002
+ enabled: true,
24003
+ config: {}
24004
+ },
24005
+ {
24006
+ id: "code_eval",
24007
+ type: "code_eval",
24008
+ name: "Code Evaluation",
24009
+ description: "Execute shell commands in the sandbox to support agent creation: unzip files, process data, run helper scripts. Distinct from the eval assessment system (run_eval).",
23644
24010
  enabled: true,
23645
24011
  config: {}
23646
24012
  },
@@ -27267,6 +27633,15 @@ function parseJudgeVerdict(raw) {
27267
27633
  return { error: error instanceof Error ? error.message : String(error) };
27268
27634
  }
27269
27635
  }
27636
+ var MAX_INTERRUPT_RESUMES = 5;
27637
+ function resolveInterruptResponse(policy, interrupt5) {
27638
+ if (policy.mode === "auto-approve") return policy.value ?? "\u540C\u610F";
27639
+ if (policy.mode === "auto-reject") return policy.value ?? "\u62D2\u7EDD";
27640
+ return policy.value ?? "";
27641
+ }
27642
+ function interruptValueText(value) {
27643
+ return typeof value === "string" ? value : JSON.stringify(value ?? "");
27644
+ }
27270
27645
  var _LatticeEval = class _LatticeEval {
27271
27646
  constructor(config = {}) {
27272
27647
  this.inMemoryLogs = [];
@@ -27333,7 +27708,8 @@ var _LatticeEval = class _LatticeEval {
27333
27708
  return acc;
27334
27709
  }, {});
27335
27710
  }
27336
- async executeAgentStep(step, threadId, inputMessage, files) {
27711
+ async executeAgentStep(step, threadId, inputMessage, files, interruptPolicy) {
27712
+ const hitlEvents = [];
27337
27713
  this.log("Executing agent step", {
27338
27714
  agent_id: step.agent_id,
27339
27715
  thread_id: threadId,
@@ -27351,19 +27727,74 @@ var _LatticeEval = class _LatticeEval {
27351
27727
  };
27352
27728
  const agent = agentInstanceManager.getAgent(agentParams);
27353
27729
  try {
27354
- const result = await agent.invoke({
27355
- input: {
27356
- message: step.override_message || inputMessage,
27357
- files: this.buildFileEntries(files)
27730
+ const stepInput = {
27731
+ message: step.override_message || inputMessage,
27732
+ files: this.buildFileEntries(files)
27733
+ };
27734
+ let result = await agent.invokeWithState({ input: stepInput });
27735
+ let resumeCount = 0;
27736
+ let pendingInterrupt;
27737
+ let interrupts = Array.isArray(result?.__interrupt__) ? result.__interrupt__ : [];
27738
+ while (interrupts.length > 0) {
27739
+ const interrupt5 = interrupts[0];
27740
+ if (!interrupt5) break;
27741
+ const policy = interruptPolicy;
27742
+ if (!policy || policy.mode === "stop" || resumeCount >= MAX_INTERRUPT_RESUMES) {
27743
+ pendingInterrupt = interrupt5;
27744
+ break;
27358
27745
  }
27359
- });
27746
+ const response = resolveInterruptResponse(policy, interrupt5);
27747
+ hitlEvents.push({
27748
+ type: "interrupt",
27749
+ id: interrupt5.id,
27750
+ value: interrupt5.value
27751
+ });
27752
+ this.log("Auto-resolving HITL interrupt", {
27753
+ agent_id: step.agent_id,
27754
+ thread_id: threadId,
27755
+ mode: policy.mode,
27756
+ interrupt_id: interrupt5.id,
27757
+ response,
27758
+ resume_count: resumeCount + 1
27759
+ });
27760
+ result = await agent.invokeWithState({ input: stepInput, command: { resume: response } });
27761
+ hitlEvents.push({
27762
+ type: "interrupt_response",
27763
+ id: interrupt5.id,
27764
+ mode: policy.mode,
27765
+ response
27766
+ });
27767
+ resumeCount++;
27768
+ interrupts = Array.isArray(result?.__interrupt__) ? result.__interrupt__ : [];
27769
+ }
27770
+ if (pendingInterrupt) {
27771
+ hitlEvents.push({
27772
+ type: "interrupt",
27773
+ id: pendingInterrupt.id,
27774
+ value: pendingInterrupt.value
27775
+ });
27776
+ this.log("Agent step interrupted by HITL (human input requested)", {
27777
+ agent_id: step.agent_id,
27778
+ thread_id: threadId,
27779
+ interrupt_id: pendingInterrupt.id,
27780
+ auto_resolved: resumeCount
27781
+ });
27782
+ } else {
27783
+ this.log("Agent step completed", {
27784
+ agent_id: step.agent_id,
27785
+ thread_id: threadId,
27786
+ response_keys: result ? Object.keys(result) : [],
27787
+ auto_resolved: resumeCount
27788
+ });
27789
+ }
27360
27790
  const responseData = { success: true, ...result };
27361
- this.log("Agent step completed", {
27362
- agent_id: step.agent_id,
27363
- thread_id: threadId,
27364
- response_keys: result ? Object.keys(result) : []
27365
- });
27366
- return { threadId, responseData };
27791
+ return {
27792
+ threadId,
27793
+ responseData,
27794
+ interrupted: pendingInterrupt ? true : void 0,
27795
+ interrupt: pendingInterrupt,
27796
+ hitlEvents
27797
+ };
27367
27798
  } catch (error) {
27368
27799
  const message = error instanceof Error ? error.message : String(error);
27369
27800
  this.log("Agent step failed", {
@@ -27426,15 +27857,32 @@ var _LatticeEval = class _LatticeEval {
27426
27857
  });
27427
27858
  let currentThreadId = threadId;
27428
27859
  let lastResponseData = null;
27860
+ let interrupt5;
27429
27861
  for (const step of evalCase.steps) {
27430
27862
  const result = await this.executeAgentStep(
27431
27863
  step,
27432
27864
  currentThreadId,
27433
27865
  evalCase.input.message,
27434
- evalCase.input.files || {}
27866
+ evalCase.input.files || {},
27867
+ evalCase.interruptPolicy
27435
27868
  );
27436
27869
  currentThreadId = result.threadId;
27437
27870
  lastResponseData = result.responseData;
27871
+ for (const evt of result.hitlEvents) {
27872
+ if (evt.type === "interrupt") {
27873
+ this.lastMessages.push({
27874
+ role: "interrupt",
27875
+ content: `HITL \u6682\u505C\uFF1AAgent \u8BF7\u6C42\u4EBA\u5DE5\u8F93\u5165 \u2014 ${interruptValueText(evt.value)}`,
27876
+ id: evt.id
27877
+ });
27878
+ } else {
27879
+ this.lastMessages.push({
27880
+ role: "interrupt_response",
27881
+ content: `\u5DF2\u81EA\u52A8\u54CD\u5E94\uFF08\u6D4B\u8BD5\u7B56\u7565 ${evt.mode}\uFF09\uFF1A${evt.response}`,
27882
+ id: evt.id
27883
+ });
27884
+ }
27885
+ }
27438
27886
  const existingIds = new Set(this.lastMessages.map((m) => m.id).filter(Boolean));
27439
27887
  if (result.responseData?.messages && Array.isArray(result.responseData.messages)) {
27440
27888
  for (const msg of result.responseData.messages) {
@@ -27456,6 +27904,13 @@ var _LatticeEval = class _LatticeEval {
27456
27904
  } else {
27457
27905
  content = String(msg.content || "");
27458
27906
  }
27907
+ if (Array.isArray(msg.tool_calls) && msg.tool_calls.length > 0) {
27908
+ const toolCallStr = msg.tool_calls.map(
27909
+ (tc) => `tool_call: ${tc.name}(${JSON.stringify(tc.args ?? {})})`
27910
+ ).join("\n");
27911
+ content = content ? `${content}
27912
+ ${toolCallStr}` : toolCallStr;
27913
+ }
27459
27914
  this.lastMessages.push({
27460
27915
  role,
27461
27916
  content,
@@ -27467,13 +27922,21 @@ var _LatticeEval = class _LatticeEval {
27467
27922
  }
27468
27923
  }
27469
27924
  }
27925
+ if (result.interrupted) {
27926
+ interrupt5 = result.interrupt;
27927
+ this.log("Case paused for HITL \u2014 remaining steps skipped; judge will evaluate the pause", {
27928
+ case_id: evalCase.caseId,
27929
+ interrupt_id: interrupt5?.id
27930
+ });
27931
+ break;
27932
+ }
27470
27933
  }
27471
27934
  this.log("All agent steps completed", {
27472
27935
  case_id: evalCase.caseId,
27473
27936
  final_thread_id: currentThreadId,
27474
27937
  message_count: this.lastMessages.length
27475
27938
  });
27476
- const finalOutput = this.extractFinalMessage(lastResponseData);
27939
+ const finalOutput = interrupt5 ? typeof interrupt5.value === "string" ? interrupt5.value : JSON.stringify(interrupt5.value ?? "") : this.extractFinalMessage(lastResponseData);
27477
27940
  this.lastFinalOutput = finalOutput;
27478
27941
  const trajectory = this.buildTrajectory();
27479
27942
  this.log("Final output extracted", {
@@ -27532,6 +27995,8 @@ ${rubricsSection}
27532
27995
  3. **\u8FC7\u7A0B\u6821\u9A8C**\uFF1A\u5982\u679C"\u6267\u884C\u8FC7\u7A0B"\u663E\u793A Agent \u672A\u6267\u884C\u5FC5\u8981\u7684\u4E2D\u95F4\u6B65\u9AA4\uFF08\u5982\u5E94\u8C03\u7528\u5DE5\u5177\u800C\u672A\u8C03\u7528\uFF09\uFF0C\u5373\u4F7F\u6700\u7EC8\u8F93\u51FA\u770B\u4F3C\u5408\u7406\uFF0C\u4E5F\u5E94\u5728\u5BF9\u5E94\u6307\u6807\u4E0A\u6263\u5206\u3002
27533
27996
  4. **\u8BC1\u636E\u5BFC\u5411**\uFF1A\u5728\u7ED9\u51FA\u539F\u56E0\uFF08reason\uFF09\u65F6\uFF0C\u5FC5\u987B\u5F15\u7528\u6267\u884C\u8FC7\u7A0B\u6216\u6700\u7EC8\u8F93\u51FA\u4E2D\u7684\u5177\u4F53\u5185\u5BB9\u3002
27534
27997
  5. **\u52A0\u6743\u8BA1\u7B97**\uFF1A\u6700\u7EC8\u5206\u6570\u4E3A\u5404\u9879\u6307\u6807\u5F97\u5206\u4E0E\u5176\u6743\u91CD\u7684\u4E58\u79EF\u4E4B\u548C\uFF080-100\u5206\u5236\uFF09\u3002
27998
+ 6. **HITL \u4E2D\u65AD\u5224\u5B9A**\uFF1A\u5982\u679C\u6267\u884C\u8FC7\u7A0B\u4E2D\u51FA\u73B0\u300CHITL \u6682\u505C\uFF1AAgent \u8BF7\u6C42\u4EBA\u5DE5\u8F93\u5165\u300D\u6761\u76EE\uFF0C\u8BF4\u660E Agent \u5728\u7B49\u5F85\u4EBA\u5DE5\u786E\u8BA4\u3002\u8BF7\u628A\u5B83\u5F53\u4F5C\u88AB\u6D4B\u4E1A\u52A1\u884C\u4E3A\u6765\u8BC4\u5224\uFF1A\u82E5\u671F\u671B\u8F93\u51FA\u8981\u6C42\u81EA\u4E3B\u5B8C\u6210\uFF08\u5982"\u65E0\u9700\u786E\u8BA4\u81EA\u52A8\u6267\u884C"\uFF09\uFF0C\u8BF7\u6C42\u4EBA\u5DE5\u8F93\u5165\u5E94\u5224\u5931\u8D25\uFF1B\u82E5\u671F\u671B\u8F93\u51FA\u8981\u6C42\u5148\u83B7\u5F97\u786E\u8BA4\u6216\u6279\u51C6\uFF08\u5982"\u6267\u884C\u524D\u5FC5\u987B\u8BF7\u6C42\u6279\u51C6"\uFF09\uFF0C\u8BF7\u6C42\u4EBA\u5DE5\u8F93\u5165\u662F\u6B63\u786E\u884C\u4E3A\uFF0C\u5E94\u7ED3\u5408\u5176\u65F6\u673A\u4E0E\u5185\u5BB9\u5224\u5B9A\u4E3A\u901A\u8FC7\u6216\u6309\u6307\u6807\u7ED9\u5206\u3002
27999
+ 7. **HITL \u81EA\u52A8\u54CD\u5E94\u5224\u5B9A**\uFF1A\u5982\u679C\u300CHITL \u6682\u505C\u300D\u6761\u76EE\u4E4B\u540E\u51FA\u73B0\u300C\u5DF2\u81EA\u52A8\u54CD\u5E94\uFF08\u6D4B\u8BD5\u7B56\u7565 auto-approve/auto-reject/canned-response\uFF09\u300D\u6761\u76EE\uFF0C\u8BF4\u660E\u6D4B\u8BD5\u6846\u67B6\u6CE8\u5165\u4E86\u4EBA\u5DE5\u56DE\u590D\u3001\u6D41\u7A0B\u5DF2\u7EE7\u7EED\u2014\u2014\u8BF7\u6309**\u5B8C\u6574\u6D41\u7A0B**\u8BC4\u5224\u6682\u505C\u4E4B\u540E\u7684\u884C\u4E3A\uFF08\u5982\u6279\u51C6\u540E\u662F\u5426\u6B63\u786E\u6267\u884C\u4E86\u64CD\u4F5C\uFF09\uFF0C\u5E76\u6838\u5BF9\u81EA\u52A8\u54CD\u5E94\u5185\u5BB9\u662F\u5426\u7B26\u5408\u4EBA\u5DE5\u56DE\u590D\u7684\u5408\u7406\u9884\u671F\u3002
27535
28000
 
27536
28001
  # \u8F93\u51FA\u683C\u5F0F\uFF08\u4EC5JSON\uFF09
27537
28002
  \u4F60\u5FC5\u987B\u4EC5\u4EE5 JSON \u683C\u5F0F\u56DE\u590D\uFF0C\u7ED3\u6784\u5982\u4E0B\uFF1A
@@ -27686,7 +28151,9 @@ ${rubricsSection}
27686
28151
  pass,
27687
28152
  final_score: finalScore,
27688
28153
  dimension_results: dimensionResults,
27689
- summary: parsedResult.summary || testResultContent
28154
+ summary: parsedResult.summary || testResultContent,
28155
+ interrupted: interrupt5 ? true : void 0,
28156
+ interrupt: interrupt5 ? { id: interrupt5.id, value: interrupt5.value } : void 0
27690
28157
  };
27691
28158
  }
27692
28159
  };
@@ -27701,6 +28168,8 @@ async function evaluateLatticeCaseWithLogs(evalCase, config) {
27701
28168
  return {
27702
28169
  caseId: evalCase.caseId,
27703
28170
  result,
28171
+ interrupted: result?.interrupted,
28172
+ interrupt: result?.interrupt,
27704
28173
  duration_ms: meta.duration_ms,
27705
28174
  thread_id: meta.thread_id,
27706
28175
  judge_thread_id: meta.judge_thread_id,
@@ -27783,7 +28252,8 @@ function resolveTemplateCase(templateCase, templates) {
27783
28252
  eval: {
27784
28253
  content_assertion: templateCase.eval.content_assertion,
27785
28254
  eval_rubrics: templateCase.eval.eval_rubrics || template.default_case.eval?.eval_rubrics
27786
- }
28255
+ },
28256
+ interruptPolicy: templateCase.interruptPolicy ?? template.default_case.interruptPolicy
27787
28257
  };
27788
28258
  return resolvedCase;
27789
28259
  }
@@ -27849,6 +28319,8 @@ var LatticeEvalSuite = class {
27849
28319
  result: run.result,
27850
28320
  error: run.error,
27851
28321
  error_stack: run.error_stack,
28322
+ interrupted: run.interrupted,
28323
+ interrupt: run.interrupt,
27852
28324
  duration_ms: run.duration_ms,
27853
28325
  thread_id: run.thread_id,
27854
28326
  judge_thread_id: run.judge_thread_id,
@@ -27881,6 +28353,8 @@ var LatticeEvalSuite = class {
27881
28353
  result: run.result,
27882
28354
  error: run.error,
27883
28355
  error_stack: run.error_stack,
28356
+ interrupted: run.interrupted,
28357
+ interrupt: run.interrupt,
27884
28358
  duration_ms: run.duration_ms,
27885
28359
  thread_id: run.thread_id,
27886
28360
  judge_thread_id: run.judge_thread_id,
@@ -28090,24 +28564,29 @@ Running batch: ${this.project.projectName} (${this.getSuiteNames().length} suite
28090
28564
  let total_cases = 0;
28091
28565
  let passed_cases = 0;
28092
28566
  let failed_cases = 0;
28567
+ let interrupted_cases = 0;
28093
28568
  const suites = [];
28094
28569
  for (const [suiteName, caseResults] of results.entries()) {
28095
28570
  const suiteTotal = caseResults.length;
28096
28571
  const suitePassed = caseResults.filter((r) => r.result?.pass).length;
28572
+ const suiteInterrupted = caseResults.filter((r) => r.interrupted).length;
28097
28573
  const suiteFailed = suiteTotal - suitePassed;
28098
28574
  total_cases += suiteTotal;
28099
28575
  passed_cases += suitePassed;
28100
28576
  failed_cases += suiteFailed;
28577
+ interrupted_cases += suiteInterrupted;
28101
28578
  suites.push({
28102
28579
  suiteName,
28103
28580
  total_cases: suiteTotal,
28104
28581
  passed_cases: suitePassed,
28105
28582
  failed_cases: suiteFailed,
28583
+ interrupted_cases: suiteInterrupted,
28106
28584
  cases: caseResults.map((r) => ({
28107
28585
  caseId: r.caseId,
28108
28586
  pass: r.result?.pass,
28109
28587
  final_score: r.result?.final_score,
28110
- error: r.error
28588
+ error: r.error,
28589
+ interrupted: r.interrupted
28111
28590
  }))
28112
28591
  });
28113
28592
  }
@@ -28125,13 +28604,14 @@ Running batch: ${this.project.projectName} (${this.getSuiteNames().length} suite
28125
28604
  total_cases,
28126
28605
  passed_cases,
28127
28606
  failed_cases,
28607
+ interrupted_cases,
28128
28608
  pass_rate: total_cases > 0 ? passed_cases / total_cases : 0
28129
28609
  },
28130
28610
  suites
28131
28611
  };
28132
28612
  console.log(`
28133
28613
  === Summary ===`);
28134
- console.log(`Total: ${report.summary.total_cases} | Passed: ${report.summary.passed_cases} | Failed: ${report.summary.failed_cases} | Pass Rate: ${(report.summary.pass_rate * 100).toFixed(2)}%`);
28614
+ console.log(`Total: ${report.summary.total_cases} | Passed: ${report.summary.passed_cases} | Failed: ${report.summary.failed_cases} | Interrupted: ${report.summary.interrupted_cases} | Pass Rate: ${(report.summary.pass_rate * 100).toFixed(2)}%`);
28135
28615
  return { batch_id, results, report };
28136
28616
  }
28137
28617
  };
@@ -28216,11 +28696,11 @@ function clearEncryptionKeyCache() {
28216
28696
  }
28217
28697
 
28218
28698
  // src/middlewares/skillMiddleware.ts
28219
- var import_langchain61 = require("langchain");
28699
+ var import_langchain62 = require("langchain");
28220
28700
 
28221
28701
  // src/tool_lattice/skill/load_skills.ts
28222
28702
  var import_zod48 = __toESM(require("zod"));
28223
- var import_langchain58 = require("langchain");
28703
+ var import_langchain59 = require("langchain");
28224
28704
  var LOAD_SKILLS_DESCRIPTION = `Load all available skills and return their metadata (name, description, license, compatibility, metadata, and subSkills) without the content. This tool returns skill information including hierarchical relationships (subSkills). Use this to discover what skills are available and their structure.`;
28225
28705
  function getSandboxFromExeConfig(_exe_config) {
28226
28706
  const runConfig = _exe_config?.configurable?.runConfig || {};
@@ -28235,7 +28715,7 @@ function getSandboxFromExeConfig(_exe_config) {
28235
28715
  });
28236
28716
  }
28237
28717
  var createLoadSkillsTool = ({ skills } = {}) => {
28238
- return (0, import_langchain58.tool)(
28718
+ return (0, import_langchain59.tool)(
28239
28719
  async (_input, _exe_config) => {
28240
28720
  try {
28241
28721
  const sandbox = await getSandboxFromExeConfig(_exe_config);
@@ -28276,7 +28756,7 @@ var createLoadSkillsTool = ({ skills } = {}) => {
28276
28756
 
28277
28757
  // src/tool_lattice/skill/load_skill_content.ts
28278
28758
  var import_zod49 = __toESM(require("zod"));
28279
- var import_langchain59 = require("langchain");
28759
+ var import_langchain60 = require("langchain");
28280
28760
  var LOAD_SKILL_CONTENT_DESCRIPTION = `
28281
28761
  Execute a skill within the main conversation
28282
28762
 
@@ -28314,7 +28794,7 @@ function getSandboxFromExeConfig2(_exe_config) {
28314
28794
  });
28315
28795
  }
28316
28796
  var createLoadSkillContentTool = (pluginSkillContents) => {
28317
- return (0, import_langchain59.tool)(
28797
+ return (0, import_langchain60.tool)(
28318
28798
  async (input, _exe_config) => {
28319
28799
  try {
28320
28800
  if (pluginSkillContents?.[input.skill_name]) {
@@ -28372,7 +28852,7 @@ var createLoadSkillContentTool = (pluginSkillContents) => {
28372
28852
 
28373
28853
  // src/tool_lattice/skill/delete_skill.ts
28374
28854
  var import_zod50 = __toESM(require("zod"));
28375
- var import_langchain60 = require("langchain");
28855
+ var import_langchain61 = require("langchain");
28376
28856
  var DELETE_SKILL_DESCRIPTION = `
28377
28857
  Delete a skill by name from the skill system.
28378
28858
  This permanently removes the skill and its SKILL.md file.
@@ -28399,7 +28879,7 @@ function validateSkillName2(name) {
28399
28879
  }
28400
28880
  }
28401
28881
  var createDeleteSkillTool = () => {
28402
- return (0, import_langchain60.tool)(
28882
+ return (0, import_langchain61.tool)(
28403
28883
  async (input, _exe_config) => {
28404
28884
  try {
28405
28885
  validateSkillName2(input.skill_name);
@@ -28441,7 +28921,7 @@ function createSkillMiddleware(params = {}) {
28441
28921
  } = params;
28442
28922
  const skills = params.skills;
28443
28923
  let latestSkills = [];
28444
- return (0, import_langchain61.createMiddleware)({
28924
+ return (0, import_langchain62.createMiddleware)({
28445
28925
  name: "skillMiddleware",
28446
28926
  contextSchema,
28447
28927
  tools: [
@@ -28576,17 +29056,17 @@ var skillPlugin = {
28576
29056
  };
28577
29057
 
28578
29058
  // src/middlewares/collectionMiddleware.ts
28579
- var import_langchain72 = require("langchain");
29059
+ var import_langchain73 = require("langchain");
28580
29060
 
28581
29061
  // src/tool_lattice/collection/list_collections.ts
28582
29062
  var import_zod51 = __toESM(require("zod"));
28583
- var import_langchain62 = require("langchain");
29063
+ var import_langchain63 = require("langchain");
28584
29064
  var LIST_COLLECTIONS_DESCRIPTION = `List all available collections for the current tenant. Returns collection names, labels, and field definitions (including field types and enum values). Use this tool to discover what collections are available before searching.`;
28585
29065
  var createListCollectionsTool = ({
28586
29066
  collectionKeys,
28587
29067
  connectAll
28588
29068
  }) => {
28589
- return (0, import_langchain62.tool)(
29069
+ return (0, import_langchain63.tool)(
28590
29070
  async (_input, _exeConfig) => {
28591
29071
  try {
28592
29072
  const tenantId2 = _exeConfig?.configurable?.runConfig?.tenantId || "default";
@@ -28627,7 +29107,7 @@ var createListCollectionsTool = ({
28627
29107
 
28628
29108
  // src/tool_lattice/collection/search_collection.ts
28629
29109
  var import_zod52 = __toESM(require("zod"));
28630
- var import_langchain63 = require("langchain");
29110
+ var import_langchain64 = require("langchain");
28631
29111
  var SEARCH_COLLECTION_DESCRIPTION = `Search for content within a specific collection using semantic (vector) similarity. Use the 'filter' parameter to narrow results by metadata fields (e.g., {"category": "cardiovascular"}). Returns the most relevant content entries with similarity scores.`;
28632
29112
  var searchSchema = import_zod52.default.object({
28633
29113
  collection: import_zod52.default.string().describe("The collection name to search in"),
@@ -28636,7 +29116,7 @@ var searchSchema = import_zod52.default.object({
28636
29116
  top_k: import_zod52.default.number().optional().default(5).describe("Number of results to return")
28637
29117
  });
28638
29118
  var createSearchCollectionTool = () => {
28639
- return (0, import_langchain63.tool)(
29119
+ return (0, import_langchain64.tool)(
28640
29120
  async (input, _exeConfig) => {
28641
29121
  try {
28642
29122
  const { collection, query, filter: filter2, top_k } = input;
@@ -28687,9 +29167,9 @@ var createSearchCollectionTool = () => {
28687
29167
 
28688
29168
  // src/tool_lattice/collection/get_collection.ts
28689
29169
  var import_zod53 = __toESM(require("zod"));
28690
- var import_langchain64 = require("langchain");
29170
+ var import_langchain65 = require("langchain");
28691
29171
  var GET_COLLECTION_DESCRIPTION = `Get a collection's full definition including its custom fields schema. Use this to discover what metadata fields are available before adding entries.`;
28692
- var createGetCollectionTool = () => (0, import_langchain64.tool)(
29172
+ var createGetCollectionTool = () => (0, import_langchain65.tool)(
28693
29173
  async (input, _exeConfig) => {
28694
29174
  try {
28695
29175
  const tenantId2 = _exeConfig?.configurable?.runConfig?.tenantId || "default";
@@ -28717,7 +29197,7 @@ Embedding: ${c.embeddingKey}${fieldsDesc}`;
28717
29197
 
28718
29198
  // src/tool_lattice/collection/create_collection.ts
28719
29199
  var import_zod54 = __toESM(require("zod"));
28720
- var import_langchain65 = require("langchain");
29200
+ var import_langchain66 = require("langchain");
28721
29201
  var createSchema = import_zod54.default.object({
28722
29202
  name: import_zod54.default.string().describe("Collection name (lowercase, underscores only)"),
28723
29203
  label: import_zod54.default.string().describe("Display name"),
@@ -28729,7 +29209,7 @@ var createSchema = import_zod54.default.object({
28729
29209
  required: import_zod54.default.boolean().optional().default(false).describe("Whether field is required")
28730
29210
  })).optional().describe("Custom field definitions for entries in this collection")
28731
29211
  });
28732
- var createCreateCollectionTool = () => (0, import_langchain65.tool)(
29212
+ var createCreateCollectionTool = () => (0, import_langchain66.tool)(
28733
29213
  async (input, _exeConfig) => {
28734
29214
  try {
28735
29215
  const tenantId2 = _exeConfig?.configurable?.runConfig?.tenantId || "default";
@@ -28755,7 +29235,7 @@ var createCreateCollectionTool = () => (0, import_langchain65.tool)(
28755
29235
 
28756
29236
  // src/tool_lattice/collection/update_collection.ts
28757
29237
  var import_zod55 = __toESM(require("zod"));
28758
- var import_langchain66 = require("langchain");
29238
+ var import_langchain67 = require("langchain");
28759
29239
  var schema = import_zod55.default.object({
28760
29240
  name: import_zod55.default.string().describe("Collection name"),
28761
29241
  label: import_zod55.default.string().optional().describe("New display name"),
@@ -28767,7 +29247,7 @@ var schema = import_zod55.default.object({
28767
29247
  required: import_zod55.default.boolean().optional().default(false).describe("Whether field is required")
28768
29248
  })).optional().describe("Custom field definitions for entries (replaces existing schema)")
28769
29249
  });
28770
- var createUpdateCollectionTool = () => (0, import_langchain66.tool)(
29250
+ var createUpdateCollectionTool = () => (0, import_langchain67.tool)(
28771
29251
  async (input, _exeConfig) => {
28772
29252
  try {
28773
29253
  const tenantId2 = _exeConfig?.configurable?.runConfig?.tenantId || "default";
@@ -28787,8 +29267,8 @@ var createUpdateCollectionTool = () => (0, import_langchain66.tool)(
28787
29267
 
28788
29268
  // src/tool_lattice/collection/delete_collection.ts
28789
29269
  var import_zod56 = __toESM(require("zod"));
28790
- var import_langchain67 = require("langchain");
28791
- var createDeleteCollectionTool = () => (0, import_langchain67.tool)(
29270
+ var import_langchain68 = require("langchain");
29271
+ var createDeleteCollectionTool = () => (0, import_langchain68.tool)(
28792
29272
  async (input, _exeConfig) => {
28793
29273
  try {
28794
29274
  const tenantId2 = _exeConfig?.configurable?.runConfig?.tenantId || "default";
@@ -28803,14 +29283,14 @@ var createDeleteCollectionTool = () => (0, import_langchain67.tool)(
28803
29283
 
28804
29284
  // src/tool_lattice/collection/list_entries.ts
28805
29285
  var import_zod57 = __toESM(require("zod"));
28806
- var import_langchain68 = require("langchain");
29286
+ var import_langchain69 = require("langchain");
28807
29287
  var schema2 = import_zod57.default.object({
28808
29288
  collection: import_zod57.default.string().describe("Collection name")
28809
29289
  });
28810
29290
  function buildKey2(tenantId2, name) {
28811
29291
  return `${tenantId2}:${name}`;
28812
29292
  }
28813
- var createListEntriesTool = () => (0, import_langchain68.tool)(
29293
+ var createListEntriesTool = () => (0, import_langchain69.tool)(
28814
29294
  async (input, _exeConfig) => {
28815
29295
  try {
28816
29296
  const tenantId2 = _exeConfig?.configurable?.runConfig?.tenantId || "default";
@@ -28838,7 +29318,7 @@ var createListEntriesTool = () => (0, import_langchain68.tool)(
28838
29318
 
28839
29319
  // src/tool_lattice/collection/add_entry.ts
28840
29320
  var import_zod58 = __toESM(require("zod"));
28841
- var import_langchain69 = require("langchain");
29321
+ var import_langchain70 = require("langchain");
28842
29322
  var import_documents = require("@langchain/core/documents");
28843
29323
  var import_uuid11 = require("uuid");
28844
29324
  var schema3 = import_zod58.default.object({
@@ -28849,7 +29329,7 @@ var schema3 = import_zod58.default.object({
28849
29329
  function key(t, n) {
28850
29330
  return `${t}:${n}`;
28851
29331
  }
28852
- var createAddEntryTool = () => (0, import_langchain69.tool)(
29332
+ var createAddEntryTool = () => (0, import_langchain70.tool)(
28853
29333
  async (input, _exeConfig) => {
28854
29334
  try {
28855
29335
  const tenantId2 = _exeConfig?.configurable?.runConfig?.tenantId || "default";
@@ -28869,7 +29349,7 @@ var createAddEntryTool = () => (0, import_langchain69.tool)(
28869
29349
 
28870
29350
  // src/tool_lattice/collection/update_entry.ts
28871
29351
  var import_zod59 = __toESM(require("zod"));
28872
- var import_langchain70 = require("langchain");
29352
+ var import_langchain71 = require("langchain");
28873
29353
  var schema4 = import_zod59.default.object({
28874
29354
  collection: import_zod59.default.string().describe("Collection name"),
28875
29355
  entryId: import_zod59.default.string().describe("Entry ID to update"),
@@ -28879,7 +29359,7 @@ var schema4 = import_zod59.default.object({
28879
29359
  function key2(t, n) {
28880
29360
  return `${t}:${n}`;
28881
29361
  }
28882
- var createUpdateEntryTool = () => (0, import_langchain70.tool)(
29362
+ var createUpdateEntryTool = () => (0, import_langchain71.tool)(
28883
29363
  async (input, _exeConfig) => {
28884
29364
  try {
28885
29365
  const tenantId2 = _exeConfig?.configurable?.runConfig?.tenantId || "default";
@@ -28899,7 +29379,7 @@ var createUpdateEntryTool = () => (0, import_langchain70.tool)(
28899
29379
 
28900
29380
  // src/tool_lattice/collection/delete_entry.ts
28901
29381
  var import_zod60 = __toESM(require("zod"));
28902
- var import_langchain71 = require("langchain");
29382
+ var import_langchain72 = require("langchain");
28903
29383
  var schema5 = import_zod60.default.object({
28904
29384
  collection: import_zod60.default.string().describe("Collection name"),
28905
29385
  entryId: import_zod60.default.string().describe("Entry ID to delete")
@@ -28907,7 +29387,7 @@ var schema5 = import_zod60.default.object({
28907
29387
  function key3(t, n) {
28908
29388
  return `${t}:${n}`;
28909
29389
  }
28910
- var createDeleteEntryTool = () => (0, import_langchain71.tool)(
29390
+ var createDeleteEntryTool = () => (0, import_langchain72.tool)(
28911
29391
  async (input, _exeConfig) => {
28912
29392
  try {
28913
29393
  const tenantId2 = _exeConfig?.configurable?.runConfig?.tenantId || "default";
@@ -28925,7 +29405,7 @@ var createDeleteEntryTool = () => (0, import_langchain71.tool)(
28925
29405
  function createCollectionMiddleware(params) {
28926
29406
  const { collectionKeys, connectAll } = params;
28927
29407
  if (!connectAll && (!collectionKeys || collectionKeys.length === 0)) {
28928
- return (0, import_langchain72.createMiddleware)({
29408
+ return (0, import_langchain73.createMiddleware)({
28929
29409
  name: "collectionMiddleware",
28930
29410
  contextSchema,
28931
29411
  tools: [
@@ -28935,7 +29415,7 @@ function createCollectionMiddleware(params) {
28935
29415
  });
28936
29416
  }
28937
29417
  const listToolParams = { collectionKeys, connectAll };
28938
- return (0, import_langchain72.createMiddleware)({
29418
+ return (0, import_langchain73.createMiddleware)({
28939
29419
  name: "collectionMiddleware",
28940
29420
  contextSchema,
28941
29421
  tools: [
@@ -28997,11 +29477,11 @@ var collectionPlugin = {
28997
29477
  };
28998
29478
 
28999
29479
  // src/middlewares/askUserClarifyMiddleware.ts
29000
- var import_langchain74 = require("langchain");
29480
+ var import_langchain75 = require("langchain");
29001
29481
  var import_langgraph15 = require("@langchain/langgraph");
29002
29482
 
29003
29483
  // src/tool_lattice/ask_user_to_clarify/index.ts
29004
- var import_langchain73 = require("langchain");
29484
+ var import_langchain74 = require("langchain");
29005
29485
  var import_zod61 = __toESM(require("zod"));
29006
29486
  var questionSchema = import_zod61.default.object({
29007
29487
  question: import_zod61.default.string().describe("The question text to ask the user. MUST include the specific context, options, or details being clarified \u2014 never use a bare generic label. Good: 'Confirm the plan: use Redis cache + PostgreSQL primary, split microservices as needed?' Bad: 'Confirm the plan?'"),
@@ -29014,7 +29494,7 @@ var inputSchema = import_zod61.default.object({
29014
29494
  questions: import_zod61.default.array(questionSchema).min(1, "At least one question is required").describe("A structured sequence of clarification questions. Use these to gather missing parameters or disambiguate user intent before proceeding.")
29015
29495
  });
29016
29496
  function createAskUserToClarifyTool() {
29017
- return (0, import_langchain73.tool)(
29497
+ return (0, import_langchain74.tool)(
29018
29498
  async (input) => {
29019
29499
  return JSON.stringify(input);
29020
29500
  },
@@ -29028,7 +29508,7 @@ function createAskUserToClarifyTool() {
29028
29508
 
29029
29509
  // src/middlewares/askUserClarifyMiddleware.ts
29030
29510
  function createAskUserClarifyMiddleware() {
29031
- return (0, import_langchain74.createMiddleware)({
29511
+ return (0, import_langchain75.createMiddleware)({
29032
29512
  name: "AskUserClarifyMiddleware",
29033
29513
  tools: [createAskUserToClarifyTool()],
29034
29514
  wrapToolCall: async (request, handler) => {
@@ -29042,7 +29522,7 @@ function createAskUserClarifyMiddleware() {
29042
29522
  throw error;
29043
29523
  }
29044
29524
  console.error(`Error executing tool "${toolName}":`, error);
29045
- return new import_langchain74.ToolMessage({
29525
+ return new import_langchain75.ToolMessage({
29046
29526
  content: `Error executing tool: ${error instanceof Error ? error.message : "Unknown error"}`,
29047
29527
  tool_call_id: toolCall?.id,
29048
29528
  name: toolName
@@ -29051,7 +29531,7 @@ function createAskUserClarifyMiddleware() {
29051
29531
  }
29052
29532
  const parsed = inputSchema.safeParse(toolCall?.args);
29053
29533
  if (!parsed.success) {
29054
- return new import_langchain74.ToolMessage({
29534
+ return new import_langchain75.ToolMessage({
29055
29535
  content: `Invalid clarify tool arguments: ${parsed.error.message}`,
29056
29536
  tool_call_id: toolCall?.id,
29057
29537
  name: toolName
@@ -29071,7 +29551,7 @@ function createAskUserClarifyMiddleware() {
29071
29551
  const result = await (0, import_langgraph15.interrupt)(md);
29072
29552
  const response = result.data;
29073
29553
  if (!response?.answers || response.answers.length === 0) {
29074
- return new import_langchain74.ToolMessage({
29554
+ return new import_langchain75.ToolMessage({
29075
29555
  content: "No clarification questions were answered.",
29076
29556
  tool_call_id: toolCall?.id,
29077
29557
  name: toolName
@@ -29081,7 +29561,7 @@ function createAskUserClarifyMiddleware() {
29081
29561
  (answer) => (answer.selectedOptions?.length ?? 0) > 0 || answer.otherText && answer.otherText.trim() !== "" || answer.filePath && answer.filePath.trim() !== ""
29082
29562
  );
29083
29563
  if (answeredQuestions.length === 0) {
29084
- return new import_langchain74.ToolMessage({
29564
+ return new import_langchain75.ToolMessage({
29085
29565
  content: "No clarification questions were answered.",
29086
29566
  tool_call_id: toolCall?.id,
29087
29567
  name: toolName
@@ -29111,7 +29591,7 @@ function createAskUserClarifyMiddleware() {
29111
29591
  }
29112
29592
  lines.push("");
29113
29593
  }
29114
- return new import_langchain74.ToolMessage({
29594
+ return new import_langchain75.ToolMessage({
29115
29595
  content: lines.join("\n"),
29116
29596
  tool_call_id: toolCall?.id,
29117
29597
  name: toolName
@@ -29137,10 +29617,10 @@ var askUserClarifyPlugin = {
29137
29617
  };
29138
29618
 
29139
29619
  // src/middlewares/widgetMiddleware.ts
29140
- var import_langchain77 = require("langchain");
29620
+ var import_langchain78 = require("langchain");
29141
29621
 
29142
29622
  // src/tool_lattice/widget/loadGuidelines.ts
29143
- var import_langchain75 = require("langchain");
29623
+ var import_langchain76 = require("langchain");
29144
29624
  var import_zod62 = require("zod");
29145
29625
 
29146
29626
  // src/middlewares/guidelines/index.ts
@@ -29938,7 +30418,7 @@ var LoadGuidelinesInputSchema = import_zod62.z.object({
29938
30418
  )
29939
30419
  });
29940
30420
  function createLoadGuidelinesTool() {
29941
- return (0, import_langchain75.tool)(
30421
+ return (0, import_langchain76.tool)(
29942
30422
  async (input) => {
29943
30423
  const result = getGuidelines(input.modules);
29944
30424
  return result;
@@ -29952,7 +30432,7 @@ function createLoadGuidelinesTool() {
29952
30432
  }
29953
30433
 
29954
30434
  // src/tool_lattice/widget/showWidget.ts
29955
- var import_langchain76 = require("langchain");
30435
+ var import_langchain77 = require("langchain");
29956
30436
  var import_zod63 = require("zod");
29957
30437
  function containsForbiddenTags(code) {
29958
30438
  const forbiddenPatterns = [
@@ -29988,7 +30468,7 @@ var ShowWidgetInputSchema = import_zod63.z.object({
29988
30468
  )
29989
30469
  });
29990
30470
  function createShowWidgetTool() {
29991
- return (0, import_langchain76.tool)(
30471
+ return (0, import_langchain77.tool)(
29992
30472
  async (input) => {
29993
30473
  if (!input.i_have_seen_guidelines) {
29994
30474
  return "Error: You must call load_guidelines before using show_widget. Set i_have_seen_guidelines to true only after loading guidelines.";
@@ -30019,7 +30499,7 @@ function createWidgetMiddleware() {
30019
30499
  createLoadGuidelinesTool(),
30020
30500
  createShowWidgetTool()
30021
30501
  ];
30022
- return (0, import_langchain77.createMiddleware)({
30502
+ return (0, import_langchain78.createMiddleware)({
30023
30503
  name: "widgetMiddleware",
30024
30504
  contextSchema,
30025
30505
  tools
@@ -30043,7 +30523,7 @@ var widgetPlugin = {
30043
30523
  };
30044
30524
 
30045
30525
  // src/middlewares/evalMiddleware.ts
30046
- var import_langchain78 = require("langchain");
30526
+ var import_langchain79 = require("langchain");
30047
30527
  var import_zod64 = require("zod");
30048
30528
  var import_uuid12 = require("uuid");
30049
30529
 
@@ -30080,10 +30560,21 @@ Write assertions as objective, verifiable natural language:
30080
30560
  - steps: [{agent_id: "a"}, {agent_id: "b", override_message: "Based on..."}] for chain
30081
30561
  - outputType: "message_content" or "file_content"
30082
30562
 
30563
+ ## Designing HITL Cases
30564
+ If the flow under test PAUSES for human input (HITL \u2014 the agent requests approval/confirmation), configure interruptPolicy on the case \u2014 otherwise the run stops at the pause and the flow AFTER the human input is never tested:
30565
+
30566
+ - interruptPolicy: {mode: "auto-approve"} \u2014 inject "\u540C\u610F"; tests the full flow after approval (e.g. payment executed after approval). Use value to override the injected text.
30567
+ - interruptPolicy: {mode: "auto-reject"} \u2014 inject "\u62D2\u7EDD"; tests the rejection path.
30568
+ - interruptPolicy: {mode: "canned-response", value: "..."} \u2014 inject an exact human reply; tests behavior under a specific response.
30569
+ - Omit (default "stop") \u2014 the case pauses at the request; the judge evaluates whether pausing was the correct behavior (e.g. "must request approval" PASSES; "must be autonomous" FAILS).
30570
+
30571
+ Choose per the assertion: if the assertion describes what happens AFTER the human input, you MUST set an auto-resolve policy.
30572
+
30083
30573
  ## Checklist
30084
30574
  1. Check existing assets with read_eval to avoid duplication
30085
30575
  2. Start with 3-5 high-signal cases
30086
- 3. Confirm with user before calling manage_eval
30576
+ 3. If the flow contains a human-approval step and the assertion covers what happens AFTER it, set interruptPolicy (auto-approve / auto-reject / canned-response) \u2014 never leave it unset in that case
30577
+ 4. Confirm with user before calling manage_eval
30087
30578
  `,
30088
30579
  "eval-run-and-govern": `---
30089
30580
  name: eval-run-and-govern
@@ -30093,8 +30584,11 @@ description: Run agent evaluations, interpret results, diagnose failures, and re
30093
30584
  # Agent Governance Loop
30094
30585
 
30095
30586
  1. Discover project \u2192 read_eval list_projects
30096
- 2. Start evaluation \u2192 run_eval start(projectId) \u2014 ASYNC, may take minutes
30097
- 3. Poll status \u2192 run_eval status(runId) with backoff: 15s, 30s, 60s, max 120s
30587
+ 2. Start evaluation \u2192 run_eval start(projectId) \u2014 SYNCHRONOUS by default:
30588
+ blocks up to ~150s and returns the FINAL RESULTS in one call.
30589
+ Hold-out (validation) runs return aggregates only.
30590
+ 3. If still running (or use wait: false for fire-and-forget) \u2192 poll
30591
+ run_eval status(runId, sleepMs) \u2014 pass sleepMs to pace (15s, 30s, 60s, max 120s)
30098
30592
  4. If runnerAlive=false and status=running \u2192 ORPHANED (gateway restart).
30099
30593
  resume(runId) marks it failed automatically \u2014 then start a new run.
30100
30594
  5. Get results \u2192 read_eval get_run_results(runId) for per-case dimension scores
@@ -30163,10 +30657,12 @@ function sanitize(obj) {
30163
30657
  }
30164
30658
  function aggregateHoldoutResults(results) {
30165
30659
  const passed = results.filter((r) => r.pass).length;
30660
+ const interrupted = results.filter((r) => r.interrupted).length;
30166
30661
  return {
30167
30662
  holdout: true,
30168
30663
  passedCases: passed,
30169
30664
  failedCases: results.length - passed,
30665
+ interruptedCases: interrupted,
30170
30666
  passRate: results.length > 0 ? passed / results.length : 0,
30171
30667
  totalCases: results.length
30172
30668
  };
@@ -30198,7 +30694,7 @@ function createReadEvalTool() {
30198
30694
  runId: import_zod64.z.string().optional(),
30199
30695
  status: import_zod64.z.string().optional().describe("Filter: running|completed|failed|aborted")
30200
30696
  });
30201
- return (0, import_langchain78.tool)(
30697
+ return (0, import_langchain79.tool)(
30202
30698
  async (input, exeConfig) => {
30203
30699
  const tid = tenantId(exeConfig);
30204
30700
  if (!tid) {
@@ -30237,13 +30733,8 @@ function createReadEvalTool() {
30237
30733
  if (!run) return JSON.stringify({ success: false, error: "Run not found" });
30238
30734
  const results = await store.getResultsByRun(tid, input.runId);
30239
30735
  if (run.holdout) {
30240
- const passed = results.filter((r) => r.pass).length;
30241
30736
  data = {
30242
- holdout: true,
30243
- passedCases: passed,
30244
- failedCases: results.length - passed,
30245
- passRate: results.length > 0 ? passed / results.length : 0,
30246
- totalCases: results.length,
30737
+ ...aggregateHoldoutResults(results),
30247
30738
  message: "Hold-out run \u2014 per-case results withheld. Only aggregates are available."
30248
30739
  };
30249
30740
  } else {
@@ -30278,6 +30769,7 @@ ACTIONS:
30278
30769
  - get_run_results(runId) \u2014 per-case results with dimension scores.
30279
30770
  For HOLD-OUT (validation-only) runs: returns AGGREGATES ONLY
30280
30771
  (passRate, counts) \u2014 per-case details are withheld by design.
30772
+ Cases paused for human input (HITL) carry interrupted=true and are judged \u2014 the judge evaluates whether pausing was correct business behavior.
30281
30773
  - get_project_report(projectId) \u2014 aggregated stats across all runs`,
30282
30774
  schema: schema6
30283
30775
  }
@@ -30308,9 +30800,13 @@ function createManageEvalTool() {
30308
30800
  steps: import_zod64.z.array(import_zod64.z.object({ agent_id: import_zod64.z.string(), override_message: import_zod64.z.string().optional() })).optional(),
30309
30801
  outputType: import_zod64.z.enum(["file_content", "message_content"]).optional(),
30310
30802
  contentAssertion: import_zod64.z.string().optional(),
30311
- rubrics: import_zod64.z.array(import_zod64.z.object({ name: import_zod64.z.string(), weight: import_zod64.z.number(), description: import_zod64.z.string() })).optional()
30803
+ rubrics: import_zod64.z.array(import_zod64.z.object({ name: import_zod64.z.string(), weight: import_zod64.z.number(), description: import_zod64.z.string() })).optional(),
30804
+ interruptPolicy: import_zod64.z.object({
30805
+ mode: import_zod64.z.enum(["stop", "auto-approve", "auto-reject", "canned-response"]).describe("stop=judge the pause; auto-approve/auto-reject/canned-response=resume the agent to test the flow after the human input"),
30806
+ value: import_zod64.z.string().optional().describe("Response to inject (defaults: \u540C\u610F / \u62D2\u7EDD; required for canned-response)")
30807
+ }).optional().describe("Optional for create_case/update_case \u2014 how HITL interrupts are handled")
30312
30808
  });
30313
- return (0, import_langchain78.tool)(
30809
+ return (0, import_langchain79.tool)(
30314
30810
  async (input, exeConfig) => {
30315
30811
  const tid = tenantId(exeConfig);
30316
30812
  if (!tid) {
@@ -30366,7 +30862,8 @@ function createManageEvalTool() {
30366
30862
  steps: input.steps,
30367
30863
  outputType: input.outputType,
30368
30864
  contentAssertion: input.contentAssertion,
30369
- rubrics: input.rubrics
30865
+ rubrics: input.rubrics,
30866
+ interruptPolicy: input.interruptPolicy
30370
30867
  });
30371
30868
  break;
30372
30869
  case "update_case":
@@ -30374,7 +30871,8 @@ function createManageEvalTool() {
30374
30871
  inputMessage: input.inputMessage,
30375
30872
  contentAssertion: input.contentAssertion,
30376
30873
  steps: input.steps,
30377
- rubrics: input.rubrics
30874
+ rubrics: input.rubrics,
30875
+ interruptPolicy: input.interruptPolicy
30378
30876
  });
30379
30877
  break;
30380
30878
  case "delete_case":
@@ -30399,9 +30897,13 @@ Project: create_project(name, description?, judgeModelKey?, concurrency?) | upda
30399
30897
  **When creating a project from within a workspace, the workspace/project context is
30400
30898
  automatically bound \u2014 eval runs will execute in the same workspace.**
30401
30899
  Suite: create_suite(projectId, name) | update_suite | delete_suite
30402
- Case: create_case(suiteId, inputMessage, steps, outputType, contentAssertion, inputFiles?, rubrics?)
30900
+ Case: create_case(suiteId, inputMessage, steps, outputType, contentAssertion, inputFiles?, rubrics?, interruptPolicy?)
30403
30901
  steps is [{agent_id, override_message?}]. outputType is "file_content" or "message_content".
30404
- rubrics is [{name, weight, description}]. | update_case | delete_case`,
30902
+ rubrics is [{name, weight, description}]. | update_case | delete_case
30903
+ interruptPolicy: {mode: "stop"|"auto-approve"|"auto-reject"|"canned-response", value?} \u2014 how HITL interrupts are handled:
30904
+ stop (default): case pauses at the human-input request; the judge evaluates the pause as business behavior.
30905
+ auto-approve / auto-reject: the runner injects approval/rejection and tests the FULL flow after the pause.
30906
+ canned-response: injects the exact value (simulates a specific human reply).`,
30405
30907
  schema: schema6
30406
30908
  }
30407
30909
  );
@@ -30416,7 +30918,7 @@ function createRunEvalTool() {
30416
30918
  sleepMs: import_zod64.z.number().int().min(0).max(12e4).optional().describe("Optional for status \u2014 sleep this many ms BEFORE checking the run, to pace polling (e.g. 15000 \u2192 30000 \u2192 60000 \u2192 120000). Omit to check immediately."),
30417
30919
  wait: import_zod64.z.boolean().optional().describe("Optional for start \u2014 defaults to true: block synchronously (up to ~150s) and return final results in one call. Set false to return the runId immediately and poll.")
30418
30920
  });
30419
- return (0, import_langchain78.tool)(
30921
+ return (0, import_langchain79.tool)(
30420
30922
  withToolTimeout(
30421
30923
  async (input, exeConfig) => {
30422
30924
  const tid = tenantId(exeConfig);
@@ -30515,6 +31017,8 @@ ACTIONS:
30515
31017
  - start(projectId, suiteIds?, caseIds?, wait?) \u2014 begin evaluation (optionally only the listed suites, and/or only the listed cases).
30516
31018
  wait=true (DEFAULT): SYNCHRONOUS \u2014 blocks up to ~150s and returns the FINAL RESULTS in one call:
30517
31019
  { status, results } with per-case pass/score (hold-out/validation runs: aggregates only \u2014 per-case details withheld by design).
31020
+ Cases paused for human input (HITL) carry interrupted=true and ARE judged \u2014 the judge evaluates whether requesting
31021
+ the human was the correct behavior (assertions like "must approve first" PASS; "must be autonomous" FAIL). interruptedCases counts these.
30518
31022
  If the run exceeds 150s: returns { runId, status: "running" } \u2014 NOT an error \u2014 then poll with status/resume until completed.
30519
31023
  wait=false: fire-and-forget \u2014 returns { runId } immediately; poll with status.
30520
31024
  - status(runId, sleepMs?) \u2014 sleep sleepMs first (to pace polling), then return current status + runnerAlive flag:
@@ -30545,7 +31049,7 @@ var evalPlugin = {
30545
31049
  defaultConfig: {}
30546
31050
  },
30547
31051
  skills: EVAL_SKILLS,
30548
- middleware: () => (0, import_langchain78.createMiddleware)({
31052
+ middleware: () => (0, import_langchain79.createMiddleware)({
30549
31053
  name: "EvalMiddleware",
30550
31054
  tools: [createReadEvalTool(), createManageEvalTool(), createRunEvalTool()]
30551
31055
  })
@@ -30820,67 +31324,64 @@ verification choice, then start benchmarking.
30820
31324
 
30821
31325
  ## Task Tracking \u2014 see [[task-tracking]]
30822
31326
 
30823
- **Create the parent task when the task is actually defined** \u2014 after
30824
- Phase 0 clarification is complete and the user confirmed the path
30825
- (fresh vs incremental). Do NOT create tasks during clarification:
30826
- while asking questions (0.0-0.4) you don't know what the task is yet.
30827
- Once the scope is clear (end of 0.5), that is the moment to create:
30828
- manage_task create("Learn [material]", ownerType: "agent"). Then a
30829
- subtask per phase as you start it. Update status to reflect reality \u2014
30830
- never mark a subtask completed while eval fails. Resume interrupted
30831
- runs with manage_task list.
31327
+ **Universal principle**: once the goal is clear and you know what to
31328
+ do, create the parent task BEFORE executing (manage_task create, see
31329
+ [[task-tracking]]). In this workflow: after Phase 0 clarification
31330
+ completes and the user confirmed the path (end of 0.5), create the
31331
+ parent task; then a subtask per phase as you start it. The parent task
31332
+ description carries the GOAL MODEL (0.1.5) as Objective + Acceptance
31333
+ Criteria; the expected output spec (2.6) updates the criteria. Update
31334
+ status to reflect reality \u2014 never mark a subtask completed while eval
31335
+ fails. Resume interrupted runs with manage_task list.
30832
31336
 
30833
31337
  Widgets: call \`load_guidelines\` ONCE before your first \`show_widget\`
30834
31338
  (show_widget hard-requires it), then reuse.
30835
31339
 
30836
31340
  ---
30837
31341
 
30838
- ## Phase 1: Probe (material-dependent)
30839
-
30840
- The probing strategy depends on the material type from Phase 0.0:
30841
-
30842
- **User-description material**: the requirements come from the
30843
- conversation itself \u2014 no probing needed. Extract the agent's goal,
30844
- inputs, outputs, and constraints from what the user described. Go
30845
- straight to design.
30846
-
30847
- **Document material** (PDF / spec / manual):
30848
- If the engine was chosen in Phase 0 (0.3 \u2460-\u2464): skip the comparison \u2014
30849
- parse directly with \`parse_document\` using the chosen engine
30850
- (file_path, engine, output_path per file).
30851
- Otherwise: run the document-parser-benchmark subagent via \`task\` on each file.
30852
- Collect engine scores, parsed output (via \`read_file\`), and feature signatures.
30853
-
30854
- **Engine selection IS distilled knowledge, not just setup.** For document
30855
- material, the benchmark answers "which engine parses THIS document (or
30856
- this class of document) best?" \u2014 that answer is knowledge that drives
30857
- the whole rest of the run:
30858
- - **Builds the agent**: the chosen engine's \`parse_document\` goes into
30859
- the production agent's middleware/tools.
30860
- - **Designs the tests**: the chosen engine's parsed output becomes the
30861
- baseline input for eval cases \u2014 cases feed parsed output to the agent
30862
- and assert correct extraction from it.
30863
- - **Seeds the skill**: the feature signature (tables? scans? mixed
30864
- zh/en?) plus the winning engine becomes a skill note ("for PO PDFs
30865
- with tables, use textin") reusable for future similar documents.
30866
- So when the user wants an agent whose purpose is document PARSING (not
30867
- extraction), the workflow is the same: benchmark to learn the engine
30868
- choice, then build the agent around that engine and test against its
30869
- output. Do NOT treat parsing as a pure tool-assembly task \u2014 the engine
30870
- choice is unknown knowledge until probed.
30871
-
30872
- **API spec material**: read the spec directly \u2014 no parsing engine needed.
30873
- Extract endpoints, schemas, request/response examples from the text.
30874
-
30875
- **Conversation material**: extract the workflow, decisions, and corrections
30876
- from the conversation context \u2014 no parsing engine needed.
30877
-
30878
- **Spreadsheet material**: parse cells directly \u2014 structured data needs
30879
- no engine comparison.
30880
- If verification will happen (0.2 \u2460 or \u2461): concurrently, \`list_agents\` to
30881
- discover existing agents with relevant capabilities (see \xA75).
30882
- For \u2460, look for agents with data-access tools (SQL / API). For \u2461, look
30883
- for agents with independence.
31342
+ ## Phase 1: Explore (goal-driven path finding)
31343
+
31344
+ The goal model (0.1.5) is set. Now EXPLORE how to achieve it \u2014 actively
31345
+ hunt for the path, do not passively read. Three exploration fronts:
31346
+
31347
+ **A. Existing assets (reuse, don't rebuild):**
31348
+ - \`list_agents\` / \`load_skills\` \u2192 are there existing agents or skills
31349
+ that already do part of this? Reuse them (update_agent if needed)
31350
+ instead of building from scratch. This is a goal-relevant check, not
31351
+ a materials step.
31352
+ - \`list_tools\` / \`list_middleware_types\` \u2192 what capabilities exist
31353
+ that the goal needs (parsing, data access, browser...)?
31354
+ - \`list_connections\` \u2192 are the data sources the goal depends on
31355
+ already connected?
31356
+ - If verification will happen (0.2 \u2460 or \u2461): concurrently discover
31357
+ executor candidates (see \xA75). \u2460 \u2192 data-access tools; \u2461 \u2192 independence.
31358
+
31359
+ **B. Material probing (by material type):**
31360
+ - **User-description**: the requirements come from the conversation.
31361
+ Extract goal, inputs, outputs, constraints \u2014 then explore the
31362
+ implementation path (A + feasibility): what assets exist, what tools
31363
+ are needed, what blockers stand between the goal and its achievement.
31364
+ - **Document** (PDF / spec / manual): benchmark engines as needed \u2014
31365
+ parse directly with the chosen engine (0.3 \u2460-\u2464) or run
31366
+ document-parser-benchmark. Engine selection IS distilled knowledge:
31367
+ it builds the agent (engine's parse_document into middleware), seeds
31368
+ the skill (feature signature + winning engine), and designs the tests
31369
+ (engine output as case baseline input).
31370
+ - **API spec**: read directly \u2014 endpoints, schemas, examples.
31371
+ - **Conversation**: extract workflow, decisions, corrections.
31372
+ - **Spreadsheet**: parse cells directly.
31373
+
31374
+ **C. Feasibility (path blockers):**
31375
+ - What stands between the goal and achievement? Missing tools, missing
31376
+ connections, data access, permission constraints, ambiguous
31377
+ requirements.
31378
+ - Does the goal require orchestration (\u2192 Phase 2 split decision)?
31379
+ - Surface these in the recommendation (Phase 1.5) \u2014 the user decides
31380
+ the path, informed by what exploration found.
31381
+
31382
+ Exploration is COMPLETE when you can answer: what exists to reuse,
31383
+ what must be built, what tools/connections are needed, and what blocks
31384
+ the goal. Do not go to design without this map.
30884
31385
 
30885
31386
  ---
30886
31387
 
@@ -30895,17 +31396,21 @@ candidate and assess (Validation Agent Design \xA70) \u2014 state which are
30895
31396
  usable and which are not, with reasons. For \u2460, the executor needs data
30896
31397
  tools + independence. For \u2461, independence only. If no candidate fits,
30897
31398
  plan to build one via \xA75.
30898
- Present probe results as widget, then MUST call
31399
+ Present the EXPLORATION map as widget \u2014 what exists to reuse, what
31400
+ must be built, tools/connections needed, blockers found \u2014 then
31401
+ recommend the IMPLEMENTATION PATH: reuse existing X, build new Y,
31402
+ split or single agent (Phase 2 input). MUST call
30899
31403
  \`ask_user_to_clarify\` NOW:
30900
31404
  {
30901
31405
  "questions": [{
30902
- "question": "Confirm the recommendation?",
31406
+ "question": "Confirm the recommended path?",
30903
31407
  "options": ["Confirm", "Adjust"],
30904
31408
  "type": "single",
30905
31409
  "required": true
30906
31410
  }]
30907
31411
  }
30908
- Skills planning belongs to Phase 2 \u2014 this phase presents data, not plans.
31412
+ Skills planning belongs to Phase 2 \u2014 this phase presents the path, not
31413
+ the detailed plan.
30909
31414
 
30910
31415
  ---
30911
31416
 
@@ -30973,9 +31478,53 @@ user-description material this IS the core phase; for material-based
30973
31478
  learning it designs the agent that runs the learned skill. Agent
30974
31479
  metadata (verified/version/source) must be set on creation.
30975
31480
 
31481
+ ## Phase 2.6: Expected Output Specification (mandatory \u2014 goal-driven)
31482
+
31483
+ **Expectations come FIRST, before writing the skill.** You cannot write
31484
+ a skill (or test cases) without a target. Define the expected output
31485
+ specification from the goal model (0.1.5: real goal / consumer / usable
31486
+ state) BEFORE Phase 3:
31487
+
31488
+ **HARD RULE \u2014 never guess the target.** If the goal, the expected
31489
+ output, the consumer, or the usable state is unclear at ANY point
31490
+ before writing test cases, you MUST ask the user via
31491
+ \`ask_user_to_clarify\` \u2014 do NOT proceed with an assumed expectation.
31492
+ A test case written against a guessed expectation is worthless: it
31493
+ validates the wrong thing. When in doubt, ask.
31494
+
31495
+ Per skill, define the EXPECTED OUTPUT SPEC (based on intent 0.1 and
31496
+ consumer 0.1.5):
31497
+ - Extract data \u2192 expected fields (names, types, formats), required vs
31498
+ optional, output structure (JSON schema shape, table columns)
31499
+ - Validate rules \u2192 expected judgment outcomes (pass/fail conditions),
31500
+ boundary values, and the reason format
31501
+ - Execute workflow \u2192 expected step sequence, decision points, final
31502
+ outcome shape
31503
+ - Answer knowledge \u2192 expected answer form (with/without sources,
31504
+ length, structure)
31505
+
31506
+ This spec IS the acceptance standard. Phase 4 contentAssertion must be
31507
+ derived from it (not invented at case-writing time). Present the
31508
+ expected output spec to the user and MUST call \`ask_user_to_clarify\`
31509
+ NOW per skill:
31510
+ {
31511
+ "questions": [{
31512
+ "question": "Confirm the expected output spec for {skill-name}?",
31513
+ "options": ["Confirm", "Adjust"],
31514
+ "type": "single",
31515
+ "required": true,
31516
+ "allowOther": true
31517
+ }]
31518
+ }
31519
+ Record the confirmed spec in the parent task description. This replaces
31520
+ guess-then-confirm: the skill is written TO MEET the spec, and test
31521
+ cases assert AGAINST the spec \u2014 no expectation is invented later.
31522
+
30976
31523
  ## Phase 3: Create Skills
30977
31524
 
30978
- Write SKILL.md to \`/root/.agents/skills/{name}/SKILL.md\` one at a time.
31525
+ Write SKILL.md to \`/root/.agents/skills/{name}/SKILL.md\` one at a time,
31526
+ designed TO MEET the expected output spec confirmed in Phase 2.6 \u2014 the
31527
+ skill encodes how to produce the spec's expected output.
30979
31528
  Show the skill content in text first, then MUST call
30980
31529
  \`ask_user_to_clarify\` NOW per skill:
30981
31530
  {
@@ -31269,7 +31818,8 @@ This learning loop adds its own scenario rules:
31269
31818
  - Business usability (output reaches the goal's "usable state")
31270
31819
  - Consumer fit (format/contract satisfies who uses the result)
31271
31820
  contentAssertion must encode the usable state from the goal model
31272
- (0.1.5), not just technical correctness.
31821
+ (0.1.5), derived from the EXPECTED OUTPUT SPEC (Phase 2.6) \u2014 never
31822
+ invented at case-writing time.
31273
31823
 
31274
31824
  1. One suite per skill per source: cases test "can this skill do it" \u2014
31275
31825
  never mix skills in one suite
@@ -31312,6 +31862,12 @@ Learning-specific suite guidance:
31312
31862
  - User-description material: {skill}-requirement-derived \u2014 cases from
31313
31863
  user's described requirements
31314
31864
 
31865
+ **Case expectations come from the confirmed spec** (Phase 2.6): the
31866
+ contentAssertion of every case must be derived from the expected output
31867
+ spec, NOT invented at case-writing time. If a case needs an expectation
31868
+ not in the spec, go back and extend the spec with user confirmation
31869
+ first \u2014 never guess expectations on the fly.
31870
+
31315
31871
  [[completion-gate]] applies \u2014 eval must pass before declaring done.
31316
31872
 
31317
31873
  ## Phase 5: Retrospective
@@ -31454,12 +32010,12 @@ var documentLearningPlugin = {
31454
32010
  };
31455
32011
 
31456
32012
  // src/middlewares/documentParserMiddleware.ts
31457
- var import_langchain80 = require("langchain");
32013
+ var import_langchain81 = require("langchain");
31458
32014
 
31459
32015
  // src/tool_lattice/document_parser/index.ts
31460
32016
  var path7 = __toESM(require("path"));
31461
32017
  var import_zod65 = __toESM(require("zod"));
31462
- var import_langchain79 = require("langchain");
32018
+ var import_langchain80 = require("langchain");
31463
32019
  var PARSE_DOCUMENT_DESCRIPTION = `Parse a document file (docx, pdf) into structured Markdown using a remote document parsing service.
31464
32020
  This tool handles the full pipeline internally: file upload \u2192 document parsing \u2192 polling until complete \u2192 download result \u2192 save to filesystem.
31465
32021
 
@@ -31581,7 +32137,7 @@ function createParseDocumentTool({
31581
32137
  baseUrl = "",
31582
32138
  apiKey = ""
31583
32139
  }) {
31584
- return (0, import_langchain79.tool)(
32140
+ return (0, import_langchain80.tool)(
31585
32141
  async (input, exe_config) => {
31586
32142
  try {
31587
32143
  const runConfig = exe_config?.configurable?.runConfig ?? { assistant_id: "", thread_id: "" };
@@ -31845,7 +32401,7 @@ function createDocumentParserMiddleware(config) {
31845
32401
  const connectAll = config.connectAll === true;
31846
32402
  const baseUrl = config.baseUrl || "";
31847
32403
  const apiKey = config.apiKey || "";
31848
- return (0, import_langchain80.createMiddleware)({
32404
+ return (0, import_langchain81.createMiddleware)({
31849
32405
  name: "DocumentParser",
31850
32406
  contextSchema,
31851
32407
  tools: [createParseDocumentTool({ connectAll, baseUrl, apiKey })]