@amitdeshmukh/ax-crew 4.1.2 → 5.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.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,24 @@
1
+ # Changelog
2
+
3
+ ## [5.0.0] - 2025-10-16
4
+
5
+ ### Added
6
+ - Provider-specific arguments via `providerArgs` in `AgentConfig` to pass through typed provider params to the underlying Ax factory.
7
+ - Typed forwarding for common providers in `parseAgentConfig`:
8
+ - azure-openai: `resourceName`, `deploymentName`, `version` (falls back to `apiURL` as `resourceName` if provided)
9
+ - anthropic: `projectId`, `region` (on Vertex AI)
10
+ - google-gemini: `projectId`, `region`, `endpointId`
11
+ - openrouter: `referer`, `title`
12
+ - ollama: `url`
13
+ - Example `examples/providerArgs.ts` demonstrating `providerArgs` with Azure OpenAI.
14
+ - JSDoc function hints for cost/usage APIs (`getMetrics`, `resetMetrics`, `resetCosts`, `getCrewMetrics`, `resetCrewMetrics`, and metrics registry helpers).
15
+
16
+ ### Docs
17
+ - README section documenting `providerArgs` usage, supported providers, and Azure configuration examples.
18
+
19
+ ### Notes
20
+ - Existing configs continue to work. For Azure, you can still set `apiURL`; when `resourceName` is omitted, the code uses `apiURL` as the `resourceName` (full endpoint) for convenience.
21
+
1
22
  # Changelog
2
23
  ## [4.1.2] - 2025-10-14
3
24
 
package/README.md CHANGED
@@ -35,12 +35,17 @@ AZURE_OPENAI_API_KEY=...
35
35
  ```
36
36
  In each agent config, set `providerKeyName` to the env var name.
37
37
 
38
- #### Azure OpenAI
39
- - Use provider `azure-openai`.
40
- - Set `providerKeyName` to `AZURE_OPENAI_API_KEY`.
41
- - Set `apiURL` to your Azure endpoint (e.g., `https://your-resource.openai.azure.com`).
38
+ #### Provider-specific arguments (`providerArgs`)
39
+ Some providers require extra top-level configuration beyond `ai.model` (e.g., Azure deployments or Gemini project/region). You can pass these via `providerArgs`; AxCrew forwards them to the underlying Ax factory with type alignment for popular providers.
42
40
 
43
- Minimal example agent config:
41
+ Supported mappings:
42
+ - `azure-openai`: `resourceName`, `deploymentName`, `version` (if `resourceName` omitted and `apiURL` set, `apiURL` is used as full endpoint)
43
+ - `anthropic`: `projectId`, `region`
44
+ - `google-gemini`: `projectId`, `region`, `endpointId`
45
+ - `openrouter`: `referer`, `title`
46
+ - `ollama`: `url`
47
+
48
+ Azure example with `providerArgs`:
44
49
  ```json
45
50
  {
46
51
  "name": "Writer",
@@ -49,7 +54,11 @@ Minimal example agent config:
49
54
  "provider": "azure-openai",
50
55
  "providerKeyName": "AZURE_OPENAI_API_KEY",
51
56
  "ai": { "model": "gpt-4o-mini", "temperature": 0 },
52
- "apiURL": "https://your-resource.openai.azure.com"
57
+ "apiURL": "https://your-resource.openai.azure.com", "providerArgs": {
58
+ "resourceName": "your-resource",
59
+ "deploymentName": "gpt-4o-mini",
60
+ "version": "api-version=2024-02-15-preview"
61
+ }
53
62
  }
54
63
  ```
55
64
 
@@ -214,6 +214,36 @@ const parseAgentConfig = async (agentName, crewConfig, functions, state) => {
214
214
  throw new Error(`Invalid apiURL provided: ${agentConfigData.apiURL}`);
215
215
  }
216
216
  }
217
+ // Forward provider-specific arguments with type-safety for Azure OpenAI
218
+ const providerArgs = agentConfigData.providerArgs;
219
+ if (provider === 'azure-openai') {
220
+ const az = providerArgs ?? {};
221
+ // If users supplied apiURL instead of resourceName, accept it (Ax supports full URL as resourceName)
222
+ if (!az.resourceName && agentConfigData.apiURL) {
223
+ az.resourceName = agentConfigData.apiURL;
224
+ }
225
+ Object.assign(aiArgs, az);
226
+ }
227
+ else if (provider === 'anthropic') {
228
+ const an = providerArgs ?? {};
229
+ Object.assign(aiArgs, an);
230
+ }
231
+ else if (provider === 'google-gemini') {
232
+ const g = providerArgs ?? {};
233
+ Object.assign(aiArgs, g);
234
+ }
235
+ else if (provider === 'openrouter') {
236
+ const o = providerArgs ?? {};
237
+ Object.assign(aiArgs, o);
238
+ }
239
+ else if (provider === 'ollama') {
240
+ const ol = providerArgs ?? {};
241
+ Object.assign(aiArgs, ol);
242
+ }
243
+ else if (providerArgs && typeof providerArgs === 'object') {
244
+ // Generic pass-through for other providers if needed in the future
245
+ Object.assign(aiArgs, providerArgs);
246
+ }
217
247
  const aiInstance = ai(aiArgs);
218
248
  // If an mcpServers config is provided in the agent config, convert to functions
219
249
  const mcpFunctions = await initializeMCPServers(agentConfigData);
@@ -5,8 +5,22 @@ import type { StateInstance, ModelUsage, ModelInfo, UsageCost, AggregatedCosts }
5
5
  */
6
6
  export declare class StateFulAxAgentUsage {
7
7
  static STATE_KEY_PREFIX: string;
8
+ /**
9
+ * Compute usage costs given a model usage record and model pricing info.
10
+ * Returns null if inputs are invalid. Token-based costs are computed with high precision.
11
+ */
8
12
  static calculateCost(modelUsage: ModelUsage, modelInfo: ModelInfo): UsageCost | null;
13
+ /**
14
+ * Persist or aggregate the cost for an agent in the shared crew state.
15
+ * No-op if cost is null.
16
+ */
9
17
  static trackCostInState(agentName: string, cost: UsageCost | null, state: StateInstance): void;
18
+ /**
19
+ * Aggregate and return total costs across all agents from the shared crew state.
20
+ */
10
21
  static getAggregatedCosts(state: StateInstance): AggregatedCosts;
22
+ /**
23
+ * Remove all stored per-agent costs from the shared crew state.
24
+ */
11
25
  static resetCosts(state: StateInstance): void;
12
26
  }
@@ -5,6 +5,10 @@ import { Decimal } from 'decimal.js';
5
5
  */
6
6
  export class StateFulAxAgentUsage {
7
7
  static STATE_KEY_PREFIX = 'agent_usage_';
8
+ /**
9
+ * Compute usage costs given a model usage record and model pricing info.
10
+ * Returns null if inputs are invalid. Token-based costs are computed with high precision.
11
+ */
8
12
  static calculateCost(modelUsage, modelInfo) {
9
13
  // Handle both direct properties and nested tokens structure
10
14
  const promptTokens = modelUsage.tokens?.promptTokens ?? modelUsage.promptTokens;
@@ -44,6 +48,10 @@ export class StateFulAxAgentUsage {
44
48
  return null;
45
49
  }
46
50
  }
51
+ /**
52
+ * Persist or aggregate the cost for an agent in the shared crew state.
53
+ * No-op if cost is null.
54
+ */
47
55
  static trackCostInState(agentName, cost, state) {
48
56
  // If cost is null, skip tracking
49
57
  if (!cost)
@@ -75,6 +83,9 @@ export class StateFulAxAgentUsage {
75
83
  state.set(stateKey, cost);
76
84
  }
77
85
  }
86
+ /**
87
+ * Aggregate and return total costs across all agents from the shared crew state.
88
+ */
78
89
  static getAggregatedCosts(state) {
79
90
  const allState = state.getAll();
80
91
  const agentCosts = {};
@@ -108,6 +119,9 @@ export class StateFulAxAgentUsage {
108
119
  }
109
120
  };
110
121
  }
122
+ /**
123
+ * Remove all stored per-agent costs from the shared crew state.
124
+ */
111
125
  static resetCosts(state) {
112
126
  const allState = state.getAll();
113
127
  Object.keys(allState).forEach(key => {
@@ -25,7 +25,17 @@ declare class StatefulAxAgent extends AxAgent<any, any> {
25
25
  streamingForward(ai: AxAI, values: Record<string, any>, options?: Readonly<AxProgramStreamingForwardOptions<any>>): AxGenStreamingOut<any>;
26
26
  getLastUsageCost(): UsageCost | null;
27
27
  getAccumulatedCosts(): UsageCost | null;
28
+ /**
29
+ * Get the current metrics snapshot for this agent.
30
+ * Includes request counts, error rates, token usage, estimated USD cost, and function call stats.
31
+ *
32
+ * @returns A metrics snapshot scoped to this agent within its crew.
33
+ */
28
34
  getMetrics(): import("../metrics/types.js").MetricsSnapshot;
35
+ /**
36
+ * Reset all tracked metrics for this agent (does not affect other agents).
37
+ * Call this to start fresh measurement windows for the agent.
38
+ */
29
39
  resetMetrics(): void;
30
40
  }
31
41
  /**
@@ -70,10 +80,21 @@ declare class AxCrew {
70
80
  */
71
81
  destroy(): void;
72
82
  /**
73
- * Resets all cost tracking for the crew
83
+ * Resets all cost and usage tracking for the entire crew.
84
+ * Also calls each agent's `resetUsage` (if available) and clears crew-level metrics.
74
85
  */
75
86
  resetCosts(): void;
87
+ /**
88
+ * Get an aggregate metrics snapshot for the entire crew.
89
+ * Sums requests, errors, tokens, and estimated cost across all agents in the crew.
90
+ *
91
+ * @returns Crew-level metrics snapshot.
92
+ */
76
93
  getCrewMetrics(): import("../metrics/types.js").MetricsSnapshot;
94
+ /**
95
+ * Reset all tracked metrics for the entire crew.
96
+ * Use to clear totals before a new measurement period.
97
+ */
77
98
  resetCrewMetrics(): void;
78
99
  }
79
100
  export { AxCrew };
@@ -156,10 +156,20 @@ class StatefulAxAgent extends AxAgent {
156
156
  // Get the accumulated costs for all runs of this agent
157
157
  getAccumulatedCosts() { return null; }
158
158
  // Metrics API for this agent
159
+ /**
160
+ * Get the current metrics snapshot for this agent.
161
+ * Includes request counts, error rates, token usage, estimated USD cost, and function call stats.
162
+ *
163
+ * @returns A metrics snapshot scoped to this agent within its crew.
164
+ */
159
165
  getMetrics() {
160
166
  const crewId = this.state?.crewId || (this.state.get?.('crewId')) || 'default';
161
167
  return MetricsRegistry.snapshot({ crewId, agent: this.agentName });
162
168
  }
169
+ /**
170
+ * Reset all tracked metrics for this agent (does not affect other agents).
171
+ * Call this to start fresh measurement windows for the agent.
172
+ */
163
173
  resetMetrics() {
164
174
  const crewId = this.state?.crewId || (this.state.get?.('crewId')) || 'default';
165
175
  MetricsRegistry.reset({ crewId, agent: this.agentName });
@@ -376,7 +386,8 @@ class AxCrew {
376
386
  this.state.reset();
377
387
  }
378
388
  /**
379
- * Resets all cost tracking for the crew
389
+ * Resets all cost and usage tracking for the entire crew.
390
+ * Also calls each agent's `resetUsage` (if available) and clears crew-level metrics.
380
391
  */
381
392
  resetCosts() {
382
393
  // Reset AxAgent built-in usage and our metrics registry
@@ -395,9 +406,19 @@ class AxCrew {
395
406
  MetricsRegistry.reset({ crewId: this.crewId });
396
407
  }
397
408
  // Metrics API
409
+ /**
410
+ * Get an aggregate metrics snapshot for the entire crew.
411
+ * Sums requests, errors, tokens, and estimated cost across all agents in the crew.
412
+ *
413
+ * @returns Crew-level metrics snapshot.
414
+ */
398
415
  getCrewMetrics() {
399
416
  return MetricsRegistry.snapshotCrew(this.crewId);
400
417
  }
418
+ /**
419
+ * Reset all tracked metrics for the entire crew.
420
+ * Use to clear totals before a new measurement period.
421
+ */
401
422
  resetCrewMetrics() {
402
423
  MetricsRegistry.reset({ crewId: this.crewId });
403
424
  }
@@ -1,9 +1,36 @@
1
1
  import type { LabelKeys, MetricsSnapshot, TokenUsage } from './types.js';
2
+ /**
3
+ * Record a completed request.
4
+ * @param labels Crew/agent/provider/model identifiers
5
+ * @param streaming Whether this was a streaming request
6
+ * @param durationMs Duration in milliseconds
7
+ */
2
8
  export declare function recordRequest(labels: LabelKeys, streaming: boolean, durationMs: number): void;
9
+ /**
10
+ * Record an error occurrence for the given labels.
11
+ */
3
12
  export declare function recordError(labels: LabelKeys): void;
13
+ /**
14
+ * Record token usage for a request (prompt and completion).
15
+ */
4
16
  export declare function recordTokens(labels: LabelKeys, usage: TokenUsage): void;
17
+ /**
18
+ * Add estimated cost (USD) to the cumulative total for the labels.
19
+ */
5
20
  export declare function recordEstimatedCost(labels: LabelKeys, usd: number): void;
21
+ /**
22
+ * Record a function call invocation and add its latency to totals.
23
+ */
6
24
  export declare function recordFunctionCall(labels: LabelKeys, latencyMs: number): void;
25
+ /**
26
+ * Get a metrics snapshot for specific labels (crew + agent + optional provider/model).
27
+ */
7
28
  export declare function snapshot(labels: LabelKeys): MetricsSnapshot;
29
+ /**
30
+ * Reset metrics for specific labels, or clear all if no labels provided.
31
+ */
8
32
  export declare function reset(labels?: LabelKeys): void;
33
+ /**
34
+ * Aggregate a crew-wide metrics snapshot across all agents in the crew.
35
+ */
9
36
  export declare function snapshotCrew(crewId: string): MetricsSnapshot;
@@ -24,6 +24,12 @@ function getOrInit(labels) {
24
24
  }
25
25
  return c;
26
26
  }
27
+ /**
28
+ * Record a completed request.
29
+ * @param labels Crew/agent/provider/model identifiers
30
+ * @param streaming Whether this was a streaming request
31
+ * @param durationMs Duration in milliseconds
32
+ */
27
33
  export function recordRequest(labels, streaming, durationMs) {
28
34
  const c = getOrInit(labels);
29
35
  c.requests += 1;
@@ -32,26 +38,41 @@ export function recordRequest(labels, streaming, durationMs) {
32
38
  c.durationMsSum += durationMs;
33
39
  c.durationCount += 1;
34
40
  }
41
+ /**
42
+ * Record an error occurrence for the given labels.
43
+ */
35
44
  export function recordError(labels) {
36
45
  const c = getOrInit(labels);
37
46
  c.errors += 1;
38
47
  }
48
+ /**
49
+ * Record token usage for a request (prompt and completion).
50
+ */
39
51
  export function recordTokens(labels, usage) {
40
52
  const c = getOrInit(labels);
41
53
  c.inputTokens += usage.promptTokens || 0;
42
54
  c.outputTokens += usage.completionTokens || 0;
43
55
  }
56
+ /**
57
+ * Add estimated cost (USD) to the cumulative total for the labels.
58
+ */
44
59
  export function recordEstimatedCost(labels, usd) {
45
60
  const c = getOrInit(labels);
46
61
  const current = new Big(c.estimatedCostUSD || 0);
47
62
  const addition = new Big(usd || 0);
48
63
  c.estimatedCostUSD = Number(current.plus(addition));
49
64
  }
65
+ /**
66
+ * Record a function call invocation and add its latency to totals.
67
+ */
50
68
  export function recordFunctionCall(labels, latencyMs) {
51
69
  const c = getOrInit(labels);
52
70
  c.functionCalls += 1;
53
71
  c.functionLatencyMs += latencyMs || 0;
54
72
  }
73
+ /**
74
+ * Get a metrics snapshot for specific labels (crew + agent + optional provider/model).
75
+ */
55
76
  export function snapshot(labels) {
56
77
  const c = getOrInit(labels);
57
78
  const totalTokens = c.inputTokens + c.outputTokens;
@@ -78,6 +99,9 @@ export function snapshot(labels) {
78
99
  },
79
100
  };
80
101
  }
102
+ /**
103
+ * Reset metrics for specific labels, or clear all if no labels provided.
104
+ */
81
105
  export function reset(labels) {
82
106
  if (!labels) {
83
107
  store.clear();
@@ -86,6 +110,9 @@ export function reset(labels) {
86
110
  const k = keyOf(labels);
87
111
  store.delete(k);
88
112
  }
113
+ /**
114
+ * Aggregate a crew-wide metrics snapshot across all agents in the crew.
115
+ */
89
116
  export function snapshotCrew(crewId) {
90
117
  const empty = {
91
118
  requests: 0,
package/dist/types.d.ts CHANGED
@@ -165,6 +165,11 @@ interface AgentConfig {
165
165
  };
166
166
  debug?: boolean;
167
167
  apiURL?: string;
168
+ /**
169
+ * Provider-specific arguments that are forwarded to the underlying Ax factory.
170
+ * Example (azure-openai): { resourceName, deploymentName, version }
171
+ */
172
+ providerArgs?: Record<string, unknown>;
168
173
  options?: Partial<AxProgramForwardOptions<any>> & Record<string, any>;
169
174
  functions?: string[];
170
175
  agents?: string[];
@@ -0,0 +1,41 @@
1
+ import { AxCrew, AxCrewConfig } from "../dist/index.js";
2
+
3
+ const crewConfig: AxCrewConfig = {
4
+ crew: [
5
+ {
6
+ name: "TestAgent",
7
+ description: "Test Agent for testing provider arguments",
8
+ provider: "azure-openai",
9
+ providerKeyName: "AZURE_OPENAI_API_KEY",
10
+ signature: "userQuery:string -> answer:string",
11
+ ai: {
12
+ model: "gpt-5-mini",
13
+ temperature: 0,
14
+ stream: false
15
+ },
16
+ providerArgs: {
17
+ resourceName: "your-resource-name",
18
+ deploymentName: "your-deployment-name",
19
+ version: "2025-01-01-preview"
20
+ },
21
+ functions: [],
22
+ options: {
23
+ debug: true,
24
+ stream: false
25
+ }
26
+ }
27
+ ]
28
+ };
29
+
30
+ const crew = new AxCrew(crewConfig);
31
+ await crew.addAllAgents();
32
+
33
+ const testAgent = crew.agents?.get("TestAgent");
34
+
35
+ const response = await testAgent?.forward({
36
+ userQuery: "What is the capital of France?"
37
+ });
38
+
39
+ console.log(response?.answer);
40
+
41
+ console.log(testAgent?.getAccumulatedCosts());
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@amitdeshmukh/ax-crew",
4
- "version": "4.1.2",
4
+ "version": "5.0.0",
5
5
  "description": "Build and launch a crew of AI agents with shared state. Built with axllm.dev",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -1,6 +1,13 @@
1
1
  import fs from 'fs';
2
2
  // Import Ax factory and MCP transports (as exported by current package)
3
3
  import { ai, AxMCPClient, AxMCPHTTPSSETransport, AxMCPStreambleHTTPTransport, AxDefaultCostTracker } from '@ax-llm/ax'
4
+ import type {
5
+ AxAIAzureOpenAIArgs,
6
+ AxAIAnthropicArgs,
7
+ AxAIGoogleGeminiArgs,
8
+ AxAIOpenRouterArgs,
9
+ AxAIOllamaArgs
10
+ } from '@ax-llm/ax';
4
11
  import type { AxFunction } from '@ax-llm/ax';
5
12
  // STDIO transport from tools package
6
13
  import { AxMCPStdioTransport } from '@ax-llm/ax-tools'
@@ -246,6 +253,36 @@ const parseAgentConfig = async (
246
253
  throw new Error(`Invalid apiURL provided: ${agentConfigData.apiURL}`);
247
254
  }
248
255
  }
256
+ // Forward provider-specific arguments with type-safety for Azure OpenAI
257
+ const providerArgs = (agentConfigData as any).providerArgs;
258
+ if (provider === 'azure-openai') {
259
+ type AzureArgs = Pick<AxAIAzureOpenAIArgs<string>, 'resourceName' | 'deploymentName' | 'version'>;
260
+ const az: Partial<AzureArgs> = providerArgs ?? {};
261
+ // If users supplied apiURL instead of resourceName, accept it (Ax supports full URL as resourceName)
262
+ if (!az.resourceName && agentConfigData.apiURL) {
263
+ az.resourceName = agentConfigData.apiURL as any;
264
+ }
265
+ Object.assign(aiArgs, az);
266
+ } else if (provider === 'anthropic') {
267
+ type AnthropicArgs = Pick<AxAIAnthropicArgs<string>, 'projectId' | 'region'>;
268
+ const an: Partial<AnthropicArgs> = providerArgs ?? {};
269
+ Object.assign(aiArgs, an);
270
+ } else if (provider === 'google-gemini') {
271
+ type GeminiArgs = Pick<AxAIGoogleGeminiArgs<string>, 'projectId' | 'region' | 'endpointId'>;
272
+ const g: Partial<GeminiArgs> = providerArgs ?? {};
273
+ Object.assign(aiArgs, g);
274
+ } else if (provider === 'openrouter') {
275
+ type OpenRouterArgs = Pick<AxAIOpenRouterArgs<string>, 'referer' | 'title'>;
276
+ const o: Partial<OpenRouterArgs> = providerArgs ?? {};
277
+ Object.assign(aiArgs, o);
278
+ } else if (provider === 'ollama') {
279
+ type OllamaArgs = Pick<AxAIOllamaArgs<string>, 'url'>;
280
+ const ol: Partial<OllamaArgs> = providerArgs ?? {};
281
+ Object.assign(aiArgs, ol);
282
+ } else if (providerArgs && typeof providerArgs === 'object') {
283
+ // Generic pass-through for other providers if needed in the future
284
+ Object.assign(aiArgs, providerArgs);
285
+ }
249
286
  const aiInstance = ai(aiArgs);
250
287
 
251
288
  // If an mcpServers config is provided in the agent config, convert to functions
@@ -15,6 +15,10 @@ import type {
15
15
  export class StateFulAxAgentUsage {
16
16
  static STATE_KEY_PREFIX = 'agent_usage_';
17
17
 
18
+ /**
19
+ * Compute usage costs given a model usage record and model pricing info.
20
+ * Returns null if inputs are invalid. Token-based costs are computed with high precision.
21
+ */
18
22
  static calculateCost(modelUsage: ModelUsage, modelInfo: ModelInfo): UsageCost | null {
19
23
  // Handle both direct properties and nested tokens structure
20
24
  const promptTokens = (modelUsage as any).tokens?.promptTokens ?? modelUsage.promptTokens;
@@ -59,6 +63,10 @@ export class StateFulAxAgentUsage {
59
63
  }
60
64
  }
61
65
 
66
+ /**
67
+ * Persist or aggregate the cost for an agent in the shared crew state.
68
+ * No-op if cost is null.
69
+ */
62
70
  static trackCostInState(agentName: string, cost: UsageCost | null, state: StateInstance) {
63
71
  // If cost is null, skip tracking
64
72
  if (!cost) return;
@@ -90,6 +98,9 @@ export class StateFulAxAgentUsage {
90
98
  }
91
99
  }
92
100
 
101
+ /**
102
+ * Aggregate and return total costs across all agents from the shared crew state.
103
+ */
93
104
  static getAggregatedCosts(state: StateInstance): AggregatedCosts {
94
105
  const allState = state.getAll();
95
106
  const agentCosts: Record<string, UsageCost> = {};
@@ -128,6 +139,9 @@ export class StateFulAxAgentUsage {
128
139
  };
129
140
  }
130
141
 
142
+ /**
143
+ * Remove all stored per-agent costs from the shared crew state.
144
+ */
131
145
  static resetCosts(state: StateInstance) {
132
146
  const allState = state.getAll();
133
147
  Object.keys(allState).forEach(key => {
@@ -238,10 +238,20 @@ class StatefulAxAgent extends AxAgent<any, any> {
238
238
  getAccumulatedCosts(): UsageCost | null { return null; }
239
239
 
240
240
  // Metrics API for this agent
241
+ /**
242
+ * Get the current metrics snapshot for this agent.
243
+ * Includes request counts, error rates, token usage, estimated USD cost, and function call stats.
244
+ *
245
+ * @returns A metrics snapshot scoped to this agent within its crew.
246
+ */
241
247
  getMetrics() {
242
248
  const crewId = (this.state as any)?.crewId || (this.state.get?.('crewId')) || 'default';
243
249
  return MetricsRegistry.snapshot({ crewId, agent: this.agentName } as any);
244
250
  }
251
+ /**
252
+ * Reset all tracked metrics for this agent (does not affect other agents).
253
+ * Call this to start fresh measurement windows for the agent.
254
+ */
245
255
  resetMetrics(): void {
246
256
  const crewId = (this.state as any)?.crewId || (this.state.get?.('crewId')) || 'default';
247
257
  MetricsRegistry.reset({ crewId, agent: this.agentName } as any);
@@ -499,7 +509,8 @@ class AxCrew {
499
509
 
500
510
 
501
511
  /**
502
- * Resets all cost tracking for the crew
512
+ * Resets all cost and usage tracking for the entire crew.
513
+ * Also calls each agent's `resetUsage` (if available) and clears crew-level metrics.
503
514
  */
504
515
  resetCosts(): void {
505
516
  // Reset AxAgent built-in usage and our metrics registry
@@ -513,9 +524,19 @@ class AxCrew {
513
524
  }
514
525
 
515
526
  // Metrics API
527
+ /**
528
+ * Get an aggregate metrics snapshot for the entire crew.
529
+ * Sums requests, errors, tokens, and estimated cost across all agents in the crew.
530
+ *
531
+ * @returns Crew-level metrics snapshot.
532
+ */
516
533
  getCrewMetrics() {
517
534
  return MetricsRegistry.snapshotCrew(this.crewId);
518
535
  }
536
+ /**
537
+ * Reset all tracked metrics for the entire crew.
538
+ * Use to clear totals before a new measurement period.
539
+ */
519
540
  resetCrewMetrics(): void {
520
541
  MetricsRegistry.reset({ crewId: this.crewId });
521
542
  }
@@ -44,6 +44,12 @@ function getOrInit(labels: LabelKeys): Counters {
44
44
  return c;
45
45
  }
46
46
 
47
+ /**
48
+ * Record a completed request.
49
+ * @param labels Crew/agent/provider/model identifiers
50
+ * @param streaming Whether this was a streaming request
51
+ * @param durationMs Duration in milliseconds
52
+ */
47
53
  export function recordRequest(labels: LabelKeys, streaming: boolean, durationMs: number) {
48
54
  const c = getOrInit(labels);
49
55
  c.requests += 1;
@@ -52,17 +58,26 @@ export function recordRequest(labels: LabelKeys, streaming: boolean, durationMs:
52
58
  c.durationCount += 1;
53
59
  }
54
60
 
61
+ /**
62
+ * Record an error occurrence for the given labels.
63
+ */
55
64
  export function recordError(labels: LabelKeys) {
56
65
  const c = getOrInit(labels);
57
66
  c.errors += 1;
58
67
  }
59
68
 
69
+ /**
70
+ * Record token usage for a request (prompt and completion).
71
+ */
60
72
  export function recordTokens(labels: LabelKeys, usage: TokenUsage) {
61
73
  const c = getOrInit(labels);
62
74
  c.inputTokens += usage.promptTokens || 0;
63
75
  c.outputTokens += usage.completionTokens || 0;
64
76
  }
65
77
 
78
+ /**
79
+ * Add estimated cost (USD) to the cumulative total for the labels.
80
+ */
66
81
  export function recordEstimatedCost(labels: LabelKeys, usd: number) {
67
82
  const c = getOrInit(labels);
68
83
  const current = new Big(c.estimatedCostUSD || 0);
@@ -70,12 +85,18 @@ export function recordEstimatedCost(labels: LabelKeys, usd: number) {
70
85
  c.estimatedCostUSD = Number(current.plus(addition));
71
86
  }
72
87
 
88
+ /**
89
+ * Record a function call invocation and add its latency to totals.
90
+ */
73
91
  export function recordFunctionCall(labels: LabelKeys, latencyMs: number) {
74
92
  const c = getOrInit(labels);
75
93
  c.functionCalls += 1;
76
94
  c.functionLatencyMs += latencyMs || 0;
77
95
  }
78
96
 
97
+ /**
98
+ * Get a metrics snapshot for specific labels (crew + agent + optional provider/model).
99
+ */
79
100
  export function snapshot(labels: LabelKeys): MetricsSnapshot {
80
101
  const c = getOrInit(labels);
81
102
  const totalTokens = c.inputTokens + c.outputTokens;
@@ -103,6 +124,9 @@ export function snapshot(labels: LabelKeys): MetricsSnapshot {
103
124
  };
104
125
  }
105
126
 
127
+ /**
128
+ * Reset metrics for specific labels, or clear all if no labels provided.
129
+ */
106
130
  export function reset(labels?: LabelKeys) {
107
131
  if (!labels) {
108
132
  store.clear();
@@ -112,6 +136,9 @@ export function reset(labels?: LabelKeys) {
112
136
  store.delete(k);
113
137
  }
114
138
 
139
+ /**
140
+ * Aggregate a crew-wide metrics snapshot across all agents in the crew.
141
+ */
115
142
  export function snapshotCrew(crewId: string): MetricsSnapshot {
116
143
  const empty: Counters = {
117
144
  requests: 0,
package/src/types.ts CHANGED
@@ -196,6 +196,11 @@ interface AgentConfig {
196
196
  ai: AxModelConfig & { model: string };
197
197
  debug?: boolean;
198
198
  apiURL?: string;
199
+ /**
200
+ * Provider-specific arguments that are forwarded to the underlying Ax factory.
201
+ * Example (azure-openai): { resourceName, deploymentName, version }
202
+ */
203
+ providerArgs?: Record<string, unknown>;
199
204
  options?: Partial<AxProgramForwardOptions<any>> & Record<string, any>;
200
205
  functions?: string[];
201
206
  agents?: string[];