agent-lattice 0.9.21 → 0.9.24
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 +67 -0
- package/dist/index.d.ts +40 -2
- package/dist/index.js +7 -7
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -283,6 +283,47 @@ const result = await agent.prompt("What is 2+2?");
|
|
|
283
283
|
console.log(result.result);
|
|
284
284
|
```
|
|
285
285
|
|
|
286
|
+
## Tool Batch Policy
|
|
287
|
+
|
|
288
|
+
Use `toolBatchPolicy` when some tools must not run in the same model response.
|
|
289
|
+
The policy sees the complete batch before any tool executes. If it rejects the
|
|
290
|
+
batch, no tool runs and every tool call receives a structured `is_error: true`
|
|
291
|
+
result.
|
|
292
|
+
|
|
293
|
+
```ts
|
|
294
|
+
const lead = createAgent({
|
|
295
|
+
model: "claude-sonnet-4-6",
|
|
296
|
+
tools: [incrementRevision],
|
|
297
|
+
toolBatchPolicy: {
|
|
298
|
+
validate({ toolCalls }) {
|
|
299
|
+
const incrementsRevision = toolCalls.find(
|
|
300
|
+
call => call.name === "incrementRevision",
|
|
301
|
+
);
|
|
302
|
+
const handoff = toolCalls.find(
|
|
303
|
+
call => call.kind === "agent_tool" &&
|
|
304
|
+
(call.input as { mode?: string }).mode === "handoff",
|
|
305
|
+
);
|
|
306
|
+
if (incrementsRevision && handoff) {
|
|
307
|
+
return {
|
|
308
|
+
allowed: false,
|
|
309
|
+
code: "invalid_tool_batch",
|
|
310
|
+
message: "Update the revision before delegating dependent work.",
|
|
311
|
+
conflictingToolCallIds: [incrementsRevision.id, handoff.id],
|
|
312
|
+
suggestedNextStep: "Run incrementRevision first, then hand off the new revision.",
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
return { allowed: true };
|
|
316
|
+
},
|
|
317
|
+
},
|
|
318
|
+
});
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
The policy may be synchronous or asynchronous. If it throws, the SDK rejects
|
|
322
|
+
the whole batch with `tool_batch_policy_error`; no tool has executed. Without a
|
|
323
|
+
policy, tool execution is unchanged. A policy prevents known bad combinations
|
|
324
|
+
inside one model response, but it does not replace database transactions or
|
|
325
|
+
revision checks against concurrent external updates.
|
|
326
|
+
|
|
286
327
|
## Business Context For Tools
|
|
287
328
|
|
|
288
329
|
Pass host application data through `context`. The SDK gives that context to
|
|
@@ -533,6 +574,13 @@ delivery: the runtime waits for the member's upstream reply, feeds it back to
|
|
|
533
574
|
the lead, and keeps going until the root lead returns the final result or the
|
|
534
575
|
run terminates.
|
|
535
576
|
|
|
577
|
+
After one model response queues one or more handoffs, the SDK does not call the
|
|
578
|
+
lead model again immediately. It first runs those members, collects their
|
|
579
|
+
completed or failed reports, and only then calls the lead again. All handoffs
|
|
580
|
+
from the current tool batch are queued before the lead pauses. The receipt keeps
|
|
581
|
+
`status: "accepted"` for compatibility and also includes `phase: "queued"`,
|
|
582
|
+
`completion_pending: true`, `message_id`, `work_item_id`, and `thread_id`.
|
|
583
|
+
|
|
536
584
|
Accepted handoffs use work-item failure isolation by default. If one member
|
|
537
585
|
returns an agent error such as `MaxTurnsError` or `APIError`, the runtime marks
|
|
538
586
|
that work item `failed`, sends a failure report to the lead, and continues the
|
|
@@ -541,6 +589,25 @@ together and decides whether to retry, revise the task, accept a partial result,
|
|
|
541
589
|
or finish. A run-wide `AbortError` still stops the runner; the runtime marks the
|
|
542
590
|
current and remaining accepted work `cancelled` before propagating the abort.
|
|
543
591
|
|
|
592
|
+
Handoff work is serial by default. Set a bounded concurrency limit on the team
|
|
593
|
+
when independent members should run at the same time:
|
|
594
|
+
|
|
595
|
+
```ts
|
|
596
|
+
const team = createTeam({
|
|
597
|
+
name: "research",
|
|
598
|
+
lead,
|
|
599
|
+
members,
|
|
600
|
+
runner: { maxConcurrentWorkItems: 4 },
|
|
601
|
+
});
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
You can also pass `maxConcurrentWorkItems` to `createTeamRunner()`. The limit
|
|
605
|
+
must be a positive integer and defaults to `1`. It applies across different
|
|
606
|
+
member mailboxes; work addressed to the same mailbox remains serial because an
|
|
607
|
+
Agent may keep mutable conversation state. Runtime events are emitted as work
|
|
608
|
+
actually progresses, while the reports injected back into the lead stay in the
|
|
609
|
+
original handoff order.
|
|
610
|
+
|
|
544
611
|
Team member tools can also request explicit shared workspace write grants:
|
|
545
612
|
|
|
546
613
|
```ts
|
package/dist/index.d.ts
CHANGED
|
@@ -100,6 +100,7 @@ export type AgentRuntimeContext = {
|
|
|
100
100
|
permissions: RuntimePermissions;
|
|
101
101
|
delegate(input: AgentRuntimeDelegateInput): Promise<AgentRuntimeDelegateResult>;
|
|
102
102
|
emit(message: TeamRunnerMessage): void;
|
|
103
|
+
shouldPauseAfterToolBatch?(): boolean;
|
|
103
104
|
};
|
|
104
105
|
export type ContextTraceEventType = "run_start" | "user_message" | "model_request" | "assistant_message" | "tool_use" | "tool_result" | "team_message" | "result" | "error";
|
|
105
106
|
export type ContextTraceEvent = {
|
|
@@ -176,6 +177,32 @@ export interface ModelClient {
|
|
|
176
177
|
export type ToolResult = {
|
|
177
178
|
content: string | ContentBlock[];
|
|
178
179
|
};
|
|
180
|
+
export type ToolKind = "tool" | "agent_tool";
|
|
181
|
+
export type ToolBatchCall = {
|
|
182
|
+
id: string;
|
|
183
|
+
name: string;
|
|
184
|
+
input: unknown;
|
|
185
|
+
kind: ToolKind;
|
|
186
|
+
};
|
|
187
|
+
export type ToolBatchPolicyContext<TContext = unknown> = {
|
|
188
|
+
source?: AgentRuntimeSource;
|
|
189
|
+
toolCalls: ToolBatchCall[];
|
|
190
|
+
context?: TContext;
|
|
191
|
+
signal?: AbortSignal;
|
|
192
|
+
};
|
|
193
|
+
export type ToolBatchPolicyRejection = {
|
|
194
|
+
allowed: false;
|
|
195
|
+
code: string;
|
|
196
|
+
message: string;
|
|
197
|
+
conflictingToolCallIds?: string[];
|
|
198
|
+
suggestedNextStep?: string;
|
|
199
|
+
};
|
|
200
|
+
export type ToolBatchPolicyResult = {
|
|
201
|
+
allowed: true;
|
|
202
|
+
} | ToolBatchPolicyRejection;
|
|
203
|
+
export type ToolBatchPolicy<TContext = unknown> = {
|
|
204
|
+
validate(context: ToolBatchPolicyContext<TContext>): ToolBatchPolicyResult | Promise<ToolBatchPolicyResult>;
|
|
205
|
+
};
|
|
179
206
|
export type ToolExecutionContext<TContext = unknown> = {
|
|
180
207
|
signal?: AbortSignal;
|
|
181
208
|
toolUseId: string;
|
|
@@ -187,6 +214,7 @@ export type ToolHandler<TInput = unknown, TContext = unknown> = (input: TInput,
|
|
|
187
214
|
export type ToolDefinition<TInput = unknown, TContext = unknown> = {
|
|
188
215
|
name: string;
|
|
189
216
|
description: string;
|
|
217
|
+
kind?: ToolKind;
|
|
190
218
|
inputSchema: unknown;
|
|
191
219
|
jsonSchema: Record<string, unknown>;
|
|
192
220
|
parse(input: unknown): TInput;
|
|
@@ -312,12 +340,17 @@ export type SQLiteMailboxOptions = {
|
|
|
312
340
|
database: SQLiteDatabaseLike;
|
|
313
341
|
tableName?: string;
|
|
314
342
|
};
|
|
343
|
+
export type TeamRunnerConfig = {
|
|
344
|
+
maxDelegateDepth?: number;
|
|
345
|
+
maxConcurrentWorkItems?: number;
|
|
346
|
+
};
|
|
315
347
|
export type TeamOptions = {
|
|
316
348
|
name: string;
|
|
317
349
|
lead: Agent<any>;
|
|
318
350
|
members: TeamMemberDefinition[];
|
|
319
351
|
mailbox?: TeamMailbox;
|
|
320
352
|
exposeLeadMailboxTools?: boolean;
|
|
353
|
+
runner?: TeamRunnerConfig;
|
|
321
354
|
};
|
|
322
355
|
export type Team = {
|
|
323
356
|
name: string;
|
|
@@ -326,6 +359,7 @@ export type Team = {
|
|
|
326
359
|
mailbox: TeamMailbox;
|
|
327
360
|
tools: Array<ToolDefinition<any, any>>;
|
|
328
361
|
memberTools: Record<string, Array<ToolDefinition<any, any>>>;
|
|
362
|
+
readonly runnerOptions?: TeamRunnerConfig;
|
|
329
363
|
send(from: string, to: string, content: string, options?: TeamSendOptions): Promise<TeamMessage>;
|
|
330
364
|
drain(options?: TeamDrainOptions): Promise<TeamDrainResult>;
|
|
331
365
|
query(prompt: string | ContentBlock[], options?: QueryOptions): AsyncGenerator<TeamRunnerMessage>;
|
|
@@ -341,12 +375,11 @@ export type TeamDrainResult = {
|
|
|
341
375
|
failed: number;
|
|
342
376
|
rounds: number;
|
|
343
377
|
};
|
|
344
|
-
export type TeamRunnerOptions = {
|
|
378
|
+
export type TeamRunnerOptions = TeamRunnerConfig & {
|
|
345
379
|
team?: Team;
|
|
346
380
|
root?: AgentLike<any>;
|
|
347
381
|
mailbox?: TeamMailbox;
|
|
348
382
|
source?: AgentRuntimeSource;
|
|
349
|
-
maxDelegateDepth?: number;
|
|
350
383
|
};
|
|
351
384
|
export type TeamRunner = {
|
|
352
385
|
root: AgentLike<any>;
|
|
@@ -380,6 +413,7 @@ export type AgentOptions<TContext = unknown> = {
|
|
|
380
413
|
maxTurns?: number;
|
|
381
414
|
thinkingConfig?: ThinkingConfig;
|
|
382
415
|
tools?: Array<ToolDefinition<any, TContext>>;
|
|
416
|
+
toolBatchPolicy?: ToolBatchPolicy<TContext>;
|
|
383
417
|
skills?: SkillDefinition[];
|
|
384
418
|
workspace?: AgentWorkspaceOptions;
|
|
385
419
|
permission?: (request: PermissionRequest) => Promise<PermissionDecision> | PermissionDecision;
|
|
@@ -484,6 +518,10 @@ export declare class MaxTurnsError extends AgentSDKError {
|
|
|
484
518
|
}
|
|
485
519
|
export declare class AbortError extends AgentSDKError {
|
|
486
520
|
}
|
|
521
|
+
export declare class ToolBatchRejectedError extends AgentSDKError {
|
|
522
|
+
readonly rejection: ToolBatchPolicyRejection;
|
|
523
|
+
constructor(rejection: ToolBatchPolicyRejection);
|
|
524
|
+
}
|
|
487
525
|
export declare class ToolPermissionDeniedError extends AgentSDKError {
|
|
488
526
|
readonly denial: PermissionDenial;
|
|
489
527
|
constructor(denial: PermissionDenial);
|