fix: allow merging andAgent output with existing workflow data via …#943
Conversation
…an optional mapper
🦋 Changeset detectedLatest commit: 959a64e The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
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 |
📝 WalkthroughWalkthroughAdds an optional mapper to andAgent so agent outputs can be transformed/merged into existing workflow data; updates types, implementation, tests, and docs to support and demonstrate the new map callback. Changes
Sequence Diagram(s)sequenceDiagram
participant Workflow as WorkflowCaller
participant Chain as WorkflowChain/Step
participant Agent as AgentRuntime
participant Mapper as MapCallback
Workflow->>Chain: call andAgent(taskFn, agentRef, schema, map?)
Chain->>Agent: invoke agent with prompt (from taskFn)
Agent-->>Chain: agent output (string/json)
Chain->>Chain: parse/validate with schema
alt mapper provided
Chain->>Mapper: call map(agentParsed, currentData, ctx)
Mapper-->>Chain: merged/transformed data (NEW_DATA)
Chain-->>Workflow: return merged data
else no mapper
Chain-->>Workflow: return parsed output (or replace data)
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 📜 Recent review detailsConfiguration used: defaults Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
✏️ Tip: You can disable this entire section by setting Comment |
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@website/docs/workflows/steps/and-agent.md`:
- Around line 85-91: The mapper in the .andAgent call is inconsistent: it
currently sets emailType to output.type but downstream code expects emailType to
be the full output object (accessing data.emailType.type). Update the mapper
used in .andAgent (the arrow function with parameters output and { data }) to
attach the entire output object to emailType (i.e., set emailType to output) so
it matches the other "Merge Output With Existing Data" examples and the
downstream usages.
🧹 Nitpick comments (1)
packages/core/src/workflow/steps/and-agent.spec.ts (1)
12-12: Consider adding test coverage for passthrough behavior.The test validates the mapper case. Consider adding a test to verify the passthrough behavior when no mapper is provided, ensuring backward compatibility.
Example additional test
it("returns agent output directly when no mapper is provided", async () => { const agent = createTestAgent({ model: createMockLanguageModel({ doGenerate: { ...defaultMockResponse, content: [ { type: "text" as const, text: safeStringify({ type: "support", priority: "high" }), }, ], }, }), }); const step = andAgent( ({ data }) => `What type of email is this: ${data.email}`, agent, { schema: z.object({ type: z.enum(["support", "sales", "spam"]), priority: z.enum(["low", "medium", "high"]), }), }, // No mapper provided ); const result = await step.execute( createMockWorkflowExecuteContext({ data: { email: "help@acme.com" }, }), ); expect(result).toEqual({ type: "support", priority: "high" }); });
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
.changeset/smart-mangos-work.mdpackages/core/src/workflow/chain.spec-d.tspackages/core/src/workflow/chain.tspackages/core/src/workflow/steps/and-agent.spec.tspackages/core/src/workflow/steps/and-agent.tswebsite/docs/workflows/steps/and-agent.md
🧰 Additional context used
📓 Path-based instructions (1)
**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
**/*.ts: Maintain type safety in TypeScript-first codebase
Never use JSON.stringify; use thesafeStringifyfunction instead, imported from@voltagent/internal
Files:
packages/core/src/workflow/steps/and-agent.tspackages/core/src/workflow/chain.spec-d.tspackages/core/src/workflow/chain.tspackages/core/src/workflow/steps/and-agent.spec.ts
🧠 Learnings (1)
📚 Learning: 2026-01-07T05:09:23.227Z
Learnt from: CR
Repo: VoltAgent/voltagent PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-01-07T05:09:23.227Z
Learning: Applies to **/*.test.ts : Test your changes - ensure all tests pass before committing
Applied to files:
packages/core/src/workflow/steps/and-agent.spec.ts
🧬 Code graph analysis (3)
packages/core/src/workflow/steps/and-agent.ts (3)
packages/core/src/workflow/index.ts (2)
WorkflowExecuteContext(39-39)andAgent(2-2)packages/core/src/workflow/steps/index.ts (2)
andAgent(1-1)WorkflowStepAgent(24-24)packages/core/src/workflow/steps/types.ts (1)
WorkflowStepAgent(31-35)
packages/core/src/workflow/chain.spec-d.ts (1)
packages/core/src/workflow/chain.ts (1)
createWorkflowChain(966-979)
packages/core/src/workflow/steps/and-agent.spec.ts (4)
packages/core/src/agent/test-utils.ts (1)
createTestAgent(345-358)packages/core/src/workflow/chain.ts (1)
andAgent(203-241)packages/core/src/workflow/steps/and-agent.ts (1)
andAgent(46-152)packages/core/src/test-utils/mocks/workflows.ts (1)
createMockWorkflowExecuteContext(19-41)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
- GitHub Check: cubic · AI code reviewer
- GitHub Check: Test server-core
- GitHub Check: Test core
- GitHub Check: Build (Node 20)
- GitHub Check: Build (Node 24)
- GitHub Check: Build (Node 22)
- GitHub Check: Cloudflare Pages
🔇 Additional comments (12)
.changeset/smart-mangos-work.md (1)
1-19: LGTM!The changeset correctly documents the new feature with a clear example demonstrating how to merge agent output with existing workflow data using the optional mapper.
website/docs/workflows/steps/and-agent.md (1)
145-159: LGTM!Clear and practical example demonstrating how to merge agent output with existing workflow data. The pattern of spreading existing data and adding the new
emailTypefield is intuitive.packages/core/src/workflow/chain.spec-d.ts (1)
446-486: LGTM!Comprehensive type test that validates:
- The mapper receives correctly typed
outputanddataparameters- The mapped result type flows correctly to subsequent steps
- Type safety is maintained through the chain
This provides good coverage for the new mapper functionality.
packages/core/src/workflow/steps/and-agent.spec.ts (1)
12-51: LGTM!Well-structured test that validates the mapper functionality. Good use of
safeStringifyfrom@voltagent/internalper coding guidelines.packages/core/src/workflow/steps/and-agent.ts (5)
17-20: LGTM!Clean type definition for the mapper function. Correctly typed to receive the inferred schema output and workflow context, returning either a sync or async result.
70-76: LGTM!The
mapOutputhelper cleanly handles both mapped and passthrough cases. The casts are necessary due to TypeScript's limitations with conditional types and are safe given the function signature constraints.Note that if the mapper throws, the error will propagate naturally through the
await, which aligns with the existing error handling pattern in thetry/catchblock below.
46-54: LGTM!Well-designed generic signature that maintains backward compatibility. The default
RESULT = z.infer<SCHEMA>ensures existing callers without a mapper continue to work unchanged.
102-102: LGTM!Consistent application of
mapOutputin both execution paths ensures the mapper (when provided) is always invoked regardless of workflow context presence.
151-151: LGTM!The
satisfiesclause correctly uses theRESULTgeneric, ensuring the returned step object conforms toWorkflowStepAgent<INPUT, DATA, RESULT>.packages/core/src/workflow/chain.ts (3)
164-165: LGTM!Documentation clearly describes the purpose of the optional
mapparameter.
183-201: LGTM!The new overload is well-designed:
- Correctly introduces
NEW_DATAgeneric for the mapped output type- The
mapcallback signature properly supports both sync and async patterns- Providing the full
contextenables merging agent output with existing workflow data as intended
203-241: Implementation correctly delegates the mapper to the underlying step factory.The underlying
andAgentstep function in./steps/and-agent.ts(line 46-54) correctly accepts and handles the optionalmapparameter, typed asAgentResultMapper<INPUT, DATA, SCHEMA, RESULT>. The delegation pattern from the chain method to the step factory is sound. The use ofDangerouslyAllowAnyin the implementation signature is appropriate given the complexity of the overloads.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
…an optional mapper
PR Checklist
Please check if your PR fulfills the following requirements:
Bugs / Features
What is the current behavior?
What is the new behavior?
fixes (issue)
Notes for reviewers
Summary by cubic
Adds an optional mapper to andAgent so you can merge or reshape the agent’s output with existing workflow data instead of replacing it.
New Features
Migration
Written for commit 959a64e. Summary will update on new commits.
Summary by CodeRabbit
New Features
Documentation
Tests
Chores
✏️ Tip: You can customize this high-level summary in your review settings.