Skip to content

fix: allow merging andAgent output with existing workflow data via …#943

Merged
omeraplak merged 2 commits into
mainfrom
feat/and-agent-map
Jan 15, 2026
Merged

fix: allow merging andAgent output with existing workflow data via …#943
omeraplak merged 2 commits into
mainfrom
feat/and-agent-map

Conversation

@omeraplak

@omeraplak omeraplak commented Jan 15, 2026

Copy link
Copy Markdown
Member

…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

    • andAgent accepts a fourth map argument to merge/transform the agent output with current data.
    • Updated WorkflowChain.andAgent overloads to support custom result types.
    • Added tests and docs showing an email classification merge pattern.
    • Changeset: patch release for @voltagent/core.
  • Migration

    • No changes required. The mapper is optional and the default behavior is unchanged.

Written for commit 959a64e. Summary will update on new commits.

Summary by CodeRabbit

  • New Features

    • Optional mapper for andAgent to merge or reshape agent output into existing workflow data.
  • Documentation

    • Updated docs with examples and patterns showing how to merge agent output into prior data and use merged fields downstream.
  • Tests

    • Added unit and type tests validating mapping behavior and resulting data shapes.
  • Chores

    • Added a changeset for a patch release documenting the new mapper capability.

✏️ Tip: You can customize this high-level summary in your review settings.

@changeset-bot

changeset-bot Bot commented Jan 15, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 959a64e

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@voltagent/core Patch

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

@coderabbitai

coderabbitai Bot commented Jan 15, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Adds 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

Cohort / File(s) Change Summary
Changeset & Manifest
​.changeset/smart-mangos-work.md
Adds a changeset documenting the optional mapper feature for andAgent in a patch release.
Type Tests
packages/core/src/workflow/chain.spec-d.ts
Adds type-level tests verifying andAgent can map agent output into existing data and that resulting chain types reflect the merged shape.
Workflow Chain API
packages/core/src/workflow/chain.ts
Adds andAgent overloads accepting an optional map callback and a NEW_DATA generic; adjusts return types (includes DangerouslyAllowAny path when mapping is used).
Step Implementation
packages/core/src/workflow/steps/and-agent.ts
Introduces AgentResultMapper type, makes andAgent generic over RESULT, adds optional map parameter, implements mapOutput helper, and returns mapped results when mapper is provided.
Unit Tests (step)
packages/core/src/workflow/steps/and-agent.spec.ts
Adds runtime test asserting that andAgent with a mapper merges parsed agent output into prior data (preserves original fields and adds merged field).
Documentation
website/docs/workflows/steps/and-agent.md
Documents the optional fourth map argument, adds examples showing merging agent output into existing workflow data, and updates downstream usage examples to reference merged fields.

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
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I nibble code where agents play,
I map their words into the fray,
I tuck old fields and stitch the new,
A bunny merge — concise and true,
Hopping workflows all the way!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly and concisely describes the main feature: allowing andAgent output to be merged with existing workflow data via an optional mapper.
Description check ✅ Passed The PR description includes all key sections from the template: checklist, what's new, notes, and auto-generated summary explaining the feature, migration path, and affected components comprehensively.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.



📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3f44667 and 959a64e.

📒 Files selected for processing (1)
  • website/docs/workflows/steps/and-agent.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • website/docs/workflows/steps/and-agent.md
⏰ 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: Test server-core
  • GitHub Check: Test core
  • GitHub Check: Test libsql
  • GitHub Check: Build (Node 24)
  • GitHub Check: Build (Node 22)
  • GitHub Check: Build (Node 20)
  • GitHub Check: Cloudflare Pages

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@ghost

This comment has been minimized.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between ab39d68 and 3f44667.

📒 Files selected for processing (6)
  • .changeset/smart-mangos-work.md
  • packages/core/src/workflow/chain.spec-d.ts
  • packages/core/src/workflow/chain.ts
  • packages/core/src/workflow/steps/and-agent.spec.ts
  • packages/core/src/workflow/steps/and-agent.ts
  • website/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 the safeStringify function instead, imported from @voltagent/internal

Files:

  • packages/core/src/workflow/steps/and-agent.ts
  • packages/core/src/workflow/chain.spec-d.ts
  • packages/core/src/workflow/chain.ts
  • packages/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 emailType field is intuitive.

packages/core/src/workflow/chain.spec-d.ts (1)

446-486: LGTM!

Comprehensive type test that validates:

  1. The mapper receives correctly typed output and data parameters
  2. The mapped result type flows correctly to subsequent steps
  3. 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 safeStringify from @voltagent/internal per 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 mapOutput helper 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 the try/catch block 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 mapOutput in both execution paths ensures the mapper (when provided) is always invoked regardless of workflow context presence.


151-151: LGTM!

The satisfies clause correctly uses the RESULT generic, ensuring the returned step object conforms to WorkflowStepAgent<INPUT, DATA, RESULT>.

packages/core/src/workflow/chain.ts (3)

164-165: LGTM!

Documentation clearly describes the purpose of the optional map parameter.


183-201: LGTM!

The new overload is well-designed:

  • Correctly introduces NEW_DATA generic for the mapped output type
  • The map callback signature properly supports both sync and async patterns
  • Providing the full context enables merging agent output with existing workflow data as intended

203-241: Implementation correctly delegates the mapper to the underlying step factory.

The underlying andAgent step function in ./steps/and-agent.ts (line 46-54) correctly accepts and handles the optional map parameter, typed as AgentResultMapper<INPUT, DATA, SCHEMA, RESULT>. The delegation pattern from the chain method to the step factory is sound. The use of DangerouslyAllowAny in 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.

Comment thread website/docs/workflows/steps/and-agent.md
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jan 15, 2026

Copy link
Copy Markdown

Deploying voltagent with  Cloudflare Pages  Cloudflare Pages

Latest commit: 959a64e
Status:⚡️  Build in progress...

View logs

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 6 files

@omeraplak
omeraplak merged commit 6217716 into main Jan 15, 2026
22 of 23 checks passed
@omeraplak
omeraplak deleted the feat/and-agent-map branch January 15, 2026 05:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant