@amitdeshmukh/ax-crew 6.0.0 → 8.0.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.
@@ -15,7 +15,9 @@ import type {
15
15
  FunctionRegistryType,
16
16
  UsageCost,
17
17
  AxCrewConfig,
18
+ AxCrewOptions,
18
19
  MCPTransportConfig,
20
+ ACEConfig,
19
21
  } from "../types.js";
20
22
 
21
23
  import { createState } from "../state/index.js";
@@ -47,6 +49,13 @@ class StatefulAxAgent extends AxAgent<any, any> {
47
49
  private agentName: string;
48
50
  private costTracker?: any;
49
51
  private lastRecordedCostUSD: number = 0;
52
+ private debugEnabled: boolean = false;
53
+ // ACE-related optional state
54
+ private aceConfig?: ACEConfig;
55
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
56
+ private aceOptimizer?: any;
57
+ private acePlaybook?: any;
58
+ private aceBaseInstruction?: string; // Original description before playbook injection
50
59
  private isAxAIService(obj: any): obj is AxAI {
51
60
  return !!obj && typeof obj.getName === 'function' && typeof obj.chat === 'function';
52
61
  }
@@ -65,10 +74,11 @@ class StatefulAxAgent extends AxAgent<any, any> {
65
74
  functions?: (AxFunction | (() => AxFunction))[] | undefined;
66
75
  examples?: Array<Record<string, any>> | undefined;
67
76
  mcpServers?: Record<string, MCPTransportConfig> | undefined;
77
+ debug?: boolean;
68
78
  }>,
69
79
  state: StateInstance
70
80
  ) {
71
- const { examples, ...restOptions } = options;
81
+ const { examples, debug, ...restOptions } = options;
72
82
  const formattedOptions = {
73
83
  ...restOptions,
74
84
  functions: restOptions.functions?.map((fn) =>
@@ -79,6 +89,7 @@ class StatefulAxAgent extends AxAgent<any, any> {
79
89
  this.state = state;
80
90
  this.axai = ai;
81
91
  this.agentName = options.name;
92
+ this.debugEnabled = debug ?? false;
82
93
 
83
94
  // Set examples if provided
84
95
  if (examples && examples.length > 0) {
@@ -97,13 +108,40 @@ class StatefulAxAgent extends AxAgent<any, any> {
97
108
  third?: Readonly<AxProgramForwardOptions<any>>
98
109
  ): Promise<Record<string, any>> {
99
110
  let result;
100
-
111
+
101
112
  const start = performance.now();
102
113
  const crewId = (this.state as any)?.crewId || (this.state.get?.('crewId')) || 'default';
103
114
  const labels = { crewId, agent: this.agentName } as any;
115
+ const input = this.isAxAIService(first) ? second : first;
116
+ const taskId = `task_${crewId}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
117
+
118
+ // Track execution context in crew for ACE feedback routing
119
+ const crewInstance = (this.state as any)?.crew as AxCrew;
120
+ if (crewInstance) {
121
+ if (this.isAxAIService(first)) {
122
+ // For sub-agent calls, track under parent task ID
123
+ const parentTaskId = (this.state as any)?.currentTaskId;
124
+ if (parentTaskId) {
125
+ crewInstance.trackAgentExecution(parentTaskId, this.agentName, input);
126
+ }
127
+ } else {
128
+ // Root-level call - start new execution tracking
129
+ crewInstance.trackAgentExecution(taskId, this.agentName, input);
130
+ (this.state as any).currentTaskId = taskId;
131
+ }
132
+ }
104
133
 
105
- // Track costs regardless of whether it's a direct or sub-agent call
106
- // This ensures we capture multiple legitimate calls to the same agent
134
+ // Before forward: compose instruction with current playbook (mirrors AxACE.compile behavior)
135
+ // This ensures the agent uses the latest playbook context for this call
136
+ if (this.debugEnabled) {
137
+ console.log(`[ACE Debug] forward() called, aceConfig=${!!this.aceConfig}`);
138
+ }
139
+ if (this.aceConfig) {
140
+ await this.composeInstructionWithPlaybook();
141
+ }
142
+
143
+ // Execute the forward call
144
+ // Note: OpenTelemetry spans are automatically created by AxAI (configured via AxCrewOptions.telemetry)
107
145
  if (this.isAxAIService(first)) {
108
146
  // Sub-agent case (called with AI service)
109
147
  result = await super.forward(this.axai, second as Record<string, any>, third);
@@ -151,6 +189,24 @@ class StatefulAxAgent extends AxAgent<any, any> {
151
189
  } catch {}
152
190
  }
153
191
 
192
+ // Record result in crew execution history for ACE feedback routing
193
+ if (crewInstance) {
194
+ if (this.isAxAIService(first)) {
195
+ // For sub-agent calls, record under parent task ID
196
+ const parentTaskId = (this.state as any)?.currentTaskId;
197
+ if (parentTaskId) {
198
+ crewInstance.recordAgentResult(parentTaskId, this.agentName, result);
199
+ }
200
+ } else {
201
+ // Root-level result - include taskId for feedback routing
202
+ crewInstance.recordAgentResult(taskId, this.agentName, result);
203
+ // Clean up current task ID
204
+ delete (this.state as any).currentTaskId;
205
+ // Attach taskId to result for feedback routing convenience
206
+ result._taskId = taskId;
207
+ }
208
+ }
209
+
154
210
  return result;
155
211
  }
156
212
 
@@ -257,6 +313,217 @@ class StatefulAxAgent extends AxAgent<any, any> {
257
313
  MetricsRegistry.reset({ crewId, agent: this.agentName } as any);
258
314
  }
259
315
 
316
+ // =============
317
+ // ACE API - Agentic Context Engineering for online learning
318
+ // Reference: https://axllm.dev/ace/
319
+ // =============
320
+
321
+ /**
322
+ * Initialize ACE (Agentic Context Engineering) for this agent.
323
+ * Builds the optimizer and loads any initial playbook from persistence.
324
+ * Sets up the optimizer for online-only mode if compileOnStart is false.
325
+ */
326
+ async initACE(ace?: ACEConfig): Promise<void> {
327
+ this.aceConfig = ace;
328
+ if (!ace) return;
329
+ try {
330
+ // Capture base instruction BEFORE any playbook injection (mirrors AxACE.extractProgramInstruction)
331
+ this.aceBaseInstruction = this.getSignature().getDescription() || '';
332
+
333
+ const { buildACEOptimizer, loadInitialPlaybook, createEmptyPlaybook } = await import('./ace.js');
334
+ // Build optimizer with agent's AI as student
335
+ this.aceOptimizer = buildACEOptimizer(this.axai, ace);
336
+
337
+ // For online-only mode (no offline compile), we need to set the program
338
+ // reference so applyOnlineUpdate can work. AxACE requires compile() to
339
+ // set the program, but we can set it directly for online-only use.
340
+ if (!ace.compileOnStart) {
341
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
342
+ (this.aceOptimizer as any).program = this;
343
+ }
344
+
345
+ // Load initial playbook or create empty one
346
+ const initial = await loadInitialPlaybook(ace.persistence);
347
+ this.applyPlaybook(initial ?? createEmptyPlaybook());
348
+
349
+ if (this.debugEnabled) {
350
+ console.log(`[ACE Debug] Initialized for ${this.agentName}, base instruction: ${this.aceBaseInstruction?.slice(0, 50)}...`);
351
+ }
352
+ } catch (error) {
353
+ console.warn(`Failed to initialize ACE for agent ${this.agentName}:`, error);
354
+ }
355
+ }
356
+
357
+ /**
358
+ * Run offline ACE compilation with examples and metric.
359
+ * Compiles the playbook based on training examples.
360
+ */
361
+ async optimizeOffline(params?: { metric?: any; examples?: any[] }): Promise<void> {
362
+ if (!this.aceConfig || !this.aceOptimizer) return;
363
+ try {
364
+ const { runOfflineCompile, resolveMetric } = await import('./ace.js');
365
+ const registry = (this as any).__functionsRegistry as FunctionRegistryType | undefined;
366
+ const metric = params?.metric || resolveMetric(this.aceConfig.metric, registry || {} as any);
367
+ const examples = params?.examples || [];
368
+
369
+ if (!metric || examples.length === 0) {
370
+ console.warn(`ACE offline compile skipped for ${this.agentName}: missing metric or examples`);
371
+ return;
372
+ }
373
+
374
+ const result = await runOfflineCompile({
375
+ program: this,
376
+ optimizer: this.aceOptimizer,
377
+ metric,
378
+ examples,
379
+ persistence: this.aceConfig.persistence
380
+ });
381
+
382
+ // Apply optimized playbook if compilation succeeded
383
+ if (result?.artifact?.playbook) {
384
+ await this.applyPlaybook(result.artifact.playbook);
385
+ }
386
+ } catch (error) {
387
+ console.warn(`ACE offline compile failed for ${this.agentName}:`, error);
388
+ }
389
+ }
390
+
391
+ /**
392
+ * Apply online ACE update based on user feedback.
393
+ *
394
+ * For preference-based feedback (e.g., "only show flights between 9am-12pm"),
395
+ * we use our own feedback analyzer that preserves specificity.
396
+ *
397
+ * Note: AxACE's built-in curator is designed for error correction (severity mismatches)
398
+ * and tends to over-abstract preference feedback into generic guidelines.
399
+ * We bypass it and directly use our feedback analyzer for better results.
400
+ */
401
+ async applyOnlineUpdate(params: { example: any; prediction: any; feedback?: string }): Promise<void> {
402
+ if (!this.aceConfig) return;
403
+ if (!params.feedback?.trim()) return; // Nothing to do without feedback
404
+
405
+ try {
406
+ const { persistPlaybook, addFeedbackToPlaybook, createEmptyPlaybook } = await import('./ace.js');
407
+
408
+ // Get or create playbook
409
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
410
+ let playbook = this.acePlaybook ?? (this.aceOptimizer as any)?.playbook;
411
+ if (!playbook) {
412
+ playbook = createEmptyPlaybook();
413
+ }
414
+
415
+ if (this.debugEnabled) {
416
+ console.log(`[ACE Debug] Adding feedback to playbook: "${params.feedback}"`);
417
+ }
418
+
419
+ // Use teacher AI (or student AI as fallback) for smart categorization
420
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
421
+ const teacherAI = (this.aceOptimizer as any)?.teacherAI;
422
+ const aiForAnalysis = teacherAI ?? this.axai;
423
+
424
+ // Directly add feedback to playbook using our analyzer (preserves specificity)
425
+ await addFeedbackToPlaybook(playbook, params.feedback, aiForAnalysis, this.debugEnabled);
426
+
427
+ // Store updated playbook (injection happens in next forward() call)
428
+ this.applyPlaybook(playbook);
429
+
430
+ // Sync with optimizer if available
431
+ if (this.aceOptimizer) {
432
+ (this.aceOptimizer as any).playbook = playbook;
433
+ }
434
+
435
+ // Persist if auto-persist enabled
436
+ if (this.aceConfig.persistence?.autoPersist) {
437
+ await persistPlaybook(playbook, this.aceConfig.persistence);
438
+ }
439
+
440
+ if (this.debugEnabled) {
441
+ console.log(`[ACE Debug] Playbook updated, sections: ${Object.keys(playbook.sections || {}).join(', ')}`);
442
+ }
443
+ } catch (error) {
444
+ console.warn(`ACE online update failed for ${this.agentName}:`, error);
445
+ }
446
+ }
447
+
448
+ /**
449
+ * Get the current ACE playbook for this agent.
450
+ */
451
+ getPlaybook(): any | undefined {
452
+ return this.acePlaybook;
453
+ }
454
+
455
+ /**
456
+ * Apply an ACE playbook to this agent.
457
+ * Stores the playbook for use in next forward() call.
458
+ * Note: Playbook is composed into instruction BEFORE each forward(), mirroring AxACE.compile behavior.
459
+ */
460
+ applyPlaybook(pb: any): void {
461
+ this.acePlaybook = pb;
462
+
463
+ // Also update optimizer's internal playbook if possible
464
+ try {
465
+ (this.aceOptimizer as any).playbook = pb;
466
+ } catch {
467
+ // Ignore - optimizer may not be initialized yet
468
+ }
469
+ }
470
+
471
+ /**
472
+ * Compose instruction with current playbook and set on agent.
473
+ * This mirrors what AxACE does internally before each forward() during compile().
474
+ * Should be called BEFORE forward() to ensure playbook is in the prompt.
475
+ */
476
+ private async composeInstructionWithPlaybook(): Promise<void> {
477
+ const playbook = this.acePlaybook ?? (this.aceOptimizer as any)?.playbook;
478
+
479
+ if (this.debugEnabled) {
480
+ console.log(`[ACE Debug] composeInstructionWithPlaybook called`);
481
+ console.log(`[ACE Debug] playbook exists: ${!!playbook}, sections: ${playbook ? Object.keys(playbook.sections || {}).length : 0}`);
482
+ console.log(`[ACE Debug] baseInstruction: "${this.aceBaseInstruction?.slice(0, 50)}..."`);
483
+ }
484
+
485
+ if (!playbook) return;
486
+
487
+ try {
488
+ const { renderPlaybook } = await import('./ace.js');
489
+ const rendered = renderPlaybook(playbook);
490
+
491
+ if (this.debugEnabled) {
492
+ console.log(`[ACE Debug] rendered playbook (${rendered.length} chars): ${rendered.slice(0, 100)}...`);
493
+ }
494
+
495
+ if (!rendered) return;
496
+
497
+ // Compose: base instruction + playbook (just like AxACE.composeInstruction)
498
+ const baseInstruction = this.aceBaseInstruction || '';
499
+ const combinedInstruction = [baseInstruction.trim(), '', rendered]
500
+ .filter((part) => part.trim().length > 0)
501
+ .join('\n\n');
502
+
503
+ if (this.debugEnabled) {
504
+ console.log(`[ACE Debug] combinedInstruction (${combinedInstruction.length} chars)`);
505
+ }
506
+
507
+ if (combinedInstruction.length >= 20) {
508
+ // Call setDescription on the internal program (like AxACE does)
509
+ // AxAgent.setDescription() only updates the signature, but we need
510
+ // to update the program's description which is used for the system prompt
511
+ const program = (this as any).program;
512
+ if (program?.setDescription) {
513
+ program.setDescription(combinedInstruction);
514
+ }
515
+ // Also update via AxAgent's setDescription for consistency
516
+ this.setDescription(combinedInstruction);
517
+
518
+ if (this.debugEnabled) {
519
+ console.log(`[ACE Debug] setDescription called successfully`);
520
+ console.log(`[ACE Debug] Verifying - signature desc length: ${this.getSignature().getDescription()?.length}`);
521
+ }
522
+ }
523
+ } catch (error) {
524
+ console.warn('[ACE Debug] Failed to compose instruction:', error);
525
+ }
526
+ }
260
527
  }
261
528
 
262
529
  /**
@@ -280,21 +547,34 @@ class StatefulAxAgent extends AxAgent<any, any> {
280
547
  */
281
548
  class AxCrew {
282
549
  private crewConfig: AxCrewConfig;
550
+ private options?: AxCrewOptions;
283
551
  functionsRegistry: FunctionRegistryType = {};
284
552
  crewId: string;
285
553
  agents: Map<string, StatefulAxAgent> | null;
286
554
  state: StateInstance;
555
+ // Execution history for ACE feedback routing
556
+ private executionHistory: Map<string, {
557
+ taskId: string;
558
+ rootAgent: string;
559
+ involvedAgents: Set<string>;
560
+ taskInput: any;
561
+ agentResults: Map<string, any>;
562
+ startTime: number;
563
+ endTime?: number;
564
+ }> = new Map();
287
565
 
288
566
  /**
289
567
  * Creates an instance of AxCrew.
290
568
  * @param {AxCrewConfig} crewConfig - JSON object with crew configuration.
291
569
  * @param {FunctionRegistryType} [functionsRegistry={}] - The registry of functions to use in the crew.
570
+ * @param {AxCrewOptions} [options] - Optional settings for the crew (e.g., telemetry).
292
571
  * @param {string} [crewId=uuidv4()] - The unique identifier for the crew.
293
572
  */
294
573
  constructor(
295
574
  crewConfig: AxCrewConfig,
296
575
  functionsRegistry: FunctionRegistryType = {},
297
- crewId: string = uuidv4()
576
+ options?: AxCrewOptions,
577
+ crewId: string = uuidv4(),
298
578
  ) {
299
579
  // Basic validation of crew configuration
300
580
  if (!crewConfig || typeof crewConfig !== 'object' || !('crew' in crewConfig)) {
@@ -311,6 +591,7 @@ class AxCrew {
311
591
  this.crewConfig = crewConfig;
312
592
  this.functionsRegistry = functionsRegistry;
313
593
  this.crewId = crewId;
594
+ this.options = options;
314
595
  this.agents = new Map<string, StatefulAxAgent>();
315
596
  this.state = createState(crewId);
316
597
  // Make crewId discoverable to metrics
@@ -329,7 +610,8 @@ class AxCrew {
329
610
  agentName,
330
611
  this.crewConfig,
331
612
  this.functionsRegistry,
332
- this.state
613
+ this.state,
614
+ this.options
333
615
  );
334
616
 
335
617
  // Destructure with type assertion
@@ -370,6 +652,8 @@ class AxCrew {
370
652
  }
371
653
 
372
654
  // Create an instance of StatefulAxAgent
655
+ // Set crew reference in state for execution tracking (ACE feedback routing)
656
+ const agentState = { ...this.state, crew: this };
373
657
  const agent = new StatefulAxAgent(
374
658
  ai,
375
659
  {
@@ -380,10 +664,26 @@ class AxCrew {
380
664
  functions: uniqueFunctions,
381
665
  agents: uniqueSubAgents,
382
666
  examples,
667
+ debug: (agentConfig as any).debug,
383
668
  },
384
- this.state
669
+ agentState as StateInstance
385
670
  );
386
671
  (agent as any).costTracker = tracker;
672
+ (agent as any).__functionsRegistry = this.functionsRegistry;
673
+
674
+ // Initialize ACE if configured
675
+ try {
676
+ const crewAgent = parseCrewConfig(this.crewConfig).crew.find(a => a.name === name) as any;
677
+ const ace: ACEConfig | undefined = crewAgent?.ace;
678
+ if (ace) {
679
+ await (agent as any).initACE?.(ace);
680
+ if (ace.compileOnStart) {
681
+ const { resolveMetric } = await import('./ace.js');
682
+ const metric = resolveMetric(ace.metric, this.functionsRegistry);
683
+ await (agent as any).optimizeOffline?.({ metric, examples });
684
+ }
685
+ }
686
+ } catch {}
387
687
 
388
688
  return agent;
389
689
  } catch (error) {
@@ -515,11 +815,119 @@ class AxCrew {
515
815
  }
516
816
  }
517
817
 
818
+ /**
819
+ * Track agent execution for ACE feedback routing
820
+ */
821
+ trackAgentExecution(taskId: string, agentName: string, input: any): void {
822
+ if (!this.executionHistory.has(taskId)) {
823
+ this.executionHistory.set(taskId, {
824
+ taskId,
825
+ rootAgent: agentName,
826
+ involvedAgents: new Set([agentName]),
827
+ taskInput: input,
828
+ agentResults: new Map(),
829
+ startTime: Date.now()
830
+ });
831
+ } else {
832
+ // Add to involved agents if not already present
833
+ const context = this.executionHistory.get(taskId)!;
834
+ context.involvedAgents.add(agentName);
835
+ }
836
+ }
837
+
838
+ /**
839
+ * Record agent result for ACE feedback routing
840
+ */
841
+ recordAgentResult(taskId: string, agentName: string, result: any): void {
842
+ const context = this.executionHistory.get(taskId);
843
+ if (context) {
844
+ context.agentResults.set(agentName, result);
845
+ context.endTime = Date.now();
846
+ }
847
+ }
848
+
849
+ /**
850
+ * Get agent involvement for a task (used for ACE feedback routing)
851
+ */
852
+ getTaskAgentInvolvement(taskId: string): {
853
+ rootAgent: string;
854
+ involvedAgents: string[];
855
+ taskInput: any;
856
+ agentResults: Map<string, any>;
857
+ duration?: number;
858
+ } | null {
859
+ const context = this.executionHistory.get(taskId);
860
+ if (!context) return null;
861
+
862
+ return {
863
+ rootAgent: context.rootAgent,
864
+ involvedAgents: Array.from(context.involvedAgents),
865
+ taskInput: context.taskInput,
866
+ agentResults: context.agentResults,
867
+ duration: context.endTime ? context.endTime - context.startTime : undefined
868
+ };
869
+ }
870
+
871
+ /**
872
+ * Apply feedback to agents involved in a task for ACE online learning
873
+ */
874
+ async applyTaskFeedback(params: {
875
+ taskId: string;
876
+ feedback: string;
877
+ strategy?: 'all' | 'primary' | 'weighted';
878
+ }): Promise<void> {
879
+ const involvement = this.getTaskAgentInvolvement(params.taskId);
880
+ if (!involvement) {
881
+ console.warn(`No execution history found for task ${params.taskId}`);
882
+ return;
883
+ }
884
+
885
+ const { involvedAgents, taskInput, agentResults } = involvement;
886
+ const strategy = params.strategy || 'all';
887
+
888
+ // Determine which agents to update based on strategy
889
+ let agentsToUpdate: string[] = [];
890
+ if (strategy === 'primary') {
891
+ agentsToUpdate = [involvement.rootAgent];
892
+ } else if (strategy === 'all' || strategy === 'weighted') {
893
+ agentsToUpdate = involvedAgents;
894
+ }
895
+
896
+ // Apply feedback to each involved agent
897
+ for (const agentName of agentsToUpdate) {
898
+ const agent = this.agents?.get(agentName);
899
+ if (agent && typeof (agent as any).applyOnlineUpdate === 'function') {
900
+ try {
901
+ await (agent as any).applyOnlineUpdate({
902
+ example: taskInput,
903
+ prediction: agentResults.get(agentName),
904
+ feedback: params.feedback
905
+ });
906
+ } catch (error) {
907
+ console.warn(`Failed to apply ACE feedback to agent ${agentName}:`, error);
908
+ }
909
+ }
910
+ }
911
+ }
912
+
913
+ /**
914
+ * Clean up old execution history (call periodically to prevent memory leaks)
915
+ */
916
+ cleanupOldExecutions(maxAgeMs: number = 3600000): void { // Default 1 hour
917
+ const cutoffTime = Date.now() - maxAgeMs;
918
+ for (const [taskId, context] of this.executionHistory) {
919
+ if (context.startTime < cutoffTime) {
920
+ this.executionHistory.delete(taskId);
921
+ }
922
+ }
923
+ }
924
+
518
925
  /**
519
926
  * Cleans up the crew by dereferencing agents and resetting the state.
520
927
  */
521
928
  destroy() {
522
929
  this.agents = null;
930
+ this.executionHistory.clear();
523
931
  this.state.reset();
524
932
  }
525
933
 
@@ -559,4 +967,4 @@ class AxCrew {
559
967
  }
560
968
 
561
969
  export { AxCrew };
562
- export type { StatefulAxAgent };
970
+ export type { StatefulAxAgent };
package/src/index.ts CHANGED
@@ -1,13 +1,18 @@
1
1
  import { AxCrew } from './agents/index.js';
2
2
  import { AxCrewFunctions } from './functions/index.js';
3
- import type { AxCrewConfig, AgentConfig } from './types.js';
3
+ import type { AxCrewConfig, AxCrewOptions, AgentConfig } from './types.js';
4
4
 
5
5
  import type {
6
6
  UsageCost,
7
7
  AggregatedMetrics,
8
8
  AggregatedCosts,
9
9
  StateInstance,
10
- FunctionRegistryType
10
+ FunctionRegistryType,
11
+ ACEConfig,
12
+ ACETeacherConfig,
13
+ ACEPersistenceConfig,
14
+ ACEOptionsConfig,
15
+ ACEMetricConfig,
11
16
  } from './types.js';
12
17
  /**
13
18
  * Metrics types and helpers for request counts, token usage, and estimated cost.
@@ -46,6 +51,13 @@ export {
46
51
  type AggregatedCosts,
47
52
  type AgentConfig,
48
53
  type AxCrewConfig,
54
+ type AxCrewOptions,
49
55
  type StateInstance,
50
56
  type UsageCost,
57
+ // ACE type exports
58
+ type ACEConfig,
59
+ type ACETeacherConfig,
60
+ type ACEPersistenceConfig,
61
+ type ACEOptionsConfig,
62
+ type ACEMetricConfig,
51
63
  };
package/src/types.ts CHANGED
@@ -147,6 +147,47 @@ interface MCPStreamableHTTPTransportConfig {
147
147
  */
148
148
  type MCPTransportConfig = MCPStdioTransportConfig | MCPHTTPSSETransportConfig | MCPStreamableHTTPTransportConfig
149
149
 
150
+ // ========================
151
+ // ACE integration types
152
+ // ========================
153
+
154
+ interface ACETeacherConfig {
155
+ provider?: Provider;
156
+ providerKeyName?: string;
157
+ apiURL?: string;
158
+ ai?: AxModelConfig & { model: string };
159
+ providerArgs?: Record<string, unknown>;
160
+ }
161
+
162
+ interface ACEPersistenceConfig {
163
+ playbookPath?: string;
164
+ initialPlaybook?: Record<string, any>;
165
+ autoPersist?: boolean;
166
+ onPersist?: (pb: any) => Promise<void> | void;
167
+ onLoad?: () => Promise<any> | any;
168
+ }
169
+
170
+ interface ACEOptionsConfig {
171
+ maxEpochs?: number;
172
+ allowDynamicSections?: boolean;
173
+ tokenBudget?: number;
174
+ reflectorPrompt?: string;
175
+ curatorPrompt?: string;
176
+ }
177
+
178
+ interface ACEMetricConfig {
179
+ metricFnName?: string;
180
+ primaryOutputField?: string;
181
+ }
182
+
183
+ interface ACEConfig {
184
+ teacher?: ACETeacherConfig;
185
+ persistence?: ACEPersistenceConfig;
186
+ options?: ACEOptionsConfig;
187
+ metric?: ACEMetricConfig;
188
+ compileOnStart?: boolean;
189
+ }
190
+
150
191
  /**
151
192
  * The configuration for an agent.
152
193
  *
@@ -193,6 +234,8 @@ interface AgentConfig {
193
234
  agents?: string[];
194
235
  examples?: Array<Record<string, any>>;
195
236
  mcpServers?: Record<string, MCPTransportConfig>;
237
+ /** Optional AxACE configuration to enable optimization for this agent */
238
+ ace?: ACEConfig;
196
239
  }
197
240
 
198
241
  /**
@@ -236,9 +279,26 @@ interface AxCrewConfig {
236
279
  crew: AgentConfig[]
237
280
  }
238
281
 
282
+ /**
283
+ * Options for the AxCrew instance, specifically allowing optional OpenTelemetry injection.
284
+ *
285
+ * @property {Object} [telemetry] - Telemetry configuration.
286
+ * @property {any} [telemetry.tracer] - OpenTelemetry Tracer instance.
287
+ * @property {any} [telemetry.meter] - OpenTelemetry Meter instance.
288
+ */
289
+ interface AxCrewOptions {
290
+ /** Enable debug logging for ACE and other internal operations */
291
+ debug?: boolean;
292
+ telemetry?: {
293
+ tracer?: any;
294
+ meter?: any;
295
+ }
296
+ }
297
+
239
298
  export {
240
299
  type AgentConfig,
241
300
  type AxCrewConfig,
301
+ type AxCrewOptions,
242
302
  type AggregatedMetrics,
243
303
  type StateInstance,
244
304
  type FunctionRegistryType,
@@ -249,5 +309,11 @@ export {
249
309
  type ModelUsage,
250
310
  type ModelInfo,
251
311
  type UsageCost,
252
- type AggregatedCosts
312
+ type AggregatedCosts,
313
+ // ACE exports
314
+ type ACEConfig,
315
+ type ACEMetricConfig,
316
+ type ACEOptionsConfig,
317
+ type ACEPersistenceConfig,
318
+ type ACETeacherConfig
253
319
  }