mastra-ai/mastra · error

Could not extract settings from ToolLoopAgent. The agent may

Error message

Could not extract settings from ToolLoopAgent. The agent may be from an incompatible version.

What it means

getSettings reads the private settings field off a ToolLoopAgent instance at runtime (TypeScript privacy does not hide it at runtime). If the field is missing or falsy, the object passed in is not a ToolLoopAgent this code can work with — likely constructed by a different (incompatible) version of the library, a plain lookalike object, or an Agent of a different class — so the utility throws instead of failing later with confusing undefined-property errors.

Source

Thrown at packages/core/src/tool-loop-agent/utils.ts:33

export function isToolLoopAgentLike(obj: any): obj is ToolLoopAgentLike {
  if (!obj) return false;
  if (obj instanceof ToolLoopAgent) return true;
  return (
    'version' in obj &&
    typeof obj.version === 'string' &&
    (obj.version === 'agent-v1' || obj.version.startsWith('agent-v'))
  );
}

/**
 * Extracts the settings from a ToolLoopAgent instance.
 * ToolLoopAgent.settings is private in TypeScript but accessible at runtime.
 */
export function getSettings(agent: ToolLoopAgentLike): ToolLoopAgentSettings<any, any, any> {
  const settings = (agent as unknown as { settings: ToolLoopAgentSettings<any, any, any> }).settings;
  if (!settings) {
    throw new Error('Could not extract settings from ToolLoopAgent. The agent may be from an incompatible version.');
  }
  return settings;
}

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Ensure a single @mastra/core version is installed: run pnpm why @mastra/core / npm ls @mastra/core and dedupe mismatched copies.
  2. Pass the actual ToolLoopAgent instance, not a serialized copy or a plain-object stand-in.
  3. Upgrade all mastra packages to matching versions so the agent's internal shape matches what getSettings expects.
  4. If you control the caller, construct the agent via the current ToolLoopAgent export rather than another Agent class.

Example fix

// before
import { Agent } from '@mastra/core/agent';
getSettings(new Agent({ name: 'a', model, instructions })); // different class, no .settings

// after
import { ToolLoopAgent } from '@mastra/core/tool-loop-agent';
getSettings(new ToolLoopAgent({ name: 'a', model, instructions }));
Defensive patterns

Strategy: type-guard

Validate before calling

import { ToolLoopAgent } from '@mastra/core/tool-loop-agent';
function assertToolLoopAgent(a: unknown): asserts a is ToolLoopAgent {
  if (!(a instanceof ToolLoopAgent)) throw new TypeError('expected a ToolLoopAgent instance');
  if (!('settings' in a) || !(a as any).settings) throw new TypeError('agent has no settings — version mismatch?');
}

Type guard

function isToolLoopAgentLike(a: unknown): a is { settings: unknown } {
  return !!a && typeof a === 'object' && 'settings' in a && (a as any).settings != null;
}

Try / catch

try {
  const settings = getSettings(agent);
} catch (err) {
  if (err instanceof Error && err.message.includes('Could not extract settings')) {
    console.error('agent instance is incompatible — check @mastra/core versions and instance type');
  } else throw err;
}

Prevention

When it happens

Trigger: Calling getSettings(agent) (directly or via utilities that depend on it, like the settings accessor) with: an agent created by an older/newer @mastra/core that renames or removes .settings; a plain object that structurally resembles an agent; an Agent from a different package (e.g. @mastra/core/agent Agent) rather than ToolLoopAgent.

Common situations: Mixed @mastra/core versions in one install (duplicated dependencies from mismatched pnpm/npm resolution) so the instance was built by another copy of the library; passing a serialized/deserialized agent (JSON round-trip drops methods and private fields); passing a mock in tests.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/ee54b456ef1b3e1a. Report an issue: GitHub.