fix(core): resolve harness v1 agents by id#17678
Conversation
Resolve Harness v1 mode and subagent agent ids from Mastra or inline agent registries so harness construction can defer missing subagent failures to tool execution. This keeps mode-backed sessions working for the agentId-based V1 config shape and preserves recoverable subagent tool errors for missing agents. Co-Authored-By: Mastra Code (openai/gpt-5.5) <noreply@mastra.ai>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🦋 Changeset detectedLatest commit: 1c034a8 The changes in this PR will be included in the next version bump. This PR includes changesets to release 20 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
WalkthroughHarness v1 now supports per-mode agent selection. Modes can specify backing agents via optional ChangesPer-Mode Agent Selection
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration. Comment |
PR triageLinked issue check skipped for core contributor @wardpeet. PR complexity score
Applied label: Changed test gateNo changed test files were detected. Label: |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/core/src/harness/v1/harness.ts (1)
54-128: 🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick winMissing validation: Modes without
agentIdmust have a harness-level default agent.The constructor doesn't validate that modes can resolve to agents. When a mode lacks
agentIdand the harness config provides no defaultagent,#agentForModewill fail at runtime (see previous comment).Consider adding validation during construction to ensure every mode either has a valid
agentIdor the harness has a valid default#agent.🔍 Proposed validation logic
Add after line 128:
// Validate that all modes can resolve to agents for (const mode of modes) { if (!mode.agentId && !this.#agent) { throw new Error( `Mode "${mode.id}" has no agentId and harness has no default agent. ` + `Either set mode.agentId or provide a harness-level agent in config.` ); } // If mode has agentId, validate it's resolvable when using inline agents if (mode.agentId && !this.#mastra && !this.#agents?.[mode.agentId]) { throw new Error( `Mode "${mode.id}" references unknown agent "${mode.agentId}". ` + `Agent must be present in config.agents registry.` ); } }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/core/src/harness/v1/harness.ts` around lines 54 - 128, Add validation in the constructor to ensure every mode can resolve to an agent: after populating this.#modesById (the modes loop in the constructor), iterate modes and for each mode check that either mode.agentId is set or this.#agent is present; if neither, throw a descriptive Error referencing mode.id; additionally, when mode.agentId is set and the harness is using inline agents (this.#mastra is falsy), verify this.#agents?.[mode.agentId] exists and throw an Error if it does not. Use the constructor, this.#agent, this.#modesById, this.#mastra and this.#agents symbols to locate where to insert these checks.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.changeset/dry-paws-wash.md:
- Line 5: Update the changeset description to be user-facing: replace "ids" with
"IDs", remove internal jargon like "agent lookup", and clearly state the
user-visible problem and outcome (e.g., in Harness v1 mode subagents using agent
IDs failed to resolve, and now subagents referenced by agent IDs resolve
correctly), referencing the existing phrases "Harness v1 mode", "subagent", and
"agent IDs" so reviewers can find and replace the current line.
In `@packages/core/src/harness/v1/harness.ts`:
- Around line 315-321: The method `#agentForMode` currently asserts this.#agent as
Agent and can return undefined; change it to validate at runtime: call
this.#tryResolveAgent(mode.agentId) and if it returns an Agent return it, but if
mode.agentId was provided and resolution failed throw a descriptive Error
mentioning the unresolved agentId and the HarnessMode; if mode.agentId is not
provided and this.#agent is undefined throw an Error stating no default agent is
configured; remove the unsafe "as Agent" assertion and ensure the method either
returns a valid Agent or throws so callers (e.g. Session) never receive
undefined.
---
Outside diff comments:
In `@packages/core/src/harness/v1/harness.ts`:
- Around line 54-128: Add validation in the constructor to ensure every mode can
resolve to an agent: after populating this.#modesById (the modes loop in the
constructor), iterate modes and for each mode check that either mode.agentId is
set or this.#agent is present; if neither, throw a descriptive Error referencing
mode.id; additionally, when mode.agentId is set and the harness is using inline
agents (this.#mastra is falsy), verify this.#agents?.[mode.agentId] exists and
throw an Error if it does not. Use the constructor, this.#agent,
this.#modesById, this.#mastra and this.#agents symbols to locate where to insert
these checks.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 549a1c7a-0aa2-4318-ab5c-5c3ebbcbd7d2
📒 Files selected for processing (4)
.changeset/dry-paws-wash.mdpackages/core/src/harness/v1/harness.tspackages/core/src/harness/v1/harness.types.tspackages/core/src/harness/v1/mode.ts
| '@mastra/core': patch | ||
| --- | ||
|
|
||
| Fixed Harness v1 mode and subagent agent lookup when using agent ids. |
There was a problem hiding this comment.
Improve the description to highlight the user-facing outcome.
The current description has several issues:
- "ids" should be capitalized as "IDs"
- The phrase "agent lookup" is internal terminology
- It doesn't explain what was broken or what now works for users
As per coding guidelines, changesets should "highlight outcomes" and avoid focusing on "internal implementation details." The description should explain what now works for developers using Harness v1.
✍️ Suggested revision
-Fixed Harness v1 mode and subagent agent lookup when using agent ids.
+Fixed Harness v1 modes and subagents to correctly resolve agents when configured with agent IDs instead of inline agent objects.Alternatively, focus even more on the outcome:
-Fixed Harness v1 mode and subagent agent lookup when using agent ids.
+Harness v1 modes and subagents now work correctly when using the agent ID–based configuration shape.📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| Fixed Harness v1 mode and subagent agent lookup when using agent ids. | |
| Fixed Harness v1 modes and subagents to correctly resolve agents when configured with agent IDs instead of inline agent objects. |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.changeset/dry-paws-wash.md at line 5, Update the changeset description to
be user-facing: replace "ids" with "IDs", remove internal jargon like "agent
lookup", and clearly state the user-visible problem and outcome (e.g., in
Harness v1 mode subagents using agent IDs failed to resolve, and now subagents
referenced by agent IDs resolve correctly), referencing the existing phrases
"Harness v1 mode", "subagent", and "agent IDs" so reviewers can find and replace
the current line.
Source: Coding guidelines
| #agentForMode(mode: HarnessMode): Agent { | ||
| if (mode.agentId) { | ||
| const agent = this.#tryResolveAgent(mode.agentId); | ||
| if (agent) return agent; | ||
| } | ||
| return this.#agent as Agent; | ||
| } |
There was a problem hiding this comment.
Critical: Unsafe type assertion can return undefined as Agent.
The #agentForMode method uses as Agent on line 320, but this.#agent is optional (#agent?: Agent). When both conditions are true:
mode.agentIdis either undefined or doesn't resolve to an agent (line 317 returns undefined)this.#agentis undefined
...the method returns undefined while claiming the return type is Agent. This will cause runtime errors when Session attempts to use the agent.
Additionally, when a mode explicitly specifies an agentId that cannot be resolved (line 317-318), the code silently falls back to this.#agent instead of failing. This masks configuration errors where a mode's agentId is misspelled or references a non-existent agent.
🛡️ Proposed fix with proper validation
`#agentForMode`(mode: HarnessMode): Agent {
if (mode.agentId) {
const agent = this.#tryResolveAgent(mode.agentId);
- if (agent) return agent;
+ if (!agent) {
+ throw new Error(`Mode "${mode.id}" references unknown agent "${mode.agentId}"`);
+ }
+ return agent;
}
- return this.#agent as Agent;
+ if (!this.#agent) {
+ throw new Error(`Mode "${mode.id}" has no agentId and harness has no default agent`);
+ }
+ return this.#agent;
}🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/core/src/harness/v1/harness.ts` around lines 315 - 321, The method
`#agentForMode` currently asserts this.#agent as Agent and can return undefined;
change it to validate at runtime: call this.#tryResolveAgent(mode.agentId) and
if it returns an Agent return it, but if mode.agentId was provided and
resolution failed throw a descriptive Error mentioning the unresolved agentId
and the HarnessMode; if mode.agentId is not provided and this.#agent is
undefined throw an Error stating no default agent is configured; remove the
unsafe "as Agent" assertion and ensure the method either returns a valid Agent
or throws so callers (e.g. Session) never receive undefined.
Fixes Harness v1 agent id resolution so modes and subagents can use the agentId-based config shape.
The harness now resolves mode agent ids from either a Mastra instance or the inline agents map when creating sessions. Subagent agent lookup still happens during tool execution, so missing subagent agents return the expected recoverable tool error instead of failing during harness construction.
Test plan:
ELI5
This PR makes it easier to tell the Harness which agent to use by allowing you to just specify an agent ID instead of having to pass the entire agent object. The system now knows how to look up the actual agent from a registry, similar to how you might look up a phone number by a name instead of having to write out the whole contact card.
Changes
Configuration Updates
HarnessConfignow makes the defaultagentfield optional in both configuration styles (when using aMastrainstance or inline agents registry)HarnessModenow supports an optionalagentIdfield to specify the backing agent for sessions entered into that modeHarness v1 Implementation
Harnessclass now stores an inlineagentsregistry when provided in config#agentForMode(mode)- prefers a mode-specificagentId, falls back to the harness-level agent#tryResolveAgent(agentId)- looks up agents via theMastrainstance or inline registry#resolveAgentto use the new lookup mechanismChangeset
.changeset/dry-paws-wash.mdto document the patch release for@mastra/core