@axlsdk/axl 0.7.6 → 0.8.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/dist/index.d.cts CHANGED
@@ -196,10 +196,22 @@ type VoteOptions<T> = {
196
196
  scorer?: (value: T) => number | Promise<number>;
197
197
  reducer?: (values: T[]) => T | Promise<T>;
198
198
  };
199
+ /** Context passed to the verify function on retry (undefined on first call). */
200
+ type VerifyRetry<T> = {
201
+ /** Error message from the failed attempt (schema or validate). */
202
+ error: string;
203
+ /** Raw return value from the previous fn call. */
204
+ output: unknown;
205
+ /** Schema-parsed object — only present when schema passed but validate failed.
206
+ * Safe to modify and return as the next attempt. */
207
+ parsed?: T;
208
+ };
199
209
  /** Verify options */
200
210
  type VerifyOptions<T> = {
201
211
  retries?: number;
202
212
  fallback?: T;
213
+ /** Post-schema business rule validation on the parsed object. */
214
+ validate?: OutputValidator<T>;
203
215
  };
204
216
  /** AwaitHuman options */
205
217
  type AwaitHumanOptions = {
@@ -211,6 +223,12 @@ type AwaitHumanOptions = {
211
223
  type AskOptions<T = unknown> = {
212
224
  schema?: z.ZodType<T>;
213
225
  retries?: number;
226
+ /** Post-schema business rule validation. Receives the parsed typed object after schema
227
+ * validation succeeds. Only runs when `schema` is set. Retries with accumulating context
228
+ * on failure (LLM sees all previous failed attempts). Throws `ValidationError` on exhaustion. */
229
+ validate?: OutputValidator<T>;
230
+ /** Maximum retries for validate failures (default: 2). */
231
+ validateRetries?: number;
214
232
  /** Per-call metadata passed to dynamic model/system selector functions. */
215
233
  metadata?: Record<string, unknown>;
216
234
  /** Override temperature for this call. */
@@ -240,11 +258,17 @@ type DelegateOptions<T = unknown> = {
240
258
  metadata?: Record<string, unknown>;
241
259
  /** Number of retries for structured output validation (passed to the final ask). */
242
260
  retries?: number;
261
+ /** Post-schema business rule validation. Passed through to the final `ctx.ask()` call. */
262
+ validate?: OutputValidator<T>;
263
+ /** Maximum retries for validate failures (default: 2). Passed through to the final `ctx.ask()` call. */
264
+ validateRetries?: number;
243
265
  };
244
266
  /** Race options */
245
267
  type RaceOptions<T = unknown> = {
246
268
  /** Schema to validate each result. Invalid results are discarded and the race continues. */
247
269
  schema?: z.ZodType<T>;
270
+ /** Post-schema business rule validation. Results that fail are discarded (same as schema failures). */
271
+ validate?: OutputValidator<T>;
248
272
  };
249
273
  /** Execution status */
250
274
  type ExecutionStatus = 'running' | 'completed' | 'failed' | 'waiting';
@@ -252,7 +276,7 @@ type ExecutionStatus = 'running' | 'completed' | 'failed' | 'waiting';
252
276
  type TraceEvent = {
253
277
  executionId: string;
254
278
  step: number;
255
- type: 'agent_call' | 'tool_call' | 'verify' | 'handoff' | 'delegate' | 'tool_denied' | 'log' | 'workflow_start' | 'workflow_end' | 'guardrail';
279
+ type: 'agent_call' | 'tool_call' | 'verify' | 'handoff' | 'delegate' | 'tool_denied' | 'log' | 'workflow_start' | 'workflow_end' | 'guardrail' | 'validate';
256
280
  workflow?: string;
257
281
  agent?: string;
258
282
  tool?: string;
@@ -287,6 +311,18 @@ type GuardrailsConfig = {
287
311
  onBlock?: GuardrailBlockHandler;
288
312
  maxRetries?: number;
289
313
  };
314
+ /** Result of a validate check (post-schema business rule validation).
315
+ * Note: uses `valid: true` = pass, unlike `GuardrailResult` which uses `block: true` = fail. */
316
+ type ValidateResult = {
317
+ valid: boolean;
318
+ reason?: string;
319
+ };
320
+ /** Output validator function. Runs after schema parsing on the typed object.
321
+ * Only invoked when a schema is provided on the `ctx.ask()` call — without a schema,
322
+ * use output guardrails for raw text validation instead. */
323
+ type OutputValidator<T = unknown> = (output: T, ctx: {
324
+ metadata: Record<string, unknown>;
325
+ }) => ValidateResult | Promise<ValidateResult>;
290
326
  /** Execution info */
291
327
  type ExecutionInfo = {
292
328
  executionId: string;
@@ -1002,7 +1038,7 @@ declare class WorkflowContext<TInput = unknown> {
1002
1038
  private numericVote;
1003
1039
  private meanVote;
1004
1040
  private medianVote;
1005
- verify<T>(fn: (lastOutput?: unknown, errorMessage?: string) => Promise<unknown>, schema: z.ZodType<T>, options?: VerifyOptions<T>): Promise<T>;
1041
+ verify<T>(fn: (retry?: VerifyRetry<T>) => Promise<unknown>, schema: z.ZodType<T>, options?: VerifyOptions<T>): Promise<T>;
1006
1042
  budget<T>(options: BudgetOptions, fn: () => Promise<T>): Promise<BudgetResult<T>>;
1007
1043
  /** Get the current budget status, or null if not inside a budget block. */
1008
1044
  getBudgetStatus(): {
@@ -1408,6 +1444,13 @@ declare class GuardrailError extends AxlError {
1408
1444
  readonly reason: string;
1409
1445
  constructor(guardrailType: 'input' | 'output', reason: string);
1410
1446
  }
1447
+ /** Thrown when post-schema business rule validation fails after all retries exhausted */
1448
+ declare class ValidationError extends AxlError {
1449
+ readonly lastOutput: unknown;
1450
+ readonly reason: string;
1451
+ readonly retries: number;
1452
+ constructor(lastOutput: unknown, reason: string, retries: number);
1453
+ }
1411
1454
  /** Internal: thrown when an agent tries to call a tool not in its ACL */
1412
1455
  declare class ToolDenied extends AxlError {
1413
1456
  readonly toolName: string;
@@ -1800,4 +1843,4 @@ declare class NoopSpanManager implements SpanManager {
1800
1843
  */
1801
1844
  declare function createSpanManager(config?: TelemetryConfig): Promise<SpanManager>;
1802
1845
 
1803
- export { type Agent, type AgentCallInfo, type AgentConfig, AnthropicProvider, type AskOptions, type AwaitHumanOptions, type AxlConfig, AxlError, AxlRuntime, AxlStream, BudgetExceededError, type BudgetOptions, type BudgetResult, type ChatMessage, type ChatOptions, type DelegateOptions, type Effort, type Embedder, type ExecutionInfo, type ExecutionState, GeminiProvider, type GuardrailBlockHandler, GuardrailError, type GuardrailResult, type GuardrailsConfig, type HandoffDescriptor, type HandoffRecord, type HumanDecision, InMemoryVectorStore, type InputGuardrail, type MapOptions, MaxTurnsError, McpManager, type McpServer, type McpServerConfig, type McpToolDefinition, type McpToolResult, type MemoryConfig, MemoryManager, MemoryStore, NoConsensus, NoopSpanManager, OpenAIEmbedder, OpenAIProvider, OpenAIResponsesProvider, type OutputGuardrail, type PendingDecision, type Provider, type ProviderAdapter, ProviderRegistry, type ProviderResponse, QuorumNotMet, type RaceOptions, type RecallOptions, RedisStore, type RememberOptions, type ResolvedThinkingOptions, type Result, type RetryPolicy, SQLiteStore, Session, type SessionOptions, type SpanHandle, type SpanManager, type SpawnOptions, SqliteVectorStore, type StateStore, type StreamChunk, type StreamEvent, type TelemetryConfig, TimeoutError, type Tool, type ToolCallMessage, type ToolChoice, type ToolConfig, ToolDenied, type ToolHooks, type TraceEvent, type VectorEntry, type VectorResult, type VectorStore, VerifyError, type VerifyOptions, type VoteOptions, type Workflow, type WorkflowConfig, WorkflowContext, type WorkflowContextInit, agent, createSpanManager, defineConfig, resolveThinkingOptions, tool, workflow, zodToJsonSchema };
1846
+ export { type Agent, type AgentCallInfo, type AgentConfig, AnthropicProvider, type AskOptions, type AwaitHumanOptions, type AxlConfig, AxlError, AxlRuntime, AxlStream, BudgetExceededError, type BudgetOptions, type BudgetResult, type ChatMessage, type ChatOptions, type DelegateOptions, type Effort, type Embedder, type ExecutionInfo, type ExecutionState, GeminiProvider, type GuardrailBlockHandler, GuardrailError, type GuardrailResult, type GuardrailsConfig, type HandoffDescriptor, type HandoffRecord, type HumanDecision, InMemoryVectorStore, type InputGuardrail, type MapOptions, MaxTurnsError, McpManager, type McpServer, type McpServerConfig, type McpToolDefinition, type McpToolResult, type MemoryConfig, MemoryManager, MemoryStore, NoConsensus, NoopSpanManager, OpenAIEmbedder, OpenAIProvider, OpenAIResponsesProvider, type OutputGuardrail, type OutputValidator, type PendingDecision, type Provider, type ProviderAdapter, ProviderRegistry, type ProviderResponse, QuorumNotMet, type RaceOptions, type RecallOptions, RedisStore, type RememberOptions, type ResolvedThinkingOptions, type Result, type RetryPolicy, SQLiteStore, Session, type SessionOptions, type SpanHandle, type SpanManager, type SpawnOptions, SqliteVectorStore, type StateStore, type StreamChunk, type StreamEvent, type TelemetryConfig, TimeoutError, type Tool, type ToolCallMessage, type ToolChoice, type ToolConfig, ToolDenied, type ToolHooks, type TraceEvent, type ValidateResult, ValidationError, type VectorEntry, type VectorResult, type VectorStore, VerifyError, type VerifyOptions, type VerifyRetry, type VoteOptions, type Workflow, type WorkflowConfig, WorkflowContext, type WorkflowContextInit, agent, createSpanManager, defineConfig, resolveThinkingOptions, tool, workflow, zodToJsonSchema };
package/dist/index.d.ts CHANGED
@@ -196,10 +196,22 @@ type VoteOptions<T> = {
196
196
  scorer?: (value: T) => number | Promise<number>;
197
197
  reducer?: (values: T[]) => T | Promise<T>;
198
198
  };
199
+ /** Context passed to the verify function on retry (undefined on first call). */
200
+ type VerifyRetry<T> = {
201
+ /** Error message from the failed attempt (schema or validate). */
202
+ error: string;
203
+ /** Raw return value from the previous fn call. */
204
+ output: unknown;
205
+ /** Schema-parsed object — only present when schema passed but validate failed.
206
+ * Safe to modify and return as the next attempt. */
207
+ parsed?: T;
208
+ };
199
209
  /** Verify options */
200
210
  type VerifyOptions<T> = {
201
211
  retries?: number;
202
212
  fallback?: T;
213
+ /** Post-schema business rule validation on the parsed object. */
214
+ validate?: OutputValidator<T>;
203
215
  };
204
216
  /** AwaitHuman options */
205
217
  type AwaitHumanOptions = {
@@ -211,6 +223,12 @@ type AwaitHumanOptions = {
211
223
  type AskOptions<T = unknown> = {
212
224
  schema?: z.ZodType<T>;
213
225
  retries?: number;
226
+ /** Post-schema business rule validation. Receives the parsed typed object after schema
227
+ * validation succeeds. Only runs when `schema` is set. Retries with accumulating context
228
+ * on failure (LLM sees all previous failed attempts). Throws `ValidationError` on exhaustion. */
229
+ validate?: OutputValidator<T>;
230
+ /** Maximum retries for validate failures (default: 2). */
231
+ validateRetries?: number;
214
232
  /** Per-call metadata passed to dynamic model/system selector functions. */
215
233
  metadata?: Record<string, unknown>;
216
234
  /** Override temperature for this call. */
@@ -240,11 +258,17 @@ type DelegateOptions<T = unknown> = {
240
258
  metadata?: Record<string, unknown>;
241
259
  /** Number of retries for structured output validation (passed to the final ask). */
242
260
  retries?: number;
261
+ /** Post-schema business rule validation. Passed through to the final `ctx.ask()` call. */
262
+ validate?: OutputValidator<T>;
263
+ /** Maximum retries for validate failures (default: 2). Passed through to the final `ctx.ask()` call. */
264
+ validateRetries?: number;
243
265
  };
244
266
  /** Race options */
245
267
  type RaceOptions<T = unknown> = {
246
268
  /** Schema to validate each result. Invalid results are discarded and the race continues. */
247
269
  schema?: z.ZodType<T>;
270
+ /** Post-schema business rule validation. Results that fail are discarded (same as schema failures). */
271
+ validate?: OutputValidator<T>;
248
272
  };
249
273
  /** Execution status */
250
274
  type ExecutionStatus = 'running' | 'completed' | 'failed' | 'waiting';
@@ -252,7 +276,7 @@ type ExecutionStatus = 'running' | 'completed' | 'failed' | 'waiting';
252
276
  type TraceEvent = {
253
277
  executionId: string;
254
278
  step: number;
255
- type: 'agent_call' | 'tool_call' | 'verify' | 'handoff' | 'delegate' | 'tool_denied' | 'log' | 'workflow_start' | 'workflow_end' | 'guardrail';
279
+ type: 'agent_call' | 'tool_call' | 'verify' | 'handoff' | 'delegate' | 'tool_denied' | 'log' | 'workflow_start' | 'workflow_end' | 'guardrail' | 'validate';
256
280
  workflow?: string;
257
281
  agent?: string;
258
282
  tool?: string;
@@ -287,6 +311,18 @@ type GuardrailsConfig = {
287
311
  onBlock?: GuardrailBlockHandler;
288
312
  maxRetries?: number;
289
313
  };
314
+ /** Result of a validate check (post-schema business rule validation).
315
+ * Note: uses `valid: true` = pass, unlike `GuardrailResult` which uses `block: true` = fail. */
316
+ type ValidateResult = {
317
+ valid: boolean;
318
+ reason?: string;
319
+ };
320
+ /** Output validator function. Runs after schema parsing on the typed object.
321
+ * Only invoked when a schema is provided on the `ctx.ask()` call — without a schema,
322
+ * use output guardrails for raw text validation instead. */
323
+ type OutputValidator<T = unknown> = (output: T, ctx: {
324
+ metadata: Record<string, unknown>;
325
+ }) => ValidateResult | Promise<ValidateResult>;
290
326
  /** Execution info */
291
327
  type ExecutionInfo = {
292
328
  executionId: string;
@@ -1002,7 +1038,7 @@ declare class WorkflowContext<TInput = unknown> {
1002
1038
  private numericVote;
1003
1039
  private meanVote;
1004
1040
  private medianVote;
1005
- verify<T>(fn: (lastOutput?: unknown, errorMessage?: string) => Promise<unknown>, schema: z.ZodType<T>, options?: VerifyOptions<T>): Promise<T>;
1041
+ verify<T>(fn: (retry?: VerifyRetry<T>) => Promise<unknown>, schema: z.ZodType<T>, options?: VerifyOptions<T>): Promise<T>;
1006
1042
  budget<T>(options: BudgetOptions, fn: () => Promise<T>): Promise<BudgetResult<T>>;
1007
1043
  /** Get the current budget status, or null if not inside a budget block. */
1008
1044
  getBudgetStatus(): {
@@ -1408,6 +1444,13 @@ declare class GuardrailError extends AxlError {
1408
1444
  readonly reason: string;
1409
1445
  constructor(guardrailType: 'input' | 'output', reason: string);
1410
1446
  }
1447
+ /** Thrown when post-schema business rule validation fails after all retries exhausted */
1448
+ declare class ValidationError extends AxlError {
1449
+ readonly lastOutput: unknown;
1450
+ readonly reason: string;
1451
+ readonly retries: number;
1452
+ constructor(lastOutput: unknown, reason: string, retries: number);
1453
+ }
1411
1454
  /** Internal: thrown when an agent tries to call a tool not in its ACL */
1412
1455
  declare class ToolDenied extends AxlError {
1413
1456
  readonly toolName: string;
@@ -1800,4 +1843,4 @@ declare class NoopSpanManager implements SpanManager {
1800
1843
  */
1801
1844
  declare function createSpanManager(config?: TelemetryConfig): Promise<SpanManager>;
1802
1845
 
1803
- export { type Agent, type AgentCallInfo, type AgentConfig, AnthropicProvider, type AskOptions, type AwaitHumanOptions, type AxlConfig, AxlError, AxlRuntime, AxlStream, BudgetExceededError, type BudgetOptions, type BudgetResult, type ChatMessage, type ChatOptions, type DelegateOptions, type Effort, type Embedder, type ExecutionInfo, type ExecutionState, GeminiProvider, type GuardrailBlockHandler, GuardrailError, type GuardrailResult, type GuardrailsConfig, type HandoffDescriptor, type HandoffRecord, type HumanDecision, InMemoryVectorStore, type InputGuardrail, type MapOptions, MaxTurnsError, McpManager, type McpServer, type McpServerConfig, type McpToolDefinition, type McpToolResult, type MemoryConfig, MemoryManager, MemoryStore, NoConsensus, NoopSpanManager, OpenAIEmbedder, OpenAIProvider, OpenAIResponsesProvider, type OutputGuardrail, type PendingDecision, type Provider, type ProviderAdapter, ProviderRegistry, type ProviderResponse, QuorumNotMet, type RaceOptions, type RecallOptions, RedisStore, type RememberOptions, type ResolvedThinkingOptions, type Result, type RetryPolicy, SQLiteStore, Session, type SessionOptions, type SpanHandle, type SpanManager, type SpawnOptions, SqliteVectorStore, type StateStore, type StreamChunk, type StreamEvent, type TelemetryConfig, TimeoutError, type Tool, type ToolCallMessage, type ToolChoice, type ToolConfig, ToolDenied, type ToolHooks, type TraceEvent, type VectorEntry, type VectorResult, type VectorStore, VerifyError, type VerifyOptions, type VoteOptions, type Workflow, type WorkflowConfig, WorkflowContext, type WorkflowContextInit, agent, createSpanManager, defineConfig, resolveThinkingOptions, tool, workflow, zodToJsonSchema };
1846
+ export { type Agent, type AgentCallInfo, type AgentConfig, AnthropicProvider, type AskOptions, type AwaitHumanOptions, type AxlConfig, AxlError, AxlRuntime, AxlStream, BudgetExceededError, type BudgetOptions, type BudgetResult, type ChatMessage, type ChatOptions, type DelegateOptions, type Effort, type Embedder, type ExecutionInfo, type ExecutionState, GeminiProvider, type GuardrailBlockHandler, GuardrailError, type GuardrailResult, type GuardrailsConfig, type HandoffDescriptor, type HandoffRecord, type HumanDecision, InMemoryVectorStore, type InputGuardrail, type MapOptions, MaxTurnsError, McpManager, type McpServer, type McpServerConfig, type McpToolDefinition, type McpToolResult, type MemoryConfig, MemoryManager, MemoryStore, NoConsensus, NoopSpanManager, OpenAIEmbedder, OpenAIProvider, OpenAIResponsesProvider, type OutputGuardrail, type OutputValidator, type PendingDecision, type Provider, type ProviderAdapter, ProviderRegistry, type ProviderResponse, QuorumNotMet, type RaceOptions, type RecallOptions, RedisStore, type RememberOptions, type ResolvedThinkingOptions, type Result, type RetryPolicy, SQLiteStore, Session, type SessionOptions, type SpanHandle, type SpanManager, type SpawnOptions, SqliteVectorStore, type StateStore, type StreamChunk, type StreamEvent, type TelemetryConfig, TimeoutError, type Tool, type ToolCallMessage, type ToolChoice, type ToolConfig, ToolDenied, type ToolHooks, type TraceEvent, type ValidateResult, ValidationError, type VectorEntry, type VectorResult, type VectorStore, VerifyError, type VerifyOptions, type VerifyRetry, type VoteOptions, type Workflow, type WorkflowConfig, WorkflowContext, type WorkflowContextInit, agent, createSpanManager, defineConfig, resolveThinkingOptions, tool, workflow, zodToJsonSchema };
package/dist/index.js CHANGED
@@ -1998,6 +1998,18 @@ var GuardrailError = class extends AxlError {
1998
1998
  this.reason = reason;
1999
1999
  }
2000
2000
  };
2001
+ var ValidationError = class extends AxlError {
2002
+ lastOutput;
2003
+ reason;
2004
+ retries;
2005
+ constructor(lastOutput, reason, retries) {
2006
+ super("VALIDATION_ERROR", `Validation failed after ${retries} retries: ${reason}`);
2007
+ this.name = "ValidationError";
2008
+ this.lastOutput = lastOutput;
2009
+ this.reason = reason;
2010
+ this.retries = retries;
2011
+ }
2012
+ };
2001
2013
  var ToolDenied = class extends AxlError {
2002
2014
  toolName;
2003
2015
  agentName;
@@ -2262,9 +2274,6 @@ var WorkflowContext = class _WorkflowContext {
2262
2274
  agent2,
2263
2275
  prompt,
2264
2276
  options,
2265
- 0,
2266
- void 0,
2267
- void 0,
2268
2277
  void 0,
2269
2278
  usageCapture
2270
2279
  );
@@ -2314,7 +2323,7 @@ var WorkflowContext = class _WorkflowContext {
2314
2323
  return result;
2315
2324
  });
2316
2325
  }
2317
- async executeAgentCall(agent2, prompt, options, retryCount = 0, previousOutput, previousError, handoffMessages, usageCapture) {
2326
+ async executeAgentCall(agent2, prompt, options, handoffMessages, usageCapture) {
2318
2327
  if (this.budgetContext?.exceeded) {
2319
2328
  const { limit, totalCost: spent, policy } = this.budgetContext;
2320
2329
  if (policy === "warn") {
@@ -2386,16 +2395,6 @@ var WorkflowContext = class _WorkflowContext {
2386
2395
 
2387
2396
  Respond with valid JSON matching this schema:
2388
2397
  ${JSON.stringify(jsonSchema, null, 2)}`;
2389
- }
2390
- if (previousOutput && previousError) {
2391
- userContent += `
2392
-
2393
- Your previous response was invalid:
2394
- ${previousOutput}
2395
-
2396
- Error: ${previousError}
2397
-
2398
- Please fix and try again.`;
2399
2398
  }
2400
2399
  messages.push({ role: "user", content: userContent });
2401
2400
  if (handoffMessages && handoffMessages.length > 0) {
@@ -2440,9 +2439,17 @@ Please fix and try again.`;
2440
2439
  const maxTurns = agent2._config.maxTurns ?? 25;
2441
2440
  const timeoutMs = parseDuration(agent2._config.timeout ?? "60s");
2442
2441
  const startTime = Date.now();
2442
+ if (this.onToken && options?.validate) {
2443
+ throw new AxlError(
2444
+ "INVALID_CONFIG",
2445
+ "Cannot use validate with streaming. Validate requires schema (JSON output) which does not benefit from token streaming. Use a non-streaming call instead."
2446
+ );
2447
+ }
2443
2448
  const currentMessages = [...messages];
2444
2449
  let turns = 0;
2445
2450
  let guardrailOutputRetries = 0;
2451
+ let schemaRetries = 0;
2452
+ let validateRetries = 0;
2446
2453
  while (turns < maxTurns) {
2447
2454
  if (Date.now() - startTime > timeoutMs) {
2448
2455
  throw new TimeoutError("ctx.ask()", timeoutMs);
@@ -2570,14 +2577,17 @@ Please fix and try again.`;
2570
2577
  }
2571
2578
  }
2572
2579
  const handoffStart = Date.now();
2573
- const handoffOptions = options ? { schema: options.schema, retries: options.retries, metadata: options.metadata } : void 0;
2580
+ const handoffOptions = options ? {
2581
+ schema: options.schema,
2582
+ retries: options.retries,
2583
+ metadata: options.metadata,
2584
+ validate: options.validate,
2585
+ validateRetries: options.validateRetries
2586
+ } : void 0;
2574
2587
  const handoffFn = () => this.executeAgentCall(
2575
2588
  descriptor.agent,
2576
2589
  handoffPrompt,
2577
2590
  handoffOptions,
2578
- 0,
2579
- void 0,
2580
- void 0,
2581
2591
  currentMessages,
2582
2592
  usageCapture
2583
2593
  );
@@ -2911,26 +2921,26 @@ Please fix and try again.`;
2911
2921
  throw new GuardrailError("output", outputResult.reason ?? "Output blocked by guardrail");
2912
2922
  }
2913
2923
  }
2924
+ let validated = void 0;
2914
2925
  if (options?.schema) {
2915
2926
  try {
2916
2927
  const parsed = JSON.parse(stripMarkdownFences(content));
2917
- const validated = options.schema.parse(parsed);
2918
- this.pushAssistantToSessionHistory(content, response.providerMetadata);
2919
- return validated;
2928
+ validated = options.schema.parse(parsed);
2920
2929
  } catch (err) {
2921
- const maxRetries = options.retries ?? 3;
2922
- if (retryCount < maxRetries) {
2930
+ const maxSchemaRetries = options.retries ?? 3;
2931
+ if (schemaRetries < maxSchemaRetries) {
2932
+ schemaRetries++;
2923
2933
  const errorMsg = err instanceof Error ? err.message : String(err);
2924
- return this.executeAgentCall(
2925
- agent2,
2926
- prompt,
2927
- options,
2928
- retryCount + 1,
2934
+ currentMessages.push({
2935
+ role: "assistant",
2929
2936
  content,
2930
- errorMsg,
2931
- void 0,
2932
- usageCapture
2933
- );
2937
+ ...response.providerMetadata ? { providerMetadata: response.providerMetadata } : {}
2938
+ });
2939
+ currentMessages.push({
2940
+ role: "system",
2941
+ content: `Your response was not valid JSON or did not match the required schema: ${errorMsg}. Please fix and try again.`
2942
+ });
2943
+ continue;
2934
2944
  }
2935
2945
  const zodErr = err instanceof ZodError ? err : new ZodError([
2936
2946
  {
@@ -2939,11 +2949,55 @@ Please fix and try again.`;
2939
2949
  message: err instanceof Error ? err.message : String(err)
2940
2950
  }
2941
2951
  ]);
2942
- throw new VerifyError(content, zodErr, maxRetries);
2952
+ throw new VerifyError(content, zodErr, maxSchemaRetries);
2953
+ }
2954
+ }
2955
+ if (options?.schema && options.validate) {
2956
+ let validateResult;
2957
+ try {
2958
+ validateResult = await options.validate(validated, {
2959
+ metadata: this.metadata
2960
+ });
2961
+ } catch (err) {
2962
+ const reason = err instanceof Error ? err.message : String(err);
2963
+ validateResult = { valid: false, reason: `Validator error: ${reason}` };
2964
+ }
2965
+ this.emitTrace({
2966
+ type: "validate",
2967
+ agent: agent2._name,
2968
+ data: {
2969
+ valid: validateResult.valid,
2970
+ ...validateResult.reason ? { reason: validateResult.reason } : {}
2971
+ }
2972
+ });
2973
+ this.spanManager?.addEventToActiveSpan("axl.validate.check", {
2974
+ "axl.validate.valid": validateResult.valid,
2975
+ ...validateResult.reason ? { "axl.validate.reason": validateResult.reason } : {}
2976
+ });
2977
+ if (!validateResult.valid) {
2978
+ const maxValidateRetries = options.validateRetries ?? 2;
2979
+ if (validateRetries < maxValidateRetries) {
2980
+ validateRetries++;
2981
+ currentMessages.push({
2982
+ role: "assistant",
2983
+ content,
2984
+ ...response.providerMetadata ? { providerMetadata: response.providerMetadata } : {}
2985
+ });
2986
+ currentMessages.push({
2987
+ role: "system",
2988
+ content: `Your response parsed correctly but failed validation: ${validateResult.reason ?? "Validation failed"}. Previous attempts are visible above. Please fix and try again.`
2989
+ });
2990
+ continue;
2991
+ }
2992
+ throw new ValidationError(
2993
+ validated,
2994
+ validateResult.reason ?? "Validation failed",
2995
+ maxValidateRetries
2996
+ );
2943
2997
  }
2944
2998
  }
2945
2999
  this.pushAssistantToSessionHistory(content, response.providerMetadata);
2946
- return content;
3000
+ return validated ?? content;
2947
3001
  }
2948
3002
  throw new MaxTurnsError("ctx.ask()", maxTurns);
2949
3003
  }
@@ -3300,32 +3354,57 @@ ${summaryResponse.content}`
3300
3354
  // ── ctx.verify() ──────────────────────────────────────────────────────
3301
3355
  async verify(fn, schema, options) {
3302
3356
  const maxRetries = options?.retries ?? 3;
3303
- let lastOutput = void 0;
3304
- let lastErrorMessage = void 0;
3357
+ let lastRetry = void 0;
3305
3358
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
3306
- let result;
3359
+ let rawOutput;
3307
3360
  try {
3308
- result = await fn(lastOutput, lastErrorMessage);
3309
- lastOutput = result;
3310
- return schema.parse(result);
3361
+ const result = await fn(lastRetry);
3362
+ rawOutput = result;
3363
+ const parsed = schema.parse(result);
3364
+ if (options?.validate) {
3365
+ let validateResult;
3366
+ try {
3367
+ validateResult = await options.validate(parsed, { metadata: this.metadata });
3368
+ } catch (err) {
3369
+ const reason = err instanceof Error ? err.message : String(err);
3370
+ validateResult = { valid: false, reason: `Validator error: ${reason}` };
3371
+ }
3372
+ if (!validateResult.valid) {
3373
+ const errorMsg = validateResult.reason ?? "Validation failed";
3374
+ lastRetry = { error: errorMsg, output: rawOutput, parsed };
3375
+ if (attempt === maxRetries) {
3376
+ if (options?.fallback !== void 0) return options.fallback;
3377
+ throw new ValidationError(parsed, errorMsg, maxRetries);
3378
+ }
3379
+ continue;
3380
+ }
3381
+ }
3382
+ return parsed;
3311
3383
  } catch (err) {
3312
- if (err instanceof ZodError) {
3313
- lastErrorMessage = err.message;
3314
- } else if (err instanceof Error) {
3315
- lastErrorMessage = err.message;
3316
- } else {
3317
- lastErrorMessage = String(err);
3384
+ if (err instanceof ValidationError) {
3385
+ lastRetry = {
3386
+ error: err.reason,
3387
+ output: rawOutput,
3388
+ parsed: err.lastOutput
3389
+ };
3390
+ if (attempt === maxRetries) {
3391
+ if (options?.fallback !== void 0) return options.fallback;
3392
+ throw err;
3393
+ }
3394
+ continue;
3318
3395
  }
3396
+ const errorMsg = err instanceof ZodError ? err.message : err instanceof Error ? err.message : String(err);
3397
+ lastRetry = { error: errorMsg, output: rawOutput };
3319
3398
  if (attempt === maxRetries) {
3320
3399
  if (options?.fallback !== void 0) return options.fallback;
3321
- const zodErr = err instanceof ZodError ? err : new ZodError([{ code: "custom", path: [], message: lastErrorMessage }]);
3322
- throw new VerifyError(lastOutput, zodErr, maxRetries);
3400
+ const zodErr = err instanceof ZodError ? err : new ZodError([{ code: "custom", path: [], message: errorMsg }]);
3401
+ throw new VerifyError(rawOutput, zodErr, maxRetries);
3323
3402
  }
3324
3403
  }
3325
3404
  }
3326
3405
  if (options?.fallback !== void 0) return options.fallback;
3327
3406
  throw new VerifyError(
3328
- lastOutput,
3407
+ lastRetry?.output,
3329
3408
  new ZodError([{ code: "custom", path: [], message: "Verify failed" }]),
3330
3409
  maxRetries
3331
3410
  );
@@ -3427,7 +3506,7 @@ ${summaryResponse.content}`
3427
3506
  let remaining = fns.length;
3428
3507
  for (const fn of fns) {
3429
3508
  const p = signalStorage.run(composedSignal, fn);
3430
- p.then((value) => {
3509
+ p.then(async (value) => {
3431
3510
  if (settled) return;
3432
3511
  if (schema) {
3433
3512
  const parsed = schema.safeParse(value);
@@ -3440,6 +3519,33 @@ ${summaryResponse.content}`
3440
3519
  }
3441
3520
  return;
3442
3521
  }
3522
+ if (options?.validate) {
3523
+ try {
3524
+ const validateResult = await options.validate(parsed.data, {
3525
+ metadata: this.metadata
3526
+ });
3527
+ if (!validateResult.valid) {
3528
+ remaining--;
3529
+ lastError = new Error(
3530
+ `Validation failed: ${validateResult.reason ?? "Validation failed"}`
3531
+ );
3532
+ if (remaining === 0 && !settled) {
3533
+ settled = true;
3534
+ reject(lastError);
3535
+ }
3536
+ return;
3537
+ }
3538
+ } catch (err) {
3539
+ remaining--;
3540
+ lastError = err instanceof Error ? err : new Error(`Validator error: ${String(err)}`);
3541
+ if (remaining === 0 && !settled) {
3542
+ settled = true;
3543
+ reject(lastError);
3544
+ }
3545
+ return;
3546
+ }
3547
+ }
3548
+ if (settled) return;
3443
3549
  settled = true;
3444
3550
  controller.abort();
3445
3551
  resolve(parsed.data);
@@ -3691,7 +3797,9 @@ ${summaryResponse.content}`
3691
3797
  return this.ask(agents[0], prompt, {
3692
3798
  schema: options?.schema,
3693
3799
  retries: options?.retries,
3694
- metadata: options?.metadata
3800
+ metadata: options?.metadata,
3801
+ validate: options?.validate,
3802
+ validateRetries: options?.validateRetries
3695
3803
  });
3696
3804
  }
3697
3805
  const resolveCtx = options?.metadata ? { metadata: { ...this.metadata, ...options.metadata } } : { metadata: this.metadata };
@@ -3732,7 +3840,9 @@ ${summaryResponse.content}`
3732
3840
  return this.ask(routerAgent, prompt, {
3733
3841
  schema: options?.schema,
3734
3842
  retries: options?.retries,
3735
- metadata: options?.metadata
3843
+ metadata: options?.metadata,
3844
+ validate: options?.validate,
3845
+ validateRetries: options?.validateRetries
3736
3846
  });
3737
3847
  }
3738
3848
  // ── Private ───────────────────────────────────────────────────────────
@@ -6012,6 +6122,7 @@ export {
6012
6122
  SqliteVectorStore,
6013
6123
  TimeoutError,
6014
6124
  ToolDenied,
6125
+ ValidationError,
6015
6126
  VerifyError,
6016
6127
  WorkflowContext,
6017
6128
  agent,