agent-lattice 0.15.0 → 0.17.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
@@ -55,6 +55,11 @@ const agent = createBareAgent({
55
55
  });
56
56
  ```
57
57
 
58
+ `Agent` is a type-only export — instances come from these factories (or
59
+ `AgentSpec.spawn()`), never from `new Agent()`, because the factories also
60
+ generate the session id and install the workspace. (Breaking in 0.17.0: the
61
+ `Agent` class constructor is no longer exported.)
62
+
58
63
  `agent.query()` yields `stream_event` messages while the model is still
59
64
  responding, so a host can render output incrementally:
60
65
 
@@ -73,6 +78,19 @@ The SDK produces the next event only after the loop takes the current one.
73
78
  Slow work in the loop body delays later events without dropping or reordering
74
79
  them, so keep expensive handling off the loop itself.
75
80
 
81
+ `query()` yields these SDK messages:
82
+
83
+ | Type | When | What it carries |
84
+ | --- | --- | --- |
85
+ | `system` | Query start | Session init metadata (model, tools, `session_id`). |
86
+ | `stream_event` | While the model is responding | Raw provider stream event for incremental rendering. |
87
+ | `assistant` | After each model turn is assembled | The `AssistantModelMessage` with text / `tool_use` blocks and provider metadata. |
88
+ | `user` | After a whole tool batch finishes | Tool results as `ToolResultBlock[]`; the prompt is never echoed. |
89
+ | `result` | Once, at the end of the query | Final text, `subtype` (`"success"`, `"interrupted"`, or an error variant), and token usage. |
90
+
91
+ For the exact per-event guarantees see
92
+ [Streaming Events](https://docs.claude-code-sdk.com/concepts/streaming-events/).
93
+
76
94
  Pass `{ stream: false }` to disable model streaming for a query:
77
95
 
78
96
  ```ts
@@ -208,9 +226,9 @@ for await (const event of team.query("Ask engineering to investigate.", {
208
226
 
209
227
  ## LangSmith Context Tracing
210
228
 
211
- Pass LangSmith's `RunTree` constructor to the SDK tracer. The SDK depends on
212
- `langsmith` directly and uses its official `RunTree` / `RunTreeConfig` types for
213
- this adapter.
229
+ The SDK depends on `langsmith` directly and uses its official `RunTree` /
230
+ `RunTreeConfig` types for this adapter, so the tracer works out of the box —
231
+ no constructor wiring needed.
214
232
 
215
233
  Configure LangSmith with its standard environment variables:
216
234
 
@@ -224,7 +242,6 @@ LANGSMITH_WORKSPACE_ID=<your-langsmith-workspace-id>
224
242
  ```
225
243
 
226
244
  ```ts
227
- import { RunTree } from "langsmith/run_trees";
228
245
  import {
229
246
  createAgent,
230
247
  createCompositeContextTracer,
@@ -235,7 +252,6 @@ import {
235
252
  const tracer = createCompositeContextTracer([
236
253
  createJsonlContextTracer({ path: ".agent-runs/session.jsonl" }),
237
254
  createLangSmithContextTracer({
238
- RunTree,
239
255
  projectName: process.env.LANGSMITH_PROJECT,
240
256
  workspaceId: process.env.LANGSMITH_WORKSPACE_ID,
241
257
  tags: ["local-debug"],
@@ -264,11 +280,9 @@ tracer. `workspaceId` is optional and only selects a LangSmith workspace; it is
264
280
  not the tracing project name.
265
281
 
266
282
  ```ts
267
- import { RunTree } from "langsmith/run_trees";
268
283
  import { createLangSmithContextTracer } from "agent-lattice";
269
284
 
270
285
  const tracer = createLangSmithContextTracer({
271
- RunTree,
272
286
  apiKey: process.env.LANGSMITH_API_KEY,
273
287
  apiUrl: process.env.LANGSMITH_ENDPOINT,
274
288
  projectName: process.env.LANGSMITH_PROJECT,
@@ -277,6 +291,9 @@ const tracer = createLangSmithContextTracer({
277
291
  });
278
292
  ```
279
293
 
294
+ `RunTree` defaults to the bundled langsmith constructor since 0.17.0; pass
295
+ `RunTree` or `runTree` only to inject a custom runtime or a test fake.
296
+
280
297
  LangSmith receives one root `chain` run per SDK query. For an `Agent` query,
281
298
  model turns and SDK tool calls appear as child `llm` and `tool` runs. For a
282
299
  `Team` query, the root represents the complete Team invocation; the initial
@@ -286,15 +303,21 @@ recorded as `agent_session_id` metadata, so tracing does not change Agent state
286
303
  or returned SDK messages.
287
304
 
288
305
  Custom sinks can implement the same interface for SQLite, OpenTelemetry, object
289
- storage, or host-specific observability. The functions below are application
290
- code you provide, not SDK exports:
306
+ storage, or host-specific observability. A `ContextTracer` port object exposes
307
+ methods only — `failOnError` is bound when the factory creates the tracer, not
308
+ set as a field afterwards. Implement a custom sink with `defineContextTracer()`.
309
+ *Requires 0.17.0 or later.* (Breaking in 0.17.0: the public `failOnError` field
310
+ was removed from `ContextTracer`; custom tracers created before 0.17.0 must go
311
+ through `defineContextTracer()`.)
291
312
 
292
313
  ```ts
293
- const tracer = {
314
+ import { defineContextTracer } from "agent-lattice";
315
+
316
+ const tracer = defineContextTracer({
294
317
  async onEvent(event) {
295
318
  // TODO: Replace with your own storage/logging code.
296
319
  },
297
- };
320
+ });
298
321
  ```
299
322
 
300
323
  ## DeepSeek Anthropic-compatible API
@@ -334,6 +357,29 @@ const result = await agent.prompt("What is 2+2?");
334
357
  console.log(result.result);
335
358
  ```
336
359
 
360
+ ## End The Run From A Tool
361
+
362
+ *Requires 0.16.0 or later.*
363
+
364
+ A tool that has the final answer can end the run itself by returning
365
+ `endTurn: true`. The SDK finishes with `subtype: "success"` and uses that
366
+ tool's text content as the result, without calling the model again:
367
+
368
+ ```ts
369
+ const finish = tool(
370
+ "finish",
371
+ "Submit the final answer and end the run",
372
+ z.object({ answer: z.string() }),
373
+ async ({ answer }) => ({ content: answer, endTurn: true }),
374
+ );
375
+ ```
376
+
377
+ `endTurn` does not cancel the other tools of the same batch — they already
378
+ started concurrently, their `tool_result` blocks still enter the history, and
379
+ `onToolResult` hooks and trace events run for them as usual. Only the next
380
+ model call is skipped. When several tools in a batch set `endTurn`, the first
381
+ one's content becomes the result text.
382
+
337
383
  ## Concurrent Tool Calls
338
384
 
339
385
  The model requests concurrency by returning multiple `tool_use` blocks in one
@@ -694,9 +740,16 @@ const mcp = await connectMCPStreamableHTTPServer("https://mcp.example.com/mcp",
694
740
  type AgentLike<TContext = unknown> = {
695
741
  query(prompt, options?): AsyncGenerator<SDKMessage | TeamRunnerMessage>;
696
742
  prompt(prompt, options?): Promise<SDKResultMessage>;
743
+ interrupt(): boolean;
697
744
  };
698
745
  ```
699
746
 
747
+ `interrupt()` ends the in-flight model request with an `"interrupted"` result
748
+ (see [Interrupting A Query](#interrupting-a-query)); on a `Team` or
749
+ `TeamRunner` it delegates to the lead/root agent. It returns `true` when a
750
+ query was interrupted and `false` when idle. *Requires 0.16.0 or later; the
751
+ `boolean` return requires 0.17.0 or later.*
752
+
700
753
  That means a team can be used anywhere a callable agent is expected. From the
701
754
  outside, a team is an agent; inside, it can contain a whole organization.
702
755
 
@@ -1074,8 +1127,8 @@ console.log(result.result);
1074
1127
  ```
1075
1128
 
1076
1129
  The SDK stores conversation state in memory for the lifetime of the `Agent`
1077
- instance. Persistent transcripts and resume support are intentionally out of
1078
- scope for the first release.
1130
+ instance. To persist it or resume a conversation in another process, attach a
1131
+ `HistoryStore` see [Persistent History And Resume](#persistent-history-and-resume).
1079
1132
 
1080
1133
  An `Agent` is a conversation, not a reusable client. Because the history is
1081
1134
  instance state, starting a query while another is still running would interleave
@@ -1084,6 +1137,88 @@ Create one Agent per concurrent conversation — in a server, per request or per
1084
1137
  user session rather than a shared module-level instance. Sequential reuse, as
1085
1138
  above, is the intended pattern.
1086
1139
 
1140
+ ## Persistent History And Resume
1141
+
1142
+ *Requires 0.16.0 or later.*
1143
+
1144
+ Pass a `HistoryStore` to seed an Agent's history from durable storage and have
1145
+ every later write mirrored back. `createJsonlHistoryStore()` persists one JSON
1146
+ message per line:
1147
+
1148
+ ```ts
1149
+ import { createAgent, createJsonlHistoryStore } from "agent-lattice";
1150
+
1151
+ const historyStore = createJsonlHistoryStore({
1152
+ path: ".agent-sessions/ada.jsonl",
1153
+ });
1154
+
1155
+ const agent = createAgent({
1156
+ apiKey: process.env.DEEPSEEK_API_KEY,
1157
+ baseURL: "https://api.deepseek.com/anthropic",
1158
+ model: "deepseek-v4-flash",
1159
+ historyStore,
1160
+ });
1161
+
1162
+ // The first query lazily loads any history the store already holds, then the
1163
+ // new prompt continues from it. Every user, assistant, and tool_result message
1164
+ // is appended to the file as it lands.
1165
+ const result = await agent.prompt("What is my name?");
1166
+
1167
+ // A copy of the live history, safe to inspect or mutate.
1168
+ const transcript = await agent.getHistory();
1169
+ ```
1170
+
1171
+ The store contract is three methods — `load()`, `append(message)`, and
1172
+ `replace(messages)` — each synchronous or returning a promise:
1173
+
1174
+ - `load()` runs once per Agent lifetime, lazily before the first query (the
1175
+ constructor cannot be async). Resuming across processes is simply a new
1176
+ Agent over the same store; the "one Agent, one conversation" rule is
1177
+ unchanged.
1178
+ - `append(message)` follows every message added to the history.
1179
+ - `replace(messages)` follows compaction, which rewrites the whole history —
1180
+ a store must support full replacement, not just appends.
1181
+
1182
+ The JSONL store's `load()` skips malformed lines rather than failing, so a
1183
+ torn final write does not lose the rest of the transcript. By default a
1184
+ failing store is swallowed and the conversation continues in memory only,
1185
+ mirroring the tracer's failure semantics; bind `failOnError: true` when the
1186
+ store is created (via `createJsonlHistoryStore()` options or
1187
+ `defineHistoryStore()`) to propagate store errors out of `query()` instead.
1188
+
1189
+ Implement a custom store with `defineHistoryStore()`, which validates the
1190
+ three methods and binds `failOnError`; the returned port object exposes
1191
+ methods only. *Requires 0.17.0 or later.* (Breaking in 0.17.0: the public
1192
+ `failOnError` field was removed from `HistoryStore`; custom stores created
1193
+ before 0.17.0 must go through `defineHistoryStore()`.)
1194
+
1195
+ ```ts
1196
+ import { defineHistoryStore } from "agent-lattice";
1197
+
1198
+ const historyStore = defineHistoryStore({
1199
+ load: () => loadMessagesFromYourDatabase(),
1200
+ append: message => appendMessageToYourDatabase(message),
1201
+ replace: messages => replaceMessagesInYourDatabase(messages),
1202
+ });
1203
+ ```
1204
+
1205
+ To rewrite the history from the host instead of from compaction, use
1206
+ `agent.replaceHistory(messages)`. *Requires 0.17.0 or later.* It is idle-only:
1207
+ calling it while a query is running throws `ConcurrentQueryError`, the same
1208
+ guard as a concurrent `query()`. When a `historyStore` is configured the store
1209
+ is replaced too, so persistence stays in sync, and the replacement also
1210
+ suppresses the lazy `load()` — seeding never overwrites what the host just
1211
+ installed. The SDK does not validate the content: the host owns it, and the
1212
+ history must be well-formed (e.g. no dangling `tool_use` without its matching
1213
+ `tool_result`).
1214
+
1215
+ ```ts
1216
+ await agent.replaceHistory([
1217
+ { role: "user", content: "My name is Ada." },
1218
+ { role: "assistant", content: [{ type: "text", text: "Nice to meet you, Ada." }] },
1219
+ ]);
1220
+ ```
1221
+
1087
1222
  ## Deadlines
1088
1223
 
1089
1224
  `QueryOptions.signal` bounds a whole query — every model request, tool call, and
@@ -1113,6 +1248,34 @@ Both limits are enforced by the SDK rather than delegated. `ModelRequest` carrie
1113
1248
  also races the call, so a `ModelClient` that honours neither cannot stall the
1114
1249
  loop indefinitely. Losing that race abandons the call rather than cancelling it.
1115
1250
 
1251
+ ## Interrupting A Query
1252
+
1253
+ *Requires 0.16.0 or later; `interrupt()` returns `boolean` from 0.17.0.*
1254
+
1255
+ `agent.interrupt()` ends the current query without tearing the conversation
1256
+ down. Where `QueryOptions.signal` terminates the query with `"error_abort"`,
1257
+ `interrupt()` aborts only the in-flight model request and finishes with
1258
+ `subtype: "interrupted"` — normal control flow, so `is_error` stays `false`.
1259
+ As on abort, the partial assistant message is dropped, but every completed
1260
+ turn stays in the history, so the host can continue the same Agent with a new
1261
+ `query()` that injects its own message:
1262
+
1263
+ ```ts
1264
+ const pending = agent.prompt("Draft the release notes.");
1265
+ agent.interrupt(); // e.g. the user typed a correction
1266
+ const result = await pending;
1267
+ // result.subtype === "interrupted"
1268
+
1269
+ await agent.prompt("Actually, skip 0.15.x and cover 0.16.0 only.");
1270
+ ```
1271
+
1272
+ An interrupt that lands while a tool batch is executing takes effect once the
1273
+ batch completes: its tool results are written to history first, and the query
1274
+ ends `"interrupted"` before the next model call. `interrupt()` returns `true`
1275
+ when a query was running and is now interrupted, and `false` when idle — a
1276
+ `false` tells the host there is nothing to wait for, so it can send its next
1277
+ query directly.
1278
+
1116
1279
  ## Token Usage And Truncation
1117
1280
 
1118
1281
  Every `result` message reports `usage`, summed over the model requests in that
@@ -1135,3 +1298,13 @@ to distinguish a complete answer from a truncated one.
1135
1298
  Usage comes from the model client. The built-in Anthropic client fills it in from
1136
1299
  the response, including the streaming path; a custom `ModelClient` that omits
1137
1300
  `usage` produces zeroed counts rather than an error.
1301
+
1302
+ Assistant messages also carry provider response metadata: `providerResponseId`
1303
+ is the provider-assigned response id and `model` is the model that actually
1304
+ served the response, which may differ from the requested `AgentOptions.model`.
1305
+ The built-in Anthropic client fills both in on streaming and non-streaming
1306
+ requests; a custom `ModelClient` may set them on the `AssistantModelMessage` it
1307
+ returns. Both fields are optional and absent when the client does not report
1308
+ them.
1309
+
1310
+ *Requires 0.16.0 or later.*
package/dist/index.d.ts CHANGED
@@ -34,6 +34,12 @@ export type AgentLikeEvent = SDKMessage | TeamRunnerMessage;
34
34
  export type AgentLike<TContext = unknown> = {
35
35
  query(prompt: string | ContentBlock[], options?: QueryOptions<TContext>): AsyncGenerator<AgentLikeEvent>;
36
36
  prompt(prompt: string | ContentBlock[], options?: QueryOptions<TContext>): Promise<SDKResultMessage>;
37
+ /**
38
+ * End the in-flight model request with an "interrupted" result; follow up
39
+ * with a new query(). Returns `true` when a query was interrupted, `false`
40
+ * when idle — a `false` means the host can send its next query directly.
41
+ */
42
+ interrupt(): boolean;
37
43
  };
38
44
  export type DelegateWaitMode = "result" | "accepted";
39
45
  export type AgentRuntimeSource = {
@@ -115,7 +121,6 @@ export type ContextTraceEvent = {
115
121
  data: Record<string, unknown>;
116
122
  };
117
123
  export type ContextTracer = {
118
- failOnError?: boolean;
119
124
  onEvent(event: ContextTraceEvent): Promise<void> | void;
120
125
  flush?(): Promise<void>;
121
126
  close?(): Promise<void>;
@@ -133,7 +138,9 @@ export type LangSmithRunTreeLike = RunTree;
133
138
  export type LangSmithRunTreeConstructor = new (config: LangSmithRunTreeConfig) => LangSmithRunTreeLike;
134
139
  export type LangSmithWriteReplicaConfig = NonNullable<LangSmithRunTreeConfig["replicas"]>[number];
135
140
  export type LangSmithContextTracerOptions = {
141
+ /** Defaults to the bundled langsmith RunTree; inject a constructor for custom runtimes. */
136
142
  RunTree?: LangSmithRunTreeConstructor;
143
+ /** Factory form of RunTree, mainly for tests. Takes precedence over RunTree. */
137
144
  runTree?: (config: LangSmithRunTreeConfig) => LangSmithRunTreeLike;
138
145
  projectName?: string;
139
146
  name?: string;
@@ -150,6 +157,33 @@ export type ModelMessage = {
150
157
  role: "user" | "assistant";
151
158
  content: string | ContentBlock[];
152
159
  };
160
+ /**
161
+ * Persistence adapter for an Agent's conversation history. `load()` runs once
162
+ * per Agent lifetime, before the first query; `append()` follows every message
163
+ * added to the history; `replace()` follows compaction, which rewrites the
164
+ * whole history — a store must support full replacement. Methods may be
165
+ * synchronous or return a promise; the Agent awaits them to preserve order.
166
+ * Like `ContextTracer`, a failing store is swallowed by default and the
167
+ * conversation continues in memory only; pass `failOnError` to the factory
168
+ * that creates the store (`createJsonlHistoryStore`, `defineHistoryStore`)
169
+ * to propagate store errors out of `query()` instead.
170
+ *
171
+ * The objects passed to `append()` and `replace()` are guaranteed to carry at
172
+ * least `role` and `content`. Runtime objects may carry extra fields (`usage`,
173
+ * `stopReason`, `providerResponseId`, `model`) that are not part of the
174
+ * contract and must not be relied on; hosts that need response metadata for
175
+ * reconciliation or analytics should use the ContextTracer's
176
+ * `assistant_message` events instead.
177
+ */
178
+ export type HistoryStore = {
179
+ load(): ModelMessage[] | Promise<ModelMessage[]>;
180
+ append(message: ModelMessage): void | Promise<void>;
181
+ replace(messages: ModelMessage[]): void | Promise<void>;
182
+ };
183
+ export type JsonlHistoryStoreOptions = {
184
+ path: string;
185
+ failOnError?: boolean;
186
+ };
153
187
  export type TokenUsage = {
154
188
  input_tokens: number;
155
189
  output_tokens: number;
@@ -171,6 +205,13 @@ export type AssistantModelMessage = {
171
205
  /** Absent when a custom ModelClient does not report it. */
172
206
  usage?: TokenUsage;
173
207
  stopReason?: StopReason;
208
+ /** The provider-assigned response id. Absent when a custom ModelClient does not report it. */
209
+ providerResponseId?: string;
210
+ /**
211
+ * The model that actually served this response, which may differ from
212
+ * `ModelRequest.model`. Absent when a custom ModelClient does not report it.
213
+ */
214
+ model?: string;
174
215
  };
175
216
  export type ModelToolDefinition = {
176
217
  name: string;
@@ -197,6 +238,8 @@ export interface ModelClient {
197
238
  }
198
239
  export type ToolResult = {
199
240
  content: string | ContentBlock[];
241
+ /** End the run after this tool batch: finish with subtype "success" instead of calling the model again. */
242
+ endTurn?: boolean;
200
243
  };
201
244
  export type ToolKind = "tool" | "agent_tool";
202
245
  export type ToolBatchCall = {
@@ -458,6 +501,8 @@ export type Team = {
458
501
  drain(options?: TeamDrainOptions): Promise<TeamDrainResult>;
459
502
  query(prompt: string | ContentBlock[], options?: QueryOptions): AsyncGenerator<TeamRunnerMessage>;
460
503
  prompt(prompt: string | ContentBlock[], options?: QueryOptions): Promise<SDKResultMessage>;
504
+ /** Interrupts the lead agent's in-flight model request; returns `true` when a query was interrupted, `false` when idle. */
505
+ interrupt(): boolean;
461
506
  };
462
507
  export type TeamDrainOptions = {
463
508
  maxRounds?: number;
@@ -480,6 +525,8 @@ export type TeamRunner = {
480
525
  mailbox: TeamMailbox;
481
526
  query(prompt: string | ContentBlock[], options?: QueryOptions): AsyncGenerator<TeamRunnerMessage>;
482
527
  prompt(prompt: string | ContentBlock[], options?: QueryOptions): Promise<SDKResultMessage>;
528
+ /** Interrupts the root agent's in-flight model request; returns `true` when a query was interrupted, `false` when idle. */
529
+ interrupt(): boolean;
483
530
  };
484
531
  export type PermissionRequest = {
485
532
  toolName: string;
@@ -524,6 +571,12 @@ export type AgentOptions<TContext = unknown> = {
524
571
  permission?: (request: PermissionRequest) => Promise<PermissionDecision> | PermissionDecision;
525
572
  modelClient?: ModelClient;
526
573
  tracer?: ContextTracer;
574
+ /**
575
+ * Persistence adapter for the conversation history. Seeded via `load()` once
576
+ * before the first query, then notified on every history write. Compaction
577
+ * calls `replace()`, so the store must support full replacement.
578
+ */
579
+ historyStore?: HistoryStore;
527
580
  };
528
581
  export type BareAgentOptions<TContext = unknown> = Omit<AgentOptions<TContext>, "workspace">;
529
582
  export type AgentWorkspaceToolsOptions = {
@@ -579,6 +632,14 @@ export type SDKAssistantMessage = {
579
632
  message: AssistantModelMessage;
580
633
  session_id: string;
581
634
  };
635
+ /**
636
+ * Emitted only after a whole tool batch finishes — one event per batch, never
637
+ * one per tool, and never for the prompt (the prompt is not echoed; subscribe
638
+ * a `ContextTracer` for a full transcript). `message.content` is always
639
+ * `ToolResultBlock[]`; the declared `ModelMessage` type is wider than this
640
+ * guarantee. `tool_use_result` is a convenience view: a single tool's result
641
+ * `content`, or the array of result blocks when the batch had several tools.
642
+ */
582
643
  export type SDKUserMessage = {
583
644
  type: "user";
584
645
  message: ModelMessage;
@@ -593,7 +654,12 @@ export type SDKStreamEventMessage = {
593
654
  };
594
655
  export type SDKResultMessage = {
595
656
  type: "result";
596
- subtype: "success" | "error" | "error_max_turns" | "error_abort" | "error_timeout";
657
+ /**
658
+ * `"interrupted"` is not an error: `Agent.interrupt()` ends the query this
659
+ * way, keeping completed turns in history so a follow-up query can continue
660
+ * the conversation. `is_error` stays `false` for it.
661
+ */
662
+ subtype: "success" | "interrupted" | "error" | "error_max_turns" | "error_abort" | "error_timeout";
597
663
  is_error: boolean;
598
664
  result: string;
599
665
  session_id: string;
@@ -720,6 +786,15 @@ export type AgentSpec<TContext = unknown> = {
720
786
  export declare function defineAgent<TContext = unknown>(options: AgentOptions<TContext>): AgentSpec<TContext>;
721
787
  export declare function isAgentSpec(target: AgentLike<any> | AgentSpec<any>): target is AgentSpec<any>;
722
788
  export declare function createBuiltinTools(options?: AgentWorkspaceToolsOptions): Array<ToolDefinition<any, any>>;
789
+ /**
790
+ * Entry point for implementing a custom trace sink. Validates that the
791
+ * required `onEvent` method exists and binds `failOnError` at creation time —
792
+ * a `ContextTracer` exposes methods only; the flag travels with the returned
793
+ * object as internal metadata the runtime reads when a call throws.
794
+ */
795
+ export declare function defineContextTracer(impl: ContextTracer & {
796
+ failOnError?: boolean;
797
+ }): ContextTracer;
723
798
  export declare function createJsonlContextTracer(options: JsonlContextTracerOptions): ContextTracer;
724
799
  /**
725
800
  * Chains hooks in array order: each one sees the previous one's output, so
@@ -728,12 +803,31 @@ export declare function createJsonlContextTracer(options: JsonlContextTracerOpti
728
803
  */
729
804
  export declare function createCompositeAgentHooks<TContext = unknown>(hooks: Array<AgentHooks<TContext> | undefined | null>): AgentHooks<TContext>;
730
805
  export declare function createCompositeContextTracer(tracers: Array<ContextTracer | undefined | null>): ContextTracer;
731
- export declare function createLangSmithContextTracer(options: LangSmithContextTracerOptions): ContextTracer;
806
+ export declare function createLangSmithContextTracer(options?: LangSmithContextTracerOptions): ContextTracer;
732
807
  export declare function skill(input: SkillInput): SkillDefinition;
733
808
  export declare function loadSkill(path: string): Promise<SkillDefinition>;
734
809
  export declare function createMCPTools(client: MCPClient, options?: MCPToolsOptions): Promise<Array<ToolDefinition<Record<string, unknown>>>>;
735
810
  export declare function connectMCPStdioServer(server: StdioServerParameters, options?: MCPStdioServerOptions): Promise<MCPStdioConnection>;
736
811
  export declare function connectMCPStreamableHTTPServer(url: string | URL, options?: MCPStreamableHTTPServerOptions): Promise<MCPStreamableHTTPConnection>;
812
+ /**
813
+ * Persists an Agent's history as one JSON message per line. `append()` adds a
814
+ * line; `replace()` rewrites the whole file, which is how compaction is
815
+ * persisted. `load()` reads every line and skips malformed ones — a truncated
816
+ * final line from a torn write must not lose the rest of the transcript.
817
+ * Writes are serialized through an internal queue, so callers may fire them
818
+ * without waiting for ordering.
819
+ */
820
+ /**
821
+ * Entry point for implementing a custom history store. Validates that the
822
+ * required `load`/`append`/`replace` methods exist and binds `failOnError` at
823
+ * creation time — a `HistoryStore` exposes methods only; the flag travels
824
+ * with the returned object as internal metadata the runtime reads when a call
825
+ * throws.
826
+ */
827
+ export declare function defineHistoryStore(impl: HistoryStore & {
828
+ failOnError?: boolean;
829
+ }): HistoryStore;
830
+ export declare function createJsonlHistoryStore(options: JsonlHistoryStoreOptions): HistoryStore;
737
831
  export declare function teamMember(input: TeamMemberInput): TeamMemberDefinition;
738
832
  export declare function createMemoryMailbox(): TeamMailbox;
739
833
  export declare function createSQLiteMailbox(options: SQLiteMailboxOptions): TeamMailbox;
@@ -749,13 +843,21 @@ export declare function query<TContext = unknown>(params: AgentOptions<TContext>
749
843
  signal?: AbortSignal;
750
844
  context?: TContext;
751
845
  }): AsyncGenerator<SDKMessage>;
752
- export declare class Agent<TContext = unknown> {
846
+ /**
847
+ * An Agent owns one conversation: history, workspace, and session identity.
848
+ * Create instances with `createAgent()` or `createBareAgent()` (or spawn from
849
+ * an `AgentSpec`) — the constructor is intentionally not exported, because the
850
+ * factories also generate the session id and install workspace tools.
851
+ */
852
+ declare class Agent<TContext = unknown> {
753
853
  private readonly options;
754
854
  private readonly modelClient;
755
855
  private readonly messages;
756
856
  private readonly sessionId;
757
857
  private readonly toolConcurrency;
758
858
  private running;
859
+ private interruptController;
860
+ private historyLoaded;
759
861
  constructor(options: AgentOptions<TContext>);
760
862
  /**
761
863
  * One Agent owns one conversation. Overlapping queries would interleave writes
@@ -763,8 +865,45 @@ export declare class Agent<TContext = unknown> {
763
865
  * a conversation containing someone else's turns.
764
866
  */
765
867
  query(prompt: string | ContentBlock[], options?: QueryOptions<TContext>): AsyncGenerator<SDKMessage>;
868
+ /**
869
+ * Abort the in-flight model request and end the current query with subtype
870
+ * "interrupted". Completed turns stay in history; follow up with a new
871
+ * query() to continue the conversation. Unlike `QueryOptions.signal`, which
872
+ * terminates the query as an error, an interrupt is normal control flow.
873
+ * Returns `true` when a query was running and is now interrupted, `false`
874
+ * when idle — a `false` tells the host it can send its next query directly
875
+ * instead of waiting for an "interrupted" result.
876
+ */
877
+ interrupt(): boolean;
878
+ /**
879
+ * The store is read once per Agent lifetime, lazily on the first query or
880
+ * getHistory() call — the constructor cannot be async. A failed load follows
881
+ * the same rule as a failed write: swallowed unless `failOnError` was bound
882
+ * by the store's factory, in which case the error propagates and the Agent
883
+ * starts empty.
884
+ */
885
+ private ensureHistoryLoaded;
886
+ private loadHistory;
887
+ private appendStoredHistory;
888
+ private replaceStoredHistory;
766
889
  private runQuery;
767
890
  prompt(prompt: string | ContentBlock[], options?: QueryOptions<TContext>): Promise<SDKResultMessage>;
891
+ /**
892
+ * The conversation history as currently held by this Agent, including any
893
+ * messages seeded from `AgentOptions.historyStore`. Returns a deep copy, so
894
+ * mutating the result cannot corrupt the live conversation.
895
+ */
896
+ getHistory(): Promise<ModelMessage[]>;
897
+ /**
898
+ * Replace the conversation history. Idle only: throws ConcurrentQueryError
899
+ * while a query is running. When a historyStore is configured the store is
900
+ * replaced too, so persistence stays in sync.
901
+ *
902
+ * The host owns the content: the SDK does not validate the messages, so the
903
+ * replacement must be a well-formed history — e.g. no dangling `tool_use`
904
+ * without its matching `tool_result`.
905
+ */
906
+ replaceHistory(messages: ModelMessage[]): Promise<void>;
768
907
  addTools(tools: Array<ToolDefinition<any, TContext>>): void;
769
908
  private initMessage;
770
909
  private resultMessage;
@@ -789,7 +928,7 @@ export declare class Agent<TContext = unknown> {
789
928
  private executeToolBatch;
790
929
  private isToolCallConcurrencySafe;
791
930
  }
931
+ export type { Agent };
792
932
  type InferInput<TSchema> = TSchema extends {
793
933
  parse(input: unknown): infer TInput;
794
934
  } ? TInput : Record<string, unknown>;
795
- export {};