agent-lattice 0.25.1 → 0.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -182,6 +182,24 @@ The Kimi Open Platform endpoint at `https://api.moonshot.cn/v1` uses the OpenAI
182
182
  Chat Completions protocol and is not a valid `baseURL` for the SDK's built-in
183
183
  Anthropic client.
184
184
 
185
+ ## Default output budget
186
+
187
+ *Requires 0.29.0 or later.*
188
+
189
+ When `baseURL` points to the official `api.deepseek.com` host and `maxTokens` is
190
+ omitted, the SDK uses **393216 tokens (384K)**, the maximum output advertised by
191
+ DeepSeek's [model metadata](https://api-docs.deepseek.com/api/list-models/) and
192
+ [API reference](https://api-docs.deepseek.com/api/create-chat-completion/).
193
+ Other endpoints keep the existing 16384-token default. An explicit `maxTokens`
194
+ always takes precedence. Set `baseURL` explicitly to use this provider default;
195
+ the SDK does not inspect environment variables to choose the output budget.
196
+
197
+ This is a maximum allowance per model request, including thinking output, not a
198
+ request to generate that many tokens. The provider can end the response sooner;
199
+ usage and billing depend on tokens actually generated. Smaller explicit limits
200
+ remain useful when an application deliberately limits output or cost. The
201
+ separate `autoCompact.maxTokens` summary budget is unchanged.
202
+
185
203
  ## Multimodal Input
186
204
 
187
205
  Pass Anthropic-compatible content blocks for image or document prompts:
@@ -535,7 +553,7 @@ The structure is enforced by the harness, not by prompt discipline:
535
553
  loop as an error `tool_result`, so the model can fix it and retry. A valid
536
554
  submission ends the run with `subtype: "success"` and the payload on
537
555
  `SDKResultMessage.structuredResult`.
538
- - If the model ends its turn without calling `submit_output`, the run fails
556
+ - If recovery is disabled or unsuccessful, ending without `submit_output` fails
539
557
  with `subtype: "error_missing_output"` and a `MissingOutputError`. There is
540
558
  no fallback that parses the final text as JSON.
541
559
  - `submit_output` must be the only tool call in its batch. A batch that mixes
@@ -553,6 +571,69 @@ ending after a submission succeeds with the last submission as
553
571
  `structuredResult`; ending without any submission still fails with
554
572
  `error_missing_output`. *Requires 0.25.0 or later.*
555
573
 
574
+ ### Retry a missing submission once
575
+
576
+ *Requires 0.27.0 or later.*
577
+
578
+ For agents with `outputSchema` or a registered `submit_output` tool, missing-output
579
+ recovery is enabled by default since 0.28.0. *Requires 0.28.0 or later for this default.*
580
+ It allows one additional model request per query when the model ends normally
581
+ without submitting structured output. Set `retryMissingOutput: false` to disable
582
+ it, restoring the immediate failure behavior. This default change is breaking
583
+ for submission agents; ordinary chat agents keep their existing behavior.
584
+ Version 0.27.0 required an explicit `retryMissingOutput: true`.
585
+
586
+ ```ts
587
+ import { createBareAgent } from "agent-lattice";
588
+ import { z } from "zod/v4";
589
+
590
+ const agent = createBareAgent({
591
+ apiKey: process.env.DEEPSEEK_API_KEY,
592
+ baseURL: "https://api.deepseek.com/anthropic",
593
+ model: "deepseek-v4-flash-vision-exp",
594
+ outputSchema: z.object({ result: z.string() }),
595
+ thinkingConfig: { type: "enabled", budgetTokens: 4096 },
596
+ maxTurns: 5,
597
+ // Recovery is enabled by default for outputSchema (since 0.28.0).
598
+ });
599
+ const result = await agent.prompt("Explain why the supplied evidence supports the conclusion.");
600
+ if (result.subtype === "success") console.log(result.structuredResult);
601
+ ```
602
+
603
+ The recovery request keeps the conversation, including thinking blocks and
604
+ completed tool results, and appends a submission reminder. Only `submit_output`
605
+ is offered; thinking is explicitly disabled, reasoning effort is omitted, and
606
+ `tool_choice` is set to `{ type: "tool", name: "submit_output" }`. The SDK also
607
+ rejects any recovery batch other than a single complete `submit_output` call
608
+ before executing handlers. Previous tools are not replayed.
609
+
610
+ The option requires `outputSchema` or a registered custom `submit_output` tool.
611
+ A custom tool keeps its own argument validation and result transformation and
612
+ must return `ToolResult.structuredResult`; handler success alone is not delivery.
613
+ Enabling the option makes submission required for that query. Custom tools
614
+ remain responsible for validating their result. With `submitOutputEndTurn: false`,
615
+ a successful recovery can still be followed by the usual summary turn; that turn
616
+ restores normal thinking and tools and is not another recovery attempt.
617
+
618
+ Recovery consumes a `maxTurns` turn and uses the existing cancellation and
619
+ per-request timeout. It does not run after refusal, truncation, or another
620
+ explicit abnormal stop. Custom model clients that omit stop reasons are treated
621
+ as normally ended. A second missing submission, invalid arguments, rejected
622
+ batch, or missing custom structured result ends with `error_missing_output`;
623
+ there is no further corrective model call in recovery. Provider errors, timeout,
624
+ interrupt, and abort retain their existing failure semantics. Recovery skips
625
+ compaction and overflow retries to preserve the conversation and the one-request
626
+ limit. `requestTimeoutMs` is per request; use `QueryOptions.signal` for an overall
627
+ deadline.
628
+
629
+ The extra request adds latency and token cost. Use it only with a provider
630
+ that supports forced tool choice with thinking disabled; otherwise set
631
+ `retryMissingOutput: false`. A custom `ModelClient`
632
+ must honour `ModelRequest.toolChoice` and the thinking override. The SDK does
633
+ not infer or parse tool calls from plain text. The reminder is persisted through
634
+ `HistoryStore` and tracing; the recovery `model_request` trace has
635
+ `missingOutputRetry: true`, the effective `thinkingConfig`, and `toolChoice`.
636
+
556
637
  Unlike `outputFormat` (which relies on the provider's
557
638
  `response_format`/`json_schema` support — DeepSeek ignores it, see
558
639
  [Provider Compatibility](https://docs.claude-code-sdk.com/reference/provider-compatibility/)),
@@ -701,6 +782,17 @@ the target's lifecycle: an `AgentSpec` spawns a fresh session per call, while an
701
782
  `AgentLike` target keeps history across calls and is usually not safe to call
702
783
  concurrently. *Requires 0.24.0 or later.*
703
784
 
785
+ For durable child sessions, `AgentToolOptions.prepareTarget` runs after the
786
+ child's input has been validated and mapped to a task, before the child starts.
787
+ It receives the target, task, tool-use ID, parent run ID, trace session ID, and
788
+ abort signal; return the `AgentLike` to call. A host can spawn the supplied
789
+ `AgentSpec` with a per-call `HistoryStore` and return an adapter that records
790
+ its event stream. Without the hook, a spec still spawns a fresh session as
791
+ before. Direct `ask` child trace events share the parent's trace session and
792
+ carry both `parent_run_id` and `parent_tool_use_id`, so concurrent calls to the
793
+ same child can be distinguished. The host owns cleanup if preparing a child
794
+ fails. *Requires 0.26.0 or later.*
795
+
704
796
  When concurrency is available, the SDK tells the model to batch independent
705
797
  calls and to use separate assistant responses when a later call needs an earlier
706
798
  result. Runtime safety checks and `toolBatchPolicy` remain authoritative.
package/dist/index.d.ts CHANGED
@@ -117,6 +117,7 @@ export type ContextTraceEvent = {
117
117
  session_id: string;
118
118
  run_id: string;
119
119
  parent_run_id?: string;
120
+ parent_tool_use_id?: string;
120
121
  seq: number;
121
122
  source: AgentRuntimeSource;
122
123
  type: ContextTraceEventType;
@@ -247,6 +248,11 @@ export type ModelRequest = {
247
248
  maxTokens: number;
248
249
  messages: ModelMessage[];
249
250
  tools: ModelToolDefinition[];
251
+ /** Forced submission during missing-output recovery. Custom clients must honour it. */
252
+ toolChoice?: {
253
+ type: "tool";
254
+ name: string;
255
+ };
250
256
  stream: boolean;
251
257
  outputFormat?: OutputFormat;
252
258
  thinkingConfig?: ThinkingConfig;
@@ -298,6 +304,11 @@ export type ToolBatchPolicy<TContext = unknown> = {
298
304
  export type ToolExecutionContext<TContext = unknown> = {
299
305
  signal?: AbortSignal;
300
306
  toolUseId: string;
307
+ /** Current agent query, when the tool is called from an agent loop. */
308
+ trace?: {
309
+ sessionId: string;
310
+ runId: string;
311
+ };
301
312
  context?: TContext;
302
313
  agentRuntime?: AgentRuntimeContext;
303
314
  permissions?: RuntimePermissions;
@@ -598,7 +609,8 @@ export type AgentOptions<TContext = unknown> = {
598
609
  * `submit_output` tool with this schema: the run only ends successfully once
599
610
  * the model submits a payload through it, and the validated payload lands on
600
611
  * `SDKResultMessage.structuredResult`. Ending the turn without submitting
601
- * fails the run with subtype `error_missing_output`. The tool must be the
612
+ * fails with `error_missing_output` if recovery is disabled or unsuccessful.
613
+ * Missing-output recovery is enabled by default (see retryMissingOutput). The tool must be the
602
614
  * only call in its batch, and its name is reserved (registering a user tool
603
615
  * with the same name throws).
604
616
  */
@@ -616,6 +628,16 @@ export type AgentOptions<TContext = unknown> = {
616
628
  * ending without any submission still fails with `error_missing_output`.
617
629
  */
618
630
  submitOutputEndTurn?: boolean;
631
+ /**
632
+ * Allow one extra model request when a normal text ending has not
633
+ * submitted output. Defaults to true for agents with submit_output, false
634
+ * for ordinary chat agents. Requires outputSchema or a custom
635
+ * submit_output tool returning structuredResult. Recovery disables thinking
636
+ * and forces submit_output; no other tool may execute in that request.
637
+ * The extra request counts toward maxTurns and respects cancellation and
638
+ * requestTimeoutMs. An unsuccessful recovery fails with error_missing_output.
639
+ */
640
+ retryMissingOutput?: boolean;
619
641
  /** Lifecycle callbacks that rewrite tool results and outgoing model requests. */
620
642
  hooks?: AgentHooks<TContext>;
621
643
  /**
@@ -782,8 +804,8 @@ export declare class ToolExecutionError extends AgentSDKError {
782
804
  export declare class MaxTurnsError extends AgentSDKError {
783
805
  }
784
806
  /**
785
- * A run with `AgentOptions.outputSchema` ended without the model calling the
786
- * `submit_output` tool, so no structured output was produced.
807
+ * A run requiring submission (`outputSchema` or `retryMissingOutput`) ended
808
+ * without structured output from the `submit_output` tool.
787
809
  */
788
810
  export declare class MissingOutputError extends AgentSDKError {
789
811
  }
@@ -853,6 +875,21 @@ export type AgentToolOptions = {
853
875
  * never shown to the model.
854
876
  */
855
877
  metadata?: Record<string, unknown>;
878
+ /**
879
+ * Resolve the child session for this invocation after input validation and
880
+ * task mapping, before the child runs. A host can spawn an AgentSpec with a
881
+ * per-call HistoryStore and return an AgentLike that records its event stream.
882
+ * The default is to spawn a spec or reuse a live AgentLike target.
883
+ */
884
+ prepareTarget?: (invocation: {
885
+ target: AgentToolTarget;
886
+ toolName: string;
887
+ toolUseId: string;
888
+ task: string | ContentBlock[];
889
+ parentRunId?: string;
890
+ traceSessionId?: string;
891
+ signal?: AbortSignal;
892
+ }) => AgentLike<any> | Promise<AgentLike<any>>;
856
893
  /**
857
894
  * Expected structured output of the target. When omitted, the declaration is
858
895
  * inherited from the target itself (an Agent's or AgentSpec's